From 3653ed66a94d0cbed26110c621273c4d17e9afc3 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 27 Jun 2024 08:20:11 +0200 Subject: [PATCH 001/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/logme to v0.16.0 (#390) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3cc059542..0c7fa1bcd 100644 --- a/go.mod +++ b/go.mod @@ -75,7 +75,7 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/argus v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.13.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.15.0 diff --git a/go.sum b/go.sum index 79e1cec73..0cecea262 100644 --- a/go.sum +++ b/go.sum @@ -133,8 +133,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.13.0 h1:W7tyIIIXgAilHpALRyrW3CrtQ2UAGZBjAG+P4tcK+QQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.13.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.15.0 h1:7gii3PZshOesHPCYlPycilXglk28imITIqjewySZwZ4= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.15.0/go.mod h1:bj9cn1treNSxKTRCEmESwqfENN8vCYn60HUnEA0P83c= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.16.0 h1:Cz4zQnEax6L3Y9gL7jtETPmiTERB7WNQtIzZ1UWeNNk= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.16.0/go.mod h1:bj9cn1treNSxKTRCEmESwqfENN8vCYn60HUnEA0P83c= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.15.0 h1:eYYyVUTS9Gjovg3z9+r6ctvsm1p1J4fHLa5QJbWHi0A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.15.0/go.mod h1:kPetkX9hNm9HkRyiKQL/tlgdi8frZdMP8afg0mEvQ9s= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 h1:FaJYVfha+atvPfFIf3h3+BFjOjeux9OBHukG1J98kq0= From 29e537bb1d32bf73819d1fc31b5dfe38f6f8c146 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Fri, 28 Jun 2024 08:17:13 +0200 Subject: [PATCH 002/619] Add env value check to project name detection (#392) * check if project id is set in env variables * changed function for getting env variable value --- internal/pkg/projectname/project_name.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/internal/pkg/projectname/project_name.go b/internal/pkg/projectname/project_name.go index a258df6e1..1c6532b48 100644 --- a/internal/pkg/projectname/project_name.go +++ b/internal/pkg/projectname/project_name.go @@ -3,6 +3,7 @@ package projectname import ( "context" "fmt" + "os" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -41,7 +42,7 @@ func GetProjectName(ctx context.Context, p *print.Printer, cmd *cobra.Command) ( // If project ID is set in config, we store the project name in config // (So next time we can just pull it from there) - if !isProjectIdSetInFlags(p, cmd) { + if !(isProjectIdSetInFlags(p, cmd) || isProjectIdSetInEnvVar()) { viper.Set(config.ProjectNameKey, projectName) err = config.Write() if err != nil { @@ -57,13 +58,14 @@ func useProjectNameFromConfig(p *print.Printer, cmd *cobra.Command) bool { // We use the project name from the config file, if: // - Project id is not set to a different value than the one in the config file // - Project name in the config file is not empty - projectIdSet := isProjectIdSetInFlags(p, cmd) + projectIdSetInFlags := isProjectIdSetInFlags(p, cmd) + projectIdSetInEnv := isProjectIdSetInEnvVar() projectName := viper.GetString(config.ProjectNameKey) projectNameSet := false if projectName != "" { projectNameSet = true } - return !projectIdSet && projectNameSet + return !projectIdSetInFlags && !projectIdSetInEnv && projectNameSet } func isProjectIdSetInFlags(p *print.Printer, cmd *cobra.Command) bool { @@ -77,3 +79,9 @@ func isProjectIdSetInFlags(p *print.Printer, cmd *cobra.Command) bool { } return projectIdSetInFlag } + +func isProjectIdSetInEnvVar() bool { + // Reads the project Id from the environment variable PROJECT_ID + _, projectIdSetInEnv := os.LookupEnv("STACKIT_PROJECT_ID") + return projectIdSetInEnv +} From 048865f773dce2efd1893ad2a6132e3b23880cf9 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:46:59 +0200 Subject: [PATCH 003/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/postgresflex to v0.15.0 (#394) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0c7fa1bcd..40c3f73b0 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.14.0 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.14.0 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 diff --git a/go.sum b/go.sum index 0cecea262..09e23d92f 100644 --- a/go.sum +++ b/go.sum @@ -143,8 +143,8 @@ github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 h1:tn1MD1n github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0/go.mod h1:dkVMJI88eJ3Xs0ZV15r4tUpgitUGJXcvrX3RL4Zq2bQ= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.14.0 h1:zkhm0r0OZ5NbHJFrm+7B+h11QL0bNLC53nzXhqCaLWo= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.14.0/go.mod h1:ZecMIf9oYj2DGZqWh93l97WdVaRdLl+tW5Fq3YKGwBM= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.14.0 h1:PZAqXd8TVyTZo8qty4bM2sSoLlLG+Nc9tcpxbQhO+GY= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.14.0/go.mod h1:SdrqGLCkilL6wl1+jcxmLtks2IocgIg+bsyeyYUIzR4= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 h1:05wQYhO37Z4y8xAD+4OTYz6rYu6eJEmwMfCG4tjETEc= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0/go.mod h1:SdrqGLCkilL6wl1+jcxmLtks2IocgIg+bsyeyYUIzR4= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.15.0 h1:Q7JxjVwb+9ugAX71AXdbfPL87HHmIIwb9LNahn6H/2o= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.15.0/go.mod h1:eSgnPBknTJh7t+jVKN+xzeAh+Cg1USOlH3QCyfvG20g= github.com/stackitcloud/stackit-sdk-go/services/redis v0.15.0 h1:/S+LOl94FqGk5Qdi5ehsiSCh6cCPEYJDctNOD0c2dmw= From 0e9c46aac387fd5455bf2ba3a2cf4817b7950fdc Mon Sep 17 00:00:00 2001 From: a_nackov Date: Mon, 1 Jul 2024 12:50:25 +0300 Subject: [PATCH 004/619] ref 643132: server backup schedules (#393) Signed-off-by: Adrian Nackov --- Makefile | 5 +- docs/stackit_beta.md | 1 + docs/stackit_beta_server.md | 33 +++ docs/stackit_beta_server_backup.md | 35 +++ docs/stackit_beta_server_backup_disable.md | 40 +++ docs/stackit_beta_server_backup_enable.md | 40 +++ docs/stackit_beta_server_backup_schedule.md | 37 +++ ...ckit_beta_server_backup_schedule_create.md | 49 ++++ ...ckit_beta_server_backup_schedule_delete.md | 40 +++ ...it_beta_server_backup_schedule_describe.md | 43 +++ ...tackit_beta_server_backup_schedule_list.md | 44 +++ ...ckit_beta_server_backup_schedule_update.md | 49 ++++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 2 + internal/cmd/beta/beta.go | 2 + internal/cmd/beta/server/backup/backup.go | 30 ++ .../cmd/beta/server/backup/disable/disable.go | 118 ++++++++ .../server/backup/disable/disable_test.go | 173 +++++++++++ .../cmd/beta/server/backup/enable/enable.go | 112 +++++++ .../beta/server/backup/enable/enable_test.go | 173 +++++++++++ .../server/backup/schedule/create/create.go | 188 ++++++++++++ .../backup/schedule/create/create_test.go | 220 ++++++++++++++ .../server/backup/schedule/delete/delete.go | 113 +++++++ .../backup/schedule/delete/delete_test.go | 209 +++++++++++++ .../backup/schedule/describe/describe.go | 159 ++++++++++ .../backup/schedule/describe/describe_test.go | 211 +++++++++++++ .../beta/server/backup/schedule/list/list.go | 166 +++++++++++ .../server/backup/schedule/list/list_test.go | 188 ++++++++++++ .../beta/server/backup/schedule/schedule.go | 34 +++ .../server/backup/schedule/update/update.go | 215 ++++++++++++++ .../backup/schedule/update/update_test.go | 277 ++++++++++++++++++ internal/cmd/beta/server/server.go | 26 ++ internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 13 + internal/pkg/config/config.go | 3 + .../services/serverbackup/client/client.go | 46 +++ .../pkg/services/serverbackup/utils/utils.go | 34 +++ .../services/serverbackup/utils/utils_test.go | 145 +++++++++ 41 files changed, 3286 insertions(+), 1 deletion(-) create mode 100644 docs/stackit_beta_server.md create mode 100644 docs/stackit_beta_server_backup.md create mode 100644 docs/stackit_beta_server_backup_disable.md create mode 100644 docs/stackit_beta_server_backup_enable.md create mode 100644 docs/stackit_beta_server_backup_schedule.md create mode 100644 docs/stackit_beta_server_backup_schedule_create.md create mode 100644 docs/stackit_beta_server_backup_schedule_delete.md create mode 100644 docs/stackit_beta_server_backup_schedule_describe.md create mode 100644 docs/stackit_beta_server_backup_schedule_list.md create mode 100644 docs/stackit_beta_server_backup_schedule_update.md create mode 100644 internal/cmd/beta/server/backup/backup.go create mode 100644 internal/cmd/beta/server/backup/disable/disable.go create mode 100644 internal/cmd/beta/server/backup/disable/disable_test.go create mode 100644 internal/cmd/beta/server/backup/enable/enable.go create mode 100644 internal/cmd/beta/server/backup/enable/enable_test.go create mode 100644 internal/cmd/beta/server/backup/schedule/create/create.go create mode 100644 internal/cmd/beta/server/backup/schedule/create/create_test.go create mode 100644 internal/cmd/beta/server/backup/schedule/delete/delete.go create mode 100644 internal/cmd/beta/server/backup/schedule/delete/delete_test.go create mode 100644 internal/cmd/beta/server/backup/schedule/describe/describe.go create mode 100644 internal/cmd/beta/server/backup/schedule/describe/describe_test.go create mode 100644 internal/cmd/beta/server/backup/schedule/list/list.go create mode 100644 internal/cmd/beta/server/backup/schedule/list/list_test.go create mode 100644 internal/cmd/beta/server/backup/schedule/schedule.go create mode 100644 internal/cmd/beta/server/backup/schedule/update/update.go create mode 100644 internal/cmd/beta/server/backup/schedule/update/update_test.go create mode 100644 internal/cmd/beta/server/server.go create mode 100644 internal/pkg/services/serverbackup/client/client.go create mode 100644 internal/pkg/services/serverbackup/utils/utils.go create mode 100644 internal/pkg/services/serverbackup/utils/utils_test.go diff --git a/Makefile b/Makefile index ab57bb905..9a6d08844 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ GOLANG_CI_ARGS ?= --allow-parallel-runners --timeout=5m --config=${GOLANG_CI_YAM build: @go build -o ./bin/stackit +fmt: + @gofmt -s -w . + # Setup and tool initialization tasks project-help: @$(SCRIPTS_BASE)/project.sh help @@ -33,4 +36,4 @@ test: # Generate docs generate-docs: @echo "Generating docs..." - @go run $(SCRIPTS_BASE)/generate.go \ No newline at end of file + @go run $(SCRIPTS_BASE)/generate.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 3fbc2395a..015a04b3f 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -40,5 +40,6 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md new file mode 100644 index 000000000..d06925458 --- /dev/null +++ b/docs/stackit_beta_server.md @@ -0,0 +1,33 @@ +## stackit beta server + +Provides functionality for Server + +### Synopsis + +Provides functionality for Server. + +``` +stackit beta server [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup + diff --git a/docs/stackit_beta_server_backup.md b/docs/stackit_beta_server_backup.md new file mode 100644 index 000000000..e2ae7ffda --- /dev/null +++ b/docs/stackit_beta_server_backup.md @@ -0,0 +1,35 @@ +## stackit beta server backup + +Provides functionality for Server Backup + +### Synopsis + +Provides functionality for Server Backup. + +``` +stackit beta server backup [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server backup disable](./stackit_beta_server_backup_disable.md) - Disables Server Backup service +* [stackit beta server backup enable](./stackit_beta_server_backup_enable.md) - Enables Server Backup service +* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule + diff --git a/docs/stackit_beta_server_backup_disable.md b/docs/stackit_beta_server_backup_disable.md new file mode 100644 index 000000000..b2175dc86 --- /dev/null +++ b/docs/stackit_beta_server_backup_disable.md @@ -0,0 +1,40 @@ +## stackit beta server backup disable + +Disables Server Backup service + +### Synopsis + +Disables Server Backup service. + +``` +stackit beta server backup disable [flags] +``` + +### Examples + +``` + Disable Server Backup functionality for your server. + $ stackit beta server backup disable --server-id=zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup disable" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup + diff --git a/docs/stackit_beta_server_backup_enable.md b/docs/stackit_beta_server_backup_enable.md new file mode 100644 index 000000000..6a297f2ae --- /dev/null +++ b/docs/stackit_beta_server_backup_enable.md @@ -0,0 +1,40 @@ +## stackit beta server backup enable + +Enables Server Backup service + +### Synopsis + +Enables Server Backup service. + +``` +stackit beta server backup enable [flags] +``` + +### Examples + +``` + Enable Server Backup functionality for your server + $ stackit beta server backup enable --server-id=zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup enable" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup + diff --git a/docs/stackit_beta_server_backup_schedule.md b/docs/stackit_beta_server_backup_schedule.md new file mode 100644 index 000000000..43655d725 --- /dev/null +++ b/docs/stackit_beta_server_backup_schedule.md @@ -0,0 +1,37 @@ +## stackit beta server backup schedule + +Provides functionality for Server Backup Schedule + +### Synopsis + +Provides functionality for Server Backup Schedule. + +``` +stackit beta server backup schedule [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup schedule" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup schedule create](./stackit_beta_server_backup_schedule_create.md) - Creates a Server Backup Schedule +* [stackit beta server backup schedule delete](./stackit_beta_server_backup_schedule_delete.md) - Deletes a Server Backup Schedule +* [stackit beta server backup schedule describe](./stackit_beta_server_backup_schedule_describe.md) - Shows details of a Server Backup Schedule +* [stackit beta server backup schedule list](./stackit_beta_server_backup_schedule_list.md) - Lists all server backup schedules +* [stackit beta server backup schedule update](./stackit_beta_server_backup_schedule_update.md) - Updates a Server Backup Schedule + diff --git a/docs/stackit_beta_server_backup_schedule_create.md b/docs/stackit_beta_server_backup_schedule_create.md new file mode 100644 index 000000000..42c05ca97 --- /dev/null +++ b/docs/stackit_beta_server_backup_schedule_create.md @@ -0,0 +1,49 @@ +## stackit beta server backup schedule create + +Creates a Server Backup Schedule + +### Synopsis + +Creates a Server Backup Schedule. + +``` +stackit beta server backup schedule create [flags] +``` + +### Examples + +``` + Create a Server Backup Schedule with name "myschedule" and backup name "mybackup" + $ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule + + Create a Server Backup Schedule with name "myschedule", backup name "mybackup" and retention period of 5 days + $ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule --backup-retention-period=5 +``` + +### Options + +``` + -b, --backup-name string Backup name + -d, --backup-retention-period int Backup retention period (in days) (default 14) + -n, --backup-schedule-name string Backup schedule name + -i, --backup-volume-ids string Backup volume ids, as comma separated UUID values. + -e, --enabled Is the server backup schedule enabled (default true) + -h, --help Help for "stackit beta server backup schedule create" + -r, --rrule string Backup RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule + diff --git a/docs/stackit_beta_server_backup_schedule_delete.md b/docs/stackit_beta_server_backup_schedule_delete.md new file mode 100644 index 000000000..4df85027d --- /dev/null +++ b/docs/stackit_beta_server_backup_schedule_delete.md @@ -0,0 +1,40 @@ +## stackit beta server backup schedule delete + +Deletes a Server Backup Schedule + +### Synopsis + +Deletes a Server Backup Schedule. + +``` +stackit beta server backup schedule delete SCHEDULE_ID [flags] +``` + +### Examples + +``` + Delete a Server Backup Schedule with ID "xxx" for server "zzz" + $ stackit beta server backup schedule delete xxx --server-id=zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup schedule delete" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule + diff --git a/docs/stackit_beta_server_backup_schedule_describe.md b/docs/stackit_beta_server_backup_schedule_describe.md new file mode 100644 index 000000000..0dcd83a5f --- /dev/null +++ b/docs/stackit_beta_server_backup_schedule_describe.md @@ -0,0 +1,43 @@ +## stackit beta server backup schedule describe + +Shows details of a Server Backup Schedule + +### Synopsis + +Shows details of a Server Backup Schedule. + +``` +stackit beta server backup schedule describe BACKUP_SCHEDULE_ID [flags] +``` + +### Examples + +``` + Get details of a Server Backup Schedule with id "my-schedule-id" + $ stackit beta server backup schedule describe my-schedule-id + + Get details of a Server Backup Schedule with id "my-schedule-id" in JSON format + $ stackit beta server backup schedule describe my-schedule-id --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup schedule describe" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule + diff --git a/docs/stackit_beta_server_backup_schedule_list.md b/docs/stackit_beta_server_backup_schedule_list.md new file mode 100644 index 000000000..5c53c99ae --- /dev/null +++ b/docs/stackit_beta_server_backup_schedule_list.md @@ -0,0 +1,44 @@ +## stackit beta server backup schedule list + +Lists all server backup schedules + +### Synopsis + +Lists all server backup schedules. + +``` +stackit beta server backup schedule list [flags] +``` + +### Examples + +``` + List all backup schedules for a server with ID "xxx" + $ stackit beta server backup schedule list --server-id xxx + + List all backup schedules for a server with ID "xxx" in JSON format + $ stackit beta server backup schedule list --server-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup schedule list" + --limit int Maximum number of entries to list + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule + diff --git a/docs/stackit_beta_server_backup_schedule_update.md b/docs/stackit_beta_server_backup_schedule_update.md new file mode 100644 index 000000000..d238045cd --- /dev/null +++ b/docs/stackit_beta_server_backup_schedule_update.md @@ -0,0 +1,49 @@ +## stackit beta server backup schedule update + +Updates a Server Backup Schedule + +### Synopsis + +Updates a Server Backup Schedule. + +``` +stackit beta server backup schedule update SCHEDULE_ID [flags] +``` + +### Examples + +``` + Update the retention period of the backup schedule "zzz" of server "xxx" + $ stackit beta server backup schedule update zzz --server-id=xxx --backup-retention-period=20 + + Update the backup name of the backup schedule "zzz" of server "xxx" + $ stackit beta server backup schedule update zzz --server-id=xxx --backup-name=newname +``` + +### Options + +``` + -b, --backup-name string Backup name + -d, --backup-retention-period int Backup retention period (in days) (default 14) + -n, --backup-schedule-name string Backup schedule name + -i, --backup-volume-ids string Backup volume ids, as comma separated UUID values. + -e, --enabled Is the server backup schedule enabled (default true) + -h, --help Help for "stackit beta server backup schedule update" + -r, --rrule string Backup RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 11c7861b7..0d9821f87 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -44,6 +44,7 @@ stackit config set [flags] --redis-custom-endpoint string Redis API base URL, used in calls to this API --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API + --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API --service-account-custom-endpoint string Service Account API base URL, used in calls to this API --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) --ske-custom-endpoint string SKE API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index b07b392a1..63c0d9779 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -44,6 +44,7 @@ stackit config unset [flags] --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL + --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL --service-account-custom-endpoint SKE API base URL. If unset, uses the default base URL --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL diff --git a/go.mod b/go.mod index 40c3f73b0..115b56655 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0 diff --git a/go.sum b/go.sum index 09e23d92f..563b90e88 100644 --- a/go.sum +++ b/go.sum @@ -153,6 +153,8 @@ github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 h1:qCbvGq github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0/go.mod h1:p16qz/pAW8b1gEhqMpIgJfutRPeDPqQLlbVGyCo3f8o= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 h1:pJBG455kmtbQFpCxcBfBK8wOuEnmsMv3h90LFcdj3q0= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0/go.mod h1:LX0Mcyr7/QP77zf7e05fHCJO38RMuTxr7nEDUDZ3oPQ= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 h1:fYCBNvh4tqE+DXYDfbJEjC3n/I78zTZajdcPTPB/yig= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0/go.mod h1:ZYI3wj/NnhhWi25ugbdcniwnY/7mF6zN582c5HPe00o= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 h1:JB1O0E9+L50ZaO36uz7azurvUuB5JdX5s2ZXuIdb9t8= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0/go.mod h1:Ni9RBJvcaXRIrDIuQBpJcuQvCQSj27crQSyc+WM4p0c= github.com/stackitcloud/stackit-sdk-go/services/ske v0.16.0 h1:trrJuRMzgXu6fiiMZiUx6+A1FNKEFhA1vGq5cr5Qn3U= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index ed6873b0e..e513b94e3 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,6 +3,7 @@ package beta import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,4 +37,5 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(sqlserverflex.NewCmd(p)) + cmd.AddCommand(server.NewCmd(p)) } diff --git a/internal/cmd/beta/server/backup/backup.go b/internal/cmd/beta/server/backup/backup.go new file mode 100644 index 000000000..54bcf1f3b --- /dev/null +++ b/internal/cmd/beta/server/backup/backup.go @@ -0,0 +1,30 @@ +package backup + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/disable" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "backup", + Short: "Provides functionality for Server Backup", + Long: "Provides functionality for Server Backup.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(enable.NewCmd(p)) + cmd.AddCommand(disable.NewCmd(p)) + cmd.AddCommand(schedule.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/backup/disable/disable.go b/internal/cmd/beta/server/backup/disable/disable.go new file mode 100644 index 000000000..a40b23fa0 --- /dev/null +++ b/internal/cmd/beta/server/backup/disable/disable.go @@ -0,0 +1,118 @@ +package disable + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + serverbackupUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "disable", + Short: "Disables Server Backup service", + Long: "Disables Server Backup service.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Disable Server Backup functionality for your server.`, + "$ stackit beta server backup disable --server-id=zzz"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + canDisable, err := serverbackupUtils.CanDisableBackupService(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + return err + } + if !canDisable { + p.Info("Cannot disable backup service for server %s - existing backups or existing backup schedules found\n", model.ServerId) + return nil + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to disable the backup service for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("disable server backup service: %w", err) + } + + p.Info("Disabled Server Backup service for server %s\n", model.ServerId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDisableServiceRequest { + req := apiClient.DisableService(ctx, model.ProjectId, model.ServerId) + return req +} diff --git a/internal/cmd/beta/server/backup/disable/disable_test.go b/internal/cmd/beta/server/backup/disable/disable_test.go new file mode 100644 index 000000000..17f9583b2 --- /dev/null +++ b/internal/cmd/beta/server/backup/disable/disable_test.go @@ -0,0 +1,173 @@ +package disable + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiDisableServiceRequest)) serverbackup.ApiDisableServiceRequest { + request := testClient.DisableService(testCtx, testProjectId, testServerId) + 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(func(model *inputModel) { + model.ServerId = "" + }), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiDisableServiceRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/enable/enable.go b/internal/cmd/beta/server/backup/enable/enable.go new file mode 100644 index 000000000..885f0e6c3 --- /dev/null +++ b/internal/cmd/beta/server/backup/enable/enable.go @@ -0,0 +1,112 @@ +package enable + +import ( + "context" + "fmt" + "strings" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "enable", + Short: "Enables Server Backup service", + Long: "Enables Server Backup service.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Enable Server Backup functionality for your server`, + "$ stackit beta server backup enable --server-id=zzz"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to enable the Server Backup service for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + if !strings.Contains(err.Error(), "Tried to activate already active service") { + return fmt.Errorf("enable Server Backup: %w", err) + } + } + + p.Info("Enabled backup service for server %s\n", model.ServerId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiEnableServiceRequest { + payload := serverbackup.EnableServicePayload{} + req := apiClient.EnableService(ctx, model.ProjectId, model.ServerId).EnableServicePayload(payload) + return req +} diff --git a/internal/cmd/beta/server/backup/enable/enable_test.go b/internal/cmd/beta/server/backup/enable/enable_test.go new file mode 100644 index 000000000..83b06f9d5 --- /dev/null +++ b/internal/cmd/beta/server/backup/enable/enable_test.go @@ -0,0 +1,173 @@ +package enable + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiEnableServiceRequest)) serverbackup.ApiEnableServiceRequest { + request := testClient.EnableService(testCtx, testProjectId, testServerId).EnableServicePayload(serverbackup.EnableServicePayload{}) + 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(func(model *inputModel) { + model.ServerId = "" + }), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiEnableServiceRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/create/create.go b/internal/cmd/beta/server/backup/schedule/create/create.go new file mode 100644 index 000000000..b87a4b0e5 --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/create/create.go @@ -0,0 +1,188 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + backupScheduleNameFlag = "backup-schedule-name" + enabledFlag = "enabled" + rruleFlag = "rrule" + backupNameFlag = "backup-name" + backupVolumeIdsFlag = "backup-volume-ids" + backupRetentionPeriodFlag = "backup-retention-period" + serverIdFlag = "server-id" + + defaultRrule = "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1" + defaultRetentionPeriod = 14 + defaultEnabled = true + defaultVolumeIds = "" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + + ServerId string + BackupScheduleName string + Enabled bool + Rrule string + BackupName string + BackupRetentionPeriod int64 + BackupVolumeIds string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a Server Backup Schedule", + Long: "Creates a Server Backup Schedule.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a Server Backup Schedule with name "myschedule" and backup name "mybackup"`, + `$ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule`), + examples.NewExample( + `Create a Server Backup Schedule with name "myschedule", backup name "mybackup" and retention period of 5 days`, + `$ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule --backup-retention-period=5`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a Backup Schedule for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create Server Backup Schedule: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().StringP(backupScheduleNameFlag, "n", "", "Backup schedule name") + cmd.Flags().StringP(backupNameFlag, "b", "", "Backup name") + cmd.Flags().Int64P(backupRetentionPeriodFlag, "d", defaultRetentionPeriod, "Backup retention period (in days)") + cmd.Flags().BoolP(enabledFlag, "e", defaultEnabled, "Is the server backup schedule enabled") + cmd.Flags().StringP(rruleFlag, "r", defaultRrule, "Backup RRULE (recurrence rule)") + cmd.Flags().StringP(backupVolumeIdsFlag, "i", defaultVolumeIds, "Backup volume ids, as comma separated UUID values.") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag, backupScheduleNameFlag, backupNameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + BackupRetentionPeriod: flags.FlagWithDefaultToInt64Value(p, cmd, backupRetentionPeriodFlag), + BackupScheduleName: flags.FlagToStringValue(p, cmd, backupScheduleNameFlag), + BackupName: flags.FlagToStringValue(p, cmd, backupNameFlag), + Rrule: flags.FlagWithDefaultToStringValue(p, cmd, rruleFlag), + Enabled: flags.FlagToBoolValue(p, cmd, enabledFlag), + BackupVolumeIds: flags.FlagToStringValue(p, cmd, backupVolumeIdsFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) (serverbackup.ApiCreateBackupScheduleRequest, error) { + req := apiClient.CreateBackupSchedule(ctx, model.ProjectId, model.ServerId) + backupProperties := serverbackup.BackupProperties{ + Name: &model.BackupName, + RetentionPeriod: &model.BackupRetentionPeriod, + } + if model.BackupVolumeIds == "" { + backupProperties.VolumeIds = nil + } else { + ids := strings.Split(model.BackupVolumeIds, ",") + backupProperties.VolumeIds = &ids + } + + req = req.CreateBackupSchedulePayload(serverbackup.CreateBackupSchedulePayload{ + Enabled: &model.Enabled, + Name: &model.BackupScheduleName, + Rrule: &model.Rrule, + BackupProperties: &backupProperties, + }) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.BackupSchedule) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal server backup schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server backup schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created server backup schedule for server %s. Backup Schedule ID: %d\n", model.ServerId, *resp.Id) + return nil + } +} diff --git a/internal/cmd/beta/server/backup/schedule/create/create_test.go b/internal/cmd/beta/server/backup/schedule/create/create_test.go new file mode 100644 index 000000000..eb772508c --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/create/create_test.go @@ -0,0 +1,220 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} + +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + backupScheduleNameFlag: "example-backup-schedule-name", + enabledFlag: "true", + rruleFlag: defaultRrule, + backupNameFlag: "example-backup-name", + backupRetentionPeriodFlag: "14", + backupVolumeIdsFlag: defaultVolumeIds, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + BackupScheduleName: "example-backup-schedule-name", + Enabled: defaultEnabled, + Rrule: defaultRrule, + BackupName: "example-backup-name", + BackupRetentionPeriod: int64(14), + BackupVolumeIds: defaultVolumeIds, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiCreateBackupScheduleRequest)) serverbackup.ApiCreateBackupScheduleRequest { + request := testClient.CreateBackupSchedule(testCtx, testProjectId, testServerId) + request = request.CreateBackupSchedulePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *serverbackup.CreateBackupSchedulePayload)) serverbackup.CreateBackupSchedulePayload { + payload := serverbackup.CreateBackupSchedulePayload{ + Name: utils.Ptr("example-backup-schedule-name"), + Enabled: utils.Ptr(defaultEnabled), + Rrule: utils.Ptr("DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1"), + BackupProperties: &serverbackup.BackupProperties{ + Name: utils.Ptr("example-backup-name"), + RetentionPeriod: utils.Ptr(int64(14)), + VolumeIds: nil, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "with defaults", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, backupRetentionPeriodFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiCreateBackupScheduleRequest + isValid bool + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/delete/delete.go b/internal/cmd/beta/server/backup/schedule/delete/delete.go new file mode 100644 index 000000000..60e30643a --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/delete/delete.go @@ -0,0 +1,113 @@ +package delete + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + scheduleIdArg = "SCHEDULE_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ScheduleId string + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", scheduleIdArg), + Short: "Deletes a Server Backup Schedule", + Long: "Deletes a Server Backup Schedule.", + Args: args.SingleArg(scheduleIdArg, nil), + Example: examples.Build( + examples.NewExample( + `Delete a Server Backup Schedule with ID "xxx" for server "zzz"`, + "$ stackit beta server backup schedule delete xxx --server-id=zzz"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete server backup schedule %q? (This cannot be undone)", model.ScheduleId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete Server Backup Schedule: %w", err) + } + + p.Info("Deleted server backup schedule %q\n", model.ScheduleId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + scheduleId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ScheduleId: scheduleId, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDeleteBackupScheduleRequest { + req := apiClient.DeleteBackupSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + return req +} diff --git a/internal/cmd/beta/server/backup/schedule/delete/delete_test.go b/internal/cmd/beta/server/backup/schedule/delete/delete_test.go new file mode 100644 index 000000000..875f1f2db --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/delete/delete_test.go @@ -0,0 +1,209 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupScheduleId = "5" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupScheduleId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + ScheduleId: testBackupScheduleId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiDeleteBackupScheduleRequest)) serverbackup.ApiDeleteBackupScheduleRequest { + request := testClient.DeleteBackupSchedule(testCtx, testProjectId, testServerId, testBackupScheduleId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiDeleteBackupScheduleRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/describe/describe.go b/internal/cmd/beta/server/backup/schedule/describe/describe.go new file mode 100644 index 000000000..27557b2c6 --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/describe/describe.go @@ -0,0 +1,159 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + backupScheduleIdArg = "BACKUP_SCHEDULE_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + BackupScheduleId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", backupScheduleIdArg), + Short: "Shows details of a Server Backup Schedule", + Long: "Shows details of a Server Backup Schedule.", + Args: args.SingleArg(backupScheduleIdArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details of a Server Backup Schedule with id "my-schedule-id"`, + "$ stackit beta server backup schedule describe my-schedule-id"), + examples.NewExample( + `Get details of a Server Backup Schedule with id "my-schedule-id" in JSON format`, + "$ stackit beta server backup schedule describe my-schedule-id --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read server backup schedule: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + backupScheduleId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + BackupScheduleId: backupScheduleId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiGetBackupScheduleRequest { + req := apiClient.GetBackupSchedule(ctx, model.ProjectId, model.ServerId, model.BackupScheduleId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, schedule *serverbackup.BackupSchedule) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(schedule, "", " ") + if err != nil { + return fmt.Errorf("marshal server backup schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(schedule, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server backup schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("SCHEDULE ID", *schedule.Id) + table.AddSeparator() + table.AddRow("SCHEDULE NAME", *schedule.Name) + table.AddSeparator() + table.AddRow("ENABLED", *schedule.Enabled) + table.AddSeparator() + table.AddRow("RRULE", *schedule.Rrule) + table.AddSeparator() + if schedule.BackupProperties != nil { + table.AddRow("BACKUP NAME", *schedule.BackupProperties.Name) + table.AddSeparator() + table.AddRow("BACKUP RETENTION DAYS", *schedule.BackupProperties.RetentionPeriod) + table.AddSeparator() + ids := schedule.BackupProperties.VolumeIds + if ids == nil || len(*ids) == 0 { + table.AddRow("BACKUP VOLUME IDS", "") + } else { + table.AddRow("BACKUP VOLUME IDS", strings.Join(*ids, "\n")) + } + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/server/backup/schedule/describe/describe_test.go b/internal/cmd/beta/server/backup/schedule/describe/describe_test.go new file mode 100644 index 000000000..985989f62 --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/describe/describe_test.go @@ -0,0 +1,211 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupScheduleId = "5" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupScheduleId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + BackupScheduleId: testBackupScheduleId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiGetBackupScheduleRequest)) serverbackup.ApiGetBackupScheduleRequest { + request := testClient.GetBackupSchedule(testCtx, testProjectId, testServerId, testBackupScheduleId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + isValid bool + expectedRequest serverbackup.ApiGetBackupScheduleRequest + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/list/list.go b/internal/cmd/beta/server/backup/schedule/list/list.go new file mode 100644 index 000000000..9ddde5860 --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/list/list.go @@ -0,0 +1,166 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + limitFlag = "limit" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all server backup schedules", + Long: "Lists all server backup schedules.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all backup schedules for a server with ID "xxx"`, + "$ stackit beta server backup schedule list --server-id xxx"), + examples.NewExample( + `List all backup schedules for a server with ID "xxx" in JSON format`, + "$ stackit beta server backup schedule list --server-id xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list server backup schedules: %w", err) + } + schedules := *resp.Items + if len(schedules) == 0 { + p.Info("No backup schedules found for server %s\n", model.ServerId) + return nil + } + + // Truncate output + if model.Limit != nil && len(schedules) > int(*model.Limit) { + schedules = schedules[:*model.Limit] + } + return outputResult(p, model.OutputFormat, schedules) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiListBackupSchedulesRequest { + req := apiClient.ListBackupSchedules(ctx, model.ProjectId, model.ServerId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, schedules []serverbackup.BackupSchedule) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(schedules, "", " ") + if err != nil { + return fmt.Errorf("marshal Server Backup Schedules list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(schedules, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal Server Backup Schedules list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("SCHEDULE ID", "SCHEDULE NAME", "ENABLED", "RRULE", "BACKUP NAME", "BACKUP RETENTION DAYS", "BACKUP VOLUME IDS") + for i := range schedules { + s := schedules[i] + + ids := "" + if s.BackupProperties.VolumeIds != nil && len(*s.BackupProperties.VolumeIds) != 0 { + ids = strings.Join(*s.BackupProperties.VolumeIds, ",") + } + table.AddRow(*s.Id, *s.Name, *s.Enabled, *s.Rrule, *s.BackupProperties.Name, *s.BackupProperties.RetentionPeriod, ids) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/backup/schedule/list/list_test.go b/internal/cmd/beta/server/backup/schedule/list/list_test.go new file mode 100644 index 000000000..e8667ba02 --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/list/list_test.go @@ -0,0 +1,188 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(int64(10)), + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiListBackupSchedulesRequest)) serverbackup.ApiListBackupSchedulesRequest { + request := testClient.ListBackupSchedules(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiListBackupSchedulesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/schedule.go b/internal/cmd/beta/server/backup/schedule/schedule.go new file mode 100644 index 000000000..73f026c5b --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/schedule.go @@ -0,0 +1,34 @@ +package schedule + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/create" + del "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "schedule", + Short: "Provides functionality for Server Backup Schedule", + Long: "Provides functionality for Server Backup Schedule.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(del.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/backup/schedule/update/update.go b/internal/cmd/beta/server/backup/schedule/update/update.go new file mode 100644 index 000000000..732062d70 --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/update/update.go @@ -0,0 +1,215 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + scheduleIdArg = "SCHEDULE_ID" + + backupScheduleNameFlag = "backup-schedule-name" + enabledFlag = "enabled" + rruleFlag = "rrule" + backupNameFlag = "backup-name" + backupVolumeIdsFlag = "backup-volume-ids" + backupRetentionPeriodFlag = "backup-retention-period" + serverIdFlag = "server-id" + + defaultRrule = "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1" + defaultRetentionPeriod = 14 + defaultEnabled = true + defaultVolumeIds = "" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + + ServerId string + BackupScheduleId string + BackupScheduleName *string + Enabled *bool + Rrule *string + BackupName *string + BackupRetentionPeriod *int64 + BackupVolumeIds *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", scheduleIdArg), + Short: "Updates a Server Backup Schedule", + Long: "Updates a Server Backup Schedule.", + Example: examples.Build( + examples.NewExample( + `Update the retention period of the backup schedule "zzz" of server "xxx"`, + "$ stackit beta server backup schedule update zzz --server-id=xxx --backup-retention-period=20"), + examples.NewExample( + `Update the backup name of the backup schedule "zzz" of server "xxx"`, + "$ stackit beta server backup schedule update zzz --server-id=xxx --backup-name=newname"), + ), + Args: args.SingleArg(scheduleIdArg, nil), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + currentBackupSchedule, err := apiClient.GetBackupScheduleExecute(ctx, model.ProjectId, model.ServerId, model.BackupScheduleId) + if err != nil { + p.Debug(print.ErrorLevel, "get current server backup schedule: %v", err) + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update Server Backup Schedule %q?", model.BackupScheduleId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient, *currentBackupSchedule) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update Server Backup Schedule: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + cmd.Flags().StringP(backupScheduleNameFlag, "n", "", "Backup schedule name") + cmd.Flags().StringP(backupNameFlag, "b", "", "Backup name") + cmd.Flags().Int64P(backupRetentionPeriodFlag, "d", defaultRetentionPeriod, "Backup retention period (in days)") + cmd.Flags().BoolP(enabledFlag, "e", defaultEnabled, "Is the server backup schedule enabled") + cmd.Flags().StringP(rruleFlag, "r", defaultRrule, "Backup RRULE (recurrence rule)") + cmd.Flags().StringP(backupVolumeIdsFlag, "i", defaultVolumeIds, "Backup volume ids, as comma separated UUID values.") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + scheduleId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + BackupScheduleId: scheduleId, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + BackupRetentionPeriod: flags.FlagToInt64Pointer(p, cmd, backupRetentionPeriodFlag), + BackupScheduleName: flags.FlagToStringPointer(p, cmd, backupScheduleNameFlag), + BackupName: flags.FlagToStringPointer(p, cmd, backupNameFlag), + Rrule: flags.FlagToStringPointer(p, cmd, rruleFlag), + Enabled: flags.FlagToBoolPointer(p, cmd, enabledFlag), + BackupVolumeIds: flags.FlagToStringPointer(p, cmd, backupVolumeIdsFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient, old serverbackup.BackupSchedule) (serverbackup.ApiUpdateBackupScheduleRequest, error) { + req := apiClient.UpdateBackupSchedule(ctx, model.ProjectId, model.ServerId, model.BackupScheduleId) + + if model.BackupName != nil { + old.BackupProperties.Name = model.BackupName + } + if model.BackupRetentionPeriod != nil { + old.BackupProperties.RetentionPeriod = model.BackupRetentionPeriod + } + if model.BackupVolumeIds != nil { + if *model.BackupVolumeIds == "" { + old.BackupProperties.VolumeIds = nil + } else { + ids := strings.Split(*model.BackupVolumeIds, ",") + old.BackupProperties.VolumeIds = &ids + } + } + if model.Enabled != nil { + old.Enabled = model.Enabled + } + if model.BackupScheduleName != nil { + old.Name = model.BackupScheduleName + } + if model.Rrule != nil { + old.Rrule = model.Rrule + } + + req = req.UpdateBackupSchedulePayload(serverbackup.UpdateBackupSchedulePayload{ + Enabled: old.Enabled, + Name: old.Name, + Rrule: old.Rrule, + BackupProperties: old.BackupProperties, + }) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.BackupSchedule) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal update server backup schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal update server backup schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Info("Updated server backup schedule %d\n", *resp.Id) + return nil + } +} diff --git a/internal/cmd/beta/server/backup/schedule/update/update_test.go b/internal/cmd/beta/server/backup/schedule/update/update_test.go new file mode 100644 index 000000000..95ec1fc1a --- /dev/null +++ b/internal/cmd/beta/server/backup/schedule/update/update_test.go @@ -0,0 +1,277 @@ +package update + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupScheduleId = "5" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupScheduleId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + backupScheduleNameFlag: "example-backup-schedule-name", + enabledFlag: "true", + rruleFlag: defaultRrule, + backupNameFlag: "example-backup-name", + backupRetentionPeriodFlag: "14", + backupVolumeIdsFlag: defaultVolumeIds, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + BackupScheduleId: testBackupScheduleId, + ServerId: testServerId, + BackupScheduleName: utils.Ptr("example-backup-schedule-name"), + Enabled: utils.Ptr(defaultEnabled), + Rrule: utils.Ptr(defaultRrule), + BackupName: utils.Ptr("example-backup-name"), + BackupRetentionPeriod: utils.Ptr(int64(14)), + BackupVolumeIds: utils.Ptr(defaultVolumeIds), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureBackupSchedule(mods ...func(schedule *serverbackup.BackupSchedule)) *serverbackup.BackupSchedule { + id, _ := strconv.ParseInt(testBackupScheduleId, 10, 64) + schedule := &serverbackup.BackupSchedule{ + Name: utils.Ptr("example-backup-schedule-name"), + Id: utils.Ptr(id), + Enabled: utils.Ptr(defaultEnabled), + Rrule: utils.Ptr(defaultRrule), + BackupProperties: &serverbackup.BackupProperties{ + Name: utils.Ptr("example-backup-name"), + RetentionPeriod: utils.Ptr(int64(14)), + VolumeIds: nil, + }, + } + for _, mod := range mods { + mod(schedule) + } + return schedule +} + +func fixturePayload(mods ...func(payload *serverbackup.UpdateBackupSchedulePayload)) serverbackup.UpdateBackupSchedulePayload { + payload := serverbackup.UpdateBackupSchedulePayload{ + Name: utils.Ptr("example-backup-schedule-name"), + Enabled: utils.Ptr(defaultEnabled), + Rrule: utils.Ptr("DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1"), + BackupProperties: &serverbackup.BackupProperties{ + Name: utils.Ptr("example-backup-name"), + RetentionPeriod: utils.Ptr(int64(14)), + VolumeIds: nil, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiUpdateBackupScheduleRequest)) serverbackup.ApiUpdateBackupScheduleRequest { + request := testClient.UpdateBackupSchedule(testCtx, testProjectId, testServerId, testBackupScheduleId) + request = request.UpdateBackupSchedulePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "backup schedule id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + + err = cmd.ValidateFlagGroups() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flag groups: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiUpdateBackupScheduleRequest + isValid bool + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + isValid: true, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient, *fixtureBackupSchedule()) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go new file mode 100644 index 000000000..8208d5b5d --- /dev/null +++ b/internal/cmd/beta/server/server.go @@ -0,0 +1,26 @@ +package server + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "server", + Short: "Provides functionality for Server", + Long: "Provides functionality for Server.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(backup.NewCmd(p)) +} diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index f2ad14ecd..70d3a5f54 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -33,6 +33,7 @@ const ( redisCustomEndpointFlag = "redis-custom-endpoint" resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" + serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" @@ -139,6 +140,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(resourceManagerCustomEndpointFlag, "", "Resource Manager API base URL, used in calls to this API") cmd.Flags().String(secretsManagerCustomEndpointFlag, "", "Secrets Manager API base URL, used in calls to this API") cmd.Flags().String(serviceAccountCustomEndpointFlag, "", "Service Account API base URL, used in calls to this API") + cmd.Flags().String(serverBackupCustomEndpointFlag, "", "Server Backup API base URL, used in calls to this API") cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") @@ -170,6 +172,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.SecretsManagerCustomEndpointKey, cmd.Flags().Lookup(secretsManagerCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.ServerBackupCustomEndpointKey, cmd.Flags().Lookup(serverBackupCustomEndpointFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.ServiceAccountCustomEndpointKey, cmd.Flags().Lookup(serviceAccountCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.SKECustomEndpointKey, cmd.Flags().Lookup(skeCustomEndpointFlag)) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index b49d213da..b5d8e494f 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -37,6 +37,7 @@ const ( resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" + serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" ) @@ -62,6 +63,7 @@ type inputModel struct { RedisCustomEndpoint bool ResourceManagerCustomEndpoint bool SecretsManagerCustomEndpoint bool + ServerBackupCustomEndpoint bool ServiceAccountCustomEndpoint bool SKECustomEndpoint bool SQLServerFlexCustomEndpoint bool @@ -148,6 +150,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.ServiceAccountCustomEndpoint { viper.Set(config.ServiceAccountCustomEndpointKey, "") } + if model.ServerBackupCustomEndpoint { + viper.Set(config.ServerBackupCustomEndpointKey, "") + } if model.SKECustomEndpoint { viper.Set(config.SKECustomEndpointKey, "") } @@ -188,6 +193,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(resourceManagerCustomEndpointFlag, false, "Resource Manager API base URL. If unset, uses the default base URL") cmd.Flags().Bool(secretsManagerCustomEndpointFlag, false, "Secrets Manager API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serviceAccountCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(serverBackupCustomEndpointFlag, false, "Server Backup base URL. If unset, uses the default base URL") cmd.Flags().Bool(skeCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") } @@ -215,6 +221,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { ResourceManagerCustomEndpoint: flags.FlagToBoolValue(p, cmd, resourceManagerCustomEndpointFlag), SecretsManagerCustomEndpoint: flags.FlagToBoolValue(p, cmd, secretsManagerCustomEndpointFlag), ServiceAccountCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceAccountCustomEndpointFlag), + ServerBackupCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverBackupCustomEndpointFlag), SKECustomEndpoint: flags.FlagToBoolValue(p, cmd, skeCustomEndpointFlag), SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), } diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 92d760471..7c89f4dd5 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -30,6 +30,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool resourceManagerCustomEndpointFlag: true, secretsManagerCustomEndpointFlag: true, serviceAccountCustomEndpointFlag: true, + serverBackupCustomEndpointFlag: true, skeCustomEndpointFlag: true, sqlServerFlexCustomEndpointFlag: true, } @@ -60,6 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { ResourceManagerCustomEndpoint: true, SecretsManagerCustomEndpoint: true, ServiceAccountCustomEndpoint: true, + ServerBackupCustomEndpoint: true, SKECustomEndpoint: true, SQLServerFlexCustomEndpoint: true, } @@ -106,6 +108,7 @@ func TestParseInput(t *testing.T) { model.ResourceManagerCustomEndpoint = false model.SecretsManagerCustomEndpoint = false model.ServiceAccountCustomEndpoint = false + model.ServerBackupCustomEndpoint = false model.SKECustomEndpoint = false model.SQLServerFlexCustomEndpoint = false }), @@ -190,6 +193,16 @@ func TestParseInput(t *testing.T) { model.ResourceManagerCustomEndpoint = false }), }, + { + description: "serverbackup custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[serverBackupCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.ServerBackupCustomEndpoint = false + }), + }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index a27b13eff..8d174e399 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -32,6 +32,7 @@ const ( ResourceManagerEndpointKey = "resource_manager_custom_endpoint" SecretsManagerCustomEndpointKey = "secrets_manager_custom_endpoint" ServiceAccountCustomEndpointKey = "service_account_custom_endpoint" + ServerBackupCustomEndpointKey = "serverbackup_custom_endpoint" SKECustomEndpointKey = "ske_custom_endpoint" SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" @@ -76,6 +77,7 @@ var ConfigKeys = []string{ ResourceManagerEndpointKey, SecretsManagerCustomEndpointKey, ServiceAccountCustomEndpointKey, + ServerBackupCustomEndpointKey, SKECustomEndpointKey, SQLServerFlexCustomEndpointKey, } @@ -145,6 +147,7 @@ func setConfigDefaults() { viper.SetDefault(ResourceManagerEndpointKey, "") viper.SetDefault(SecretsManagerCustomEndpointKey, "") viper.SetDefault(ServiceAccountCustomEndpointKey, "") + viper.SetDefault(ServerBackupCustomEndpointKey, "") viper.SetDefault(SKECustomEndpointKey, "") viper.SetDefault(SQLServerFlexCustomEndpointKey, "") } diff --git a/internal/pkg/services/serverbackup/client/client.go b/internal/pkg/services/serverbackup/client/client.go new file mode 100644 index 000000000..87a96bc94 --- /dev/null +++ b/internal/pkg/services/serverbackup/client/client.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/spf13/viper" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +func ConfigureClient(p *print.Printer) (*serverbackup.APIClient, error) { + var err error + var apiClient *serverbackup.APIClient + var cfgOptions []sdkConfig.ConfigurationOption + + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return nil, &errors.AuthError{} + } + cfgOptions = append(cfgOptions, authCfgOption) + + customEndpoint := viper.GetString(config.ServerBackupCustomEndpointKey) + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } else { + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err = serverbackup.NewAPIClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return nil, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/internal/pkg/services/serverbackup/utils/utils.go b/internal/pkg/services/serverbackup/utils/utils.go new file mode 100644 index 000000000..1dc32dfec --- /dev/null +++ b/internal/pkg/services/serverbackup/utils/utils.go @@ -0,0 +1,34 @@ +package utils + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +type ServerBackupClient interface { + ListBackupSchedulesExecute(ctx context.Context, projectId, serverId string) (*serverbackup.ListBackupSchedules200Response, error) + ListBackupsExecute(ctx context.Context, projectId, serverId string) (*serverbackup.ListBackups200Response, error) +} + +func CanDisableBackupService(ctx context.Context, client ServerBackupClient, projectId, serverId string) (bool, error) { + schedules, err := client.ListBackupSchedulesExecute(ctx, projectId, serverId) + if err != nil { + return false, fmt.Errorf("list backup schedules: %w", err) + } + if *schedules.Items != nil && len(*schedules.Items) > 0 { + return false, nil + } + + backups, err := client.ListBackupsExecute(ctx, projectId, serverId) + if err != nil { + return false, fmt.Errorf("list backups: %w", err) + } + if *backups.Items != nil && len(*backups.Items) > 0 { + return false, nil + } + + // no backups and no backup schedules found for this server => can disable backup service + return true, nil +} diff --git a/internal/pkg/services/serverbackup/utils/utils_test.go b/internal/pkg/services/serverbackup/utils/utils_test.go new file mode 100644 index 000000000..a25ce9ba5 --- /dev/null +++ b/internal/pkg/services/serverbackup/utils/utils_test.go @@ -0,0 +1,145 @@ +package utils + +import ( + "context" + "fmt" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var ( + testProjectId = uuid.NewString() + testServerId = uuid.NewString() +) + +type serverbackupClientMocked struct { + listBackupSchedulesFails bool + listBackupSchedulesResp *serverbackup.ListBackupSchedules200Response + listBackupsFails bool + listBackupsResp *serverbackup.ListBackups200Response +} + +func (m *serverbackupClientMocked) ListBackupSchedulesExecute(_ context.Context, _, _ string) (*serverbackup.ListBackupSchedules200Response, error) { + if m.listBackupSchedulesFails { + return nil, fmt.Errorf("could not list backup schedules") + } + return m.listBackupSchedulesResp, nil +} + +func (m *serverbackupClientMocked) ListBackupsExecute(_ context.Context, _, _ string) (*serverbackup.ListBackups200Response, error) { + if m.listBackupsFails { + return nil, fmt.Errorf("could not list backups") + } + return m.listBackupsResp, nil +} + +func TestCanDisableBackupService(t *testing.T) { + tests := []struct { + description string + listBackupsFails bool + listBackupSchedulesFails bool + listBackups *serverbackup.ListBackups200Response + listBackupSchedules *serverbackup.ListBackupSchedules200Response + isValid bool // isValid ==> err == nil + expectedOutput bool // expectedCanDisable + }{ + { + description: "base-ok-can-disable-backups-service-no-backups-no-backup-schedules", + listBackupsFails: false, + listBackupSchedulesFails: false, + listBackups: &serverbackup.ListBackups200Response{Items: &[]serverbackup.Backup{}}, + listBackupSchedules: &serverbackup.ListBackupSchedules200Response{Items: &[]serverbackup.BackupSchedule{}}, + isValid: true, + expectedOutput: true, + }, + { + description: "not-ok-api-error-list-backups", + listBackupsFails: true, + listBackupSchedulesFails: false, + listBackups: &serverbackup.ListBackups200Response{Items: &[]serverbackup.Backup{}}, + listBackupSchedules: &serverbackup.ListBackupSchedules200Response{Items: &[]serverbackup.BackupSchedule{}}, + isValid: false, + expectedOutput: false, + }, + { + description: "not-ok-api-error-list-backup-schedules", + listBackupsFails: true, + listBackupSchedulesFails: false, + listBackups: &serverbackup.ListBackups200Response{Items: &[]serverbackup.Backup{}}, + listBackupSchedules: &serverbackup.ListBackupSchedules200Response{Items: &[]serverbackup.BackupSchedule{}}, + isValid: false, + expectedOutput: false, + }, + { + description: "not-ok-has-backups-cannot-disable", + listBackupsFails: false, + listBackupSchedulesFails: false, + listBackups: &serverbackup.ListBackups200Response{ + Items: &[]serverbackup.Backup{ + { + CreatedAt: utils.Ptr("test timestamp"), + ExpireAt: utils.Ptr("test timestamp"), + Id: utils.Ptr("5"), + LastRestoredAt: utils.Ptr("test timestamp"), + Name: utils.Ptr("test name"), + Size: utils.Ptr(int64(5)), + Status: utils.Ptr("test status"), + VolumeBackups: nil, + }, + }, + }, + listBackupSchedules: &serverbackup.ListBackupSchedules200Response{Items: &[]serverbackup.BackupSchedule{}}, + isValid: true, + expectedOutput: false, + }, + { + description: "not-ok-has-backups-schedules-cannot-disable", + listBackupsFails: false, + listBackupSchedulesFails: false, + listBackups: &serverbackup.ListBackups200Response{Items: &[]serverbackup.Backup{}}, + listBackupSchedules: &serverbackup.ListBackupSchedules200Response{ + Items: &[]serverbackup.BackupSchedule{ + { + BackupProperties: nil, + Enabled: utils.Ptr(false), + Id: utils.Ptr(int64(5)), + Name: utils.Ptr("some name"), + Rrule: utils.Ptr("some rrule"), + }, + }, + }, + isValid: true, + expectedOutput: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &serverbackupClientMocked{ + listBackupsFails: tt.listBackupsFails, + listBackupSchedulesFails: tt.listBackupSchedulesFails, + listBackupsResp: tt.listBackups, + listBackupSchedulesResp: tt.listBackupSchedules, + } + + output, err := CanDisableBackupService(context.Background(), client, testProjectId, testServerId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %t, got %t", tt.expectedOutput, output) + } + }) + } +} From 02ea25dcdaf3b4090e7292800c971128939e8a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Mon, 1 Jul 2024 10:55:50 +0100 Subject: [PATCH 005/619] Add server backup to the services overview table (#395) Co-authored-by: test.test@freiheit.com --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 95c04687d..06364eb27 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Redis | `redis` | :white_check_mark: | | Resource Manager | `project` | :white_check_mark: | | Secrets Manager | `secrets-manager` | :white_check_mark: | +| Server Backup Management | `beta server backup` | :white_check_mark: | | Service Account | `service-account` | :white_check_mark: | | SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | From 43b7c2f9d0b0e238ef8d0cdc3e7341e9f384fdd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Tue, 2 Jul 2024 15:54:48 +0100 Subject: [PATCH 006/619] Check for service enablement before bucket creation (#398) * Check for service enablement before bucket creation * Fix comment * Fix linter * Improve variable naming --------- Co-authored-by: test.test@freiheit.com --- .../object-storage/bucket/create/create.go | 12 ++++ internal/cmd/ske/cluster/create/create.go | 6 +- internal/pkg/errors/errors.go | 13 ++++ .../services/object-storage/utils/utils.go | 18 +++++ .../object-storage/utils/utils_test.go | 65 +++++++++++++++++++ internal/pkg/services/ske/utils/utils.go | 11 +++- internal/pkg/services/ske/utils/utils_test.go | 13 ++++ 7 files changed, 135 insertions(+), 3 deletions(-) diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index 5d145819b..9e030b954 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -12,6 +12,7 @@ import ( "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/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/spf13/cobra" @@ -60,6 +61,17 @@ func NewCmd(p *print.Printer) *cobra.Command { } } + // Check if the project is enabled before trying to create + enabled, err := utils.ProjectEnabled(ctx, apiClient, model.ProjectId) + 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() diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 4a9324f3d..c1309f00d 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -87,13 +87,15 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - // Check if SKE is enabled for this project + // Check if the project is enabled before trying to create enabled, err := skeUtils.ProjectEnabled(ctx, apiClient, model.ProjectId) if err != nil { return err } if !enabled { - return fmt.Errorf("SKE isn't enabled for this project, please run 'stackit ske enable'") + return &errors.ServiceDisabledError{ + Service: "ske", + } } // Check if cluster exists diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index 7ebe01ad5..463fcf533 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -133,6 +133,11 @@ The profile name can only contain lowercase letters, numbers, and "-" and cannot USAGE_TIP = `For usage help, run: $ %s --help` + + SERVICE_DISABLED = `This service isn't enabled for the current project. + +To enable it, run: + $ stackit %s enable` ) type ProjectIdError struct{} @@ -364,3 +369,11 @@ type InvalidProfileNameError struct { func (e *InvalidProfileNameError) Error() string { return fmt.Sprintf(INVALID_PROFILE_NAME, e.Profile) } + +type ServiceDisabledError struct { + Service string +} + +func (e *ServiceDisabledError) Error() string { + return fmt.Sprintf(SERVICE_DISABLED, e.Service) +} diff --git a/internal/pkg/services/object-storage/utils/utils.go b/internal/pkg/services/object-storage/utils/utils.go index 0f744d9da..e596eb203 100644 --- a/internal/pkg/services/object-storage/utils/utils.go +++ b/internal/pkg/services/object-storage/utils/utils.go @@ -3,15 +3,33 @@ package utils import ( "context" "fmt" + "net/http" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) type ObjectStorageClient interface { + GetServiceStatusExecute(ctx context.Context, projectId string) (*objectstorage.ProjectStatus, error) ListCredentialsGroupsExecute(ctx context.Context, projectId string) (*objectstorage.ListCredentialsGroupsResponse, error) ListAccessKeys(ctx context.Context, projectId string) objectstorage.ApiListAccessKeysRequest } +func ProjectEnabled(ctx context.Context, apiClient ObjectStorageClient, projectId string) (bool, error) { + _, err := apiClient.GetServiceStatusExecute(ctx, projectId) + if err != nil { + oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped + if !ok { + return false, err + } + if oapiErr.StatusCode == http.StatusNotFound { + return false, nil + } + return false, err + } + return true, nil +} + func GetCredentialsGroupName(ctx context.Context, apiClient ObjectStorageClient, projectId, credentialsGroupId string) (string, error) { resp, err := apiClient.ListCredentialsGroupsExecute(ctx, projectId) if err != nil { diff --git a/internal/pkg/services/object-storage/utils/utils_test.go b/internal/pkg/services/object-storage/utils/utils_test.go index 4fec25892..7c2a2f427 100644 --- a/internal/pkg/services/object-storage/utils/utils_test.go +++ b/internal/pkg/services/object-storage/utils/utils_test.go @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) @@ -27,11 +28,23 @@ const ( ) type objectStorageClientMocked struct { + serviceDisabled bool + getServiceStatusFails bool listCredentialsGroupsFails bool listCredentialsGroupsResp *objectstorage.ListCredentialsGroupsResponse listAccessKeysReq objectstorage.ApiListAccessKeysRequest } +func (m *objectStorageClientMocked) GetServiceStatusExecute(_ context.Context, _ string) (*objectstorage.ProjectStatus, error) { + if m.getServiceStatusFails { + return nil, fmt.Errorf("could not get service status") + } + if m.serviceDisabled { + return nil, &oapierror.GenericOpenAPIError{StatusCode: 404} + } + return &objectstorage.ProjectStatus{}, nil +} + func (m *objectStorageClientMocked) ListCredentialsGroupsExecute(_ context.Context, _ string) (*objectstorage.ListCredentialsGroupsResponse, error) { if m.listCredentialsGroupsFails { return nil, fmt.Errorf("could not list credentials groups") @@ -43,6 +56,58 @@ func (m *objectStorageClientMocked) ListAccessKeys(_ context.Context, _ string) return m.listAccessKeysReq } +func TestProjectEnabled(t *testing.T) { + tests := []struct { + description string + serviceDisabled bool + getProjectFails bool + isValid bool + expectedOutput bool + }{ + { + description: "project enabled", + isValid: true, + expectedOutput: true, + }, + { + description: "project disabled (404)", + serviceDisabled: true, + isValid: true, + expectedOutput: false, + }, + { + description: "get project fails", + getProjectFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &objectStorageClientMocked{ + serviceDisabled: tt.serviceDisabled, + getServiceStatusFails: tt.getProjectFails, + } + + output, err := ProjectEnabled(context.Background(), client, testProjectId) + + if tt.isValid && err != nil { + fmt.Printf("failed on valid input: %v", err) + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %t, got %t", tt.expectedOutput, output) + } + }) + } +} + func TestGetCredentialsGroupName(t *testing.T) { tests := []struct { description string diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 901e961c3..8af234111 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -3,12 +3,14 @@ package utils import ( "context" "fmt" + "net/http" "os" "path/filepath" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/services/ske" "golang.org/x/mod/semver" ) @@ -37,7 +39,14 @@ type SKEClient interface { func ProjectEnabled(ctx context.Context, apiClient SKEClient, projectId string) (bool, error) { project, err := apiClient.GetServiceStatusExecute(ctx, projectId) if err != nil { - return false, fmt.Errorf("get SKE status: %w", err) + oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped + if !ok { + return false, err + } + if oapiErr.StatusCode == http.StatusNotFound { + return false, nil + } + return false, err } return *project.State == ske.PROJECTSTATE_CREATED, nil } diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index 2158e175a..bcf8139b5 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -11,6 +11,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) @@ -23,6 +24,7 @@ const ( ) type skeClientMocked struct { + serviceDisabled bool getServiceStatusFails bool getServiceStatusResp *ske.ProjectResponse listClustersFails bool @@ -35,6 +37,9 @@ func (m *skeClientMocked) GetServiceStatusExecute(_ context.Context, _ string) ( if m.getServiceStatusFails { return nil, fmt.Errorf("could not get service status") } + if m.serviceDisabled { + return nil, &oapierror.GenericOpenAPIError{StatusCode: 404} + } return m.getServiceStatusResp, nil } @@ -55,6 +60,7 @@ func (m *skeClientMocked) ListProviderOptionsExecute(_ context.Context) (*ske.Pr func TestProjectEnabled(t *testing.T) { tests := []struct { description string + serviceDisabled bool getProjectFails bool getProjectResp *ske.ProjectResponse isValid bool @@ -66,6 +72,12 @@ func TestProjectEnabled(t *testing.T) { isValid: true, expectedOutput: true, }, + { + description: "project disabled (404)", + serviceDisabled: true, + isValid: true, + expectedOutput: false, + }, { description: "project disabled 1", getProjectResp: &ske.ProjectResponse{State: ske.PROJECTSTATE_CREATING.Ptr()}, @@ -88,6 +100,7 @@ func TestProjectEnabled(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { client := &skeClientMocked{ + serviceDisabled: tt.serviceDisabled, getServiceStatusFails: tt.getProjectFails, getServiceStatusResp: tt.getProjectResp, } From 076188530d4f8a92087b3e7c5051c114d814d1e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Wed, 3 Jul 2024 16:11:56 +0100 Subject: [PATCH 007/619] Add warning regarding migration to new IDP (#399) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add warning regarding migration to new IDP * Update internal/cmd/auth/login/login.go Co-authored-by: Diogo Ferrão --------- Co-authored-by: Diogo Ferrão --- internal/cmd/auth/login/login.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/cmd/auth/login/login.go b/internal/cmd/auth/login/login.go index 3ba46f3d5..90bc05b02 100644 --- a/internal/cmd/auth/login/login.go +++ b/internal/cmd/auth/login/login.go @@ -23,6 +23,14 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit auth login"), ), RunE: func(cmd *cobra.Command, args []string) error { + p.Warn(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n\n", + "Starting on July 9 2024, the new STACKIT Identity Provider (IDP) will be available.", + "On this date, we will release a new version of the STACKIT CLI that will use the new IDP for user authentication.", + "This also means that the user authentication on STACKIT CLI versions released before July 9 2024 is no longer guaranteed to work for all services.", + "Please make sure to update your STACKIT CLI to the latest version after July 9 2024 to ensure that you can continue to use all STACKIT services.", + "You can find more information regarding the new IDP at https://docs.stackit.cloud/stackit/en/release-notes-23101442.html#ReleaseNotes-2024-06-21-identity-provider", + )) + err := auth.AuthorizeUser(p, false) if err != nil { return fmt.Errorf("authorization failed: %w", err) From b799e96c996484a7a3c2a6061311cf0e66ffb944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Thu, 4 Jul 2024 15:25:10 +0100 Subject: [PATCH 008/619] Add support for custom IDP endpoint and client ID (#400) * Add support for custom IDP endpoint and client ID * Add debug log for client ID * Add warning when using custom IDP endpoint * Handle error in PromptForEnter * Remove IDO custom flags from command, will live only in config commands * Improve flag documentation * Improve flag documentation * Validate custom IDP endpoint belongs to STACKIT * Remove client ID custom endpoint * Update docs * Simplify code * Remove unneeded debug log * Simplify test --- docs/stackit_config_set.md | 41 ++++++++--------- docs/stackit_config_unset.md | 49 ++++++++++---------- internal/cmd/config/set/set.go | 12 +++-- internal/cmd/config/unset/unset.go | 39 ++++++++++------ internal/cmd/config/unset/unset_test.go | 38 +++++++++++----- internal/cmd/curl/curl.go | 19 +------- internal/pkg/auth/user_login.go | 27 +++++++++--- internal/pkg/auth/user_token_flow.go | 9 +++- internal/pkg/auth/user_token_flow_test.go | 18 +++----- internal/pkg/auth/utils.go | 24 ++++++++++ internal/pkg/auth/utils_test.go | 54 +++++++++++++++++++++++ internal/pkg/config/config.go | 5 +++ internal/pkg/utils/utils.go | 17 +++++++ internal/pkg/utils/utils_test.go | 40 ++++++++++++++++- 14 files changed, 282 insertions(+), 110 deletions(-) create mode 100644 internal/pkg/auth/utils.go create mode 100644 internal/pkg/auth/utils_test.go diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 0d9821f87..4d351ea33 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -29,26 +29,27 @@ stackit config set [flags] ### Options ``` - --argus-custom-endpoint string Argus API base URL, used in calls to this API - --authorization-custom-endpoint string Authorization API base URL, used in calls to this API - --dns-custom-endpoint string DNS API base URL, used in calls to this API - -h, --help Help for "stackit config set" - --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API - --logme-custom-endpoint string LogMe API base URL, used in calls to this API - --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API - --mongodbflex-custom-endpoint string MongoDB Flex API base URL, used in calls to this API - --object-storage-custom-endpoint string Object Storage API base URL, used in calls to this API - --opensearch-custom-endpoint string OpenSearch API base URL, used in calls to this API - --postgresflex-custom-endpoint string PostgreSQL Flex API base URL, used in calls to this API - --rabbitmq-custom-endpoint string RabbitMQ API base URL, used in calls to this API - --redis-custom-endpoint string Redis API base URL, used in calls to this API - --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API - --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API - --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API - --service-account-custom-endpoint string Service Account API base URL, used in calls to this API - --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) - --ske-custom-endpoint string SKE API base URL, used in calls to this API - --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API + --argus-custom-endpoint string Argus API base URL, used in calls to this API + --authorization-custom-endpoint string Authorization API base URL, used in calls to this API + --dns-custom-endpoint string DNS API base URL, used in calls to this API + -h, --help Help for "stackit config set" + --identity-provider-custom-endpoint string Identity Provider base URL, used for user authentication + --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API + --logme-custom-endpoint string LogMe API base URL, used in calls to this API + --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API + --mongodbflex-custom-endpoint string MongoDB Flex API base URL, used in calls to this API + --object-storage-custom-endpoint string Object Storage API base URL, used in calls to this API + --opensearch-custom-endpoint string OpenSearch API base URL, used in calls to this API + --postgresflex-custom-endpoint string PostgreSQL Flex API base URL, used in calls to this API + --rabbitmq-custom-endpoint string RabbitMQ API base URL, used in calls to this API + --redis-custom-endpoint string Redis API base URL, used in calls to this API + --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API + --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API + --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API + --service-account-custom-endpoint string Service Account API base URL, used in calls to this API + --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) + --ske-custom-endpoint string SKE API base URL, used in calls to this API + --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API ``` ### Options inherited from parent commands diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 63c0d9779..65d3e2cc7 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -26,30 +26,31 @@ stackit config unset [flags] ### Options ``` - --argus-custom-endpoint Argus API base URL. If unset, uses the default base URL - --async Configuration option to run commands asynchronously - --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL - --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL - -h, --help Help for "stackit config unset" - --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL - --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL - --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL - --mongodbflex-custom-endpoint MongoDB Flex API base URL. If unset, uses the default base URL - --object-storage-custom-endpoint Object Storage API base URL. If unset, uses the default base URL - --opensearch-custom-endpoint OpenSearch API base URL. If unset, uses the default base URL - --output-format Output format - --postgresflex-custom-endpoint PostgreSQL Flex API base URL. If unset, uses the default base URL - --project-id Project ID - --rabbitmq-custom-endpoint RabbitMQ API base URL. If unset, uses the default base URL - --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL - --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL - --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL - --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL - --service-account-custom-endpoint SKE API base URL. If unset, uses the default base URL - --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h - --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL - --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL - --verbosity Verbosity of the CLI + --argus-custom-endpoint Argus API base URL. If unset, uses the default base URL + --async Configuration option to run commands asynchronously + --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL + --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL + -h, --help Help for "stackit config unset" + --identity-provider-custom-endpoint Identity Provider base URL. If unset, uses the default base URL + --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL + --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL + --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL + --mongodbflex-custom-endpoint MongoDB Flex API base URL. If unset, uses the default base URL + --object-storage-custom-endpoint Object Storage API base URL. If unset, uses the default base URL + --opensearch-custom-endpoint OpenSearch API base URL. If unset, uses the default base URL + --output-format Output format + --postgresflex-custom-endpoint PostgreSQL Flex API base URL. If unset, uses the default base URL + --project-id Project ID + --rabbitmq-custom-endpoint RabbitMQ API base URL. If unset, uses the default base URL + --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL + --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL + --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL + --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL + --service-account-custom-endpoint SKE API base URL. If unset, uses the default base URL + --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h + --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL + --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL + --verbosity Verbosity of the CLI ``` ### Options inherited from parent commands diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 70d3a5f54..887ea342b 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -17,7 +17,8 @@ import ( ) const ( - sessionTimeLimitFlag = "session-time-limit" + sessionTimeLimitFlag = "session-time-limit" + identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" @@ -124,7 +125,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e func configureFlags(cmd *cobra.Command) { cmd.Flags().String(sessionTimeLimitFlag, "", "Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect)") - + cmd.Flags().String(identityProviderCustomEndpointFlag, "", "Identity Provider base URL, used for user authentication") cmd.Flags().String(argusCustomEndpointFlag, "", "Argus API base URL, used in calls to this API") cmd.Flags().String(authorizationCustomEndpointFlag, "", "Authorization API base URL, used in calls to this API") cmd.Flags().String(dnsCustomEndpointFlag, "", "DNS API base URL, used in calls to this API") @@ -144,7 +145,12 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") - err := viper.BindPFlag(config.ArgusCustomEndpointKey, cmd.Flags().Lookup(argusCustomEndpointFlag)) + err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) + cobra.CheckErr(err) + err = viper.BindPFlag(config.IdentityProviderCustomEndpointKey, cmd.Flags().Lookup(identityProviderCustomEndpointFlag)) + cobra.CheckErr(err) + + err = viper.BindPFlag(config.ArgusCustomEndpointKey, cmd.Flags().Lookup(argusCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.AuthorizationCustomEndpointKey, cmd.Flags().Lookup(authorizationCustomEndpointFlag)) cobra.CheckErr(err) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index b5d8e494f..17128a035 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -20,7 +20,8 @@ const ( projectIdFlag = globalflags.ProjectIdFlag verbosityFlag = globalflags.VerbosityFlag - sessionTimeLimitFlag = "session-time-limit" + sessionTimeLimitFlag = "session-time-limit" + identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" @@ -43,11 +44,13 @@ const ( ) type inputModel struct { - Async bool - OutputFormat bool - ProjectId bool - SessionTimeLimit bool - Verbosity bool + Async bool + OutputFormat bool + ProjectId bool + Verbosity bool + + SessionTimeLimit bool + IdentityProviderCustomEndpoint bool ArgusCustomEndpoint bool AuthorizationCustomEndpoint bool @@ -98,11 +101,15 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.ProjectId { viper.Set(config.ProjectIdKey, "") } + if model.Verbosity { + viper.Set(config.VerbosityKey, globalflags.VerbosityDefault) + } + if model.SessionTimeLimit { viper.Set(config.SessionTimeLimitKey, config.SessionTimeLimitDefault) } - if model.Verbosity { - viper.Set(config.VerbosityKey, globalflags.VerbosityDefault) + if model.IdentityProviderCustomEndpoint { + viper.Set(config.IdentityProviderCustomEndpointKey, "") } if model.ArgusCustomEndpoint { @@ -175,9 +182,11 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(asyncFlag, false, "Configuration option to run commands asynchronously") cmd.Flags().Bool(projectIdFlag, false, "Project ID") cmd.Flags().Bool(outputFormatFlag, false, "Output format") - cmd.Flags().Bool(sessionTimeLimitFlag, false, fmt.Sprintf("Maximum time before authentication is required again. If unset, defaults to %s", config.SessionTimeLimitDefault)) cmd.Flags().Bool(verbosityFlag, false, "Verbosity of the CLI") + cmd.Flags().Bool(sessionTimeLimitFlag, false, fmt.Sprintf("Maximum time before authentication is required again. If unset, defaults to %s", config.SessionTimeLimitDefault)) + cmd.Flags().Bool(identityProviderCustomEndpointFlag, false, "Identity Provider base URL. If unset, uses the default base URL") + cmd.Flags().Bool(argusCustomEndpointFlag, false, "Argus API base URL. If unset, uses the default base URL") cmd.Flags().Bool(authorizationCustomEndpointFlag, false, "Authorization API base URL. If unset, uses the default base URL") cmd.Flags().Bool(dnsCustomEndpointFlag, false, "DNS API base URL. If unset, uses the default base URL") @@ -200,11 +209,13 @@ func configureFlags(cmd *cobra.Command) { func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { model := inputModel{ - Async: flags.FlagToBoolValue(p, cmd, asyncFlag), - OutputFormat: flags.FlagToBoolValue(p, cmd, outputFormatFlag), - ProjectId: flags.FlagToBoolValue(p, cmd, projectIdFlag), - SessionTimeLimit: flags.FlagToBoolValue(p, cmd, sessionTimeLimitFlag), - Verbosity: flags.FlagToBoolValue(p, cmd, verbosityFlag), + Async: flags.FlagToBoolValue(p, cmd, asyncFlag), + OutputFormat: flags.FlagToBoolValue(p, cmd, outputFormatFlag), + ProjectId: flags.FlagToBoolValue(p, cmd, projectIdFlag), + Verbosity: flags.FlagToBoolValue(p, cmd, verbosityFlag), + + SessionTimeLimit: flags.FlagToBoolValue(p, cmd, sessionTimeLimitFlag), + IdentityProviderCustomEndpoint: flags.FlagToBoolValue(p, cmd, identityProviderCustomEndpointFlag), ArgusCustomEndpoint: flags.FlagToBoolValue(p, cmd, argusCustomEndpointFlag), AuthorizationCustomEndpoint: flags.FlagToBoolValue(p, cmd, authorizationCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 7c89f4dd5..c1e87f48c 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -11,11 +11,13 @@ import ( func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool { flagValues := map[string]bool{ - asyncFlag: true, - outputFormatFlag: true, - projectIdFlag: true, - sessionTimeLimitFlag: true, - verbosityFlag: true, + asyncFlag: true, + outputFormatFlag: true, + projectIdFlag: true, + verbosityFlag: true, + + sessionTimeLimitFlag: true, + identityProviderCustomEndpointFlag: true, argusCustomEndpointFlag: true, authorizationCustomEndpointFlag: true, @@ -42,11 +44,13 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - Async: true, - OutputFormat: true, - ProjectId: true, - SessionTimeLimit: true, - Verbosity: true, + Async: true, + OutputFormat: true, + ProjectId: true, + Verbosity: true, + + SessionTimeLimit: true, + IdentityProviderCustomEndpoint: true, ArgusCustomEndpoint: true, AuthorizationCustomEndpoint: true, @@ -92,9 +96,11 @@ func TestParseInput(t *testing.T) { model.Async = false model.OutputFormat = false model.ProjectId = false - model.SessionTimeLimit = false model.Verbosity = false + model.SessionTimeLimit = false + model.IdentityProviderCustomEndpoint = false + model.ArgusCustomEndpoint = false model.AuthorizationCustomEndpoint = false model.DNSCustomEndpoint = false @@ -133,6 +139,16 @@ func TestParseInput(t *testing.T) { model.OutputFormat = false }), }, + { + description: "identity provider custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[identityProviderCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IdentityProviderCustomEndpoint = false + }), + }, { description: "argus custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index dcc7529f3..05caa082c 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -6,7 +6,6 @@ import ( "io" "net/http" "net/http/httputil" - "net/url" "os" "strings" "time" @@ -17,6 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) @@ -67,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones -X POST -H "Authorization: Bearer yyy" --fail`, ), ), - Args: args.SingleArg(urlArg, validateURL), + Args: args.SingleArg(urlArg, utils.ValidateSTACKITURL), RunE: func(cmd *cobra.Command, args []string) (err error) { model, err := parseInput(p, cmd, args) if err != nil { @@ -113,21 +113,6 @@ func NewCmd(p *print.Printer) *cobra.Command { return cmd } -func validateURL(value string) error { - urlStruct, err := url.Parse(value) - if err != nil { - return fmt.Errorf("parse URL: %w", err) - } - urlHost := urlStruct.Hostname() - if urlHost == "" { - return fmt.Errorf("bad url") - } - if !strings.HasSuffix(urlHost, "stackit.cloud") { - return fmt.Errorf("only urls belonging to STACKIT are permitted, hostname must end in stackit.cloud") - } - return nil -} - func configureFlags(cmd *cobra.Command) { requestMethodOptions := []string{ http.MethodGet, diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index 577a47846..4101134f9 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -23,8 +23,9 @@ import ( ) const ( - authDomain = "auth.01.idp.eu01.stackit.cloud/oauth" - clientId = "stackit-cli-client-id" + defaultIDPEndpoint = "https://auth.01.idp.eu01.stackit.cloud/oauth" + cliClientID = "stackit-cli-client-id" + loginSuccessPath = "/login-successful" stackitLandingPage = "https://www.stackit.de" htmlTemplatesPath = "templates" @@ -40,6 +41,18 @@ type User struct { // AuthorizeUser implements the PKCE OAuth2 flow. func AuthorizeUser(p *print.Printer, isReauthentication bool) error { + idpEndpoint, err := getIDPEndpoint() + if err != nil { + return err + } + if idpEndpoint != defaultIDPEndpoint { + p.Warn("You are using a custom identity provider (%s) for authentication.\n", idpEndpoint) + err := p.PromptForEnter("Press Enter to proceed with the login...") + if err != nil { + return err + } + } + if isReauthentication { err := p.PromptForEnter("Your session has expired, press Enter to login again...") if err != nil { @@ -58,9 +71,9 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { redirectURL := fmt.Sprintf("http://localhost:%d", address.Port) conf := &oauth2.Config{ - ClientID: clientId, + ClientID: cliClientID, Endpoint: oauth2.Endpoint{ - AuthURL: fmt.Sprintf("https://%s/authorize", authDomain), + AuthURL: fmt.Sprintf("%s/authorize", idpEndpoint), }, Scopes: []string{"openid"}, RedirectURL: redirectURL, @@ -103,7 +116,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { p.Debug(print.DebugLevel, "trading authorization code for access and refresh tokens") // Trade the authorization code and the code verifier for access and refresh tokens - accessToken, refreshToken, err := getUserAccessAndRefreshTokens(authDomain, clientId, codeVerifier, code, redirectURL) + accessToken, refreshToken, err := getUserAccessAndRefreshTokens(idpEndpoint, cliClientID, codeVerifier, code, redirectURL) if err != nil { errServer = fmt.Errorf("retrieve tokens: %w", err) return @@ -184,7 +197,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { }) p.Debug(print.DebugLevel, "opening browser for authentication") - p.Debug(print.DebugLevel, "using authentication server on %s", authDomain) + p.Debug(print.DebugLevel, "using authentication server on %s", idpEndpoint) // Open a browser window to the authorizationURL err = openBrowser(authorizationURL) @@ -211,7 +224,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { // getUserAccessAndRefreshTokens trades the authorization code retrieved from the first OAuth2 leg for an access token and a refresh token func getUserAccessAndRefreshTokens(authDomain, clientID, codeVerifier, authorizationCode, callbackURL string) (accessToken, refreshToken string, err error) { // Set the authUrl and form-encoded data for the POST to the access token endpoint - authUrl := fmt.Sprintf("https://%s/token", authDomain) + authUrl := fmt.Sprintf("%s/token", authDomain) data := fmt.Sprintf( "grant_type=authorization_code&client_id=%s"+ "&code_verifier=%s"+ diff --git a/internal/pkg/auth/user_token_flow.go b/internal/pkg/auth/user_token_flow.go index d3e3a5a1d..ebb90b2a3 100644 --- a/internal/pkg/auth/user_token_flow.go +++ b/internal/pkg/auth/user_token_flow.go @@ -157,9 +157,14 @@ func refreshTokens(utf *userTokenFlow) (err error) { } func buildRequestToRefreshTokens(utf *userTokenFlow) (*http.Request, error) { + idpEndpoint, err := getIDPEndpoint() + if err != nil { + return nil, err + } + req, err := http.NewRequest( http.MethodPost, - fmt.Sprintf("https://%s/token", authDomain), + fmt.Sprintf("%s/token", idpEndpoint), http.NoBody, ) if err != nil { @@ -167,7 +172,7 @@ func buildRequestToRefreshTokens(utf *userTokenFlow) (*http.Request, error) { } reqQuery := url.Values{} reqQuery.Set("grant_type", "refresh_token") - reqQuery.Set("client_id", clientId) + reqQuery.Set("client_id", cliClientID) reqQuery.Set("refresh_token", utf.refreshToken) reqQuery.Set("token_format", "jwt") req.URL.RawQuery = reqQuery.Encode() diff --git a/internal/pkg/auth/user_token_flow_test.go b/internal/pkg/auth/user_token_flow_test.go index b89f29bb8..e5113e67f 100644 --- a/internal/pkg/auth/user_token_flow_test.go +++ b/internal/pkg/auth/user_token_flow_test.go @@ -28,11 +28,11 @@ func (rt *clientTransport) RoundTrip(req *http.Request) (*http.Response, error) if reqURL == rt.requestURL { return rt.roundTripRequest() } - if reqURL == fmt.Sprintf("%s/token", authDomain) { + if fmt.Sprintf("https://%s", reqURL) == fmt.Sprintf("%s/token", defaultIDPEndpoint) { return rt.roundTripRefreshTokens() } - rt.t.Fatalf("unexpected request to \"%s\"", reqURL) - return nil, fmt.Errorf("unexpected request to \"%s\"", reqURL) + rt.t.Fatalf("unexpected request to %q", reqURL) + return nil, fmt.Errorf("unexpected request to %q", reqURL) } func (rt *clientTransport) roundTripRequest() (*http.Response, error) { @@ -302,20 +302,16 @@ func TestRoundTrip(t *testing.T) { } if !tt.isValid && err == nil { - if err == nil { - t.Errorf("should have failed") - } if requestSent { - t.Errorf("request was sent") + t.Logf("request was sent") } + t.Errorf("should have failed") } if tt.isValid && err != nil { - if err != nil { - t.Errorf("shouldn't have failed: %v", err) - } if !requestSent { - t.Errorf("request wasn't sent") + t.Logf("request wasn't sent") } + t.Errorf("shouldn't have failed: %v", err) } if authorizeUserCalled && !tt.expectedReautorizeUserCalled { t.Errorf("reauthorizeUser was called") diff --git a/internal/pkg/auth/utils.go b/internal/pkg/auth/utils.go new file mode 100644 index 000000000..cdb38c137 --- /dev/null +++ b/internal/pkg/auth/utils.go @@ -0,0 +1,24 @@ +package auth + +import ( + "fmt" + + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func getIDPEndpoint() (string, error) { + idpEndpoint := defaultIDPEndpoint + + customIDPEndpoint := viper.GetString(config.IdentityProviderCustomEndpointKey) + if customIDPEndpoint != "" { + idpEndpoint = customIDPEndpoint + } + err := utils.ValidateSTACKITURL(idpEndpoint) + if err != nil { + return "", fmt.Errorf("validate custom identity provider endpoint: %w", err) + } + + return idpEndpoint, nil +} diff --git a/internal/pkg/auth/utils_test.go b/internal/pkg/auth/utils_test.go new file mode 100644 index 000000000..375bd8462 --- /dev/null +++ b/internal/pkg/auth/utils_test.go @@ -0,0 +1,54 @@ +package auth + +import ( + "testing" + + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" +) + +func TestGetIDPEndpoint(t *testing.T) { + tests := []struct { + name string + idpCustomEndpoint string + isValid bool + expected string + }{ + { + name: "custom endpoint specified", + idpCustomEndpoint: "https://example.stackit.cloud", + isValid: true, + expected: "https://example.stackit.cloud", + }, + { + name: "custom endpoint outside STACKIT", + idpCustomEndpoint: "https://www.very-suspicious-website.com/", + isValid: false, + }, + { + name: "custom endpoint not specified", + idpCustomEndpoint: "", + isValid: true, + expected: defaultIDPEndpoint, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + viper.Reset() + viper.Set(config.IdentityProviderCustomEndpointKey, tt.idpCustomEndpoint) + + got, err := getIDPEndpoint() + + if tt.isValid && err != nil { + t.Fatalf("expected no error, got %v", err) + } + if !tt.isValid && err == nil { + t.Fatalf("expected error, got none") + } + + if got != tt.expected { + t.Fatalf("expected idp endpoint %q, got %q", tt.expected, got) + } + }) + } +} diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 8d174e399..4716fb5db 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -17,6 +17,8 @@ const ( SessionTimeLimitKey = "session_time_limit" VerbosityKey = "verbosity" + IdentityProviderCustomEndpointKey = "identity_provider_custom_endpoint" + ArgusCustomEndpointKey = "argus_custom_endpoint" AuthorizationCustomEndpointKey = "authorization_custom_endpoint" DNSCustomEndpointKey = "dns_custom_endpoint" @@ -61,6 +63,8 @@ var ConfigKeys = []string{ SessionTimeLimitKey, VerbosityKey, + IdentityProviderCustomEndpointKey, + DNSCustomEndpointKey, LoadBalancerCustomEndpointKey, LogMeCustomEndpointKey, @@ -137,6 +141,7 @@ func setConfigDefaults() { viper.SetDefault(OutputFormatKey, "") viper.SetDefault(ProjectIdKey, "") viper.SetDefault(SessionTimeLimitKey, SessionTimeLimitDefault) + viper.SetDefault(IdentityProviderCustomEndpointKey, "") viper.SetDefault(DNSCustomEndpointKey, "") viper.SetDefault(ArgusCustomEndpointKey, "") viper.SetDefault(AuthorizationCustomEndpointKey, "") diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index f14ea7214..c369b92d7 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -2,6 +2,8 @@ package utils import ( "fmt" + "net/url" + "strings" "github.com/google/uuid" "github.com/spf13/cobra" @@ -48,3 +50,18 @@ func ConvertInt64PToFloat64P(i *int64) *float64 { f := float64(*i) return &f } + +func ValidateSTACKITURL(value string) error { + urlStruct, err := url.Parse(value) + if err != nil { + return fmt.Errorf("parse url: %w", err) + } + urlHost := urlStruct.Hostname() + if urlHost == "" { + return fmt.Errorf("bad url") + } + if !strings.HasSuffix(urlHost, "stackit.cloud") { + return fmt.Errorf(`only urls belonging to STACKIT are allowed, hostname must end in "stackit.cloud"`) + } + return nil +} diff --git a/internal/pkg/utils/utils_test.go b/internal/pkg/utils/utils_test.go index 3dc7b54a7..77f5cffef 100644 --- a/internal/pkg/utils/utils_test.go +++ b/internal/pkg/utils/utils_test.go @@ -1,6 +1,8 @@ package utils -import "testing" +import ( + "testing" +) func TestConvertInt64PToFloat64P(t *testing.T) { tests := []struct { @@ -43,3 +45,39 @@ func TestConvertInt64PToFloat64P(t *testing.T) { }) } } + +func TestValidateSTACKITURL(t *testing.T) { + tests := []struct { + name string + input string + isValid bool + }{ + { + name: "STACKIT URL", + input: "https://example.stackit.cloud", + isValid: true, + }, + { + name: "non-STACKIT URL", + input: "https://www.very-suspicious-website.com/", + isValid: false, + }, + { + name: "invalid URL", + input: "", + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidateSTACKITURL(tt.input) + if tt.isValid && err != nil { + t.Errorf("expected URL to be valid, got error: %v", err) + } + if !tt.isValid && err == nil { + t.Errorf("expected URL to be invalid, got no error") + } + }) + } +} From 3426b75e1f587d750beb0d22b49e754296ea332f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Thu, 4 Jul 2024 16:06:49 +0100 Subject: [PATCH 009/619] Add warning regarding new IDP to README (#401) --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 06364eb27..4f57a5bd8 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,15 @@ Welcome to the [STACKIT](https://www.stackit.de/en) CLI, a command-line interfac This CLI is in a BETA state. More services and functionality will be supported soon. Your feedback is appreciated! + + +> [!WARNING] +> Starting on July 9 2024, the new [STACKIT Identity Provider (IDP)](https://docs.stackit.cloud/stackit/en/release-notes-23101442.html#ReleaseNotes-2024-06-21-identity-provider) will be available. +> +> On this date, we will release a new version of the STACKIT CLI that will use the new IDP for user authentication. This also means that the **user authentication on STACKIT CLI versions released before July 9 2024 is no longer guaranteed to work for all services**. +> +> Please make sure to **update your STACKIT CLI to the latest version after July 9 2024** to ensure that you can continue to use all STACKIT services. + ## Installation Please refer to our [installation guide](./INSTALLATION.md) for instructions on how to install and get started using the STACKIT CLI. From e8b22aa3f89993f86daddfbd4a0cb77a5b591a86 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 5 Jul 2024 10:05:02 +0200 Subject: [PATCH 010/619] fix(deps): update module golang.org/x/mod to v0.19.0 (#402) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 115b56655..e63dbd337 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0 github.com/zalando/go-keyring v0.2.5 - golang.org/x/mod v0.18.0 + golang.org/x/mod v0.19.0 golang.org/x/oauth2 v0.21.0 golang.org/x/term v0.21.0 golang.org/x/text v0.16.0 diff --git a/go.sum b/go.sum index 563b90e88..6ad60269a 100644 --- a/go.sum +++ b/go.sum @@ -189,8 +189,8 @@ golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRj golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From 11efa5f919cdaafd4ad92c94e2a24494f34ba629 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 5 Jul 2024 10:05:18 +0200 Subject: [PATCH 011/619] fix(deps): update module golang.org/x/term to v0.22.0 (#403) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index e63dbd337..3f14b1feb 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.19.0 golang.org/x/oauth2 v0.21.0 - golang.org/x/term v0.21.0 + golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 @@ -84,7 +84,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 6ad60269a..16538402f 100644 --- a/go.sum +++ b/go.sum @@ -207,10 +207,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= From 69cda1cbe75dc71cfa2008d40b15f741f34583cd Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:25:32 +0200 Subject: [PATCH 012/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/ske to v0.17.0 (#405) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3f14b1feb..32a76562d 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.19.0 diff --git a/go.sum b/go.sum index 16538402f..7569c2c7a 100644 --- a/go.sum +++ b/go.sum @@ -157,8 +157,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 h1:fYCBNvh4t github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0/go.mod h1:ZYI3wj/NnhhWi25ugbdcniwnY/7mF6zN582c5HPe00o= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 h1:JB1O0E9+L50ZaO36uz7azurvUuB5JdX5s2ZXuIdb9t8= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0/go.mod h1:Ni9RBJvcaXRIrDIuQBpJcuQvCQSj27crQSyc+WM4p0c= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.16.0 h1:trrJuRMzgXu6fiiMZiUx6+A1FNKEFhA1vGq5cr5Qn3U= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.16.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0 h1:4S3MwNmpMfjzBz9JtKbXvkos7j+7hGeFMf7XsjMLL/g= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0 h1:aIXxXx6u4+6C02MPb+hdItigeKeen7m+hEEG+Ej9sNs= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0/go.mod h1:fQJOQMfasStZ8J9iGX0vTjyJoQtLqMXJ5Npb03QJk84= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From cd9c22632e8d0c40df9f1b783475ad81b7e645a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Mon, 8 Jul 2024 17:39:15 +0100 Subject: [PATCH 013/619] Migrate to new STACKIT IDP (#404) * Migrate to new STACKIT IDP * Add additional debug log * Remove warning on auth login command * Add email scope to IDP requests --- docs/stackit_auth_login.md | 1 + internal/cmd/auth/login/login.go | 14 +++------ internal/pkg/auth/user_login.go | 37 ++++++++++++++++------- internal/pkg/auth/user_token_flow.go | 12 +++----- internal/pkg/auth/user_token_flow_test.go | 15 ++++++--- 5 files changed, 46 insertions(+), 33 deletions(-) diff --git a/docs/stackit_auth_login.md b/docs/stackit_auth_login.md index e839b4997..5175c94b6 100644 --- a/docs/stackit_auth_login.md +++ b/docs/stackit_auth_login.md @@ -5,6 +5,7 @@ Logs in to the STACKIT CLI ### Synopsis Logs in to the STACKIT CLI using a user account. +The authentication is done via a web-based authorization flow, where the command will open a browser window in which you can login to your STACKIT account. ``` stackit auth login [flags] diff --git a/internal/cmd/auth/login/login.go b/internal/cmd/auth/login/login.go index 90bc05b02..e19f962f0 100644 --- a/internal/cmd/auth/login/login.go +++ b/internal/cmd/auth/login/login.go @@ -15,22 +15,16 @@ func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "login", Short: "Logs in to the STACKIT CLI", - Long: "Logs in to the STACKIT CLI using a user account.", - Args: args.NoArgs, + Long: fmt.Sprintf("%s\n%s", + "Logs in to the STACKIT CLI using a user account.", + "The authentication is done via a web-based authorization flow, where the command will open a browser window in which you can login to your STACKIT account."), + Args: args.NoArgs, Example: examples.Build( examples.NewExample( `Login to the STACKIT CLI. This command will open a browser window where you can login to your STACKIT account`, "$ stackit auth login"), ), RunE: func(cmd *cobra.Command, args []string) error { - p.Warn(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n\n", - "Starting on July 9 2024, the new STACKIT Identity Provider (IDP) will be available.", - "On this date, we will release a new version of the STACKIT CLI that will use the new IDP for user authentication.", - "This also means that the user authentication on STACKIT CLI versions released before July 9 2024 is no longer guaranteed to work for all services.", - "Please make sure to update your STACKIT CLI to the latest version after July 9 2024 to ensure that you can continue to use all STACKIT services.", - "You can find more information regarding the new IDP at https://docs.stackit.cloud/stackit/en/release-notes-23101442.html#ReleaseNotes-2024-06-21-identity-provider", - )) - err := auth.AuthorizeUser(p, false) if err != nil { return fmt.Errorf("authorization failed: %w", err) diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index 4101134f9..41f850457 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -23,13 +23,18 @@ import ( ) const ( - defaultIDPEndpoint = "https://auth.01.idp.eu01.stackit.cloud/oauth" - cliClientID = "stackit-cli-client-id" + defaultIDPEndpoint = "https://accounts.stackit.cloud/oauth/v2" + cliClientID = "stackit-cli-0000-0000-000000000001" loginSuccessPath = "/login-successful" stackitLandingPage = "https://www.stackit.de" htmlTemplatesPath = "templates" loginSuccessfulHTMLFile = "login-successful.html" + + // The IDP doesn't support wildcards for the port, + // so we configure a range of ports from 8000 to 8020 + defaultPort = 8000 + configuredPortRange = 20 ) //go:embed templates/* @@ -60,22 +65,32 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { } } - listener, err := net.Listen("tcp", ":0") - if err != nil { - return fmt.Errorf("bind port for login redirect: %w", err) + var redirectURL string + var listener net.Listener + var listenerErr error + var port int + for i := range configuredPortRange { + port = defaultPort + i + portString := fmt.Sprintf(":%s", strconv.Itoa(port)) + p.Debug(print.DebugLevel, "trying to bind port %d for login redirect", port) + listener, listenerErr = net.Listen("tcp", portString) + if listenerErr == nil { + redirectURL = fmt.Sprintf("http://localhost:%d", port) + p.Debug(print.DebugLevel, "bound port %d for login redirect", port) + break + } + p.Debug(print.DebugLevel, "unable to bind port %d for login redirect: %s", port, listenerErr) } - address, ok := listener.Addr().(*net.TCPAddr) - if !ok { - return fmt.Errorf("assert listener address type to TCP address") + if listenerErr != nil { + return fmt.Errorf("unable to bind port for login redirect, tried from port %d to %d: %w", defaultPort, port, err) } - redirectURL := fmt.Sprintf("http://localhost:%d", address.Port) conf := &oauth2.Config{ ClientID: cliClientID, Endpoint: oauth2.Endpoint{ AuthURL: fmt.Sprintf("%s/authorize", idpEndpoint), }, - Scopes: []string{"openid"}, + Scopes: []string{"openid offline_access email"}, RedirectURL: redirectURL, } @@ -98,7 +113,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { p.Debug(print.DebugLevel, "received request from authentication server") // Close the server only if there was an error - // Otherwise, it will redirect to the succesfull login page + // Otherwise, it will redirect to the successful login page defer func() { if errServer != nil { fmt.Println(errServer) diff --git a/internal/pkg/auth/user_token_flow.go b/internal/pkg/auth/user_token_flow.go index ebb90b2a3..a15c33c17 100644 --- a/internal/pkg/auth/user_token_flow.go +++ b/internal/pkg/auth/user_token_flow.go @@ -43,19 +43,18 @@ func (utf *userTokenFlow) RoundTrip(req *http.Request) (*http.Response, error) { } accessTokenValid := false - if accessTokenExpired, err := tokenExpired(utf.accessToken); err != nil { + accessTokenExpired, err := tokenExpired(utf.accessToken) + if err != nil { return nil, fmt.Errorf("check if access token has expired: %w", err) } else if !accessTokenExpired { accessTokenValid = true - } else if refreshTokenExpired, err := tokenExpired(utf.refreshToken); err != nil { - return nil, fmt.Errorf("check if refresh token has expired: %w", err) - } else if !refreshTokenExpired { + } else { utf.printer.Debug(print.DebugLevel, "access token expired, refreshing...") err = refreshTokens(utf) if err == nil { accessTokenValid = true } else { - utf.printer.Debug(print.ErrorLevel, "refresh access token: %v", err) + utf.printer.Debug(print.ErrorLevel, "refresh access token: %w", err) } } @@ -177,9 +176,6 @@ func buildRequestToRefreshTokens(utf *userTokenFlow) (*http.Request, error) { reqQuery.Set("token_format", "jwt") req.URL.RawQuery = reqQuery.Encode() - // without this header, the API returns error "An Authentication object was not found in the SecurityContext" - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - return req, nil } diff --git a/internal/pkg/auth/user_token_flow_test.go b/internal/pkg/auth/user_token_flow_test.go index e5113e67f..b014c5887 100644 --- a/internal/pkg/auth/user_token_flow_test.go +++ b/internal/pkg/auth/user_token_flow_test.go @@ -28,7 +28,11 @@ func (rt *clientTransport) RoundTrip(req *http.Request) (*http.Response, error) if reqURL == rt.requestURL { return rt.roundTripRequest() } - if fmt.Sprintf("https://%s", reqURL) == fmt.Sprintf("%s/token", defaultIDPEndpoint) { + idpEndpoint, err := getIDPEndpoint() + if err != nil { + rt.t.Fatalf("get IDP endpoint for test: %v", err) + } + if fmt.Sprintf("https://%s", reqURL) == fmt.Sprintf("%s/token", idpEndpoint) { return rt.roundTripRefreshTokens() } rt.t.Fatalf("unexpected request to %q", reqURL) @@ -163,6 +167,7 @@ func TestRoundTrip(t *testing.T) { desc: "tokens expired", accessTokenExpiresAt: time.Now().Add(-time.Hour), refreshTokenExpiresAt: time.Now().Add(-time.Hour), + refreshTokensFails: true, // Fails because refresh token is expired isValid: true, expectedReautorizeUserCalled: true, expectedTokensRefreshed: true, @@ -190,9 +195,10 @@ func TestRoundTrip(t *testing.T) { accessTokenExpiresAt: time.Now().Add(-time.Hour), refreshTokenExpiresAt: time.Now().Add(time.Hour), refreshTokenInvalid: true, - isValid: false, - expectedReautorizeUserCalled: false, - expectedTokensRefreshed: false, + refreshTokensFails: true, // Fails because refresh token is invalid + isValid: true, + expectedReautorizeUserCalled: true, + expectedTokensRefreshed: true, // Refreshed during reauthorization }, { desc: "refresh token invalid but unused", @@ -207,6 +213,7 @@ func TestRoundTrip(t *testing.T) { desc: "authorize user fails", accessTokenExpiresAt: time.Now().Add(-time.Hour), refreshTokenExpiresAt: time.Now().Add(-time.Hour), + refreshTokensFails: true, // Fails because refresh token is expired authorizeUserFails: true, isValid: false, expectedReautorizeUserCalled: true, From e46a6077e0432595f95ac29788e8f48ed2c81bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Tue, 9 Jul 2024 09:12:55 +0100 Subject: [PATCH 014/619] Update README IDP migration warning (#406) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f57a5bd8..f5981017b 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,9 @@ Your feedback is appreciated! > [!WARNING] -> Starting on July 9 2024, the new [STACKIT Identity Provider (IDP)](https://docs.stackit.cloud/stackit/en/release-notes-23101442.html#ReleaseNotes-2024-06-21-identity-provider) will be available. +> On July 9 2024, the new [STACKIT Identity Provider (IDP)](https://docs.stackit.cloud/stackit/en/release-notes-23101442.html#ReleaseNotes-2024-06-21-identity-provider) was released. We are happy to announce that on [v0.9.0](https://github.com/stackitcloud/stackit-cli/releases/tag/v0.9.0), the new IDP was integrated in the STACKIT CLI, where it is used for user authentication. > -> On this date, we will release a new version of the STACKIT CLI that will use the new IDP for user authentication. This also means that the **user authentication on STACKIT CLI versions released before July 9 2024 is no longer guaranteed to work for all services**. +> This also means that the **user authentication on STACKIT CLI versions released before July 9 2024 is no longer guaranteed to work for all services**. > > Please make sure to **update your STACKIT CLI to the latest version after July 9 2024** to ensure that you can continue to use all STACKIT services. From dc0da3ad4a82b052b492b9947668437f5606a226 Mon Sep 17 00:00:00 2001 From: a_nackov Date: Tue, 9 Jul 2024 16:59:17 +0300 Subject: [PATCH 015/619] ref 644868 - server backup subcommands (#397) Signed-off-by: Adrian Nackov --- docs/stackit_beta_server_backup.md | 6 + docs/stackit_beta_server_backup_create.md | 46 ++++ docs/stackit_beta_server_backup_delete.md | 40 ++++ docs/stackit_beta_server_backup_describe.md | 43 ++++ docs/stackit_beta_server_backup_list.md | 44 ++++ docs/stackit_beta_server_backup_restore.md | 45 ++++ ...ckit_beta_server_backup_schedule_create.md | 2 +- ...ckit_beta_server_backup_schedule_update.md | 2 +- ...tackit_beta_server_backup_volume-backup.md | 34 +++ ...beta_server_backup_volume-backup_delete.md | 41 ++++ ...eta_server_backup_volume-backup_restore.md | 42 ++++ internal/cmd/beta/server/backup/backup.go | 12 + .../cmd/beta/server/backup/create/create.go | 164 +++++++++++++ .../beta/server/backup/create/create_test.go | 210 +++++++++++++++++ .../cmd/beta/server/backup/delete/delete.go | 114 +++++++++ .../beta/server/backup/delete/delete_test.go | 209 +++++++++++++++++ .../beta/server/backup/describe/describe.go | 161 +++++++++++++ .../server/backup/describe/describe_test.go | 211 +++++++++++++++++ internal/cmd/beta/server/backup/list/list.go | 165 +++++++++++++ .../cmd/beta/server/backup/list/list_test.go | 188 +++++++++++++++ .../cmd/beta/server/backup/restore/restore.go | 135 +++++++++++ .../server/backup/restore/restore_test.go | 211 +++++++++++++++++ .../server/backup/schedule/create/create.go | 15 +- .../backup/schedule/create/create_test.go | 7 +- .../server/backup/schedule/update/update.go | 15 +- .../backup/schedule/update/update_test.go | 9 +- .../backup/volume-backup/delete/delete.go | 118 ++++++++++ .../volume-backup/delete/delete_test.go | 212 +++++++++++++++++ .../backup/volume-backup/restore/restore.go | 126 ++++++++++ .../volume-backup/restore/restore_test.go | 218 ++++++++++++++++++ .../backup/volume-backup/volumebackup.go | 28 +++ 31 files changed, 2843 insertions(+), 30 deletions(-) create mode 100644 docs/stackit_beta_server_backup_create.md create mode 100644 docs/stackit_beta_server_backup_delete.md create mode 100644 docs/stackit_beta_server_backup_describe.md create mode 100644 docs/stackit_beta_server_backup_list.md create mode 100644 docs/stackit_beta_server_backup_restore.md create mode 100644 docs/stackit_beta_server_backup_volume-backup.md create mode 100644 docs/stackit_beta_server_backup_volume-backup_delete.md create mode 100644 docs/stackit_beta_server_backup_volume-backup_restore.md create mode 100644 internal/cmd/beta/server/backup/create/create.go create mode 100644 internal/cmd/beta/server/backup/create/create_test.go create mode 100644 internal/cmd/beta/server/backup/delete/delete.go create mode 100644 internal/cmd/beta/server/backup/delete/delete_test.go create mode 100644 internal/cmd/beta/server/backup/describe/describe.go create mode 100644 internal/cmd/beta/server/backup/describe/describe_test.go create mode 100644 internal/cmd/beta/server/backup/list/list.go create mode 100644 internal/cmd/beta/server/backup/list/list_test.go create mode 100644 internal/cmd/beta/server/backup/restore/restore.go create mode 100644 internal/cmd/beta/server/backup/restore/restore_test.go create mode 100644 internal/cmd/beta/server/backup/volume-backup/delete/delete.go create mode 100644 internal/cmd/beta/server/backup/volume-backup/delete/delete_test.go create mode 100644 internal/cmd/beta/server/backup/volume-backup/restore/restore.go create mode 100644 internal/cmd/beta/server/backup/volume-backup/restore/restore_test.go create mode 100644 internal/cmd/beta/server/backup/volume-backup/volumebackup.go diff --git a/docs/stackit_beta_server_backup.md b/docs/stackit_beta_server_backup.md index e2ae7ffda..74164a5a1 100644 --- a/docs/stackit_beta_server_backup.md +++ b/docs/stackit_beta_server_backup.md @@ -29,7 +29,13 @@ stackit beta server backup [flags] ### SEE ALSO * [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server backup create](./stackit_beta_server_backup_create.md) - Creates a Server Backup. +* [stackit beta server backup delete](./stackit_beta_server_backup_delete.md) - Deletes a Server Backup. +* [stackit beta server backup describe](./stackit_beta_server_backup_describe.md) - Shows details of a Server Backup * [stackit beta server backup disable](./stackit_beta_server_backup_disable.md) - Disables Server Backup service * [stackit beta server backup enable](./stackit_beta_server_backup_enable.md) - Enables Server Backup service +* [stackit beta server backup list](./stackit_beta_server_backup_list.md) - Lists all server backups +* [stackit beta server backup restore](./stackit_beta_server_backup_restore.md) - Restores a Server Backup. * [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule +* [stackit beta server backup volume-backup](./stackit_beta_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups diff --git a/docs/stackit_beta_server_backup_create.md b/docs/stackit_beta_server_backup_create.md new file mode 100644 index 000000000..713b10dd1 --- /dev/null +++ b/docs/stackit_beta_server_backup_create.md @@ -0,0 +1,46 @@ +## stackit beta server backup create + +Creates a Server Backup. + +### Synopsis + +Creates a Server Backup. Operation always is async. + +``` +stackit beta server backup create [flags] +``` + +### Examples + +``` + Create a Server Backup with name "mybackup" + $ stackit beta server backup create --server-id xxx --name=mybackup + + Create a Server Backup with name "mybackup" and retention period of 5 days + $ stackit beta server backup create --server-id xxx --name=mybackup --retention-period=5 +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup create" + -b, --name string Backup name + -d, --retention-period int Backup retention period (in days) (default 14) + -s, --server-id string Server ID + -i, --volume-ids strings Backup volume IDs, as comma separated UUID values. (default []) +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup + diff --git a/docs/stackit_beta_server_backup_delete.md b/docs/stackit_beta_server_backup_delete.md new file mode 100644 index 000000000..82c96299d --- /dev/null +++ b/docs/stackit_beta_server_backup_delete.md @@ -0,0 +1,40 @@ +## stackit beta server backup delete + +Deletes a Server Backup. + +### Synopsis + +Deletes a Server Backup. Operation always is async. + +``` +stackit beta server backup delete BACKUP_ID [flags] +``` + +### Examples + +``` + Delete a Server Backup with ID "xxx" for server "zzz" + $ stackit beta server backup delete xxx --server-id=zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup delete" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup + diff --git a/docs/stackit_beta_server_backup_describe.md b/docs/stackit_beta_server_backup_describe.md new file mode 100644 index 000000000..6ce6eb8be --- /dev/null +++ b/docs/stackit_beta_server_backup_describe.md @@ -0,0 +1,43 @@ +## stackit beta server backup describe + +Shows details of a Server Backup + +### Synopsis + +Shows details of a Server Backup. + +``` +stackit beta server backup describe BACKUP_ID [flags] +``` + +### Examples + +``` + Get details of a Server Backup with id "my-backup-id" + $ stackit beta server backup describe my-backup-id + + Get details of a Server Backup with id "my-backup-id" in JSON format + $ stackit beta server backup describe my-backup-id --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup describe" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup + diff --git a/docs/stackit_beta_server_backup_list.md b/docs/stackit_beta_server_backup_list.md new file mode 100644 index 000000000..f7313d09f --- /dev/null +++ b/docs/stackit_beta_server_backup_list.md @@ -0,0 +1,44 @@ +## stackit beta server backup list + +Lists all server backups + +### Synopsis + +Lists all server backups. + +``` +stackit beta server backup list [flags] +``` + +### Examples + +``` + List all backups for a server with ID "xxx" + $ stackit beta server backup list --server-id xxx + + List all backups for a server with ID "xxx" in JSON format + $ stackit beta server backup list --server-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup list" + --limit int Maximum number of entries to list + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup + diff --git a/docs/stackit_beta_server_backup_restore.md b/docs/stackit_beta_server_backup_restore.md new file mode 100644 index 000000000..8009a85ef --- /dev/null +++ b/docs/stackit_beta_server_backup_restore.md @@ -0,0 +1,45 @@ +## stackit beta server backup restore + +Restores a Server Backup. + +### Synopsis + +Restores a Server Backup. Operation always is async. + +``` +stackit beta server backup restore BACKUP_ID [flags] +``` + +### Examples + +``` + Restore a Server Backup with ID "xxx" for server "zzz" + $ stackit beta server backup restore xxx --server-id=zzz + + Restore a Server Backup with ID "xxx" for server "zzz" and start the server afterwards + $ stackit beta server backup restore xxx --server-id=zzz --start-server-after-restore +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup restore" + -s, --server-id string Server ID + -u, --start-server-after-restore Should the server start after the backup restoring. + -i, --volume-ids strings Backup volume IDs, as comma separated UUID values. (default []) +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup + diff --git a/docs/stackit_beta_server_backup_schedule_create.md b/docs/stackit_beta_server_backup_schedule_create.md index 42c05ca97..216dc17ff 100644 --- a/docs/stackit_beta_server_backup_schedule_create.md +++ b/docs/stackit_beta_server_backup_schedule_create.md @@ -26,7 +26,7 @@ stackit beta server backup schedule create [flags] -b, --backup-name string Backup name -d, --backup-retention-period int Backup retention period (in days) (default 14) -n, --backup-schedule-name string Backup schedule name - -i, --backup-volume-ids string Backup volume ids, as comma separated UUID values. + -i, --backup-volume-ids strings Backup volume IDs, as comma separated UUID values. (default []) -e, --enabled Is the server backup schedule enabled (default true) -h, --help Help for "stackit beta server backup schedule create" -r, --rrule string Backup RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") diff --git a/docs/stackit_beta_server_backup_schedule_update.md b/docs/stackit_beta_server_backup_schedule_update.md index d238045cd..a4192f936 100644 --- a/docs/stackit_beta_server_backup_schedule_update.md +++ b/docs/stackit_beta_server_backup_schedule_update.md @@ -26,7 +26,7 @@ stackit beta server backup schedule update SCHEDULE_ID [flags] -b, --backup-name string Backup name -d, --backup-retention-period int Backup retention period (in days) (default 14) -n, --backup-schedule-name string Backup schedule name - -i, --backup-volume-ids string Backup volume ids, as comma separated UUID values. + -i, --backup-volume-ids strings Backup volume IDs, as comma separated UUID values. (default []) -e, --enabled Is the server backup schedule enabled (default true) -h, --help Help for "stackit beta server backup schedule update" -r, --rrule string Backup RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") diff --git a/docs/stackit_beta_server_backup_volume-backup.md b/docs/stackit_beta_server_backup_volume-backup.md new file mode 100644 index 000000000..5964784c8 --- /dev/null +++ b/docs/stackit_beta_server_backup_volume-backup.md @@ -0,0 +1,34 @@ +## stackit beta server backup volume-backup + +Provides functionality for Server Backup Volume Backups + +### Synopsis + +Provides functionality for Server Backup Volume Backups. + +``` +stackit beta server backup volume-backup [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server backup volume-backup" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup volume-backup delete](./stackit_beta_server_backup_volume-backup_delete.md) - Deletes a Server Volume Backup. +* [stackit beta server backup volume-backup restore](./stackit_beta_server_backup_volume-backup_restore.md) - Restore a Server Volume Backup to a volume. + diff --git a/docs/stackit_beta_server_backup_volume-backup_delete.md b/docs/stackit_beta_server_backup_volume-backup_delete.md new file mode 100644 index 000000000..7e58424c7 --- /dev/null +++ b/docs/stackit_beta_server_backup_volume-backup_delete.md @@ -0,0 +1,41 @@ +## stackit beta server backup volume-backup delete + +Deletes a Server Volume Backup. + +### Synopsis + +Deletes a Server Volume Backup. Operation always is async. + +``` +stackit beta server backup volume-backup delete VOLUME_BACKUP_ID [flags] +``` + +### Examples + +``` + Delete a Server Volume Backup with ID "xxx" for server "zzz" and backup "bbb" + $ stackit beta server backup volume-backup delete xxx --server-id=zzz --backup-id=bbb +``` + +### Options + +``` + -b, --backup-id string Backup ID + -h, --help Help for "stackit beta server backup volume-backup delete" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup volume-backup](./stackit_beta_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups + diff --git a/docs/stackit_beta_server_backup_volume-backup_restore.md b/docs/stackit_beta_server_backup_volume-backup_restore.md new file mode 100644 index 000000000..c1f6c1be0 --- /dev/null +++ b/docs/stackit_beta_server_backup_volume-backup_restore.md @@ -0,0 +1,42 @@ +## stackit beta server backup volume-backup restore + +Restore a Server Volume Backup to a volume. + +### Synopsis + +Restore a Server Volume Backup to a volume. Operation always is async. + +``` +stackit beta server backup volume-backup restore VOLUME_BACKUP_ID [flags] +``` + +### Examples + +``` + Restore a Server Volume Backup with ID "xxx" for server "zzz" and backup "bbb" to volume "rrr" + $ stackit beta server backup volume-backup restore xxx --server-id=zzz --backup-id=bbb --restore-volume-id=rrr +``` + +### Options + +``` + -b, --backup-id string Backup ID + -h, --help Help for "stackit beta server backup volume-backup restore" + -r, --restore-volume-id string Restore Volume ID + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server backup volume-backup](./stackit_beta_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups + diff --git a/internal/cmd/beta/server/backup/backup.go b/internal/cmd/beta/server/backup/backup.go index 54bcf1f3b..37312d2a3 100644 --- a/internal/cmd/beta/server/backup/backup.go +++ b/internal/cmd/beta/server/backup/backup.go @@ -1,9 +1,15 @@ package backup import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/create" + del "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/disable" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/restore" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule" + volumebackup "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/volume-backup" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -26,5 +32,11 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(enable.NewCmd(p)) cmd.AddCommand(disable.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) cmd.AddCommand(schedule.NewCmd(p)) + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(restore.NewCmd(p)) + cmd.AddCommand(del.NewCmd(p)) + cmd.AddCommand(volumebackup.NewCmd(p)) } diff --git a/internal/cmd/beta/server/backup/create/create.go b/internal/cmd/beta/server/backup/create/create.go new file mode 100644 index 000000000..92a78a7cb --- /dev/null +++ b/internal/cmd/beta/server/backup/create/create.go @@ -0,0 +1,164 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + backupNameFlag = "name" + backupRetentionPeriodFlag = "retention-period" + backupVolumeIdsFlag = "volume-ids" + serverIdFlag = "server-id" + + defaultRetentionPeriod = 14 +) + +type inputModel struct { + *globalflags.GlobalFlagModel + + ServerId string + BackupName string + BackupRetentionPeriod int64 + BackupVolumeIds []string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a Server Backup.", + Long: "Creates a Server Backup. Operation always is async.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a Server Backup with name "mybackup"`, + `$ stackit beta server backup create --server-id xxx --name=mybackup`), + examples.NewExample( + `Create a Server Backup with name "mybackup" and retention period of 5 days`, + `$ stackit beta server backup create --server-id xxx --name=mybackup --retention-period=5`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a Backup for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create Server Backup: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().StringP(backupNameFlag, "b", "", "Backup name") + cmd.Flags().Int64P(backupRetentionPeriodFlag, "d", defaultRetentionPeriod, "Backup retention period (in days)") + cmd.Flags().VarP(flags.UUIDSliceFlag(), backupVolumeIdsFlag, "i", "Backup volume IDs, as comma separated UUID values.") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag, backupNameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + BackupRetentionPeriod: flags.FlagWithDefaultToInt64Value(p, cmd, backupRetentionPeriodFlag), + BackupName: flags.FlagToStringValue(p, cmd, backupNameFlag), + BackupVolumeIds: flags.FlagToStringSliceValue(p, cmd, backupVolumeIdsFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) (serverbackup.ApiCreateBackupRequest, error) { + req := apiClient.CreateBackup(ctx, model.ProjectId, model.ServerId) + payload := serverbackup.CreateBackupPayload{ + Name: &model.BackupName, + RetentionPeriod: &model.BackupRetentionPeriod, + VolumeIds: &model.BackupVolumeIds, + } + if model.BackupVolumeIds == nil { + payload.VolumeIds = nil + } + req = req.CreateBackupPayload(payload) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.BackupJob) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal server backup: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server backup: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Triggered creation of server backup for server %s. Backup ID: %s\n", model.ServerId, *resp.Id) + return nil + } +} diff --git a/internal/cmd/beta/server/backup/create/create_test.go b/internal/cmd/beta/server/backup/create/create_test.go new file mode 100644 index 000000000..18bf4046d --- /dev/null +++ b/internal/cmd/beta/server/backup/create/create_test.go @@ -0,0 +1,210 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} + +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupVolumeId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + backupNameFlag: "example-backup-name", + backupRetentionPeriodFlag: "14", + backupVolumeIdsFlag: testBackupVolumeId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + BackupName: "example-backup-name", + BackupRetentionPeriod: int64(14), + BackupVolumeIds: []string{testBackupVolumeId}, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiCreateBackupRequest)) serverbackup.ApiCreateBackupRequest { + request := testClient.CreateBackup(testCtx, testProjectId, testServerId) + request = request.CreateBackupPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *serverbackup.CreateBackupPayload)) serverbackup.CreateBackupPayload { + payload := serverbackup.CreateBackupPayload{ + Name: utils.Ptr("example-backup-name"), + RetentionPeriod: utils.Ptr(int64(14)), + VolumeIds: utils.Ptr([]string{testBackupVolumeId}), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "with defaults", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, backupRetentionPeriodFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiCreateBackupRequest + isValid bool + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/delete/delete.go b/internal/cmd/beta/server/backup/delete/delete.go new file mode 100644 index 000000000..e8d92c351 --- /dev/null +++ b/internal/cmd/beta/server/backup/delete/delete.go @@ -0,0 +1,114 @@ +package delete + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + backupIdArg = "BACKUP_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + BackupId string + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", backupIdArg), + Short: "Deletes a Server Backup.", + Long: "Deletes a Server Backup. Operation always is async.", + Args: args.SingleArg(backupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a Server Backup with ID "xxx" for server "zzz"`, + "$ stackit beta server backup delete xxx --server-id=zzz"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete server backup %q? (This cannot be undone)", model.BackupId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete Server Backup: %w", err) + } + + p.Info("Triggered deletion of server backup %q\n", model.BackupId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + backupId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + BackupId: backupId, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDeleteBackupRequest { + req := apiClient.DeleteBackup(ctx, model.ProjectId, model.ServerId, model.BackupId) + return req +} diff --git a/internal/cmd/beta/server/backup/delete/delete_test.go b/internal/cmd/beta/server/backup/delete/delete_test.go new file mode 100644 index 000000000..feb988f4b --- /dev/null +++ b/internal/cmd/beta/server/backup/delete/delete_test.go @@ -0,0 +1,209 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + BackupId: testBackupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiDeleteBackupRequest)) serverbackup.ApiDeleteBackupRequest { + request := testClient.DeleteBackup(testCtx, testProjectId, testServerId, testBackupId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiDeleteBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/describe/describe.go b/internal/cmd/beta/server/backup/describe/describe.go new file mode 100644 index 000000000..38509fb97 --- /dev/null +++ b/internal/cmd/beta/server/backup/describe/describe.go @@ -0,0 +1,161 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + backupIdArg = "BACKUP_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + BackupId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", backupIdArg), + Short: "Shows details of a Server Backup", + Long: "Shows details of a Server Backup.", + Args: args.SingleArg(backupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get details of a Server Backup with id "my-backup-id"`, + "$ stackit beta server backup describe my-backup-id"), + examples.NewExample( + `Get details of a Server Backup with id "my-backup-id" in JSON format`, + "$ stackit beta server backup describe my-backup-id --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read server backup: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + backupId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + BackupId: backupId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiGetBackupRequest { + req := apiClient.GetBackup(ctx, model.ProjectId, model.ServerId, model.BackupId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, backup *serverbackup.Backup) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(backup, "", " ") + if err != nil { + return fmt.Errorf("marshal server backup: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server backup: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *backup.Id) + table.AddSeparator() + table.AddRow("NAME", *backup.Name) + table.AddSeparator() + table.AddRow("SIZE (GB)", *backup.Size) + table.AddSeparator() + table.AddRow("STATUS", *backup.Status) + table.AddSeparator() + table.AddRow("CREATED AT", *backup.CreatedAt) + table.AddSeparator() + table.AddRow("EXPIRES AT", *backup.ExpireAt) + table.AddSeparator() + + lastRestored := "" + if backup.LastRestoredAt != nil { + lastRestored = *backup.LastRestoredAt + } + table.AddRow("LAST RESTORED AT", lastRestored) + table.AddSeparator() + table.AddRow("VOLUME BACKUPS", len(*backup.VolumeBackups)) + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/server/backup/describe/describe_test.go b/internal/cmd/beta/server/backup/describe/describe_test.go new file mode 100644 index 000000000..a4f979e0a --- /dev/null +++ b/internal/cmd/beta/server/backup/describe/describe_test.go @@ -0,0 +1,211 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + BackupId: testBackupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiGetBackupRequest)) serverbackup.ApiGetBackupRequest { + request := testClient.GetBackup(testCtx, testProjectId, testServerId, testBackupId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + isValid bool + expectedRequest serverbackup.ApiGetBackupRequest + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/list/list.go b/internal/cmd/beta/server/backup/list/list.go new file mode 100644 index 000000000..fd3897d3c --- /dev/null +++ b/internal/cmd/beta/server/backup/list/list.go @@ -0,0 +1,165 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + limitFlag = "limit" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all server backups", + Long: "Lists all server backups.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all backups for a server with ID "xxx"`, + "$ stackit beta server backup list --server-id xxx"), + examples.NewExample( + `List all backups for a server with ID "xxx" in JSON format`, + "$ stackit beta server backup list --server-id xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list server backups: %w", err) + } + backups := *resp.Items + if len(backups) == 0 { + p.Info("No backups found for server %s\n", model.ServerId) + return nil + } + + // Truncate output + if model.Limit != nil && len(backups) > int(*model.Limit) { + backups = backups[:*model.Limit] + } + return outputResult(p, model.OutputFormat, backups) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiListBackupsRequest { + req := apiClient.ListBackups(ctx, model.ProjectId, model.ServerId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, backups []serverbackup.Backup) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(backups, "", " ") + if err != nil { + return fmt.Errorf("marshal Server Backup list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal Server Backup list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "SIZE (GB)", "STATUS", "CREATED AT", "EXPIRES AT", "LAST RESTORED AT", "VOLUME BACKUPS") + for i := range backups { + s := backups[i] + + lastRestored := "" + if s.LastRestoredAt != nil { + lastRestored = *s.LastRestoredAt + } + table.AddRow(*s.Id, *s.Name, *s.Size, *s.Status, *s.CreatedAt, *s.ExpireAt, lastRestored, len(*s.VolumeBackups)) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/backup/list/list_test.go b/internal/cmd/beta/server/backup/list/list_test.go new file mode 100644 index 000000000..fccc16027 --- /dev/null +++ b/internal/cmd/beta/server/backup/list/list_test.go @@ -0,0 +1,188 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(int64(10)), + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiListBackupsRequest)) serverbackup.ApiListBackupsRequest { + request := testClient.ListBackups(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiListBackupsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/restore/restore.go b/internal/cmd/beta/server/backup/restore/restore.go new file mode 100644 index 000000000..cfb9be8bd --- /dev/null +++ b/internal/cmd/beta/server/backup/restore/restore.go @@ -0,0 +1,135 @@ +package restore + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + backupIdArg = "BACKUP_ID" + serverIdFlag = "server-id" + startServerAfterRestoreFlag = "start-server-after-restore" + backupVolumeIdsFlag = "volume-ids" + + defaultStartServerAfterRestore = false +) + +type inputModel struct { + *globalflags.GlobalFlagModel + BackupId string + ServerId string + StartServerAfterRestore bool + BackupVolumeIds []string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("restore %s", backupIdArg), + Short: "Restores a Server Backup.", + Long: "Restores a Server Backup. Operation always is async.", + Args: args.SingleArg(backupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Restore a Server Backup with ID "xxx" for server "zzz"`, + "$ stackit beta server backup restore xxx --server-id=zzz"), + examples.NewExample( + `Restore a Server Backup with ID "xxx" for server "zzz" and start the server afterwards`, + "$ stackit beta server backup restore xxx --server-id=zzz --start-server-after-restore"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to restore server backup %q? (This cannot be undone)", model.BackupId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("restore Server Backup: %w", err) + } + + p.Info("Triggered restoring of server backup %q\n", model.BackupId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().VarP(flags.UUIDSliceFlag(), backupVolumeIdsFlag, "i", "Backup volume IDs, as comma separated UUID values.") + cmd.Flags().BoolP(startServerAfterRestoreFlag, "u", defaultStartServerAfterRestore, "Should the server start after the backup restoring.") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + backupId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + BackupId: backupId, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + BackupVolumeIds: flags.FlagToStringSliceValue(p, cmd, backupVolumeIdsFlag), + StartServerAfterRestore: flags.FlagToBoolValue(p, cmd, startServerAfterRestoreFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiRestoreBackupRequest { + req := apiClient.RestoreBackup(ctx, model.ProjectId, model.ServerId, model.BackupId) + payload := serverbackup.RestoreBackupPayload{ + StartServerAfterRestore: &model.StartServerAfterRestore, + VolumeIds: &model.BackupVolumeIds, + } + if model.BackupVolumeIds == nil { + payload.VolumeIds = nil + } + req = req.RestoreBackupPayload(payload) + return req +} diff --git a/internal/cmd/beta/server/backup/restore/restore_test.go b/internal/cmd/beta/server/backup/restore/restore_test.go new file mode 100644 index 000000000..cb0c88bba --- /dev/null +++ b/internal/cmd/beta/server/backup/restore/restore_test.go @@ -0,0 +1,211 @@ +package restore + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + BackupId: testBackupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiRestoreBackupRequest)) serverbackup.ApiRestoreBackupRequest { + request := testClient.RestoreBackup(testCtx, testProjectId, testServerId, testBackupId) + startServerAfterRestore := false + request = request.RestoreBackupPayload(serverbackup.RestoreBackupPayload{StartServerAfterRestore: &startServerAfterRestore}) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiRestoreBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/create/create.go b/internal/cmd/beta/server/backup/schedule/create/create.go index b87a4b0e5..5227c4bb0 100644 --- a/internal/cmd/beta/server/backup/schedule/create/create.go +++ b/internal/cmd/beta/server/backup/schedule/create/create.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -31,7 +30,6 @@ const ( defaultRrule = "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1" defaultRetentionPeriod = 14 defaultEnabled = true - defaultVolumeIds = "" ) type inputModel struct { @@ -43,7 +41,7 @@ type inputModel struct { Rrule string BackupName string BackupRetentionPeriod int64 - BackupVolumeIds string + BackupVolumeIds []string } func NewCmd(p *print.Printer) *cobra.Command { @@ -106,7 +104,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64P(backupRetentionPeriodFlag, "d", defaultRetentionPeriod, "Backup retention period (in days)") cmd.Flags().BoolP(enabledFlag, "e", defaultEnabled, "Is the server backup schedule enabled") cmd.Flags().StringP(rruleFlag, "r", defaultRrule, "Backup RRULE (recurrence rule)") - cmd.Flags().StringP(backupVolumeIdsFlag, "i", defaultVolumeIds, "Backup volume ids, as comma separated UUID values.") + cmd.Flags().VarP(flags.UUIDSliceFlag(), backupVolumeIdsFlag, "i", "Backup volume IDs, as comma separated UUID values.") err := flags.MarkFlagsRequired(cmd, serverIdFlag, backupScheduleNameFlag, backupNameFlag) cobra.CheckErr(err) @@ -126,7 +124,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { BackupName: flags.FlagToStringValue(p, cmd, backupNameFlag), Rrule: flags.FlagWithDefaultToStringValue(p, cmd, rruleFlag), Enabled: flags.FlagToBoolValue(p, cmd, enabledFlag), - BackupVolumeIds: flags.FlagToStringValue(p, cmd, backupVolumeIdsFlag), + BackupVolumeIds: flags.FlagToStringSliceValue(p, cmd, backupVolumeIdsFlag), } if p.IsVerbosityDebug() { @@ -146,14 +144,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku backupProperties := serverbackup.BackupProperties{ Name: &model.BackupName, RetentionPeriod: &model.BackupRetentionPeriod, + VolumeIds: &model.BackupVolumeIds, } - if model.BackupVolumeIds == "" { + if model.BackupVolumeIds == nil { backupProperties.VolumeIds = nil - } else { - ids := strings.Split(model.BackupVolumeIds, ",") - backupProperties.VolumeIds = &ids } - req = req.CreateBackupSchedulePayload(serverbackup.CreateBackupSchedulePayload{ Enabled: &model.Enabled, Name: &model.BackupScheduleName, diff --git a/internal/cmd/beta/server/backup/schedule/create/create_test.go b/internal/cmd/beta/server/backup/schedule/create/create_test.go index eb772508c..54307cb30 100644 --- a/internal/cmd/beta/server/backup/schedule/create/create_test.go +++ b/internal/cmd/beta/server/backup/schedule/create/create_test.go @@ -23,6 +23,7 @@ var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() +var testVolumeId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ @@ -33,7 +34,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st rruleFlag: defaultRrule, backupNameFlag: "example-backup-name", backupRetentionPeriodFlag: "14", - backupVolumeIdsFlag: defaultVolumeIds, + backupVolumeIdsFlag: testVolumeId, } for _, mod := range mods { mod(flagValues) @@ -53,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Rrule: defaultRrule, BackupName: "example-backup-name", BackupRetentionPeriod: int64(14), - BackupVolumeIds: defaultVolumeIds, + BackupVolumeIds: []string{testVolumeId}, } for _, mod := range mods { mod(model) @@ -78,7 +79,7 @@ func fixturePayload(mods ...func(payload *serverbackup.CreateBackupSchedulePaylo BackupProperties: &serverbackup.BackupProperties{ Name: utils.Ptr("example-backup-name"), RetentionPeriod: utils.Ptr(int64(14)), - VolumeIds: nil, + VolumeIds: utils.Ptr([]string{testVolumeId}), }, } for _, mod := range mods { diff --git a/internal/cmd/beta/server/backup/schedule/update/update.go b/internal/cmd/beta/server/backup/schedule/update/update.go index 732062d70..0d69981ea 100644 --- a/internal/cmd/beta/server/backup/schedule/update/update.go +++ b/internal/cmd/beta/server/backup/schedule/update/update.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -33,7 +32,6 @@ const ( defaultRrule = "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1" defaultRetentionPeriod = 14 defaultEnabled = true - defaultVolumeIds = "" ) type inputModel struct { @@ -46,7 +44,7 @@ type inputModel struct { Rrule *string BackupName *string BackupRetentionPeriod *int64 - BackupVolumeIds *string + BackupVolumeIds []string } func NewCmd(p *print.Printer) *cobra.Command { @@ -116,7 +114,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64P(backupRetentionPeriodFlag, "d", defaultRetentionPeriod, "Backup retention period (in days)") cmd.Flags().BoolP(enabledFlag, "e", defaultEnabled, "Is the server backup schedule enabled") cmd.Flags().StringP(rruleFlag, "r", defaultRrule, "Backup RRULE (recurrence rule)") - cmd.Flags().StringP(backupVolumeIdsFlag, "i", defaultVolumeIds, "Backup volume ids, as comma separated UUID values.") + cmd.Flags().VarP(flags.UUIDSliceFlag(), backupVolumeIdsFlag, "i", "Backup volume IDs, as comma separated UUID values.") err := flags.MarkFlagsRequired(cmd, serverIdFlag) cobra.CheckErr(err) @@ -139,7 +137,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BackupName: flags.FlagToStringPointer(p, cmd, backupNameFlag), Rrule: flags.FlagToStringPointer(p, cmd, rruleFlag), Enabled: flags.FlagToBoolPointer(p, cmd, enabledFlag), - BackupVolumeIds: flags.FlagToStringPointer(p, cmd, backupVolumeIdsFlag), + BackupVolumeIds: flags.FlagToStringSliceValue(p, cmd, backupVolumeIdsFlag), } if p.IsVerbosityDebug() { @@ -164,12 +162,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku old.BackupProperties.RetentionPeriod = model.BackupRetentionPeriod } if model.BackupVolumeIds != nil { - if *model.BackupVolumeIds == "" { - old.BackupProperties.VolumeIds = nil - } else { - ids := strings.Split(*model.BackupVolumeIds, ",") - old.BackupProperties.VolumeIds = &ids - } + old.BackupProperties.VolumeIds = &model.BackupVolumeIds } if model.Enabled != nil { old.Enabled = model.Enabled diff --git a/internal/cmd/beta/server/backup/schedule/update/update_test.go b/internal/cmd/beta/server/backup/schedule/update/update_test.go index 95ec1fc1a..86a5be4bc 100644 --- a/internal/cmd/beta/server/backup/schedule/update/update_test.go +++ b/internal/cmd/beta/server/backup/schedule/update/update_test.go @@ -23,6 +23,7 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() +var testVolumeId = uuid.NewString() var testBackupScheduleId = "5" func fixtureArgValues(mods ...func(argValues []string)) []string { @@ -44,7 +45,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st rruleFlag: defaultRrule, backupNameFlag: "example-backup-name", backupRetentionPeriodFlag: "14", - backupVolumeIdsFlag: defaultVolumeIds, + backupVolumeIdsFlag: testVolumeId, } for _, mod := range mods { mod(flagValues) @@ -65,7 +66,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Rrule: utils.Ptr(defaultRrule), BackupName: utils.Ptr("example-backup-name"), BackupRetentionPeriod: utils.Ptr(int64(14)), - BackupVolumeIds: utils.Ptr(defaultVolumeIds), + BackupVolumeIds: []string{testVolumeId}, } for _, mod := range mods { mod(model) @@ -83,7 +84,7 @@ func fixtureBackupSchedule(mods ...func(schedule *serverbackup.BackupSchedule)) BackupProperties: &serverbackup.BackupProperties{ Name: utils.Ptr("example-backup-name"), RetentionPeriod: utils.Ptr(int64(14)), - VolumeIds: nil, + VolumeIds: utils.Ptr([]string{testVolumeId}), }, } for _, mod := range mods { @@ -100,7 +101,7 @@ func fixturePayload(mods ...func(payload *serverbackup.UpdateBackupSchedulePaylo BackupProperties: &serverbackup.BackupProperties{ Name: utils.Ptr("example-backup-name"), RetentionPeriod: utils.Ptr(int64(14)), - VolumeIds: nil, + VolumeIds: utils.Ptr([]string{testVolumeId}), }, } for _, mod := range mods { diff --git a/internal/cmd/beta/server/backup/volume-backup/delete/delete.go b/internal/cmd/beta/server/backup/volume-backup/delete/delete.go new file mode 100644 index 000000000..1d996b80a --- /dev/null +++ b/internal/cmd/beta/server/backup/volume-backup/delete/delete.go @@ -0,0 +1,118 @@ +package delete + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + volumeBackupIdArg = "VOLUME_BACKUP_ID" + serverIdFlag = "server-id" + backupIdFlag = "backup-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + BackupId string + VolumeId string + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", volumeBackupIdArg), + Short: "Deletes a Server Volume Backup.", + Long: "Deletes a Server Volume Backup. Operation always is async.", + Args: args.SingleArg(volumeBackupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a Server Volume Backup with ID "xxx" for server "zzz" and backup "bbb"`, + "$ stackit beta server backup volume-backup delete xxx --server-id=zzz --backup-id=bbb"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete server volume backup %q? (This cannot be undone)", model.VolumeId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete Server Volume Backup: %w", err) + } + + p.Info("Triggered deletion of server volume backup %q\n", model.VolumeId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().VarP(flags.UUIDFlag(), backupIdFlag, "b", "Backup ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + VolumeId: volumeId, + BackupId: flags.FlagToStringValue(p, cmd, backupIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDeleteVolumeBackupRequest { + req := apiClient.DeleteVolumeBackup(ctx, model.ProjectId, model.ServerId, model.BackupId, model.VolumeId) + return req +} diff --git a/internal/cmd/beta/server/backup/volume-backup/delete/delete_test.go b/internal/cmd/beta/server/backup/volume-backup/delete/delete_test.go new file mode 100644 index 000000000..d7f647c86 --- /dev/null +++ b/internal/cmd/beta/server/backup/volume-backup/delete/delete_test.go @@ -0,0 +1,212 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + backupIdFlag: testBackupId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + VolumeId: testVolumeId, + BackupId: testBackupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiDeleteVolumeBackupRequest)) serverbackup.ApiDeleteVolumeBackupRequest { + request := testClient.DeleteVolumeBackup(testCtx, testProjectId, testServerId, testBackupId, testVolumeId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiDeleteVolumeBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/volume-backup/restore/restore.go b/internal/cmd/beta/server/backup/volume-backup/restore/restore.go new file mode 100644 index 000000000..110eca832 --- /dev/null +++ b/internal/cmd/beta/server/backup/volume-backup/restore/restore.go @@ -0,0 +1,126 @@ +package restore + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +const ( + volumeBackupIdArg = "VOLUME_BACKUP_ID" + serverIdFlag = "server-id" + backupIdFlag = "backup-id" + restoreVolumeIdFlag = "restore-volume-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + VolumeBackupId string + BackupId string + ServerId string + RestoreVolumeId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("restore %s", volumeBackupIdArg), + Short: "Restore a Server Volume Backup to a volume.", + Long: "Restore a Server Volume Backup to a volume. Operation always is async.", + Args: args.SingleArg(volumeBackupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Restore a Server Volume Backup with ID "xxx" for server "zzz" and backup "bbb" to volume "rrr"`, + "$ stackit beta server backup volume-backup restore xxx --server-id=zzz --backup-id=bbb --restore-volume-id=rrr"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to restore volume backup %q? (This cannot be undone)", model.VolumeBackupId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("restore Server Volume Backup: %w", err) + } + + p.Info("Triggered restoring of server volume backup %q\n", model.VolumeBackupId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().VarP(flags.UUIDFlag(), backupIdFlag, "b", "Backup ID") + cmd.Flags().VarP(flags.UUIDFlag(), restoreVolumeIdFlag, "r", "Restore Volume ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeBackupId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + VolumeBackupId: volumeBackupId, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + BackupId: flags.FlagToStringValue(p, cmd, backupIdFlag), + RestoreVolumeId: flags.FlagToStringValue(p, cmd, restoreVolumeIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiRestoreVolumeBackupRequest { + req := apiClient.RestoreVolumeBackup(ctx, model.ProjectId, model.ServerId, model.BackupId, model.VolumeBackupId) + payload := serverbackup.RestoreVolumeBackupPayload{ + RestoreVolumeId: &model.RestoreVolumeId, + } + req = req.RestoreVolumeBackupPayload(payload) + return req +} diff --git a/internal/cmd/beta/server/backup/volume-backup/restore/restore_test.go b/internal/cmd/beta/server/backup/volume-backup/restore/restore_test.go new file mode 100644 index 000000000..f5ca5b1a1 --- /dev/null +++ b/internal/cmd/beta/server/backup/volume-backup/restore/restore_test.go @@ -0,0 +1,218 @@ +package restore + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverbackup.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testBackupId = uuid.NewString() +var testVolumeBackupId = uuid.NewString() +var testRestoreVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeBackupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + backupIdFlag: testBackupId, + restoreVolumeIdFlag: testRestoreVolumeId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + BackupId: testBackupId, + VolumeBackupId: testVolumeBackupId, + RestoreVolumeId: testRestoreVolumeId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverbackup.ApiRestoreVolumeBackupRequest)) serverbackup.ApiRestoreVolumeBackupRequest { + request := testClient.RestoreVolumeBackup(testCtx, testProjectId, testServerId, testBackupId, testVolumeBackupId) + request = request.RestoreVolumeBackupPayload(serverbackup.RestoreVolumeBackupPayload{ + RestoreVolumeId: &testRestoreVolumeId, + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverbackup.ApiRestoreVolumeBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/volume-backup/volumebackup.go b/internal/cmd/beta/server/backup/volume-backup/volumebackup.go new file mode 100644 index 000000000..17d8840ee --- /dev/null +++ b/internal/cmd/beta/server/backup/volume-backup/volumebackup.go @@ -0,0 +1,28 @@ +package volumebackup + +import ( + del "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/volume-backup/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/volume-backup/restore" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "volume-backup", + Short: "Provides functionality for Server Backup Volume Backups", + Long: "Provides functionality for Server Backup Volume Backups.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(del.NewCmd(p)) + cmd.AddCommand(restore.NewCmd(p)) +} From 26e6b057ec6c1c52ab9ef26405aef3814874eaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Wed, 10 Jul 2024 16:41:25 +0100 Subject: [PATCH 016/619] Implement `sqlserverflex database list/describe` commands (#409) * Update to latest sqlserverflex version and fix breaking changes * Implement database list/describe commands * Improve user create description * Improve error message in database list command --- docs/stackit_beta_sqlserverflex_database.md | 2 + ...it_beta_sqlserverflex_database_describe.md | 43 ++++ ...tackit_beta_sqlserverflex_database_list.md | 47 ++++ .../stackit_beta_sqlserverflex_user_create.md | 8 +- go.mod | 2 +- go.sum | 4 +- .../sqlserverflex/database/create/create.go | 7 +- .../database/create/create_test.go | 7 +- .../beta/sqlserverflex/database/database.go | 4 + .../database/describe/describe.go | 169 +++++++++++++ .../database/describe/describe_test.go | 239 ++++++++++++++++++ .../beta/sqlserverflex/database/list/list.go | 171 +++++++++++++ .../sqlserverflex/database/list/list_test.go | 212 ++++++++++++++++ .../beta/sqlserverflex/user/create/create.go | 22 +- .../sqlserverflex/user/create/create_test.go | 4 +- .../sqlserverflex/user/describe/describe.go | 6 +- .../sqlserverflex/utils/utils_test.go | 2 +- 17 files changed, 917 insertions(+), 32 deletions(-) create mode 100644 docs/stackit_beta_sqlserverflex_database_describe.md create mode 100644 docs/stackit_beta_sqlserverflex_database_list.md create mode 100644 internal/cmd/beta/sqlserverflex/database/describe/describe.go create mode 100644 internal/cmd/beta/sqlserverflex/database/describe/describe_test.go create mode 100644 internal/cmd/beta/sqlserverflex/database/list/list.go create mode 100644 internal/cmd/beta/sqlserverflex/database/list/list_test.go diff --git a/docs/stackit_beta_sqlserverflex_database.md b/docs/stackit_beta_sqlserverflex_database.md index 0ff6409a5..60dc3674a 100644 --- a/docs/stackit_beta_sqlserverflex_database.md +++ b/docs/stackit_beta_sqlserverflex_database.md @@ -31,4 +31,6 @@ stackit beta sqlserverflex database [flags] * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex * [stackit beta sqlserverflex database create](./stackit_beta_sqlserverflex_database_create.md) - Creates a SQLServer Flex database * [stackit beta sqlserverflex database delete](./stackit_beta_sqlserverflex_database_delete.md) - Deletes a SQLServer Flex database +* [stackit beta sqlserverflex database describe](./stackit_beta_sqlserverflex_database_describe.md) - Shows details of an SQLServer Flex database +* [stackit beta sqlserverflex database list](./stackit_beta_sqlserverflex_database_list.md) - Lists all SQLServer Flex databases diff --git a/docs/stackit_beta_sqlserverflex_database_describe.md b/docs/stackit_beta_sqlserverflex_database_describe.md new file mode 100644 index 000000000..97715ae2b --- /dev/null +++ b/docs/stackit_beta_sqlserverflex_database_describe.md @@ -0,0 +1,43 @@ +## stackit beta sqlserverflex database describe + +Shows details of an SQLServer Flex database + +### Synopsis + +Shows details of an SQLServer Flex database. + +``` +stackit beta sqlserverflex database describe DATABASE_NAME [flags] +``` + +### Examples + +``` + Get details of an SQLServer Flex database with name "my-database" of instance with ID "xxx" + $ stackit beta sqlserverflex database describe my-database --instance-id xxx + + Get details of an SQLServer Flex database with name "my-database" of instance with ID "xxx" in JSON format + $ stackit beta sqlserverflex database describe my-database --instance-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta sqlserverflex database describe" + --instance-id string SQLServer Flex instance ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta sqlserverflex database](./stackit_beta_sqlserverflex_database.md) - Provides functionality for SQLServer Flex databases + diff --git a/docs/stackit_beta_sqlserverflex_database_list.md b/docs/stackit_beta_sqlserverflex_database_list.md new file mode 100644 index 000000000..637f262e1 --- /dev/null +++ b/docs/stackit_beta_sqlserverflex_database_list.md @@ -0,0 +1,47 @@ +## stackit beta sqlserverflex database list + +Lists all SQLServer Flex databases + +### Synopsis + +Lists all SQLServer Flex databases. + +``` +stackit beta sqlserverflex database list [flags] +``` + +### Examples + +``` + List all SQLServer Flex databases of instance with ID "xxx" + $ stackit beta sqlserverflex database list --instance-id xxx + + List all SQLServer Flex databases of instance with ID "xxx" in JSON format + $ stackit beta sqlserverflex database list --instance-id xxx --output-format json + + List up to 10 SQLServer Flex databases of instance with ID "xxx" + $ stackit beta sqlserverflex database list --instance-id xxx --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta sqlserverflex database list" + --instance-id string SQLServer Flex instance ID + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta sqlserverflex database](./stackit_beta_sqlserverflex_database.md) - Provides functionality for SQLServer Flex databases + diff --git a/docs/stackit_beta_sqlserverflex_user_create.md b/docs/stackit_beta_sqlserverflex_user_create.md index 910a469ab..4b3a00c46 100644 --- a/docs/stackit_beta_sqlserverflex_user_create.md +++ b/docs/stackit_beta_sqlserverflex_user_create.md @@ -5,11 +5,15 @@ Creates a SQLServer Flex user ### Synopsis Creates a SQLServer Flex user for an instance. + The password is only visible upon creation and cannot be retrieved later. Alternatively, you can reset the password and access the new one by running: $ stackit beta sqlserverflex user reset-password USER_ID --instance-id INSTANCE_ID Please refer to https://docs.stackit.cloud/stackit/en/creating-logins-and-users-in-sqlserver-flex-instances-210862358.html for additional information. +The allowed user roles for your instance can be obtained by running: + $ stackit beta sqlserverflex options --user-roles --instance-id INSTANCE_ID + ``` stackit beta sqlserverflex user create [flags] ``` @@ -18,10 +22,10 @@ stackit beta sqlserverflex user create [flags] ``` Create a SQLServer Flex user for instance with ID "xxx" and specify the username, role and database - $ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles my-role --database my-database + $ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_DatabaseManager##" --database my-database Create a SQLServer Flex user for instance with ID "xxx", specifying multiple roles - $ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "my-role-1,my-role-2" + $ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_LoginManager##,##STACKIT_DatabaseManager##" ``` ### Options diff --git a/go.mod b/go.mod index 32a76562d..f5f9f574f 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.19.0 golang.org/x/oauth2 v0.21.0 diff --git a/go.sum b/go.sum index 7569c2c7a..b316b522d 100644 --- a/go.sum +++ b/go.sum @@ -159,8 +159,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 h1:JB1O0E9 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0/go.mod h1:Ni9RBJvcaXRIrDIuQBpJcuQvCQSj27crQSyc+WM4p0c= github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0 h1:4S3MwNmpMfjzBz9JtKbXvkos7j+7hGeFMf7XsjMLL/g= github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0 h1:aIXxXx6u4+6C02MPb+hdItigeKeen7m+hEEG+Ej9sNs= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0/go.mod h1:fQJOQMfasStZ8J9iGX0vTjyJoQtLqMXJ5Npb03QJk84= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 h1:M6tcXUMNM6XMfHVQeQzB6IjfPdAxnZar3YD+YstRStc= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0/go.mod h1:Qnn+06i21XtagtMQ4cTwOCR3OLnXX+t1n+Vf/HH49Yw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index 4cb15352f..fa3467d2d 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -14,7 +14,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" "github.com/spf13/cobra" @@ -125,9 +124,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl req := apiClient.CreateDatabase(ctx, model.ProjectId, model.InstanceId) payload := sqlserverflex.CreateDatabasePayload{ Name: &model.DatabaseName, - Options: utils.Ptr(map[string]string{ - "owner": model.Owner, - }), + Options: &sqlserverflex.DatabaseDocumentationCreateDatabaseRequestOptions{ + Owner: &model.Owner, + }, } req = req.CreateDatabasePayload(payload) return req diff --git a/internal/cmd/beta/sqlserverflex/database/create/create_test.go b/internal/cmd/beta/sqlserverflex/database/create/create_test.go index fc98c388a..eedda7fa7 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create_test.go @@ -6,7 +6,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" "github.com/google/go-cmp/cmp" @@ -67,9 +66,9 @@ func fixtureRequest(mods ...func(request *sqlserverflex.ApiCreateDatabaseRequest request := testClient.CreateDatabase(testCtx, testProjectId, testInstanceId) payload := sqlserverflex.CreateDatabasePayload{ Name: &testDatabaseName, - Options: utils.Ptr(map[string]string{ - "owner": testOwner, - }), + Options: &sqlserverflex.DatabaseDocumentationCreateDatabaseRequestOptions{ + Owner: &testOwner, + }, } request = request.CreateDatabasePayload(payload) for _, mod := range mods { diff --git a/internal/cmd/beta/sqlserverflex/database/database.go b/internal/cmd/beta/sqlserverflex/database/database.go index 382b646c1..3fbd641ce 100644 --- a/internal/cmd/beta/sqlserverflex/database/database.go +++ b/internal/cmd/beta/sqlserverflex/database/database.go @@ -3,6 +3,8 @@ package database import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/create" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -25,4 +27,6 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(create.NewCmd(p)) cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) } diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go new file mode 100644 index 000000000..21323b958 --- /dev/null +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -0,0 +1,169 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" + + "github.com/spf13/cobra" +) + +const ( + databaseNameArg = "DATABASE_NAME" + + instanceIdFlag = "instance-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + DatabaseName string + InstanceId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", databaseNameArg), + Short: "Shows details of an SQLServer Flex database", + Long: "Shows details of an SQLServer Flex database.", + Args: args.SingleArg(databaseNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details of an SQLServer Flex database with name "my-database" of instance with ID "xxx"`, + "$ stackit beta sqlserverflex database describe my-database --instance-id xxx"), + examples.NewExample( + `Get details of an SQLServer Flex database with name "my-database" of instance with ID "xxx" in JSON format`, + "$ stackit beta sqlserverflex database describe my-database --instance-id xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read SQLServer Flex database: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "SQLServer Flex instance ID") + + err := flags.MarkFlagsRequired(cmd, instanceIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + databaseName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + DatabaseName: databaseName, + InstanceId: flags.FlagToStringValue(p, cmd, instanceIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiGetDatabaseRequest { + req := apiClient.GetDatabase(ctx, model.ProjectId, model.InstanceId, model.DatabaseName) + return req +} + +func outputResult(p *print.Printer, outputFormat string, database *sqlserverflex.GetDatabaseResponse) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(database, "", " ") + if err != nil { + return fmt.Errorf("marshal SQLServer Flex database: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(database, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal SQLServer Flex database: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + database := database.Database + table := tables.NewTable() + table.AddRow("ID", *database.Id) + table.AddSeparator() + table.AddRow("NAME", *database.Name) + table.AddSeparator() + if database.CreateDate != nil { + table.AddRow("CREATE DATE", *database.CreateDate) + table.AddSeparator() + } + if database.Collation != nil { + table.AddRow("COLLATION", *database.Collation) + table.AddSeparator() + } + if database.Options != nil { + if database.Options.CompatibilityLevel != nil { + table.AddRow("COMPATIBILITY LEVEL", *database.Options.CompatibilityLevel) + table.AddSeparator() + } + if database.Options.IsEncrypted != nil { + table.AddRow("IS ENCRYPTED", *database.Options.IsEncrypted) + table.AddSeparator() + } + if database.Options.Owner != nil { + table.AddRow("OWNER", *database.Options.Owner) + table.AddSeparator() + } + if database.Options.UserAccess != nil { + table.AddRow("USER ACCESS", *database.Options.UserAccess) + } + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go new file mode 100644 index 000000000..a48d2e0d8 --- /dev/null +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go @@ -0,0 +1,239 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sqlserverflex.APIClient{} +var testProjectId = uuid.NewString() +var testInstanceId = uuid.NewString() +var testDatabaseName = "my-database" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testDatabaseName, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + DatabaseName: testDatabaseName, + InstanceId: testInstanceId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sqlserverflex.ApiGetDatabaseRequest)) sqlserverflex.ApiGetDatabaseRequest { + request := testClient.GetDatabase(testCtx, testProjectId, testInstanceId, testDatabaseName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "instance id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, instanceIdFlag) + }), + isValid: false, + }, + { + description: "instance id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[instanceIdFlag] = "" + }), + isValid: false, + }, + { + description: "instance id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[instanceIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "database name invalid", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sqlserverflex.ApiGetDatabaseRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go new file mode 100644 index 000000000..7398206f6 --- /dev/null +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -0,0 +1,171 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" + + "github.com/spf13/cobra" +) + +const ( + instanceIdFlag = "instance-id" + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + InstanceId string + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all SQLServer Flex databases", + Long: "Lists all SQLServer Flex databases.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all SQLServer Flex databases of instance with ID "xxx"`, + "$ stackit beta sqlserverflex database list --instance-id xxx"), + examples.NewExample( + `List all SQLServer Flex databases of instance with ID "xxx" in JSON format`, + "$ stackit beta sqlserverflex database list --instance-id xxx --output-format json"), + examples.NewExample( + `List up to 10 SQLServer Flex databases of instance with ID "xxx"`, + "$ stackit beta sqlserverflex database list --instance-id xxx --limit 10"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get SQLServer Flex databases: %w", err) + } + if resp.Databases == nil || len(*resp.Databases) == 0 { + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + p.Info("No databases found for instance %s on project %s\n", model.InstanceId, projectLabel) + return nil + } + databases := *resp.Databases + + // Truncate output + if model.Limit != nil && len(databases) > int(*model.Limit) { + databases = databases[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, databases) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "SQLServer Flex instance ID") + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + + err := flags.MarkFlagsRequired(cmd, instanceIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + InstanceId: flags.FlagToStringValue(p, cmd, instanceIdFlag), + Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiListDatabasesRequest { + req := apiClient.ListDatabases(ctx, model.ProjectId, model.InstanceId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, databases []sqlserverflex.Database) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(databases, "", " ") + if err != nil { + return fmt.Errorf("marshal SQLServer Flex database list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(databases, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal SQLServer Flex database list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME") + for i := range databases { + database := databases[i] + table.AddRow(*database.Id, *database.Name) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/sqlserverflex/database/list/list_test.go b/internal/cmd/beta/sqlserverflex/database/list/list_test.go new file mode 100644 index 000000000..ae2ea8f27 --- /dev/null +++ b/internal/cmd/beta/sqlserverflex/database/list/list_test.go @@ -0,0 +1,212 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sqlserverflex.APIClient{} +var testProjectId = uuid.NewString() +var testInstanceId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, + limitFlag: "10", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + InstanceId: testInstanceId, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sqlserverflex.ApiListDatabasesRequest)) sqlserverflex.ApiListDatabasesRequest { + request := testClient.ListDatabases(testCtx, testProjectId, testInstanceId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "instance id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, instanceIdFlag) + }), + isValid: false, + }, + { + description: "instance id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[instanceIdFlag] = "" + }), + isValid: false, + }, + { + description: "instance id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[instanceIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + configureFlags(cmd) + + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sqlserverflex.ApiListDatabasesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 305845dbd..29b416460 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/goccy/go-yaml" "github.com/spf13/cobra" @@ -36,20 +37,22 @@ func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a SQLServer Flex user", - Long: fmt.Sprintf("%s\n%s\n%s\n%s\n%s", + Long: fmt.Sprintf("%s\n\n%s\n%s\n%s\n%s\n\n%s\n%s", "Creates a SQLServer Flex user for an instance.", "The password is only visible upon creation and cannot be retrieved later.", "Alternatively, you can reset the password and access the new one by running:", " $ stackit beta sqlserverflex user reset-password USER_ID --instance-id INSTANCE_ID", "Please refer to https://docs.stackit.cloud/stackit/en/creating-logins-and-users-in-sqlserver-flex-instances-210862358.html for additional information.", + "The allowed user roles for your instance can be obtained by running:", + " $ stackit beta sqlserverflex options --user-roles --instance-id INSTANCE_ID", ), Example: examples.Build( examples.NewExample( `Create a SQLServer Flex user for instance with ID "xxx" and specify the username, role and database`, - "$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles my-role --database my-database"), + `$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_DatabaseManager##" --database my-database`), examples.NewExample( `Create a SQLServer Flex user for instance with ID "xxx", specifying multiple roles`, - `$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "my-role-1,my-role-2"`), + `$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_LoginManager##,##STACKIT_DatabaseManager##"`), ), Args: args.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { @@ -132,21 +135,14 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiCreateUserRequest { req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId) - var roles []sqlserverflex.Role - if model.Roles != nil { - for _, r := range *model.Roles { - roles = append(roles, sqlserverflex.Role(r)) - } - } - req = req.CreateUserPayload(sqlserverflex.CreateUserPayload{ Username: model.Username, - Roles: &roles, + Roles: model.Roles, }) return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, user *sqlserverflex.User) error { +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, user *sqlserverflex.SingleUser) error { switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") @@ -169,7 +165,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, use p.Outputf("Username: %s\n", *user.Username) p.Outputf("Password: %s\n", *user.Password) if user.Roles != nil && len(*user.Roles) != 0 { - p.Outputf("Roles: %v\n", *user.Roles) + p.Outputf("Roles: [%v]\n", strings.Join(*user.Roles, ", ")) } if user.Host != nil && *user.Host != "" { p.Outputf("Host: %s\n", *user.Host) diff --git a/internal/cmd/beta/sqlserverflex/user/create/create_test.go b/internal/cmd/beta/sqlserverflex/user/create/create_test.go index e0583f9fc..5d5f52ccd 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create_test.go @@ -57,7 +57,7 @@ func fixtureRequest(mods ...func(request *sqlserverflex.ApiCreateUserRequest)) s request := testClient.CreateUser(testCtx, testProjectId, testInstanceId) request = request.CreateUserPayload(sqlserverflex.CreateUserPayload{ Username: utils.Ptr("johndoe"), - Roles: utils.Ptr([]sqlserverflex.Role{"read"}), + Roles: utils.Ptr([]string{"read"}), }) for _, mod := range mods { @@ -204,7 +204,7 @@ func TestBuildRequest(t *testing.T) { model.Username = nil }), expectedRequest: fixtureRequest().CreateUserPayload(sqlserverflex.CreateUserPayload{ - Roles: utils.Ptr([]sqlserverflex.Role{"read"}), + Roles: utils.Ptr([]string{"read"}), }), }, } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index d12b232b6..0f0e28ae5 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -117,7 +117,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, outputFormat string, user sqlserverflex.InstanceResponseUser) error { +func outputResult(p *print.Printer, outputFormat string, user sqlserverflex.UserResponseUser) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") @@ -144,9 +144,9 @@ func outputResult(p *print.Printer, outputFormat string, user sqlserverflex.Inst table.AddSeparator() table.AddRow("ROLES", strings.Join(*user.Roles, "\n")) } - if user.Database != nil && *user.Database != "" { + if user.DefaultDatabase != nil && *user.DefaultDatabase != "" { table.AddSeparator() - table.AddRow("DATABASE", *user.Database) + table.AddRow("DATABASE", *user.DefaultDatabase) } if user.Host != nil && *user.Host != "" { table.AddSeparator() diff --git a/internal/pkg/services/sqlserverflex/utils/utils_test.go b/internal/pkg/services/sqlserverflex/utils/utils_test.go index 8776baf4a..953965121 100644 --- a/internal/pkg/services/sqlserverflex/utils/utils_test.go +++ b/internal/pkg/services/sqlserverflex/utils/utils_test.go @@ -434,7 +434,7 @@ func TestGetUserName(t *testing.T) { { description: "base", getUserResp: &sqlserverflex.GetUserResponse{ - Item: &sqlserverflex.InstanceResponseUser{ + Item: &sqlserverflex.UserResponseUser{ Username: utils.Ptr(testUserName), }, }, From c94a5862afb980acadd2024787248d179a8dfdf5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 11 Jul 2024 18:32:06 +0200 Subject: [PATCH 017/619] fix(deps): update stackit sdk modules (#410) * fix(deps): update stackit sdk modules * Ignore linter errors on deprecated methods (commands are depreacted already) --------- Co-authored-by: Renovate Bot Co-authored-by: test.test@freiheit.com --- go.mod | 14 +++++----- go.sum | 28 +++++++++---------- .../cmd/ske/credentials/describe/describe.go | 2 +- .../ske/credentials/describe/describe_test.go | 2 +- internal/cmd/ske/credentials/rotate/rotate.go | 2 +- .../cmd/ske/credentials/rotate/rotate_test.go | 2 +- internal/cmd/ske/describe/describe.go | 2 +- internal/cmd/ske/describe/describe_test.go | 2 +- internal/cmd/ske/disable/disable.go | 2 +- internal/cmd/ske/disable/disable_test.go | 2 +- internal/cmd/ske/enable/enable.go | 2 +- internal/cmd/ske/enable/enable_test.go | 2 +- 12 files changed, 31 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index f5f9f574f..3a109ac87 100644 --- a/go.mod +++ b/go.mod @@ -19,13 +19,13 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.14.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.19.0 @@ -75,12 +75,12 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/argus v0.11.0 - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.13.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.16.0 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.15.0 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.17.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect diff --git a/go.sum b/go.sum index b316b522d..bcd424cd0 100644 --- a/go.sum +++ b/go.sum @@ -131,24 +131,24 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.13.0 h1:W7tyIIIXgAilHpALRyrW3CrtQ2UAGZBjAG+P4tcK+QQ= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.13.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.16.0 h1:Cz4zQnEax6L3Y9gL7jtETPmiTERB7WNQtIzZ1UWeNNk= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.16.0/go.mod h1:bj9cn1treNSxKTRCEmESwqfENN8vCYn60HUnEA0P83c= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.15.0 h1:eYYyVUTS9Gjovg3z9+r6ctvsm1p1J4fHLa5QJbWHi0A= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.15.0/go.mod h1:kPetkX9hNm9HkRyiKQL/tlgdi8frZdMP8afg0mEvQ9s= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 h1:/GwkGMD7ID5hSjdZs1l/Mj8waceCt7oj3TxHgBfEMDQ= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 h1:S8UZYBu2lHmKCPTR17jZetIal8X7cHO1gVRv101UdPw= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0/go.mod h1:bj9cn1treNSxKTRCEmESwqfENN8vCYn60HUnEA0P83c= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.17.0 h1:+amOO/LW/PfUVU2ptxoB8PuNacawjjX2gGh7bHd45RE= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.17.0/go.mod h1:kPetkX9hNm9HkRyiKQL/tlgdi8frZdMP8afg0mEvQ9s= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 h1:FaJYVfha+atvPfFIf3h3+BFjOjeux9OBHukG1J98kq0= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0/go.mod h1:iFerEzGmkg6R13ldFUyHUWHm0ac9cS4ftTDLhP0k/dU= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 h1:tn1MD1nu+gYEbT3lslRI6BrapKwuvHv5Wi2Zw9uVPPc= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0/go.mod h1:dkVMJI88eJ3Xs0ZV15r4tUpgitUGJXcvrX3RL4Zq2bQ= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.14.0 h1:zkhm0r0OZ5NbHJFrm+7B+h11QL0bNLC53nzXhqCaLWo= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.14.0/go.mod h1:ZecMIf9oYj2DGZqWh93l97WdVaRdLl+tW5Fq3YKGwBM= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 h1:EEjhfIFiC4TsaFKB4mkxz6NFz4InfVs5STmWc+oEjgQ= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0/go.mod h1:ZecMIf9oYj2DGZqWh93l97WdVaRdLl+tW5Fq3YKGwBM= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 h1:05wQYhO37Z4y8xAD+4OTYz6rYu6eJEmwMfCG4tjETEc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0/go.mod h1:SdrqGLCkilL6wl1+jcxmLtks2IocgIg+bsyeyYUIzR4= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.15.0 h1:Q7JxjVwb+9ugAX71AXdbfPL87HHmIIwb9LNahn6H/2o= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.15.0/go.mod h1:eSgnPBknTJh7t+jVKN+xzeAh+Cg1USOlH3QCyfvG20g= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.15.0 h1:/S+LOl94FqGk5Qdi5ehsiSCh6cCPEYJDctNOD0c2dmw= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.15.0/go.mod h1:3LhiTR/DMbKR2HuleTzlFHltR1MT1KD0DeW46X6K2GE= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.17.0 h1:k8GIrOQj+COIgkkHNNXw5ciUzvWU/RjL5XD7t5DTrOM= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.17.0/go.mod h1:eSgnPBknTJh7t+jVKN+xzeAh+Cg1USOlH3QCyfvG20g= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0 h1:jnApmhchW5FYNWss1d2hJzH7O3slBOYa2wEseg5pl3o= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0/go.mod h1:3LhiTR/DMbKR2HuleTzlFHltR1MT1KD0DeW46X6K2GE= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 h1:qCbvGqdG9saRB++UlhXt5ieCCDCITROqL5K2nm38efU= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0/go.mod h1:p16qz/pAW8b1gEhqMpIgJfutRPeDPqQLlbVGyCo3f8o= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 h1:pJBG455kmtbQFpCxcBfBK8wOuEnmsMv3h90LFcdj3q0= @@ -157,8 +157,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 h1:fYCBNvh4t github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0/go.mod h1:ZYI3wj/NnhhWi25ugbdcniwnY/7mF6zN582c5HPe00o= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 h1:JB1O0E9+L50ZaO36uz7azurvUuB5JdX5s2ZXuIdb9t8= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0/go.mod h1:Ni9RBJvcaXRIrDIuQBpJcuQvCQSj27crQSyc+WM4p0c= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0 h1:4S3MwNmpMfjzBz9JtKbXvkos7j+7hGeFMf7XsjMLL/g= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0 h1:gxbOYBpHBLMuzltbOGz7OwRFtjCZ9X56a2apsPP/8uU= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 h1:M6tcXUMNM6XMfHVQeQzB6IjfPdAxnZar3YD+YstRStc= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0/go.mod h1:Qnn+06i21XtagtMQ4cTwOCR3OLnXX+t1n+Vf/HH49Yw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/internal/cmd/ske/credentials/describe/describe.go b/internal/cmd/ske/credentials/describe/describe.go index 692bb9ace..a793628b5 100644 --- a/internal/cmd/ske/credentials/describe/describe.go +++ b/internal/cmd/ske/credentials/describe/describe.go @@ -109,7 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiGetCredentialsRequest { - req := apiClient.GetCredentials(ctx, model.ProjectId, model.ClusterName) + req := apiClient.GetCredentials(ctx, model.ProjectId, model.ClusterName) //nolint:staticcheck //command will be removed in a later update return req } diff --git a/internal/cmd/ske/credentials/describe/describe_test.go b/internal/cmd/ske/credentials/describe/describe_test.go index 809b2eb16..c589ca77b 100644 --- a/internal/cmd/ske/credentials/describe/describe_test.go +++ b/internal/cmd/ske/credentials/describe/describe_test.go @@ -57,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiGetCredentialsRequest)) ske.ApiGetCredentialsRequest { - request := testClient.GetCredentials(testCtx, testProjectId, testClusterName) + request := testClient.GetCredentials(testCtx, testProjectId, testClusterName) //nolint:staticcheck //command will be removed in a later update for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/credentials/rotate/rotate.go b/internal/cmd/ske/credentials/rotate/rotate.go index 5b1969a0a..676c712e2 100644 --- a/internal/cmd/ske/credentials/rotate/rotate.go +++ b/internal/cmd/ske/credentials/rotate/rotate.go @@ -120,6 +120,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerRotateCredentialsRequest { - req := apiClient.TriggerRotateCredentials(ctx, model.ProjectId, model.ClusterName) + req := apiClient.TriggerRotateCredentials(ctx, model.ProjectId, model.ClusterName) //nolint:staticcheck //command will be removed in a later update return req } diff --git a/internal/cmd/ske/credentials/rotate/rotate_test.go b/internal/cmd/ske/credentials/rotate/rotate_test.go index efe1e3709..9156795fb 100644 --- a/internal/cmd/ske/credentials/rotate/rotate_test.go +++ b/internal/cmd/ske/credentials/rotate/rotate_test.go @@ -57,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiTriggerRotateCredentialsRequest)) ske.ApiTriggerRotateCredentialsRequest { - request := testClient.TriggerRotateCredentials(testCtx, testProjectId, testClusterName) + request := testClient.TriggerRotateCredentials(testCtx, testProjectId, testClusterName) //nolint:staticcheck //command will be removed in a later update for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index 433a60cd3..d56850a6b 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -81,7 +81,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiGetServiceStatusRequest { - req := apiClient.GetServiceStatus(ctx, model.ProjectId) + req := apiClient.GetServiceStatus(ctx, model.ProjectId) //nolint:staticcheck //command will be removed in a later update return req } diff --git a/internal/cmd/ske/describe/describe_test.go b/internal/cmd/ske/describe/describe_test.go index aa2efd992..5805585aa 100644 --- a/internal/cmd/ske/describe/describe_test.go +++ b/internal/cmd/ske/describe/describe_test.go @@ -46,7 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiGetServiceStatusRequest)) ske.ApiGetServiceStatusRequest { - request := testClient.GetServiceStatus(testCtx, testProjectId) + request := testClient.GetServiceStatus(testCtx, testProjectId) //nolint:staticcheck //command will be removed in a later update for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index 94d15d9a7..23fe45a02 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -112,6 +112,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiDisableServiceRequest { - req := apiClient.DisableService(ctx, model.ProjectId) + req := apiClient.DisableService(ctx, model.ProjectId) //nolint:staticcheck //command will be removed in a later update return req } diff --git a/internal/cmd/ske/disable/disable_test.go b/internal/cmd/ske/disable/disable_test.go index 01f253e99..b3047fe54 100644 --- a/internal/cmd/ske/disable/disable_test.go +++ b/internal/cmd/ske/disable/disable_test.go @@ -46,7 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiDisableServiceRequest)) ske.ApiDisableServiceRequest { - request := testClient.DisableService(testCtx, testProjectId) + request := testClient.DisableService(testCtx, testProjectId) //nolint:staticcheck //command will be removed in a later update for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index 0a9717ff4..d8dd3e814 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -112,6 +112,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiEnableServiceRequest { - req := apiClient.EnableService(ctx, model.ProjectId) + req := apiClient.EnableService(ctx, model.ProjectId) //nolint:staticcheck //command will be removed in a later update return req } diff --git a/internal/cmd/ske/enable/enable_test.go b/internal/cmd/ske/enable/enable_test.go index faba53553..81103b3ae 100644 --- a/internal/cmd/ske/enable/enable_test.go +++ b/internal/cmd/ske/enable/enable_test.go @@ -46,7 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiEnableServiceRequest)) ske.ApiEnableServiceRequest { - request := testClient.EnableService(testCtx, testProjectId) + request := testClient.EnableService(testCtx, testProjectId) //nolint:staticcheck //command will be removed in a later update for _, mod := range mods { mod(&request) } From eaf32eab8049a9cbeb920add0cbc85a714bdcaf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Tue, 16 Jul 2024 09:19:25 +0100 Subject: [PATCH 018/619] Move SKE enable/disable to the Service Enablement API (#413) * Move SKE enable/disable to the Service Enablement API * move serviceId consts to service-enablement package --- docs/stackit_config_set.md | 43 +++---- docs/stackit_config_unset.md | 51 ++++---- go.mod | 1 + go.sum | 2 + internal/cmd/config/set/set.go | 40 +++--- internal/cmd/config/unset/unset.go | 117 ++++++++++-------- internal/cmd/ske/disable/disable.go | 15 +-- internal/cmd/ske/disable/disable_test.go | 11 +- internal/cmd/ske/enable/enable.go | 15 +-- internal/cmd/ske/enable/enable_test.go | 11 +- internal/pkg/config/config.go | 39 +++--- .../service-enablement/client/client.go | 46 +++++++ .../service-enablement/utils/utils.go | 5 + 13 files changed, 235 insertions(+), 161 deletions(-) create mode 100644 internal/pkg/services/service-enablement/client/client.go create mode 100644 internal/pkg/services/service-enablement/utils/utils.go diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 4d351ea33..469a907ed 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -29,27 +29,28 @@ stackit config set [flags] ### Options ``` - --argus-custom-endpoint string Argus API base URL, used in calls to this API - --authorization-custom-endpoint string Authorization API base URL, used in calls to this API - --dns-custom-endpoint string DNS API base URL, used in calls to this API - -h, --help Help for "stackit config set" - --identity-provider-custom-endpoint string Identity Provider base URL, used for user authentication - --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API - --logme-custom-endpoint string LogMe API base URL, used in calls to this API - --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API - --mongodbflex-custom-endpoint string MongoDB Flex API base URL, used in calls to this API - --object-storage-custom-endpoint string Object Storage API base URL, used in calls to this API - --opensearch-custom-endpoint string OpenSearch API base URL, used in calls to this API - --postgresflex-custom-endpoint string PostgreSQL Flex API base URL, used in calls to this API - --rabbitmq-custom-endpoint string RabbitMQ API base URL, used in calls to this API - --redis-custom-endpoint string Redis API base URL, used in calls to this API - --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API - --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API - --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API - --service-account-custom-endpoint string Service Account API base URL, used in calls to this API - --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) - --ske-custom-endpoint string SKE API base URL, used in calls to this API - --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API + --argus-custom-endpoint string Argus API base URL, used in calls to this API + --authorization-custom-endpoint string Authorization API base URL, used in calls to this API + --dns-custom-endpoint string DNS API base URL, used in calls to this API + -h, --help Help for "stackit config set" + --identity-provider-custom-endpoint string Identity Provider base URL, used for user authentication + --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API + --logme-custom-endpoint string LogMe API base URL, used in calls to this API + --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API + --mongodbflex-custom-endpoint string MongoDB Flex API base URL, used in calls to this API + --object-storage-custom-endpoint string Object Storage API base URL, used in calls to this API + --opensearch-custom-endpoint string OpenSearch API base URL, used in calls to this API + --postgresflex-custom-endpoint string PostgreSQL Flex API base URL, used in calls to this API + --rabbitmq-custom-endpoint string RabbitMQ API base URL, used in calls to this API + --redis-custom-endpoint string Redis API base URL, used in calls to this API + --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API + --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API + --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API + --service-account-custom-endpoint string Service Account API base URL, used in calls to this API + --service-enablement-custom-endpoint string Service Enablement API base URL, used in calls to this API + --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) + --ske-custom-endpoint string SKE API base URL, used in calls to this API + --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API ``` ### Options inherited from parent commands diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 65d3e2cc7..f8c1e7b0c 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -26,31 +26,32 @@ stackit config unset [flags] ### Options ``` - --argus-custom-endpoint Argus API base URL. If unset, uses the default base URL - --async Configuration option to run commands asynchronously - --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL - --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL - -h, --help Help for "stackit config unset" - --identity-provider-custom-endpoint Identity Provider base URL. If unset, uses the default base URL - --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL - --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL - --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL - --mongodbflex-custom-endpoint MongoDB Flex API base URL. If unset, uses the default base URL - --object-storage-custom-endpoint Object Storage API base URL. If unset, uses the default base URL - --opensearch-custom-endpoint OpenSearch API base URL. If unset, uses the default base URL - --output-format Output format - --postgresflex-custom-endpoint PostgreSQL Flex API base URL. If unset, uses the default base URL - --project-id Project ID - --rabbitmq-custom-endpoint RabbitMQ API base URL. If unset, uses the default base URL - --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL - --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL - --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL - --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL - --service-account-custom-endpoint SKE API base URL. If unset, uses the default base URL - --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h - --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL - --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL - --verbosity Verbosity of the CLI + --argus-custom-endpoint Argus API base URL. If unset, uses the default base URL + --async Configuration option to run commands asynchronously + --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL + --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL + -h, --help Help for "stackit config unset" + --identity-provider-custom-endpoint Identity Provider base URL. If unset, uses the default base URL + --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL + --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL + --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL + --mongodbflex-custom-endpoint MongoDB Flex API base URL. If unset, uses the default base URL + --object-storage-custom-endpoint Object Storage API base URL. If unset, uses the default base URL + --opensearch-custom-endpoint OpenSearch API base URL. If unset, uses the default base URL + --output-format Output format + --postgresflex-custom-endpoint PostgreSQL Flex API base URL. If unset, uses the default base URL + --project-id Project ID + --rabbitmq-custom-endpoint RabbitMQ API base URL. If unset, uses the default base URL + --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL + --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL + --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL + --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL + --service-account-custom-endpoint Service Account API base URL. If unset, uses the default base URL + --service-enablement-custom-endpoint Service Enablement API base URL. If unset, uses the default base URL + --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h + --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL + --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL + --verbosity Verbosity of the CLI ``` ### Options inherited from parent commands diff --git a/go.mod b/go.mod index 3a109ac87..2244279de 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 github.com/zalando/go-keyring v0.2.5 diff --git a/go.sum b/go.sum index bcd424cd0..853f88f74 100644 --- a/go.sum +++ b/go.sum @@ -157,6 +157,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 h1:fYCBNvh4t github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0/go.mod h1:ZYI3wj/NnhhWi25ugbdcniwnY/7mF6zN582c5HPe00o= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 h1:JB1O0E9+L50ZaO36uz7azurvUuB5JdX5s2ZXuIdb9t8= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0/go.mod h1:Ni9RBJvcaXRIrDIuQBpJcuQvCQSj27crQSyc+WM4p0c= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 h1:HAEFciLgeCY+kIcGcb+/zFUF3zt3z326v6JCen6fSjs= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0/go.mod h1:z6XdA+ndaWzcPW/P0QrUIcTXJzKlajxgGZ5+EwXNS+c= github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0 h1:gxbOYBpHBLMuzltbOGz7OwRFtjCZ9X56a2apsPP/8uU= github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 h1:M6tcXUMNM6XMfHVQeQzB6IjfPdAxnZar3YD+YstRStc= diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 887ea342b..e62407792 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -20,24 +20,25 @@ const ( sessionTimeLimitFlag = "session-time-limit" identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" - argusCustomEndpointFlag = "argus-custom-endpoint" - authorizationCustomEndpointFlag = "authorization-custom-endpoint" - dnsCustomEndpointFlag = "dns-custom-endpoint" - loadBalancerCustomEndpointFlag = "load-balancer-custom-endpoint" - logMeCustomEndpointFlag = "logme-custom-endpoint" - mariaDBCustomEndpointFlag = "mariadb-custom-endpoint" - mongoDBFlexCustomEndpointFlag = "mongodbflex-custom-endpoint" - objectStorageCustomEndpointFlag = "object-storage-custom-endpoint" - openSearchCustomEndpointFlag = "opensearch-custom-endpoint" - postgresFlexCustomEndpointFlag = "postgresflex-custom-endpoint" - rabbitMQCustomEndpointFlag = "rabbitmq-custom-endpoint" - redisCustomEndpointFlag = "redis-custom-endpoint" - resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" - secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" - serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" - serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" - skeCustomEndpointFlag = "ske-custom-endpoint" - sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" + argusCustomEndpointFlag = "argus-custom-endpoint" + authorizationCustomEndpointFlag = "authorization-custom-endpoint" + dnsCustomEndpointFlag = "dns-custom-endpoint" + loadBalancerCustomEndpointFlag = "load-balancer-custom-endpoint" + logMeCustomEndpointFlag = "logme-custom-endpoint" + mariaDBCustomEndpointFlag = "mariadb-custom-endpoint" + mongoDBFlexCustomEndpointFlag = "mongodbflex-custom-endpoint" + objectStorageCustomEndpointFlag = "object-storage-custom-endpoint" + openSearchCustomEndpointFlag = "opensearch-custom-endpoint" + postgresFlexCustomEndpointFlag = "postgresflex-custom-endpoint" + rabbitMQCustomEndpointFlag = "rabbitmq-custom-endpoint" + redisCustomEndpointFlag = "redis-custom-endpoint" + resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" + secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" + serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" + serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" + serviceEnablementCustomEndpointFlag = "service-enablement-custom-endpoint" + skeCustomEndpointFlag = "ske-custom-endpoint" + sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" ) type inputModel struct { @@ -141,6 +142,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(resourceManagerCustomEndpointFlag, "", "Resource Manager API base URL, used in calls to this API") cmd.Flags().String(secretsManagerCustomEndpointFlag, "", "Secrets Manager API base URL, used in calls to this API") cmd.Flags().String(serviceAccountCustomEndpointFlag, "", "Service Account API base URL, used in calls to this API") + cmd.Flags().String(serviceEnablementCustomEndpointFlag, "", "Service Enablement API base URL, used in calls to this API") cmd.Flags().String(serverBackupCustomEndpointFlag, "", "Server Backup API base URL, used in calls to this API") cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") @@ -182,6 +184,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.ServiceAccountCustomEndpointKey, cmd.Flags().Lookup(serviceAccountCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.ServiceEnablementCustomEndpointKey, cmd.Flags().Lookup(serviceEnablementCustomEndpointFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.SKECustomEndpointKey, cmd.Flags().Lookup(skeCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.SQLServerFlexCustomEndpointKey, cmd.Flags().Lookup(sqlServerFlexCustomEndpointFlag)) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 17128a035..46c541af5 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -23,24 +23,25 @@ const ( sessionTimeLimitFlag = "session-time-limit" identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" - argusCustomEndpointFlag = "argus-custom-endpoint" - authorizationCustomEndpointFlag = "authorization-custom-endpoint" - dnsCustomEndpointFlag = "dns-custom-endpoint" - loadBalancerCustomEndpointFlag = "load-balancer-custom-endpoint" - logMeCustomEndpointFlag = "logme-custom-endpoint" - mariaDBCustomEndpointFlag = "mariadb-custom-endpoint" - mongoDBFlexCustomEndpointFlag = "mongodbflex-custom-endpoint" - objectStorageCustomEndpointFlag = "object-storage-custom-endpoint" - openSearchCustomEndpointFlag = "opensearch-custom-endpoint" - postgresFlexCustomEndpointFlag = "postgresflex-custom-endpoint" - rabbitMQCustomEndpointFlag = "rabbitmq-custom-endpoint" - redisCustomEndpointFlag = "redis-custom-endpoint" - resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" - secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" - serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" - serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" - skeCustomEndpointFlag = "ske-custom-endpoint" - sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" + argusCustomEndpointFlag = "argus-custom-endpoint" + authorizationCustomEndpointFlag = "authorization-custom-endpoint" + dnsCustomEndpointFlag = "dns-custom-endpoint" + loadBalancerCustomEndpointFlag = "load-balancer-custom-endpoint" + logMeCustomEndpointFlag = "logme-custom-endpoint" + mariaDBCustomEndpointFlag = "mariadb-custom-endpoint" + mongoDBFlexCustomEndpointFlag = "mongodbflex-custom-endpoint" + objectStorageCustomEndpointFlag = "object-storage-custom-endpoint" + openSearchCustomEndpointFlag = "opensearch-custom-endpoint" + postgresFlexCustomEndpointFlag = "postgresflex-custom-endpoint" + rabbitMQCustomEndpointFlag = "rabbitmq-custom-endpoint" + redisCustomEndpointFlag = "redis-custom-endpoint" + resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" + secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" + serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" + serviceEnablementCustomEndpointFlag = "service-enablement-custom-endpoint" + serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" + skeCustomEndpointFlag = "ske-custom-endpoint" + sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" ) type inputModel struct { @@ -52,24 +53,25 @@ type inputModel struct { SessionTimeLimit bool IdentityProviderCustomEndpoint bool - ArgusCustomEndpoint bool - AuthorizationCustomEndpoint bool - DNSCustomEndpoint bool - LoadBalancerCustomEndpoint bool - LogMeCustomEndpoint bool - MariaDBCustomEndpoint bool - MongoDBFlexCustomEndpoint bool - ObjectStorageCustomEndpoint bool - OpenSearchCustomEndpoint bool - PostgresFlexCustomEndpoint bool - RabbitMQCustomEndpoint bool - RedisCustomEndpoint bool - ResourceManagerCustomEndpoint bool - SecretsManagerCustomEndpoint bool - ServerBackupCustomEndpoint bool - ServiceAccountCustomEndpoint bool - SKECustomEndpoint bool - SQLServerFlexCustomEndpoint bool + ArgusCustomEndpoint bool + AuthorizationCustomEndpoint bool + DNSCustomEndpoint bool + LoadBalancerCustomEndpoint bool + LogMeCustomEndpoint bool + MariaDBCustomEndpoint bool + MongoDBFlexCustomEndpoint bool + ObjectStorageCustomEndpoint bool + OpenSearchCustomEndpoint bool + PostgresFlexCustomEndpoint bool + RabbitMQCustomEndpoint bool + RedisCustomEndpoint bool + ResourceManagerCustomEndpoint bool + SecretsManagerCustomEndpoint bool + ServerBackupCustomEndpoint bool + ServiceAccountCustomEndpoint bool + ServiceEnablementCustomEndpoint bool + SKECustomEndpoint bool + SQLServerFlexCustomEndpoint bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -157,6 +159,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.ServiceAccountCustomEndpoint { viper.Set(config.ServiceAccountCustomEndpointKey, "") } + if model.ServiceEnablementCustomEndpoint { + viper.Set(config.ServiceEnablementCustomEndpointKey, "") + } if model.ServerBackupCustomEndpoint { viper.Set(config.ServerBackupCustomEndpointKey, "") } @@ -201,7 +206,8 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(redisCustomEndpointFlag, false, "Redis API base URL. If unset, uses the default base URL") cmd.Flags().Bool(resourceManagerCustomEndpointFlag, false, "Resource Manager API base URL. If unset, uses the default base URL") cmd.Flags().Bool(secretsManagerCustomEndpointFlag, false, "Secrets Manager API base URL. If unset, uses the default base URL") - cmd.Flags().Bool(serviceAccountCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(serviceAccountCustomEndpointFlag, false, "Service Account API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(serviceEnablementCustomEndpointFlag, false, "Service Enablement API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serverBackupCustomEndpointFlag, false, "Server Backup base URL. If unset, uses the default base URL") cmd.Flags().Bool(skeCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") @@ -217,24 +223,25 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { SessionTimeLimit: flags.FlagToBoolValue(p, cmd, sessionTimeLimitFlag), IdentityProviderCustomEndpoint: flags.FlagToBoolValue(p, cmd, identityProviderCustomEndpointFlag), - ArgusCustomEndpoint: flags.FlagToBoolValue(p, cmd, argusCustomEndpointFlag), - AuthorizationCustomEndpoint: flags.FlagToBoolValue(p, cmd, authorizationCustomEndpointFlag), - DNSCustomEndpoint: flags.FlagToBoolValue(p, cmd, dnsCustomEndpointFlag), - LoadBalancerCustomEndpoint: flags.FlagToBoolValue(p, cmd, loadBalancerCustomEndpointFlag), - LogMeCustomEndpoint: flags.FlagToBoolValue(p, cmd, logMeCustomEndpointFlag), - MariaDBCustomEndpoint: flags.FlagToBoolValue(p, cmd, mariaDBCustomEndpointFlag), - MongoDBFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, mongoDBFlexCustomEndpointFlag), - ObjectStorageCustomEndpoint: flags.FlagToBoolValue(p, cmd, objectStorageCustomEndpointFlag), - OpenSearchCustomEndpoint: flags.FlagToBoolValue(p, cmd, openSearchCustomEndpointFlag), - PostgresFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, postgresFlexCustomEndpointFlag), - RabbitMQCustomEndpoint: flags.FlagToBoolValue(p, cmd, rabbitMQCustomEndpointFlag), - RedisCustomEndpoint: flags.FlagToBoolValue(p, cmd, redisCustomEndpointFlag), - ResourceManagerCustomEndpoint: flags.FlagToBoolValue(p, cmd, resourceManagerCustomEndpointFlag), - SecretsManagerCustomEndpoint: flags.FlagToBoolValue(p, cmd, secretsManagerCustomEndpointFlag), - ServiceAccountCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceAccountCustomEndpointFlag), - ServerBackupCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverBackupCustomEndpointFlag), - SKECustomEndpoint: flags.FlagToBoolValue(p, cmd, skeCustomEndpointFlag), - SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), + ArgusCustomEndpoint: flags.FlagToBoolValue(p, cmd, argusCustomEndpointFlag), + AuthorizationCustomEndpoint: flags.FlagToBoolValue(p, cmd, authorizationCustomEndpointFlag), + DNSCustomEndpoint: flags.FlagToBoolValue(p, cmd, dnsCustomEndpointFlag), + LoadBalancerCustomEndpoint: flags.FlagToBoolValue(p, cmd, loadBalancerCustomEndpointFlag), + LogMeCustomEndpoint: flags.FlagToBoolValue(p, cmd, logMeCustomEndpointFlag), + MariaDBCustomEndpoint: flags.FlagToBoolValue(p, cmd, mariaDBCustomEndpointFlag), + MongoDBFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, mongoDBFlexCustomEndpointFlag), + ObjectStorageCustomEndpoint: flags.FlagToBoolValue(p, cmd, objectStorageCustomEndpointFlag), + OpenSearchCustomEndpoint: flags.FlagToBoolValue(p, cmd, openSearchCustomEndpointFlag), + PostgresFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, postgresFlexCustomEndpointFlag), + RabbitMQCustomEndpoint: flags.FlagToBoolValue(p, cmd, rabbitMQCustomEndpointFlag), + RedisCustomEndpoint: flags.FlagToBoolValue(p, cmd, redisCustomEndpointFlag), + ResourceManagerCustomEndpoint: flags.FlagToBoolValue(p, cmd, resourceManagerCustomEndpointFlag), + SecretsManagerCustomEndpoint: flags.FlagToBoolValue(p, cmd, secretsManagerCustomEndpointFlag), + ServiceAccountCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceAccountCustomEndpointFlag), + ServiceEnablementCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceEnablementCustomEndpointFlag), + ServerBackupCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverBackupCustomEndpointFlag), + SKECustomEndpoint: flags.FlagToBoolValue(p, cmd, skeCustomEndpointFlag), + SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), } if p.IsVerbosityDebug() { diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index 23fe45a02..1a05ef2ad 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -10,12 +10,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/ske" - "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/wait" ) type inputModel struct { @@ -62,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Call API req := buildRequest(ctx, model, apiClient) - _, err = req.Execute() + err = req.Execute() if err != nil { return fmt.Errorf("disable SKE: %w", err) } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Disabling SKE") - _, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.ProjectId).WaitWithContext(ctx) + _, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SKE disabling: %w", err) } @@ -111,7 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiDisableServiceRequest { - req := apiClient.DisableService(ctx, model.ProjectId) //nolint:staticcheck //command will be removed in a later update +func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiDisableServiceRequest { + req := apiClient.DisableService(ctx, model.ProjectId, utils.SKEServiceId) return req } diff --git a/internal/cmd/ske/disable/disable_test.go b/internal/cmd/ske/disable/disable_test.go index b3047fe54..cc9a528a6 100644 --- a/internal/cmd/ske/disable/disable_test.go +++ b/internal/cmd/ske/disable/disable_test.go @@ -6,12 +6,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -19,7 +20,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &ske.APIClient{} +var testClient = &serviceenablement.APIClient{} var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { @@ -45,8 +46,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *ske.ApiDisableServiceRequest)) ske.ApiDisableServiceRequest { - request := testClient.DisableService(testCtx, testProjectId) //nolint:staticcheck //command will be removed in a later update +func fixtureRequest(mods ...func(request *serviceenablement.ApiDisableServiceRequest)) serviceenablement.ApiDisableServiceRequest { + request := testClient.DisableService(testCtx, testProjectId, utils.SKEServiceId) for _, mod := range mods { mod(&request) } @@ -144,7 +145,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest ske.ApiDisableServiceRequest + expectedRequest serviceenablement.ApiDisableServiceRequest }{ { description: "base", diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index d8dd3e814..ab1afb319 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -10,12 +10,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/ske" - "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/wait" ) type inputModel struct { @@ -62,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Call API req := buildRequest(ctx, model, apiClient) - _, err = req.Execute() + err = req.Execute() if err != nil { return fmt.Errorf("enable SKE: %w", err) } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Enabling SKE") - _, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.ProjectId).WaitWithContext(ctx) + _, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SKE enabling: %w", err) } @@ -111,7 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiEnableServiceRequest { - req := apiClient.EnableService(ctx, model.ProjectId) //nolint:staticcheck //command will be removed in a later update +func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiEnableServiceRequest { + req := apiClient.EnableService(ctx, model.ProjectId, utils.SKEServiceId) return req } diff --git a/internal/cmd/ske/enable/enable_test.go b/internal/cmd/ske/enable/enable_test.go index 81103b3ae..e0f93b8fc 100644 --- a/internal/cmd/ske/enable/enable_test.go +++ b/internal/cmd/ske/enable/enable_test.go @@ -6,12 +6,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -19,7 +20,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &ske.APIClient{} +var testClient = &serviceenablement.APIClient{} var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { @@ -45,8 +46,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *ske.ApiEnableServiceRequest)) ske.ApiEnableServiceRequest { - request := testClient.EnableService(testCtx, testProjectId) //nolint:staticcheck //command will be removed in a later update +func fixtureRequest(mods ...func(request *serviceenablement.ApiEnableServiceRequest)) serviceenablement.ApiEnableServiceRequest { + request := testClient.EnableService(testCtx, testProjectId, utils.SKEServiceId) for _, mod := range mods { mod(&request) } @@ -144,7 +145,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest ske.ApiEnableServiceRequest + expectedRequest serviceenablement.ApiEnableServiceRequest }{ { description: "base", diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 4716fb5db..016b6248a 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -19,24 +19,25 @@ const ( IdentityProviderCustomEndpointKey = "identity_provider_custom_endpoint" - ArgusCustomEndpointKey = "argus_custom_endpoint" - AuthorizationCustomEndpointKey = "authorization_custom_endpoint" - DNSCustomEndpointKey = "dns_custom_endpoint" - LoadBalancerCustomEndpointKey = "load_balancer_custom_endpoint" - LogMeCustomEndpointKey = "logme_custom_endpoint" - MariaDBCustomEndpointKey = "mariadb_custom_endpoint" - MongoDBFlexCustomEndpointKey = "mongodbflex_custom_endpoint" - ObjectStorageCustomEndpointKey = "object_storage_custom_endpoint" - OpenSearchCustomEndpointKey = "opensearch_custom_endpoint" - PostgresFlexCustomEndpointKey = "postgresflex_custom_endpoint" - RabbitMQCustomEndpointKey = "rabbitmq_custom_endpoint" - RedisCustomEndpointKey = "redis_custom_endpoint" - ResourceManagerEndpointKey = "resource_manager_custom_endpoint" - SecretsManagerCustomEndpointKey = "secrets_manager_custom_endpoint" - ServiceAccountCustomEndpointKey = "service_account_custom_endpoint" - ServerBackupCustomEndpointKey = "serverbackup_custom_endpoint" - SKECustomEndpointKey = "ske_custom_endpoint" - SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" + ArgusCustomEndpointKey = "argus_custom_endpoint" + AuthorizationCustomEndpointKey = "authorization_custom_endpoint" + DNSCustomEndpointKey = "dns_custom_endpoint" + LoadBalancerCustomEndpointKey = "load_balancer_custom_endpoint" + LogMeCustomEndpointKey = "logme_custom_endpoint" + MariaDBCustomEndpointKey = "mariadb_custom_endpoint" + MongoDBFlexCustomEndpointKey = "mongodbflex_custom_endpoint" + ObjectStorageCustomEndpointKey = "object_storage_custom_endpoint" + OpenSearchCustomEndpointKey = "opensearch_custom_endpoint" + PostgresFlexCustomEndpointKey = "postgresflex_custom_endpoint" + RabbitMQCustomEndpointKey = "rabbitmq_custom_endpoint" + RedisCustomEndpointKey = "redis_custom_endpoint" + ResourceManagerEndpointKey = "resource_manager_custom_endpoint" + SecretsManagerCustomEndpointKey = "secrets_manager_custom_endpoint" + ServiceAccountCustomEndpointKey = "service_account_custom_endpoint" + ServiceEnablementCustomEndpointKey = "service_enablement_custom_endpoint" + ServerBackupCustomEndpointKey = "serverbackup_custom_endpoint" + SKECustomEndpointKey = "ske_custom_endpoint" + SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" ProjectNameKey = "project_name" DefaultProfileName = "default" @@ -81,6 +82,7 @@ var ConfigKeys = []string{ ResourceManagerEndpointKey, SecretsManagerCustomEndpointKey, ServiceAccountCustomEndpointKey, + ServiceEnablementCustomEndpointKey, ServerBackupCustomEndpointKey, SKECustomEndpointKey, SQLServerFlexCustomEndpointKey, @@ -152,6 +154,7 @@ func setConfigDefaults() { viper.SetDefault(ResourceManagerEndpointKey, "") viper.SetDefault(SecretsManagerCustomEndpointKey, "") viper.SetDefault(ServiceAccountCustomEndpointKey, "") + viper.SetDefault(ServiceEnablementCustomEndpointKey, "") viper.SetDefault(ServerBackupCustomEndpointKey, "") viper.SetDefault(SKECustomEndpointKey, "") viper.SetDefault(SQLServerFlexCustomEndpointKey, "") diff --git a/internal/pkg/services/service-enablement/client/client.go b/internal/pkg/services/service-enablement/client/client.go new file mode 100644 index 000000000..9c260d51b --- /dev/null +++ b/internal/pkg/services/service-enablement/client/client.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" +) + +func ConfigureClient(p *print.Printer) (*serviceenablement.APIClient, error) { + var err error + var apiClient *serviceenablement.APIClient + var cfgOptions []sdkConfig.ConfigurationOption + + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return nil, &errors.AuthError{} + } + cfgOptions = append(cfgOptions, authCfgOption) + + customEndpoint := viper.GetString(config.ServiceEnablementCustomEndpointKey) + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } else { + cfgOptions = append(cfgOptions, sdkConfig.WithRegion("eu01")) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err = serviceenablement.NewAPIClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return nil, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/internal/pkg/services/service-enablement/utils/utils.go b/internal/pkg/services/service-enablement/utils/utils.go new file mode 100644 index 000000000..27952a763 --- /dev/null +++ b/internal/pkg/services/service-enablement/utils/utils.go @@ -0,0 +1,5 @@ +package utils + +const ( + SKEServiceId = "cloud.stackit.ske" +) From f09f4289a047e980205537cdf1a0bfe8009923cf Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 18 Jul 2024 11:03:53 +0200 Subject: [PATCH 019/619] fix(deps): update module github.com/lmittmann/tint to v1.0.5 (#412) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2244279de..7ef9887aa 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jedib0t/go-pretty/v6 v6.5.9 - github.com/lmittmann/tint v1.0.4 + github.com/lmittmann/tint v1.0.5 github.com/mattn/go-colorable v0.1.13 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index 853f88f74..5cc49ab4e 100644 --- a/go.sum +++ b/go.sum @@ -73,8 +73,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lmittmann/tint v1.0.4 h1:LeYihpJ9hyGvE0w+K2okPTGUdVLfng1+nDNVR4vWISc= -github.com/lmittmann/tint v1.0.4/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw= +github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= From 57e701a4e374a4e6e04b13fe1b3deb7503b4130a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 18 Jul 2024 11:04:39 +0200 Subject: [PATCH 020/619] fix(deps): update module github.com/goccy/go-yaml to v1.12.0 (#414) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7ef9887aa..62202607c 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/fatih/color v1.17.0 - github.com/goccy/go-yaml v1.11.3 + github.com/goccy/go-yaml v1.12.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 5cc49ab4e..58d693ad8 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/goccy/go-yaml v1.11.3 h1:B3W9IdWbvrUu2OYQGwvU1nZtvMQJPBKgBUuweJjLj6I= -github.com/goccy/go-yaml v1.11.3/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= +github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= +github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 026497391ef55f8a9a92e93ce9d83ab5d002dfb8 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 19 Jul 2024 08:01:05 +0200 Subject: [PATCH 021/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/ske to v0.19.0 (#417) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 62202607c..99a1161be 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.19.0 diff --git a/go.sum b/go.sum index 58d693ad8..135da9258 100644 --- a/go.sum +++ b/go.sum @@ -159,8 +159,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 h1:JB1O0E9 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0/go.mod h1:Ni9RBJvcaXRIrDIuQBpJcuQvCQSj27crQSyc+WM4p0c= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 h1:HAEFciLgeCY+kIcGcb+/zFUF3zt3z326v6JCen6fSjs= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0/go.mod h1:z6XdA+ndaWzcPW/P0QrUIcTXJzKlajxgGZ5+EwXNS+c= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0 h1:gxbOYBpHBLMuzltbOGz7OwRFtjCZ9X56a2apsPP/8uU= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.18.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 h1:vmkfa26HO1VA40pKPNnYMHkcNMxBEWAdYbX+5LVIo48= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 h1:M6tcXUMNM6XMfHVQeQzB6IjfPdAxnZar3YD+YstRStc= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0/go.mod h1:Qnn+06i21XtagtMQ4cTwOCR3OLnXX+t1n+Vf/HH49Yw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 9bac68084a5ccce50c0f5c64db227c52acb304f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Fri, 19 Jul 2024 11:18:18 +0100 Subject: [PATCH 022/619] Add `stackit auth logout` command (#416) * initial implementation * Improve testing * address PR comments --- internal/cmd/auth/auth.go | 2 + internal/cmd/auth/logout/logout.go | 36 +++ internal/cmd/config/profile/delete/delete.go | 4 +- internal/pkg/auth/storage.go | 102 +++++- internal/pkg/auth/storage_test.go | 319 ++++++++++++++++--- internal/pkg/auth/user_login.go | 8 +- 6 files changed, 409 insertions(+), 62 deletions(-) create mode 100644 internal/cmd/auth/logout/logout.go diff --git a/internal/cmd/auth/auth.go b/internal/cmd/auth/auth.go index 061e5e85e..5513451d0 100644 --- a/internal/cmd/auth/auth.go +++ b/internal/cmd/auth/auth.go @@ -3,6 +3,7 @@ package auth import ( activateserviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/auth/activate-service-account" "github.com/stackitcloud/stackit-cli/internal/cmd/auth/login" + "github.com/stackitcloud/stackit-cli/internal/cmd/auth/logout" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -24,5 +25,6 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(login.NewCmd(p)) + cmd.AddCommand(logout.NewCmd(p)) cmd.AddCommand(activateserviceaccount.NewCmd(p)) } diff --git a/internal/cmd/auth/logout/logout.go b/internal/cmd/auth/logout/logout.go new file mode 100644 index 000000000..454b977af --- /dev/null +++ b/internal/cmd/auth/logout/logout.go @@ -0,0 +1,36 @@ +package logout + +import ( + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "logout", + Short: "Logs the user account out of the STACKIT CLI", + Long: "Logs the user account out of the STACKIT CLI.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Log out of the STACKIT CLI.`, + "$ stackit auth logout"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + err := auth.LogoutUser() + if err != nil { + return fmt.Errorf("log out failed: %w", err) + } + + p.Info("Successfully logged out of the STACKIT CLI.\n") + return nil + }, + } + return cmd +} diff --git a/internal/cmd/config/profile/delete/delete.go b/internal/cmd/config/profile/delete/delete.go index f93a6163f..992750c29 100644 --- a/internal/cmd/config/profile/delete/delete.go +++ b/internal/cmd/config/profile/delete/delete.go @@ -76,9 +76,9 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete profile: %w", err) } - err = auth.DeleteProfileFromKeyring(model.Profile) + err = auth.DeleteProfileAuth(model.Profile) if err != nil { - return fmt.Errorf("delete profile from keyring: %w", err) + return fmt.Errorf("delete profile authentication: %w", err) } p.Info("Successfully deleted profile %q\n", model.Profile) diff --git a/internal/pkg/auth/storage.go b/internal/pkg/auth/storage.go index d44cc1133..a53b5a256 100644 --- a/internal/pkg/auth/storage.go +++ b/internal/pkg/auth/storage.go @@ -62,6 +62,15 @@ var authFieldKeys = []authFieldKey{ authFlowType, } +// All fields that are set when a user logs in +// These fields should match the ones in LoginUser, which is ensured by the tests +var loginAuthFieldKeys = []authFieldKey{ + SESSION_EXPIRES_AT_UNIX, + ACCESS_TOKEN, + REFRESH_TOKEN, + USER_EMAIL, +} + func SetAuthFlow(value AuthFlow) error { return SetAuthField(authFlowType, string(value)) } @@ -105,6 +114,65 @@ func setAuthFieldInKeyring(activeProfile string, key authFieldKey, value string) return keyring.Set(keyringService, string(key), value) } +func DeleteAuthField(key authFieldKey) error { + activeProfile, err := config.GetProfile() + if err != nil { + return fmt.Errorf("get profile: %w", err) + } + return deleteAuthFieldWithProfile(activeProfile, key) +} + +func deleteAuthFieldWithProfile(profile string, key authFieldKey) error { + err := deleteAuthFieldInKeyring(profile, key) + if err != nil { + // if the key is not found, we can ignore the error + if !errors.Is(err, keyring.ErrNotFound) { + errFallback := deleteAuthFieldInEncodedTextFile(profile, key) + if errFallback != nil { + return fmt.Errorf("delete from keyring failed (%w), try deleting from encoded text file: %w", err, errFallback) + } + } + } + return nil +} + +func deleteAuthFieldInEncodedTextFile(activeProfile string, key authFieldKey) error { + err := createEncodedTextFile(activeProfile) + if err != nil { + return err + } + + textFileDir := config.GetProfileFolderPath(activeProfile) + textFilePath := filepath.Join(textFileDir, textFileName) + + contentEncoded, err := os.ReadFile(textFilePath) + if err != nil { + return fmt.Errorf("read file: %w", err) + } + contentBytes, err := base64.StdEncoding.DecodeString(string(contentEncoded)) + if err != nil { + return fmt.Errorf("decode file: %w", err) + } + content := map[authFieldKey]string{} + err = json.Unmarshal(contentBytes, &content) + if err != nil { + return fmt.Errorf("unmarshal file: %w", err) + } + + delete(content, key) + + contentBytes, err = json.Marshal(content) + if err != nil { + return fmt.Errorf("marshal file: %w", err) + } + contentEncoded = []byte(base64.StdEncoding.EncodeToString(contentBytes)) + err = os.WriteFile(textFilePath, contentEncoded, 0o600) + if err != nil { + return fmt.Errorf("write file: %w", err) + } + return nil +} + func deleteAuthFieldInKeyring(activeProfile string, key authFieldKey) error { keyringServiceLocal := keyringService if activeProfile != config.DefaultProfileName { @@ -273,7 +341,32 @@ func GetProfileEmail(profile string) string { return email } -func DeleteProfileFromKeyring(profile string) error { +func LoginUser(email, accessToken, refreshToken, sessionExpiresAtUnix string) error { + authFields := map[authFieldKey]string{ + SESSION_EXPIRES_AT_UNIX: sessionExpiresAtUnix, + ACCESS_TOKEN: accessToken, + REFRESH_TOKEN: refreshToken, + USER_EMAIL: email, + } + + err := SetAuthFieldMap(authFields) + if err != nil { + return fmt.Errorf("set auth fields: %w", err) + } + return nil +} + +func LogoutUser() error { + for _, key := range loginAuthFieldKeys { + err := DeleteAuthField(key) + if err != nil { + return fmt.Errorf("delete auth field \"%s\": %w", key, err) + } + } + return nil +} + +func DeleteProfileAuth(profile string) error { err := config.ValidateProfile(profile) if err != nil { return fmt.Errorf("validate profile: %w", err) @@ -284,12 +377,9 @@ func DeleteProfileFromKeyring(profile string) error { } for _, key := range authFieldKeys { - err := deleteAuthFieldInKeyring(profile, key) + err := deleteAuthFieldWithProfile(profile, key) if err != nil { - // if the key is not found, we can ignore the error - if !errors.Is(err, keyring.ErrNotFound) { - return fmt.Errorf("delete auth field \"%s\" from keyring: %w", key, err) - } + return fmt.Errorf("delete auth field \"%s\": %w", key, err) } } diff --git a/internal/pkg/auth/storage_test.go b/internal/pkg/auth/storage_test.go index 1591a024f..37eeee33e 100644 --- a/internal/pkg/auth/storage_test.go +++ b/internal/pkg/auth/storage_test.go @@ -1,17 +1,13 @@ package auth import ( - "encoding/base64" - "encoding/json" "fmt" "os" - "path/filepath" "testing" "time" - "github.com/zalando/go-keyring" - "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/zalando/go-keyring" ) func TestSetGetAuthField(t *testing.T) { @@ -317,7 +313,7 @@ func TestSetGetAuthFieldWithProfile(t *testing.T) { } } - err = deleteAuthFieldProfile(tt.activeProfile) + err = deleteProfileFiles(tt.activeProfile) if err != nil { t.Errorf("Post-test cleanup failed: remove profile \"%s\": %v. Please remove it manually", tt.activeProfile, err) } @@ -468,6 +464,156 @@ func TestSetGetAuthFieldKeyring(t *testing.T) { } } +func TestDeleteAuthField(t *testing.T) { + tests := []struct { + description string + keyringFails bool + key authFieldKey + noKey bool + }{ + { + description: "base", + key: "test-field-1", + }, + { + description: "key doesnt exist", + key: "doesnt-exist", + noKey: true, + }, + { + description: "keyring fails", + keyringFails: true, + key: "test-field-1", + }, + { + description: "keyring fails, no key exists", + keyringFails: true, + noKey: true, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + if !tt.keyringFails { + keyring.MockInit() + } else { + keyring.MockInitWithError(fmt.Errorf("keyring unavailable for testing")) + } + + // Append random string to auth field key and value to avoid conflicts + testField1 := authFieldKey(fmt.Sprintf("test-field-1-%s", time.Now().Format(time.RFC3339))) + testValue1 := fmt.Sprintf("value-1-%s", time.Now().Format(time.RFC3339)) + + if !tt.noKey { + err := SetAuthField(testField1, testValue1) + if err != nil { + t.Fatalf("Failed to set \"%s\" as \"%s\": %v", testField1, testValue1, err) + } + } + + err := DeleteAuthField(tt.key) + if err != nil { + t.Fatalf("Failed to delete field \"%s\": %v", tt.key, err) + } + + // Check if key still exists + _, err = GetAuthField(tt.key) + if err == nil { + t.Fatalf("Key \"%s\" still exists after deletion", tt.key) + } + }) + } +} + +func TestDeleteAuthFieldWithProfile(t *testing.T) { + tests := []struct { + description string + keyringFails bool + profile string + key authFieldKey + noKey bool + }{ + { + description: "base", + profile: "default", + key: "test-field-1", + }, + { + description: "key doesnt exist", + profile: "default", + key: "doesnt-exist", + noKey: true, + }, + { + description: "keyring fails", + profile: "default", + keyringFails: true, + key: "test-field-1", + }, + { + description: "keyring fails, no key exists", + profile: "default", + keyringFails: true, + noKey: true, + }, + { + description: "base, custom profile", + profile: "test-profile", + key: "test-field-1", + }, + { + description: "key doesnt exist, custom profile", + profile: "test-profile", + key: "doesnt-exist", + noKey: true, + }, + { + description: "keyring fails, custom profile", + profile: "test-profile", + keyringFails: true, + key: "test-field-1", + }, + { + description: "keyring fails, no key exists, custom profile", + profile: "test-profile", + keyringFails: true, + noKey: true, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + if !tt.keyringFails { + keyring.MockInit() + } else { + keyring.MockInitWithError(fmt.Errorf("keyring unavailable for testing")) + } + + // Append random string to auth field key and value to avoid conflicts + testField1 := authFieldKey(fmt.Sprintf("test-field-1-%s", time.Now().Format(time.RFC3339))) + testValue1 := fmt.Sprintf("value-1-%s", time.Now().Format(time.RFC3339)) + + if !tt.noKey { + err := SetAuthField(testField1, testValue1) + if err != nil { + t.Fatalf("Failed to set \"%s\" as \"%s\": %v", testField1, testValue1, err) + } + } + + err := deleteAuthFieldWithProfile(tt.profile, tt.key) + if err != nil { + t.Fatalf("Failed to delete field \"%s\": %v", tt.key, err) + } + + // Check if key still exists + _, err = GetAuthField(tt.key) + if err == nil { + t.Fatalf("Key \"%s\" still exists after deletion", tt.key) + } + }) + } +} + func TestDeleteAuthFieldKeyring(t *testing.T) { tests := []struct { description string @@ -606,7 +752,7 @@ func TestDeleteProfileFromKeyring(t *testing.T) { } } - err := DeleteProfileFromKeyring(tt.activeProfile) + err := DeleteProfileAuth(tt.activeProfile) if err != nil { if tt.isValid { t.Fatalf("Failed to delete profile \"%s\" from keyring: %v", tt.activeProfile, err) @@ -767,7 +913,7 @@ func TestSetGetAuthFieldEncodedTextFile(t *testing.T) { } } - err = deleteAuthFieldProfile(tt.activeProfile) + err = deleteProfileFiles(tt.activeProfile) if err != nil { t.Errorf("Post-test cleanup failed: remove profile \"%s\": %v. Please remove it manually", tt.activeProfile, err) } @@ -925,7 +1071,7 @@ func TestGetProfileEmail(t *testing.T) { t.Fatalf("Failed to remove service account email: %v", err) } - err = deleteAuthFieldProfile(tt.activeProfile) + err = deleteProfileFiles(tt.activeProfile) if err != nil { t.Fatalf("Failed to remove profile: %v", err) } @@ -933,44 +1079,7 @@ func TestGetProfileEmail(t *testing.T) { } } -func deleteAuthFieldInEncodedTextFile(activeProfile string, key authFieldKey) error { - err := createEncodedTextFile(activeProfile) - if err != nil { - return err - } - - textFileDir := config.GetProfileFolderPath(activeProfile) - textFilePath := filepath.Join(textFileDir, textFileName) - - contentEncoded, err := os.ReadFile(textFilePath) - if err != nil { - return fmt.Errorf("read file: %w", err) - } - contentBytes, err := base64.StdEncoding.DecodeString(string(contentEncoded)) - if err != nil { - return fmt.Errorf("decode file: %w", err) - } - content := map[authFieldKey]string{} - err = json.Unmarshal(contentBytes, &content) - if err != nil { - return fmt.Errorf("unmarshal file: %w", err) - } - - delete(content, key) - - contentBytes, err = json.Marshal(content) - if err != nil { - return fmt.Errorf("marshal file: %w", err) - } - contentEncoded = []byte(base64.StdEncoding.EncodeToString(contentBytes)) - err = os.WriteFile(textFilePath, contentEncoded, 0o600) - if err != nil { - return fmt.Errorf("write file: %w", err) - } - return nil -} - -func deleteAuthFieldProfile(activeProfile string) error { +func deleteProfileFiles(activeProfile string) error { if activeProfile == config.DefaultProfileName { // Do not delete the default profile return nil @@ -990,3 +1099,119 @@ func makeProfileNameUnique(profile string) string { } return fmt.Sprintf("%s-%s", profile, time.Now().Format("20060102150405")) } + +func TestAuthorizeDeauthorizeUserProfileAuth(t *testing.T) { + type args struct { + sessionExpiresAtUnix string + accessToken string + refreshToken string + email string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "base", + args: args{ + sessionExpiresAtUnix: "1234567890", + accessToken: "accessToken", + refreshToken: "refreshToken", + email: "test@example.com", + }, + wantErr: false, + }, + { + name: "no email", + args: args{ + sessionExpiresAtUnix: "1234567890", + accessToken: "accessToken", + refreshToken: "refreshToken", + email: "", + }, + wantErr: false, + }, + { + name: "no session expires", + args: args{ + sessionExpiresAtUnix: "", + accessToken: "accessToken", + refreshToken: "refreshToken", + email: "test@example.com", + }, + wantErr: false, + }, + { + name: "no access token", + args: args{ + sessionExpiresAtUnix: "1234567890", + accessToken: "", + refreshToken: "refreshToken", + email: "test@example.com", + }, + wantErr: false, + }, + { + name: "no refresh token", + args: args{ + sessionExpiresAtUnix: "1234567890", + accessToken: "accessToken", + refreshToken: "", + email: "test@example.com", + }, + wantErr: false, + }, + { + name: "all empty args", + args: args{ + sessionExpiresAtUnix: "", + accessToken: "", + refreshToken: "", + email: "", + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + keyring.MockInit() + + if err := LoginUser(tt.args.email, tt.args.accessToken, tt.args.refreshToken, tt.args.sessionExpiresAtUnix); (err != nil) != tt.wantErr { + t.Errorf("AuthorizeUserProfileAuth() error = %v, wantErr %v", err, tt.wantErr) + } + + // Test values + testLoginAuthFields := []string{ + tt.args.sessionExpiresAtUnix, + tt.args.accessToken, + tt.args.refreshToken, + tt.args.email, + } + + // Check if the fields are set + for i := range loginAuthFieldKeys { + gotKey, err := GetAuthField(loginAuthFieldKeys[i]) + if err != nil { + t.Errorf("Field \"%s\" not set after authorization", loginAuthFieldKeys[i]) + } + expectedKey := testLoginAuthFields[i] + if gotKey != expectedKey { + t.Errorf("Field \"%s\" is wrong: expected \"%s\", got \"%s\"", loginAuthFieldKeys[i], expectedKey, gotKey) + } + } + + if err := LogoutUser(); err != nil { + t.Errorf("DeauthorizeUserProfileAuth() error = %v", err) + } + + // Check if the fields are deleted + for _, key := range loginAuthFieldKeys { + _, err := GetAuthField(key) + if err == nil { + t.Errorf("Field \"%s\" still exists after deauthorization", key) + } + } + }) + } +} diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index 41f850457..ad519f628 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -167,13 +167,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { p.Debug(print.DebugLevel, "user %s logged in successfully", email) - authFields := map[authFieldKey]string{ - SESSION_EXPIRES_AT_UNIX: sessionExpiresAtUnix, - ACCESS_TOKEN: accessToken, - REFRESH_TOKEN: refreshToken, - USER_EMAIL: email, - } - err = SetAuthFieldMap(authFields) + err = LoginUser(email, accessToken, refreshToken, sessionExpiresAtUnix) if err != nil { errServer = fmt.Errorf("set in auth storage: %w", err) return From 455fd95d118d26f7c4854da888cbad7d558388d6 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Mon, 22 Jul 2024 09:44:45 +0200 Subject: [PATCH 023/619] add log out docs (#418) --- docs/stackit_auth.md | 1 + docs/stackit_auth_logout.md | 39 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 docs/stackit_auth_logout.md diff --git a/docs/stackit_auth.md b/docs/stackit_auth.md index 9cf637bb9..9561fb5ae 100644 --- a/docs/stackit_auth.md +++ b/docs/stackit_auth.md @@ -31,4 +31,5 @@ stackit auth [flags] * [stackit](./stackit.md) - Manage STACKIT resources using the command line * [stackit auth activate-service-account](./stackit_auth_activate-service-account.md) - Authenticates using a service account * [stackit auth login](./stackit_auth_login.md) - Logs in to the STACKIT CLI +* [stackit auth logout](./stackit_auth_logout.md) - Logs the user account out of the STACKIT CLI diff --git a/docs/stackit_auth_logout.md b/docs/stackit_auth_logout.md new file mode 100644 index 000000000..8e9cdf8f1 --- /dev/null +++ b/docs/stackit_auth_logout.md @@ -0,0 +1,39 @@ +## stackit auth logout + +Logs the user account out of the STACKIT CLI + +### Synopsis + +Logs the user account out of the STACKIT CLI. + +``` +stackit auth logout [flags] +``` + +### Examples + +``` + Log out of the STACKIT CLI. + $ stackit auth logout +``` + +### Options + +``` + -h, --help Help for "stackit auth logout" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit auth](./stackit_auth.md) - Authenticates the STACKIT CLI + From 37584fcff83625f066c36d73a8a3a2e2d47db7ea Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 22 Jul 2024 16:07:04 +0200 Subject: [PATCH 024/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex to v0.4.0 (#420) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex to v0.4.0 * apply breaking sdk changes --------- Co-authored-by: Renovate Bot Co-authored-by: Gökçe Gök Klingel --- go.mod | 2 +- go.sum | 4 ++-- .../sqlserverflex/database/describe/describe.go | 16 ++-------------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 99a1161be..19637df59 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.4.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.19.0 golang.org/x/oauth2 v0.21.0 diff --git a/go.sum b/go.sum index 135da9258..95b906dad 100644 --- a/go.sum +++ b/go.sum @@ -161,8 +161,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 h1:HAEF github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0/go.mod h1:z6XdA+ndaWzcPW/P0QrUIcTXJzKlajxgGZ5+EwXNS+c= github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 h1:vmkfa26HO1VA40pKPNnYMHkcNMxBEWAdYbX+5LVIo48= github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0 h1:M6tcXUMNM6XMfHVQeQzB6IjfPdAxnZar3YD+YstRStc= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.3.0/go.mod h1:Qnn+06i21XtagtMQ4cTwOCR3OLnXX+t1n+Vf/HH49Yw= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.4.0 h1:Ly8dDjjggO7udf5kyyQU6Lm6UPoWzJVJONYeaIDkFVM= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.4.0/go.mod h1:Qnn+06i21XtagtMQ4cTwOCR3OLnXX+t1n+Vf/HH49Yw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index 21323b958..26f5babc4 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -134,29 +134,17 @@ func outputResult(p *print.Printer, outputFormat string, database *sqlserverflex table.AddSeparator() table.AddRow("NAME", *database.Name) table.AddSeparator() - if database.CreateDate != nil { - table.AddRow("CREATE DATE", *database.CreateDate) - table.AddSeparator() - } - if database.Collation != nil { - table.AddRow("COLLATION", *database.Collation) - table.AddSeparator() - } if database.Options != nil { if database.Options.CompatibilityLevel != nil { table.AddRow("COMPATIBILITY LEVEL", *database.Options.CompatibilityLevel) table.AddSeparator() } - if database.Options.IsEncrypted != nil { - table.AddRow("IS ENCRYPTED", *database.Options.IsEncrypted) - table.AddSeparator() - } if database.Options.Owner != nil { table.AddRow("OWNER", *database.Options.Owner) table.AddSeparator() } - if database.Options.UserAccess != nil { - table.AddRow("USER ACCESS", *database.Options.UserAccess) + if database.Options.CollationName != nil { + table.AddRow("COLLATION", *database.Options.CollationName) } } err := table.Display(p) From 76606adf96336ebfac6f66274c3f06972474d5cf Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Mon, 22 Jul 2024 16:34:48 +0200 Subject: [PATCH 025/619] Onboard dns zone clone command (#419) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * onboard dns zone clone command * Update examples Co-authored-by: Diogo Ferrão --------- Co-authored-by: Diogo Ferrão --- docs/stackit_dns_zone.md | 1 + docs/stackit_dns_zone_clone.md | 49 ++++ internal/cmd/dns/zone/clone/clone.go | 188 +++++++++++++++ internal/cmd/dns/zone/clone/clone_test.go | 267 ++++++++++++++++++++++ internal/cmd/dns/zone/zone.go | 2 + 5 files changed, 507 insertions(+) create mode 100644 docs/stackit_dns_zone_clone.md create mode 100644 internal/cmd/dns/zone/clone/clone.go create mode 100644 internal/cmd/dns/zone/clone/clone_test.go diff --git a/docs/stackit_dns_zone.md b/docs/stackit_dns_zone.md index cd1bef180..bc46f8a62 100644 --- a/docs/stackit_dns_zone.md +++ b/docs/stackit_dns_zone.md @@ -29,6 +29,7 @@ stackit dns zone [flags] ### SEE ALSO * [stackit dns](./stackit_dns.md) - Provides functionality for DNS +* [stackit dns zone clone](./stackit_dns_zone_clone.md) - Clones a DNS zone * [stackit dns zone create](./stackit_dns_zone_create.md) - Creates a DNS zone * [stackit dns zone delete](./stackit_dns_zone_delete.md) - Deletes a DNS zone * [stackit dns zone describe](./stackit_dns_zone_describe.md) - Shows details of a DNS zone diff --git a/docs/stackit_dns_zone_clone.md b/docs/stackit_dns_zone_clone.md new file mode 100644 index 000000000..b63d3dbaa --- /dev/null +++ b/docs/stackit_dns_zone_clone.md @@ -0,0 +1,49 @@ +## stackit dns zone clone + +Clones a DNS zone + +### Synopsis + +Clones an existing DNS zone with all record sets to a new zone with a different name. + +``` +stackit dns zone clone [flags] +``` + +### Examples + +``` + Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" + $ stackit dns zone clone xxx --dns-name www.my-zone.com + + Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" and adjust records "true" + $ stackit dns zone clone xxx --dns-name www.my-zone.com --adjust-records + + Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" and display name "new-zone" + $ stackit dns zone clone xxx --dns-name www.my-zone.com --name new-zone +``` + +### Options + +``` + --adjust-records Sets content and replaces the DNS name of the original zone with the new DNS name of the cloned zone + --description string New description for the cloned zone + --dns-name string Fully qualified domain name of the new DNS zone to clone + -h, --help Help for "stackit dns zone clone" + --name string User given new name for the cloned zone +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit dns zone](./stackit_dns_zone.md) - Provides functionality for DNS zones + diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go new file mode 100644 index 000000000..85afbdfa8 --- /dev/null +++ b/internal/cmd/dns/zone/clone/clone.go @@ -0,0 +1,188 @@ +package clone + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/dns/client" + dnsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/dns/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/dns" + "github.com/stackitcloud/stackit-sdk-go/services/dns/wait" +) + +const ( + nameFlag = "name" + dnsNameFlag = "dns-name" + descriptionFlag = "description" + adjustRecordsFlag = "adjust-records" + zoneIdArg = "ZONE_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name *string + DnsName *string + Description *string + AdjustRecords *bool + ZoneId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "clone", + Short: "Clones a DNS zone", + Long: "Clones an existing DNS zone with all record sets to a new zone with a different name.", + Args: args.SingleArg(zoneIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com"`, + "$ stackit dns zone clone xxx --dns-name www.my-zone.com"), + examples.NewExample( + `Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" and display name "new-zone"`, + "$ stackit dns zone clone xxx --dns-name www.my-zone.com --name new-zone"), + examples.NewExample( + `Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" and adjust records "true"`, + "$ stackit dns zone clone xxx --dns-name www.my-zone.com --adjust-records"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) + if err != nil { + p.Debug(print.ErrorLevel, "get zone name: %v", err) + zoneLabel = model.ZoneId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to clone the zone %s?", zoneLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("clone DNS zone: %w", err) + } + zoneId := *resp.Zone.Id + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Cloning zone") + _, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for DNS zone cloning: %w", err) + } + s.Stop() + } + + return outputResult(p, model, zoneLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "User given new name for the cloned zone") + cmd.Flags().String(dnsNameFlag, "", "Fully qualified domain name of the new DNS zone to clone") + cmd.Flags().String(descriptionFlag, "", "New description for the cloned zone") + cmd.Flags().Bool(adjustRecordsFlag, false, "Sets content and replaces the DNS name of the original zone with the new DNS name of the cloned zone") + + err := flags.MarkFlagsRequired(cmd, dnsNameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + zoneId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + DnsName: flags.FlagToStringPointer(p, cmd, dnsNameFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + AdjustRecords: flags.FlagToBoolPointer(p, cmd, adjustRecordsFlag), + ZoneId: zoneId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClient) dns.ApiCloneZoneRequest { + req := apiClient.CloneZone(ctx, model.ProjectId, model.ZoneId) + req = req.CloneZonePayload(dns.CloneZonePayload{ + Name: model.Name, + DnsName: model.DnsName, + Description: model.Description, + AdjustRecords: model.AdjustRecords, + }) + 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 + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal DNS zone: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Cloned" + if model.Async { + operationState = "Triggered cloning of" + } + p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, *resp.Zone.Id) + return nil + } +} diff --git a/internal/cmd/dns/zone/clone/clone_test.go b/internal/cmd/dns/zone/clone/clone_test.go new file mode 100644 index 000000000..e450aae2b --- /dev/null +++ b/internal/cmd/dns/zone/clone/clone_test.go @@ -0,0 +1,267 @@ +package clone + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/dns" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &dns.APIClient{} +var testProjectId = uuid.NewString() +var testZoneId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testZoneId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + nameFlag: "example", + dnsNameFlag: "example.com", + descriptionFlag: "Example", + adjustRecordsFlag: "false", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example"), + DnsName: utils.Ptr("example.com"), + Description: utils.Ptr("Example"), + AdjustRecords: utils.Ptr(false), + ZoneId: testZoneId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *dns.ApiCloneZoneRequest)) dns.ApiCloneZoneRequest { + request := testClient.CloneZone(testCtx, testProjectId, testZoneId) + request = request.CloneZonePayload(dns.CloneZonePayload{ + Name: utils.Ptr("example"), + DnsName: utils.Ptr("example.com"), + Description: utils.Ptr("Example"), + AdjustRecords: utils.Ptr(false), + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "required fields only", + argValues: []string{testZoneId}, + flagValues: map[string]string{ + projectIdFlag: testProjectId, + dnsNameFlag: "example.com", + }, + isValid: true, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + DnsName: utils.Ptr("example.com"), + ZoneId: testZoneId, + }, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "zone id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "zone id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + isValid bool + expectedRequest dns.ApiCloneZoneRequest + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + expectedRequest: fixtureRequest(), + }, + { + description: "required fields only", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + DnsName: utils.Ptr("example.com"), + ZoneId: testZoneId, + }, + expectedRequest: testClient.CloneZone(testCtx, testProjectId, testZoneId). + CloneZonePayload(dns.CloneZonePayload{ + DnsName: utils.Ptr("example.com"), + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/dns/zone/zone.go b/internal/cmd/dns/zone/zone.go index c3578401f..77247e3c4 100644 --- a/internal/cmd/dns/zone/zone.go +++ b/internal/cmd/dns/zone/zone.go @@ -1,6 +1,7 @@ package zone import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/clone" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/create" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/describe" @@ -31,4 +32,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(describe.NewCmd(p)) cmd.AddCommand(update.NewCmd(p)) cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(clone.NewCmd(p)) } From a71a1b656b1fa19b894eb7a8ba1f23807bb2faac Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:24:32 +0200 Subject: [PATCH 026/619] Format prompt test for dns zone commands (#423) * add quotes around zone name * update docs --- docs/stackit_dns_zone_clone.md | 6 +++--- internal/cmd/dns/zone/clone/clone.go | 2 +- internal/cmd/dns/zone/delete/delete.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/stackit_dns_zone_clone.md b/docs/stackit_dns_zone_clone.md index b63d3dbaa..db3d15ef4 100644 --- a/docs/stackit_dns_zone_clone.md +++ b/docs/stackit_dns_zone_clone.md @@ -16,11 +16,11 @@ stackit dns zone clone [flags] Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" $ stackit dns zone clone xxx --dns-name www.my-zone.com - Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" and adjust records "true" - $ stackit dns zone clone xxx --dns-name www.my-zone.com --adjust-records - Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" and display name "new-zone" $ stackit dns zone clone xxx --dns-name www.my-zone.com --name new-zone + + Clones a DNS zone with ID "xxx" to a new zone with DNS name "www.my-zone.com" and adjust records "true" + $ stackit dns zone clone xxx --dns-name www.my-zone.com --adjust-records ``` ### Options diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index 85afbdfa8..b0cc72f7f 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -76,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to clone the zone %s?", zoneLabel) + prompt := fmt.Sprintf("Are you sure you want to clone the zone %q?", zoneLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err diff --git a/internal/cmd/dns/zone/delete/delete.go b/internal/cmd/dns/zone/delete/delete.go index d5309d65e..2ad4373dd 100644 --- a/internal/cmd/dns/zone/delete/delete.go +++ b/internal/cmd/dns/zone/delete/delete.go @@ -58,7 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { zoneLabel = model.ZoneId } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete zone %s? (This cannot be undone)", zoneLabel) + prompt := fmt.Sprintf("Are you sure you want to delete zone %q? (This cannot be undone)", zoneLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err From 1fe4a904a259b5a91058e55756e4aa9d56abe51d Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:36:31 +0200 Subject: [PATCH 027/619] upgrade github-action to 40.2.3 (#424) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index f4976ea1a..982f43403 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v40.1.12 + uses: renovatebot/github-action@v40.2.3 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 59fa566464d718107988cc13e76236700205fe94 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:56:51 +0200 Subject: [PATCH 028/619] Add IaaS endpoint to config set unset (#435) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Onboard IaaS network-area `create` and `update` commands (#422) * create command * improve create command, update command * update GetOrganizationName docs * address PR comment * add network area id to create output * Onboard IaaS network `list` and `describe` commands (#425) * improve create command, update command * update GetOrganizationName docs * address PR comment * delete command * describe and initial list * list and describe * remove delete command * address PR comments * Onboard the IaaS network `delete` command and extend `project create` (#426) * improve create command, update command * update GetOrganizationName docs * address PR comment * delete command * describe and initial list * list and describe * add flag to project create * update main network area * remove duplicate calls * improve docs, address PR comments * Onboard `network-ranges delete` and `network-ranges create` commands (#427) * create network range * ranges delete command * improve help * address PR comments * Onboard `network-ranges list` and `network-ranges describe` commands (#429) * list and describe commands * small fixes * improve describe output * improve descriptions * address PR comments * address PR comments * Onboard `routes create` and `routes delete` command (#431) * create command * delete command * generate docs * document the lack of waiters in create command * move functions to utils, improve outputs * Onboard `routes list` and `routes describe` commands (#432) * delete command * move functions to utils, improve outputs * list command * describe command * Update internal/cmd/beta/network-area/routes/describe/describe.go * change flag order * Update internal/cmd/beta/network-area/routes/describe/describe_test.go * Update internal/cmd/beta/network-area/routes/describe/describe_test.go * Update internal/cmd/beta/network-area/routes/describe/describe_test.go * Update internal/cmd/beta/network-area/routes/describe/describe_test.go * Update internal/cmd/beta/network-area/routes/list/list.go --------- Co-authored-by: GokceGK <161626272+GokceGK@users.noreply.github.com> Co-authored-by: Gökçe Gök Klingel * add iaas custom endpoint to config * add iaas command to read me * update docs * Update internal/pkg/services/iaas/client/client.go Co-authored-by: João Palet --------- Co-authored-by: Diogo Ferrão Co-authored-by: João Palet --- README.md | 4 +- docs/stackit_beta.md | 1 + docs/stackit_beta_network-area.md | 39 +++ docs/stackit_beta_network-area_create.md | 53 +++ docs/stackit_beta_network-area_delete.md | 42 +++ docs/stackit_beta_network-area_describe.md | 47 +++ docs/stackit_beta_network-area_list.md | 47 +++ ...tackit_beta_network-area_network-ranges.md | 36 ++ ...beta_network-area_network-ranges_create.md | 42 +++ ...beta_network-area_network-ranges_delete.md | 41 +++ ...ta_network-area_network-ranges_describe.md | 41 +++ ...t_beta_network-area_network-ranges_list.md | 48 +++ docs/stackit_beta_network-area_routes.md | 36 ++ ...stackit_beta_network-area_routes_create.md | 45 +++ ...stackit_beta_network-area_routes_delete.md | 41 +++ ...ackit_beta_network-area_routes_describe.md | 44 +++ docs/stackit_beta_network-area_routes_list.md | 48 +++ docs/stackit_beta_network-area_update.md | 45 +++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + docs/stackit_project_create.md | 17 +- go.mod | 1 + go.sum | 2 + internal/cmd/beta/beta.go | 2 + .../cmd/beta/network-area/create/create.go | 203 +++++++++++ .../beta/network-area/create/create_test.go | 248 +++++++++++++ .../cmd/beta/network-area/delete/delete.go | 137 ++++++++ .../beta/network-area/delete/delete_test.go | 216 ++++++++++++ .../beta/network-area/describe/describe.go | 211 +++++++++++ .../network-area/describe/describe_test.go | 229 ++++++++++++ internal/cmd/beta/network-area/list/list.go | 174 ++++++++++ .../cmd/beta/network-area/list/list_test.go | 188 ++++++++++ .../network-ranges/create/create.go | 162 +++++++++ .../network-ranges/create/create_test.go | 217 ++++++++++++ .../network-ranges/delete/delete.go | 128 +++++++ .../network-ranges/delete/delete_test.go | 236 +++++++++++++ .../network-ranges/describe/describe.go | 141 ++++++++ .../network-ranges/describe/describe_test.go | 236 +++++++++++++ .../network-area/network-ranges/list/list.go | 171 +++++++++ .../network-ranges/list/list_test.go | 212 ++++++++++++ .../network-ranges/network_ranges.go | 33 ++ .../cmd/beta/network-area/network_area.go | 38 ++ .../beta/network-area/routes/create/create.go | 170 +++++++++ .../network-area/routes/create/create_test.go | 242 +++++++++++++ .../beta/network-area/routes/delete/delete.go | 122 +++++++ .../network-area/routes/delete/delete_test.go | 236 +++++++++++++ .../network-area/routes/describe/describe.go | 147 ++++++++ .../routes/describe/describe_test.go | 236 +++++++++++++ .../cmd/beta/network-area/routes/list/list.go | 171 +++++++++ .../network-area/routes/list/list_test.go | 212 ++++++++++++ .../cmd/beta/network-area/routes/routes.go | 32 ++ .../cmd/beta/network-area/update/update.go | 185 ++++++++++ .../beta/network-area/update/update_test.go | 268 ++++++++++++++ internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 3 + internal/cmd/project/create/create.go | 49 ++- internal/cmd/project/create/create_test.go | 98 +++++- internal/pkg/config/config.go | 3 + internal/pkg/projectname/project_name.go | 8 +- internal/pkg/services/iaas/client/client.go | 46 +++ internal/pkg/services/iaas/utils/utils.go | 60 ++++ .../pkg/services/iaas/utils/utils_test.go | 327 ++++++++++++++++++ .../services/resourcemanager/utils/utils.go | 32 ++ .../resourcemanager/utils/utils_test.go | 136 ++++++++ 65 files changed, 6667 insertions(+), 31 deletions(-) create mode 100644 docs/stackit_beta_network-area.md create mode 100644 docs/stackit_beta_network-area_create.md create mode 100644 docs/stackit_beta_network-area_delete.md create mode 100644 docs/stackit_beta_network-area_describe.md create mode 100644 docs/stackit_beta_network-area_list.md create mode 100644 docs/stackit_beta_network-area_network-ranges.md create mode 100644 docs/stackit_beta_network-area_network-ranges_create.md create mode 100644 docs/stackit_beta_network-area_network-ranges_delete.md create mode 100644 docs/stackit_beta_network-area_network-ranges_describe.md create mode 100644 docs/stackit_beta_network-area_network-ranges_list.md create mode 100644 docs/stackit_beta_network-area_routes.md create mode 100644 docs/stackit_beta_network-area_routes_create.md create mode 100644 docs/stackit_beta_network-area_routes_delete.md create mode 100644 docs/stackit_beta_network-area_routes_describe.md create mode 100644 docs/stackit_beta_network-area_routes_list.md create mode 100644 docs/stackit_beta_network-area_update.md create mode 100644 internal/cmd/beta/network-area/create/create.go create mode 100644 internal/cmd/beta/network-area/create/create_test.go create mode 100644 internal/cmd/beta/network-area/delete/delete.go create mode 100644 internal/cmd/beta/network-area/delete/delete_test.go create mode 100644 internal/cmd/beta/network-area/describe/describe.go create mode 100644 internal/cmd/beta/network-area/describe/describe_test.go create mode 100644 internal/cmd/beta/network-area/list/list.go create mode 100644 internal/cmd/beta/network-area/list/list_test.go create mode 100644 internal/cmd/beta/network-area/network-ranges/create/create.go create mode 100644 internal/cmd/beta/network-area/network-ranges/create/create_test.go create mode 100644 internal/cmd/beta/network-area/network-ranges/delete/delete.go create mode 100644 internal/cmd/beta/network-area/network-ranges/delete/delete_test.go create mode 100644 internal/cmd/beta/network-area/network-ranges/describe/describe.go create mode 100644 internal/cmd/beta/network-area/network-ranges/describe/describe_test.go create mode 100644 internal/cmd/beta/network-area/network-ranges/list/list.go create mode 100644 internal/cmd/beta/network-area/network-ranges/list/list_test.go create mode 100644 internal/cmd/beta/network-area/network-ranges/network_ranges.go create mode 100644 internal/cmd/beta/network-area/network_area.go create mode 100644 internal/cmd/beta/network-area/routes/create/create.go create mode 100644 internal/cmd/beta/network-area/routes/create/create_test.go create mode 100644 internal/cmd/beta/network-area/routes/delete/delete.go create mode 100644 internal/cmd/beta/network-area/routes/delete/delete_test.go create mode 100644 internal/cmd/beta/network-area/routes/describe/describe.go create mode 100644 internal/cmd/beta/network-area/routes/describe/describe_test.go create mode 100644 internal/cmd/beta/network-area/routes/list/list.go create mode 100644 internal/cmd/beta/network-area/routes/list/list_test.go create mode 100644 internal/cmd/beta/network-area/routes/routes.go create mode 100644 internal/cmd/beta/network-area/update/update.go create mode 100644 internal/cmd/beta/network-area/update/update_test.go create mode 100644 internal/pkg/services/iaas/client/client.go create mode 100644 internal/pkg/services/iaas/utils/utils.go create mode 100644 internal/pkg/services/iaas/utils/utils_test.go create mode 100644 internal/pkg/services/resourcemanager/utils/utils.go create mode 100644 internal/pkg/services/resourcemanager/utils/utils_test.go diff --git a/README.md b/README.md index f5981017b..6c9a9eb1d 100644 --- a/README.md +++ b/README.md @@ -66,9 +66,9 @@ Help is available for any command by specifying the special flag `--help` (or si Below you can find a list of the STACKIT services already available in the CLI (along with their respective command names) and the ones that are currently planned to be integrated. | Service | CLI Commands | Status | -| ---------------------------------- | ------------------------- | ------------------------- | +| ---------------------------------- |---------------------------|---------------------------| | Argus | `argus` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | | Will be integrated soon | +| Infrastructure as a Service (IaaS) | `beta network-area` | :white_check_mark: (beta) | | Authorization | `project`, `organization` | :white_check_mark: | | DNS | `dns` | :white_check_mark: | | Kubernetes Engine (SKE) | `ske` | :white_check_mark: | diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 015a04b3f..5d56bcd5c 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -40,6 +40,7 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) * [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_network-area.md b/docs/stackit_beta_network-area.md new file mode 100644 index 000000000..49859b4c1 --- /dev/null +++ b/docs/stackit_beta_network-area.md @@ -0,0 +1,39 @@ +## stackit beta network-area + +Provides functionality for STACKIT Network Area (SNA) + +### Synopsis + +Provides functionality for STACKIT Network Area (SNA). + +``` +stackit beta network-area [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta network-area create](./stackit_beta_network-area_create.md) - Creates a STACKIT Network Area (SNA) +* [stackit beta network-area delete](./stackit_beta_network-area_delete.md) - Deletes a STACKIT Network Area (SNA) +* [stackit beta network-area describe](./stackit_beta_network-area_describe.md) - Shows details of a STACKIT Network Area +* [stackit beta network-area list](./stackit_beta_network-area_list.md) - Lists all STACKIT Network Areas (SNA) of an organization +* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit beta network-area update](./stackit_beta_network-area_update.md) - Updates a STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_create.md b/docs/stackit_beta_network-area_create.md new file mode 100644 index 000000000..decb37c1e --- /dev/null +++ b/docs/stackit_beta_network-area_create.md @@ -0,0 +1,53 @@ +## stackit beta network-area create + +Creates a STACKIT Network Area (SNA) + +### Synopsis + +Creates a STACKIT Network Area (SNA) in an organization. + +``` +stackit beta network-area create [flags] +``` + +### Examples + +``` + Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network + $ stackit beta network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" + + Create a network area with name "network-area-2" in organization with ID "xxx" with network ranges, transfer network and DNS name server + $ stackit beta network-area create --name network-area-2 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --dns-name-servers "1.1.1.1" + + Create a network area with name "network-area-3" in organization with ID "xxx" with network ranges, transfer network and additional options + $ stackit beta network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24 +``` + +### Options + +``` + --default-prefix-length int The default prefix length for networks in the network area + --dns-name-servers strings List of DNS name server IPs + -h, --help Help for "stackit beta network-area create" + --max-prefix-length int The maximum prefix length for networks in the network area + --min-prefix-length int The minimum prefix length for networks in the network area + -n, --name string Network area name + --network-ranges strings List of network ranges (default []) + --organization-id string Organization ID + --transfer-network string Transfer network in CIDR notation +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_delete.md b/docs/stackit_beta_network-area_delete.md new file mode 100644 index 000000000..656d2ec32 --- /dev/null +++ b/docs/stackit_beta_network-area_delete.md @@ -0,0 +1,42 @@ +## stackit beta network-area delete + +Deletes a STACKIT Network Area (SNA) + +### Synopsis + +Deletes a STACKIT Network Area (SNA) in an organization. +If the SNA is attached to any projects, the deletion will fail + + +``` +stackit beta network-area delete [flags] +``` + +### Examples + +``` + Delete network area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area delete xxx --organization-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area delete" + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_describe.md b/docs/stackit_beta_network-area_describe.md new file mode 100644 index 000000000..31e86ddeb --- /dev/null +++ b/docs/stackit_beta_network-area_describe.md @@ -0,0 +1,47 @@ +## stackit beta network-area describe + +Shows details of a STACKIT Network Area + +### Synopsis + +Shows details of a STACKIT Network Area in an organization. + +``` +stackit beta network-area describe [flags] +``` + +### Examples + +``` + Show details of a network area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area describe xxx --organization-id yyy + + Show details of a network area with ID "xxx" in organization with ID "yyy" and show attached projects + $ stackit beta network-area describe xxx --organization-id yyy --show-attached-projects + + Show details of a network area with ID "xxx" in organization with ID "yyy" in JSON format + $ stackit beta network-area describe xxx --organization-id yyy --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area describe" + --organization-id string Organization ID + --show-attached-projects Whether to show attached projects. If a network area has several attached projects, their retrieval may take some time and the output may be extensive. +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_list.md b/docs/stackit_beta_network-area_list.md new file mode 100644 index 000000000..d7a4861fe --- /dev/null +++ b/docs/stackit_beta_network-area_list.md @@ -0,0 +1,47 @@ +## stackit beta network-area list + +Lists all STACKIT Network Areas (SNA) of an organization + +### Synopsis + +Lists all STACKIT Network Areas (SNA) of an organization. + +``` +stackit beta network-area list [flags] +``` + +### Examples + +``` + Lists all network areas of organization "xxx" + $ stackit beta network-area list --organization-id xxx + + Lists all network areas of organization "xxx" in JSON format + $ stackit beta network-area list --organization-id xxx --output-format json + + Lists up to 10 network areas of organization "xxx" + $ stackit beta network-area list --organization-id xxx --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area list" + --limit int Maximum number of entries to list + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_network-ranges.md b/docs/stackit_beta_network-area_network-ranges.md new file mode 100644 index 000000000..2fa256f86 --- /dev/null +++ b/docs/stackit_beta_network-area_network-ranges.md @@ -0,0 +1,36 @@ +## stackit beta network-area network-ranges + +Provides functionality for network ranges in STACKIT Network Areas + +### Synopsis + +Provides functionality for network ranges in STACKIT Network Areas. + +``` +stackit beta network-area network-ranges [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area network-ranges" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit beta network-area network-ranges create](./stackit_beta_network-area_network-ranges_create.md) - Creates a network range in a STACKIT Network Area (SNA) +* [stackit beta network-area network-ranges delete](./stackit_beta_network-area_network-ranges_delete.md) - Deletes a network range in a STACKIT Network Area (SNA) +* [stackit beta network-area network-ranges describe](./stackit_beta_network-area_network-ranges_describe.md) - Shows details of a network range in a STACKIT Network Area (SNA) +* [stackit beta network-area network-ranges list](./stackit_beta_network-area_network-ranges_list.md) - Lists all network ranges in a STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_network-ranges_create.md b/docs/stackit_beta_network-area_network-ranges_create.md new file mode 100644 index 000000000..1c2f86443 --- /dev/null +++ b/docs/stackit_beta_network-area_network-ranges_create.md @@ -0,0 +1,42 @@ +## stackit beta network-area network-ranges create + +Creates a network range in a STACKIT Network Area (SNA) + +### Synopsis + +Creates a network range in a STACKIT Network Area (SNA). + +``` +stackit beta network-area network-ranges create [flags] +``` + +### Examples + +``` + Create a network range in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area network-ranges create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24" +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area network-ranges create" + --network-area-id string STACKIT Network Area (SNA) ID + --network-range string Network range to create in CIDR notation + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas + diff --git a/docs/stackit_beta_network-area_network-ranges_delete.md b/docs/stackit_beta_network-area_network-ranges_delete.md new file mode 100644 index 000000000..3dfa26a05 --- /dev/null +++ b/docs/stackit_beta_network-area_network-ranges_delete.md @@ -0,0 +1,41 @@ +## stackit beta network-area network-ranges delete + +Deletes a network range in a STACKIT Network Area (SNA) + +### Synopsis + +Deletes a network range in a STACKIT Network Area (SNA). + +``` +stackit beta network-area network-ranges delete [flags] +``` + +### Examples + +``` + Delete network range with id "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" + $ stackit beta network-area network-ranges delete xxx --network-area-id yyy --organization-id zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area network-ranges delete" + --network-area-id string STACKIT Network Area (SNA) ID + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas + diff --git a/docs/stackit_beta_network-area_network-ranges_describe.md b/docs/stackit_beta_network-area_network-ranges_describe.md new file mode 100644 index 000000000..4d5b2442f --- /dev/null +++ b/docs/stackit_beta_network-area_network-ranges_describe.md @@ -0,0 +1,41 @@ +## stackit beta network-area network-ranges describe + +Shows details of a network range in a STACKIT Network Area (SNA) + +### Synopsis + +Shows details of a network range in a STACKIT Network Area (SNA). + +``` +stackit beta network-area network-ranges describe [flags] +``` + +### Examples + +``` + Show details of a network range with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" + $ stackit beta network-area network-ranges describe xxx --network-area-id yyy --organization-id zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area network-ranges describe" + --network-area-id string STACKIT Network Area (SNA) ID + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas + diff --git a/docs/stackit_beta_network-area_network-ranges_list.md b/docs/stackit_beta_network-area_network-ranges_list.md new file mode 100644 index 000000000..e42a53e1b --- /dev/null +++ b/docs/stackit_beta_network-area_network-ranges_list.md @@ -0,0 +1,48 @@ +## stackit beta network-area network-ranges list + +Lists all network ranges in a STACKIT Network Area (SNA) + +### Synopsis + +Lists all network ranges in a STACKIT Network Area (SNA). + +``` +stackit beta network-area network-ranges list [flags] +``` + +### Examples + +``` + Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy + + Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format + $ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy --output-format json + + Lists up to 10 network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area network-ranges list" + --limit int Maximum number of entries to list + --network-area-id string STACKIT Network Area (SNA) ID + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas + diff --git a/docs/stackit_beta_network-area_routes.md b/docs/stackit_beta_network-area_routes.md new file mode 100644 index 000000000..d8d7bd82e --- /dev/null +++ b/docs/stackit_beta_network-area_routes.md @@ -0,0 +1,36 @@ +## stackit beta network-area routes + +Provides functionality for static routes in STACKIT Network Areas + +### Synopsis + +Provides functionality for static routes in STACKIT Network Areas. + +``` +stackit beta network-area routes [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area routes" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit beta network-area routes create](./stackit_beta_network-area_routes_create.md) - Creates a static route in a STACKIT Network Area (SNA) +* [stackit beta network-area routes delete](./stackit_beta_network-area_routes_delete.md) - Deletes a static route in a STACKIT Network Area (SNA) +* [stackit beta network-area routes describe](./stackit_beta_network-area_routes_describe.md) - Shows details of a static route in a STACKIT Network Area (SNA) +* [stackit beta network-area routes list](./stackit_beta_network-area_routes_list.md) - Lists all static routes in a STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_routes_create.md b/docs/stackit_beta_network-area_routes_create.md new file mode 100644 index 000000000..83b183f2a --- /dev/null +++ b/docs/stackit_beta_network-area_routes_create.md @@ -0,0 +1,45 @@ +## stackit beta network-area routes create + +Creates a static route in a STACKIT Network Area (SNA) + +### Synopsis + +Creates a static route in a STACKIT Network Area (SNA). +This command is currently asynchonous only due to limitations in the waiting functionality of the SDK. This will be updated in a future release. + + +``` +stackit beta network-area routes create [flags] +``` + +### Examples + +``` + Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area routes create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area routes create" + --network-area-id string STACKIT Network Area ID + --next-hop string Next hop IP address. Must be a valid IPv4 + --organization-id string Organization ID + --prefix string Static route prefix +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas + diff --git a/docs/stackit_beta_network-area_routes_delete.md b/docs/stackit_beta_network-area_routes_delete.md new file mode 100644 index 000000000..50edd02fc --- /dev/null +++ b/docs/stackit_beta_network-area_routes_delete.md @@ -0,0 +1,41 @@ +## stackit beta network-area routes delete + +Deletes a static route in a STACKIT Network Area (SNA) + +### Synopsis + +Deletes a static route in a STACKIT Network Area (SNA). + +``` +stackit beta network-area routes delete [flags] +``` + +### Examples + +``` + Delete a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" + $ stackit beta network-area routes delete xxx --organization-id zzz --network-area-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area routes delete" + --network-area-id string STACKIT Network Area ID + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas + diff --git a/docs/stackit_beta_network-area_routes_describe.md b/docs/stackit_beta_network-area_routes_describe.md new file mode 100644 index 000000000..dbd6483ba --- /dev/null +++ b/docs/stackit_beta_network-area_routes_describe.md @@ -0,0 +1,44 @@ +## stackit beta network-area routes describe + +Shows details of a static route in a STACKIT Network Area (SNA) + +### Synopsis + +Shows details of a static route in a STACKIT Network Area (SNA). + +``` +stackit beta network-area routes describe [flags] +``` + +### Examples + +``` + Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" + $ stackit beta network-area routes describe xxx --network-area-id yyy --organization-id zzz + + Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" in JSON format + $ stackit beta network-area routes describe xxx --network-area-id yyy --organization-id zzz --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area routes describe" + --network-area-id string STACKIT Network Area ID + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas + diff --git a/docs/stackit_beta_network-area_routes_list.md b/docs/stackit_beta_network-area_routes_list.md new file mode 100644 index 000000000..b38b34cfd --- /dev/null +++ b/docs/stackit_beta_network-area_routes_list.md @@ -0,0 +1,48 @@ +## stackit beta network-area routes list + +Lists all static routes in a STACKIT Network Area (SNA) + +### Synopsis + +Lists all static routes in a STACKIT Network Area (SNA). + +``` +stackit beta network-area routes list [flags] +``` + +### Examples + +``` + Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area routes list --network-area-id xxx --organization-id yyy + + Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format + $ stackit beta network-area routes list --network-area-id xxx --organization-id yyy --output-format json + + Lists up to 10 static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area routes list --network-area-id xxx --organization-id yyy --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area routes list" + --limit int Maximum number of entries to list + --network-area-id string STACKIT Network Area ID + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas + diff --git a/docs/stackit_beta_network-area_update.md b/docs/stackit_beta_network-area_update.md new file mode 100644 index 000000000..2beecc037 --- /dev/null +++ b/docs/stackit_beta_network-area_update.md @@ -0,0 +1,45 @@ +## stackit beta network-area update + +Updates a STACKIT Network Area (SNA) + +### Synopsis + +Updates a STACKIT Network Area (SNA) in an organization. + +``` +stackit beta network-area update [flags] +``` + +### Examples + +``` + Update network area with ID "xxx" in organization with ID "yyy" with new name "network-area-1-new" + $ stackit beta network-area update xxx --organization-id yyy --name network-area-1-new +``` + +### Options + +``` + --default-prefix-length int The default prefix length for networks in the network area + --dns-name-servers strings List of DNS name server IPs + -h, --help Help for "stackit beta network-area update" + --max-prefix-length int The maximum prefix length for networks in the network area + --min-prefix-length int The minimum prefix length for networks in the network area + -n, --name string Network area name + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 469a907ed..3b3d666a7 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -33,6 +33,7 @@ stackit config set [flags] --authorization-custom-endpoint string Authorization API base URL, used in calls to this API --dns-custom-endpoint string DNS API base URL, used in calls to this API -h, --help Help for "stackit config set" + --iaas-custom-endpoint string IaaS API base URL, used in calls to this API --identity-provider-custom-endpoint string Identity Provider base URL, used for user authentication --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API --logme-custom-endpoint string LogMe API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index f8c1e7b0c..b4edb27d7 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -31,6 +31,7 @@ stackit config unset [flags] --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL -h, --help Help for "stackit config unset" + --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL --identity-provider-custom-endpoint Identity Provider base URL. If unset, uses the default base URL --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL diff --git a/docs/stackit_project_create.md b/docs/stackit_project_create.md index ae6e22723..8f01c8f31 100644 --- a/docs/stackit_project_create.md +++ b/docs/stackit_project_create.md @@ -5,6 +5,11 @@ Creates a STACKIT project ### Synopsis Creates a STACKIT project. +You can associate a project with a STACKIT Network Area (SNA) by providing the ID of the SNA. +The STACKIT Network Area (SNA) allows projects within an organization to be connected to each other on a network level. +This makes it possible to connect various resources of the projects within an SNA and also simplifies the connection with on-prem environments (hybrid cloud). +The network type can no longer be changed after the project has been created. If you require a different network type, you must create a new project. + ``` stackit project create [flags] @@ -18,15 +23,19 @@ stackit project create [flags] Create a STACKIT project with a set of labels $ stackit project create --parent-id xxxx --name my-project --label key=value --label foo=bar + + Create a STACKIT project with a network area + $ stackit project create --parent-id xxxx --name my-project --network-area-id yyyy ``` ### Options ``` - -h, --help Help for "stackit project create" - --label stringToString Labels are key-value string pairs which can be attached to a project. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) - --name string Project name - --parent-id string Parent resource identifier. Both container ID (user-friendly) and UUID are supported + -h, --help Help for "stackit project create" + --label stringToString Labels are key-value string pairs which can be attached to a project. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) + --name string Project name + --network-area-id string ID of a STACKIT Network Area (SNA) to associate with the project. + --parent-id string Parent resource identifier. Both container ID (user-friendly) and UUID are supported ``` ### Options inherited from parent commands diff --git a/go.mod b/go.mod index 19637df59..f11f6a752 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 diff --git a/go.sum b/go.sum index 95b906dad..eeb74d819 100644 --- a/go.sum +++ b/go.sum @@ -131,6 +131,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.4.0 h1:W6Zxyq487RpWfEIb6GL7tGTt5SsBzxHPeYTzmB11GtY= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.4.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 h1:/GwkGMD7ID5hSjdZs1l/Mj8waceCt7oj3TxHgBfEMDQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 h1:S8UZYBu2lHmKCPTR17jZetIal8X7cHO1gVRv101UdPw= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index e513b94e3..0a53bac25 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,6 +3,7 @@ package beta import ( "fmt" + networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -38,4 +39,5 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(sqlserverflex.NewCmd(p)) cmd.AddCommand(server.NewCmd(p)) + cmd.AddCommand(networkArea.NewCmd(p)) } diff --git a/internal/cmd/beta/network-area/create/create.go b/internal/cmd/beta/network-area/create/create.go new file mode 100644 index 000000000..814241f05 --- /dev/null +++ b/internal/cmd/beta/network-area/create/create.go @@ -0,0 +1,203 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" + rmUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + nameFlag = "name" + organizationIdFlag = "organization-id" + dnsNameServersFlag = "dns-name-servers" + networkRangesFlag = "network-ranges" + transferNetworkFlag = "transfer-network" + defaultPrefixLengthFlag = "default-prefix-length" + maxPrefixLengthFlag = "max-prefix-length" + minPrefixLengthFlag = "min-prefix-length" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name *string + OrganizationId *string + DnsNameServers *[]string + NetworkRanges *[]string + TransferNetwork *string + DefaultPrefixLength *int64 + MaxPrefixLength *int64 + MinPrefixLength *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a STACKIT Network Area (SNA)", + Long: "Creates a STACKIT Network Area (SNA) in an organization.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network`, + `$ stackit beta network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24"`, + ), + examples.NewExample( + `Create a network area with name "network-area-2" in organization with ID "xxx" with network ranges, transfer network and DNS name server`, + `$ stackit beta network-area create --name network-area-2 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --dns-name-servers "1.1.1.1"`, + ), + examples.NewExample( + `Create a network area with name "network-area-3" in organization with ID "xxx" with network ranges, transfer network and additional options`, + `$ stackit beta network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + var orgLabel string + rmApiClient, err := rmClient.ConfigureClient(p) + if err == nil { + orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) + if err != nil { + p.Debug(print.ErrorLevel, "get organization name: %v", err) + orgLabel = *model.OrganizationId + } + } else { + p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a network area for organization %q?", orgLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create network area: %w", err) + } + + return outputResult(p, model, orgLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(nameFlag, "n", "", "Network area name") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().StringSlice(dnsNameServersFlag, nil, "List of DNS name server IPs") + cmd.Flags().Var(flags.CIDRSliceFlag(), networkRangesFlag, "List of network ranges") + cmd.Flags().Var(flags.CIDRFlag(), transferNetworkFlag, "Transfer network in CIDR notation") + cmd.Flags().Int64(defaultPrefixLengthFlag, 0, "The default prefix length for networks in the network area") + cmd.Flags().Int64(maxPrefixLengthFlag, 0, "The maximum prefix length for networks in the network area") + cmd.Flags().Int64(minPrefixLengthFlag, 0, "The minimum prefix length for networks in the network area") + + err := flags.MarkFlagsRequired(cmd, nameFlag, organizationIdFlag, networkRangesFlag, transferNetworkFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, dnsNameServersFlag), + NetworkRanges: flags.FlagToStringSlicePointer(p, cmd, networkRangesFlag), + TransferNetwork: flags.FlagToStringPointer(p, cmd, transferNetworkFlag), + DefaultPrefixLength: flags.FlagToInt64Pointer(p, cmd, defaultPrefixLengthFlag), + MaxPrefixLength: flags.FlagToInt64Pointer(p, cmd, maxPrefixLengthFlag), + MinPrefixLength: flags.FlagToInt64Pointer(p, cmd, minPrefixLengthFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRequest { + req := apiClient.CreateNetworkArea(ctx, *model.OrganizationId) + + networkRanges := make([]iaas.NetworkRange, len(*model.NetworkRanges)) + for i, networkRange := range *model.NetworkRanges { + networkRanges[i] = iaas.NetworkRange{ + Prefix: utils.Ptr(networkRange), + } + } + + payload := iaas.CreateNetworkAreaPayload{ + Name: model.Name, + AddressFamily: &iaas.CreateAreaAddressFamily{ + Ipv4: &iaas.CreateAreaIPv4{ + DefaultNameservers: model.DnsNameServers, + NetworkRanges: utils.Ptr(networkRanges), + TransferNetwork: model.TransferNetwork, + DefaultPrefixLen: model.DefaultPrefixLength, + MaxPrefixLen: model.MaxPrefixLength, + MinPrefixLen: model.MinPrefixLength, + }, + }, + } + + return req.CreateNetworkAreaPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, orgLabel string, networkArea *iaas.NetworkArea) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(networkArea, "", " ") + if err != nil { + return fmt.Errorf("marshal network area: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network area: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created STACKIT Network Area for organization %q.\nNetwork area ID: %s\n", orgLabel, *networkArea.AreaId) + return nil + } +} diff --git a/internal/cmd/beta/network-area/create/create_test.go b/internal/cmd/beta/network-area/create/create_test.go new file mode 100644 index 000000000..2912000db --- /dev/null +++ b/internal/cmd/beta/network-area/create/create_test.go @@ -0,0 +1,248 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + nameFlag: "example-network-area-name", + organizationIdFlag: testOrgId, + dnsNameServersFlag: "1.1.1.0,1.1.2.0", + networkRangesFlag: "192.0.0.0/24,102.0.0.0/24", + transferNetworkFlag: "100.0.0.0/24", + defaultPrefixLengthFlag: "24", + maxPrefixLengthFlag: "24", + minPrefixLengthFlag: "24", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example-network-area-name"), + OrganizationId: utils.Ptr(testOrgId), + DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + NetworkRanges: utils.Ptr([]string{"192.0.0.0/24", "102.0.0.0/24"}), + TransferNetwork: utils.Ptr("100.0.0.0/24"), + DefaultPrefixLength: utils.Ptr(int64(24)), + MaxPrefixLength: utils.Ptr(int64(24)), + MinPrefixLength: utils.Ptr(int64(24)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkAreaRequest)) iaas.ApiCreateNetworkAreaRequest { + request := testClient.CreateNetworkArea(testCtx, testOrgId) + request = request.CreateNetworkAreaPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaPayload)) iaas.CreateNetworkAreaPayload { + payload := iaas.CreateNetworkAreaPayload{ + Name: utils.Ptr("example-network-area-name"), + AddressFamily: &iaas.CreateAreaAddressFamily{ + Ipv4: &iaas.CreateAreaIPv4{ + DefaultNameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + NetworkRanges: &[]iaas.NetworkRange{ + { + Prefix: utils.Ptr("192.0.0.0/24"), + }, + { + Prefix: utils.Ptr("102.0.0.0/24"), + }, + }, + TransferNetwork: utils.Ptr("100.0.0.0/24"), + DefaultPrefixLen: utils.Ptr(int64(24)), + MaxPrefixLen: utils.Ptr(int64(24)), + MinPrefixLen: utils.Ptr(int64(24)), + }, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, dnsNameServersFlag) + delete(flagValues, defaultPrefixLengthFlag) + delete(flagValues, maxPrefixLengthFlag) + delete(flagValues, minPrefixLengthFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.DnsNameServers = nil + model.DefaultPrefixLength = nil + model.MaxPrefixLength = nil + model.MinPrefixLength = nil + }), + }, + { + description: "name missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + { + description: "network ranges missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkRangesFlag) + }), + isValid: false, + }, + { + description: "transfer network missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, transferNetworkFlag) + }), + isValid: false, + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateNetworkAreaRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/delete/delete.go b/internal/cmd/beta/network-area/delete/delete.go new file mode 100644 index 000000000..ca1afcb4d --- /dev/null +++ b/internal/cmd/beta/network-area/delete/delete.go @@ -0,0 +1,137 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + areaIdArg = "AREA_ID" + organizationIdFlag = "organization-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + AreaId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a STACKIT Network Area (SNA)", + Long: fmt.Sprintf("%s\n%s\n", + "Deletes a STACKIT Network Area (SNA) in an organization.", + "If the SNA is attached to any projects, the deletion will fail", + ), + Args: args.SingleArg(areaIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete network area with ID "xxx" in organization with ID "yyy"`, + "$ stackit beta network-area delete xxx --organization-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, model.AreaId) + if err != nil { + p.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = model.AreaId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete network area %q?", networkAreaLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete network area: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Deleting network area") + _, err = wait.DeleteNetworkAreaWaitHandler(ctx, apiClient, *model.OrganizationId, model.AreaId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for network area deletion: %w", err) + } + s.Stop() + } + + operationState := "Deleted" + if model.Async { + operationState = "Triggered deletion of" + } + p.Info("%s STACKIT Network Area %q\n", operationState, networkAreaLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + areaId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + AreaId: areaId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNetworkAreaRequest { + return apiClient.DeleteNetworkArea(ctx, *model.OrganizationId, model.AreaId) +} diff --git a/internal/cmd/beta/network-area/delete/delete_test.go b/internal/cmd/beta/network-area/delete/delete_test.go new file mode 100644 index 000000000..a3ff4f430 --- /dev/null +++ b/internal/cmd/beta/network-area/delete/delete_test.go @@ -0,0 +1,216 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testOrganizationId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNetworkAreaId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrganizationId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: &testOrganizationId, + AreaId: testNetworkAreaId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteNetworkAreaRequest)) iaas.ApiDeleteNetworkAreaRequest { + request := testClient.DeleteNetworkArea(testCtx, testOrganizationId, testNetworkAreaId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "organization id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "organization id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "organization id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "instance id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "instance id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteNetworkAreaRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/describe/describe.go b/internal/cmd/beta/network-area/describe/describe.go new file mode 100644 index 000000000..cd13cfaae --- /dev/null +++ b/internal/cmd/beta/network-area/describe/describe.go @@ -0,0 +1,211 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + areaIdArg = "AREA_ID" + organizationIdFlag = "organization-id" + showAttachedProjectsFlag = "show-attached-projects" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + AreaId string + ShowAttachedProjects bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a STACKIT Network Area", + Long: "Shows details of a STACKIT Network Area in an organization.", + Args: args.SingleArg(areaIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Show details of a network area with ID "xxx" in organization with ID "yyy"`, + "$ stackit beta network-area describe xxx --organization-id yyy", + ), + examples.NewExample( + `Show details of a network area with ID "xxx" in organization with ID "yyy" and show attached projects`, + "$ stackit beta network-area describe xxx --organization-id yyy --show-attached-projects", + ), + examples.NewExample( + `Show details of a network area with ID "xxx" in organization with ID "yyy" in JSON format`, + "$ stackit beta network-area describe xxx --organization-id yyy --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read network area: %w", err) + } + + var projects []string + + if model.ShowAttachedProjects { + projects, err = iaasUtils.ListAttachedProjects(ctx, apiClient, *model.OrganizationId, model.AreaId) + if err != nil { + return fmt.Errorf("get attached projects: %w", err) + } + } + + return outputResult(p, model.OutputFormat, resp, projects) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Bool(showAttachedProjectsFlag, false, "Whether to show attached projects. If a network area has several attached projects, their retrieval may take some time and the output may be extensive.") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + areaId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + AreaId: areaId, + ShowAttachedProjects: flags.FlagToBoolValue(p, cmd, showAttachedProjectsFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNetworkAreaRequest { + return apiClient.GetNetworkArea(ctx, *model.OrganizationId, model.AreaId) +} + +func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.NetworkArea, attachedProjects []string) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(networkArea, "", " ") + if err != nil { + return fmt.Errorf("marshal network area: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network area: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + var routes []string + if networkArea.Ipv4.Routes != nil { + for _, route := range *networkArea.Ipv4.Routes { + routes = append(routes, fmt.Sprintf("next hop: %s\nprefix: %s", *route.Nexthop, *route.Prefix)) + } + } + + var networkRanges []string + if networkArea.Ipv4.NetworkRanges != nil { + for _, networkRange := range *networkArea.Ipv4.NetworkRanges { + networkRanges = append(networkRanges, *networkRange.Prefix) + } + } + + table := tables.NewTable() + table.AddRow("ID", *networkArea.AreaId) + table.AddSeparator() + table.AddRow("NAME", *networkArea.Name) + table.AddSeparator() + table.AddRow("STATE", *networkArea.State) + table.AddSeparator() + if len(networkRanges) > 0 { + table.AddRow("NETWORK RANGES", strings.Join(networkRanges, ",")) + } + table.AddSeparator() + for i, route := range routes { + table.AddRow(fmt.Sprintf("STATIC ROUTE %d", i+1), route) + table.AddSeparator() + } + if networkArea.Ipv4.TransferNetwork != nil { + table.AddRow("TRANSFER RANGE", *networkArea.Ipv4.TransferNetwork) + table.AddSeparator() + } + if networkArea.Ipv4.DefaultNameservers != nil { + table.AddRow("DNS NAME SERVERS", strings.Join(*networkArea.Ipv4.DefaultNameservers, ",")) + table.AddSeparator() + } + if networkArea.Ipv4.DefaultPrefixLen != nil { + table.AddRow("DEFAULT PREFIX LENGTH", *networkArea.Ipv4.DefaultPrefixLen) + table.AddSeparator() + } + if networkArea.Ipv4.MaxPrefixLen != nil { + table.AddRow("MAX PREFIX LENGTH", *networkArea.Ipv4.MaxPrefixLen) + table.AddSeparator() + } + if networkArea.Ipv4.MinPrefixLen != nil { + table.AddRow("MIN PREFIX LENGTH", *networkArea.Ipv4.MinPrefixLen) + table.AddSeparator() + } + if len(attachedProjects) > 0 { + table.AddRow("ATTACHED PROJECTS IDS", strings.Join(attachedProjects, "\n")) + table.AddSeparator() + } else { + table.AddRow("# ATTACHED PROJECTS", *networkArea.ProjectCount) + table.AddSeparator() + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/network-area/describe/describe_test.go b/internal/cmd/beta/network-area/describe/describe_test.go new file mode 100644 index 000000000..98975e10e --- /dev/null +++ b/internal/cmd/beta/network-area/describe/describe_test.go @@ -0,0 +1,229 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testOrganizationId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNetworkAreaId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrganizationId, + showAttachedProjectsFlag: "false", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: &testOrganizationId, + AreaId: testNetworkAreaId, + ShowAttachedProjects: false, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetNetworkAreaRequest)) iaas.ApiGetNetworkAreaRequest { + request := testClient.GetNetworkArea(testCtx, testOrganizationId, testNetworkAreaId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "organization id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "organization id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "organization id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "instance id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "instance id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "show attached projects true", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[showAttachedProjectsFlag] = "true" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.ShowAttachedProjects = true + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetNetworkAreaRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/list/list.go b/internal/cmd/beta/network-area/list/list.go new file mode 100644 index 000000000..1f3f9c294 --- /dev/null +++ b/internal/cmd/beta/network-area/list/list.go @@ -0,0 +1,174 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" + rmUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + organizationIdFlag = "organization-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + OrganizationId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all STACKIT Network Areas (SNA) of an organization", + Long: "Lists all STACKIT Network Areas (SNA) of an organization.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all network areas of organization "xxx"`, + "$ stackit beta network-area list --organization-id xxx", + ), + examples.NewExample( + `Lists all network areas of organization "xxx" in JSON format`, + "$ stackit beta network-area list --organization-id xxx --output-format json", + ), + examples.NewExample( + `Lists up to 10 network areas of organization "xxx"`, + "$ stackit beta network-area list --organization-id xxx --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list network areas: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + var orgLabel string + rmApiClient, err := rmClient.ConfigureClient(p) + if err == nil { + orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) + if err != nil { + p.Debug(print.ErrorLevel, "get organization name: %v", err) + orgLabel = *model.OrganizationId + } + } else { + p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) + } + p.Info("No STACKIT Network Areas found for organization %q\n", orgLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworkAreasRequest { + return apiClient.ListNetworkAreas(ctx, *model.OrganizationId) +} + +func outputResult(p *print.Printer, outputFormat string, networkAreas []iaas.NetworkArea) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(networkAreas, "", " ") + if err != nil { + return fmt.Errorf("marshal network area: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(networkAreas, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal area: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "Name", "Status", "Network Ranges", "# Attached Projects") + + for _, networkArea := range networkAreas { + table.AddRow(*networkArea.AreaId, *networkArea.Name, *networkArea.State, len(*networkArea.Ipv4.NetworkRanges), *networkArea.ProjectCount) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/network-area/list/list_test.go b/internal/cmd/beta/network-area/list/list_test.go new file mode 100644 index 000000000..46282da26 --- /dev/null +++ b/internal/cmd/beta/network-area/list/list_test.go @@ -0,0 +1,188 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testOrganizationId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrganizationId, + limitFlag: "10", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: &testOrganizationId, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreasRequest)) iaas.ApiListNetworkAreasRequest { + request := testClient.ListNetworkAreas(testCtx, testOrganizationId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "organization id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "organization id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "organization id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListNetworkAreasRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/network-ranges/create/create.go b/internal/cmd/beta/network-area/network-ranges/create/create.go new file mode 100644 index 000000000..56aceb7dc --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/create/create.go @@ -0,0 +1,162 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" + networkRangeFlag = "network-range" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + NetworkAreaId *string + NetworkRange *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a network range in a STACKIT Network Area (SNA)", + Long: "Creates a network range in a STACKIT Network Area (SNA).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a network range in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + `$ stackit beta network-area network-ranges create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24"`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Get network area label + networkAreaLabel, err := utils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + if err != nil { + p.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = *model.NetworkAreaId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a network range for STACKIT Network Area (SNA) %q?", networkAreaLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create network range: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + return fmt.Errorf("empty response from API") + } + + networkRange, err := utils.GetNetworkRangeFromAPIResponse(*model.NetworkRange, resp.Items) + if err != nil { + return err + } + + return outputResult(p, model, networkAreaLabel, networkRange) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + cmd.Flags().Var(flags.CIDRFlag(), networkRangeFlag, "Network range to create in CIDR notation") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag, networkRangeFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + NetworkRange: flags.FlagToStringPointer(p, cmd, networkRangeFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRangeRequest { + req := apiClient.CreateNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId) + payload := iaas.CreateNetworkAreaRangePayload{ + Ipv4: &[]iaas.NetworkRange{ + { + Prefix: model.NetworkRange, + }, + }, + } + return req.CreateNetworkAreaRangePayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, networkRange iaas.NetworkRange) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(networkRange, "", " ") + if err != nil { + return fmt.Errorf("marshal network range: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(networkRange, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network range: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created network range for SNA %q.\nNetwork range ID: %s\n", networkAreaLabel, *networkRange.NetworkRangeId) + return nil + } +} diff --git a/internal/cmd/beta/network-area/network-ranges/create/create_test.go b/internal/cmd/beta/network-area/network-ranges/create/create_test.go new file mode 100644 index 000000000..028259648 --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/create/create_test.go @@ -0,0 +1,217 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrgId, + networkAreaIdFlag: testNetworkAreaId, + networkRangeFlag: "1.1.1.0/24", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: utils.Ptr(testOrgId), + NetworkAreaId: utils.Ptr(testNetworkAreaId), + NetworkRange: utils.Ptr("1.1.1.0/24"), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkAreaRangeRequest)) iaas.ApiCreateNetworkAreaRangeRequest { + request := testClient.CreateNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId) + request = request.CreateNetworkAreaRangePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaRangePayload)) iaas.CreateNetworkAreaRangePayload { + payload := iaas.CreateNetworkAreaRangePayload{ + Ipv4: &[]iaas.NetworkRange{ + { + Prefix: utils.Ptr("1.1.1.0/24"), + }, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "network range missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkRangeFlag) + }), + isValid: false, + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateNetworkAreaRangeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/network-ranges/delete/delete.go b/internal/cmd/beta/network-area/network-ranges/delete/delete.go new file mode 100644 index 000000000..ec439f87f --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/delete/delete.go @@ -0,0 +1,128 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + networkRangeIdArg = "NETWORK_RANGE_ID" + + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + NetworkAreaId *string + NetworkRangeId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a network range in a STACKIT Network Area (SNA)", + Long: "Deletes a network range in a STACKIT Network Area (SNA).", + Args: args.SingleArg(networkRangeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete network range with id "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, + `$ stackit beta network-area network-ranges delete xxx --network-area-id yyy --organization-id zzz`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + if err != nil { + p.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = *model.NetworkAreaId + } + networkRangeLabel, err := iaasUtils.GetNetworkRangePrefix(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) + if err != nil { + p.Debug(print.ErrorLevel, "get network range prefix: %v", err) + networkRangeLabel = model.NetworkRangeId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete network range %q on STACKIT Network Area (SNA) %q?", networkRangeLabel, networkAreaLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete network range: %w", err) + } + + p.Info("Deleted network range %q on SNA %q\n", networkRangeLabel, networkAreaLabel) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + networkRangeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + NetworkRangeId: networkRangeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNetworkAreaRangeRequest { + req := apiClient.DeleteNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) + return req +} diff --git a/internal/cmd/beta/network-area/network-ranges/delete/delete_test.go b/internal/cmd/beta/network-area/network-ranges/delete/delete_test.go new file mode 100644 index 000000000..5955ea316 --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/delete/delete_test.go @@ -0,0 +1,236 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() +var testNetworkRangeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNetworkRangeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrgId, + networkAreaIdFlag: testNetworkAreaId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: utils.Ptr(testOrgId), + NetworkAreaId: utils.Ptr(testNetworkAreaId), + NetworkRangeId: testNetworkRangeId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteNetworkAreaRangeRequest)) iaas.ApiDeleteNetworkAreaRangeRequest { + request := testClient.DeleteNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId, testNetworkRangeId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network range id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkRangeIdArg) + }), + isValid: false, + }, + { + description: "network range id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkRangeIdArg] = "" + }), + isValid: false, + }, + { + description: "network range id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkRangeIdArg] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteNetworkAreaRangeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/network-ranges/describe/describe.go b/internal/cmd/beta/network-area/network-ranges/describe/describe.go new file mode 100644 index 000000000..dbfaf1c24 --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/describe/describe.go @@ -0,0 +1,141 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + networkRangeIdArg = "NETWORK_RANGE_ID" + + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + NetworkAreaId *string + NetworkRangeId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a network range in a STACKIT Network Area (SNA)", + Long: "Shows details of a network range in a STACKIT Network Area (SNA).", + Args: args.SingleArg(networkRangeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Show details of a network range with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, + `$ stackit beta network-area network-ranges describe xxx --network-area-id yyy --organization-id zzz`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("describe network range: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + networkRangeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + NetworkRangeId: networkRangeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNetworkAreaRangeRequest { + req := apiClient.GetNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, networkRange *iaas.NetworkRange) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(networkRange, "", " ") + if err != nil { + return fmt.Errorf("marshal network range: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(networkRange, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network range: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *networkRange.NetworkRangeId) + table.AddSeparator() + table.AddRow("Network range", *networkRange.Prefix) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/network-area/network-ranges/describe/describe_test.go b/internal/cmd/beta/network-area/network-ranges/describe/describe_test.go new file mode 100644 index 000000000..bce857d1c --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/describe/describe_test.go @@ -0,0 +1,236 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() +var testNetworkRangeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNetworkRangeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrgId, + networkAreaIdFlag: testNetworkAreaId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: utils.Ptr(testOrgId), + NetworkAreaId: utils.Ptr(testNetworkAreaId), + NetworkRangeId: testNetworkRangeId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetNetworkAreaRangeRequest)) iaas.ApiGetNetworkAreaRangeRequest { + request := testClient.GetNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId, testNetworkRangeId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network range id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkRangeIdArg) + }), + isValid: false, + }, + { + description: "network range id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkRangeIdArg] = "" + }), + isValid: false, + }, + { + description: "network range id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkRangeIdArg] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetNetworkAreaRangeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/network-ranges/list/list.go b/internal/cmd/beta/network-area/network-ranges/list/list.go new file mode 100644 index 000000000..fb815ec3b --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/list/list.go @@ -0,0 +1,171 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + OrganizationId *string + NetworkAreaId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all network ranges in a STACKIT Network Area (SNA)", + Long: "Lists all network ranges in a STACKIT Network Area (SNA).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + "$ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy", + ), + examples.NewExample( + `Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format`, + "$ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy --output-format json", + ), + examples.NewExample( + `Lists up to 10 network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + "$ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list network ranges: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + var networkAreaLabel string + networkAreaLabel, err = iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + if err != nil { + p.Debug(print.ErrorLevel, "get organization name: %v", err) + networkAreaLabel = *model.NetworkAreaId + } + p.Info("No network ranges found for SNA %q\n", networkAreaLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworkAreaRangesRequest { + return apiClient.ListNetworkAreaRanges(ctx, *model.OrganizationId, *model.NetworkAreaId) +} + +func outputResult(p *print.Printer, outputFormat string, networkRanges []iaas.NetworkRange) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(networkRanges, "", " ") + if err != nil { + return fmt.Errorf("marshal network ranges: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(networkRanges, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network ranges: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "Network Range") + + for _, networkRange := range networkRanges { + table.AddRow(*networkRange.NetworkRangeId, *networkRange.Prefix) + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/network-area/network-ranges/list/list_test.go b/internal/cmd/beta/network-area/network-ranges/list/list_test.go new file mode 100644 index 000000000..07ca84414 --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/list/list_test.go @@ -0,0 +1,212 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testOrganizationId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrganizationId, + networkAreaIdFlag: testNetworkAreaId, + limitFlag: "10", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: &testOrganizationId, + NetworkAreaId: &testNetworkAreaId, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreaRangesRequest)) iaas.ApiListNetworkAreaRangesRequest { + request := testClient.ListNetworkAreaRanges(testCtx, testOrganizationId, testNetworkAreaId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "organization id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "organization id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "organization id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListNetworkAreaRangesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/network-ranges/network_ranges.go b/internal/cmd/beta/network-area/network-ranges/network_ranges.go new file mode 100644 index 000000000..49c765198 --- /dev/null +++ b/internal/cmd/beta/network-area/network-ranges/network_ranges.go @@ -0,0 +1,33 @@ +package networkranges + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "network-ranges", + Aliases: []string{"ranges"}, + Short: "Provides functionality for network ranges in STACKIT Network Areas", + Long: "Provides functionality for network ranges in STACKIT Network Areas.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} diff --git a/internal/cmd/beta/network-area/network_area.go b/internal/cmd/beta/network-area/network_area.go new file mode 100644 index 000000000..21abd15a6 --- /dev/null +++ b/internal/cmd/beta/network-area/network_area.go @@ -0,0 +1,38 @@ +package networkarea + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/list" + networkranges "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "network-area", + Short: "Provides functionality for STACKIT Network Area (SNA)", + Long: "Provides functionality for STACKIT Network Area (SNA).", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(networkranges.NewCmd(p)) + cmd.AddCommand(routes.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) +} diff --git a/internal/cmd/beta/network-area/routes/create/create.go b/internal/cmd/beta/network-area/routes/create/create.go new file mode 100644 index 000000000..5f61c3677 --- /dev/null +++ b/internal/cmd/beta/network-area/routes/create/create.go @@ -0,0 +1,170 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" + prefixFlag = "prefix" + nexthopFlag = "next-hop" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + NetworkAreaId *string + Prefix *string + Nexthop *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a static route in a STACKIT Network Area (SNA)", + Long: fmt.Sprintf("%s\n%s\n", + "Creates a static route in a STACKIT Network Area (SNA).", + "This command is currently asynchonous only due to limitations in the waiting functionality of the SDK. This will be updated in a future release.", + ), + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + "$ stackit beta network-area routes create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Get network area label + networkAreaLabel, err := utils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + if err != nil { + p.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = *model.NetworkAreaId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a static route for STACKIT Network Area (SNA) %q?", networkAreaLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create static route: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + return fmt.Errorf("empty response from API") + } + + route, err := utils.GetRouteFromAPIResponse(*model.Prefix, *model.Nexthop, resp.Items) + if err != nil { + return err + } + + return outputResult(p, model, networkAreaLabel, route) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area ID") + cmd.Flags().Var(flags.CIDRFlag(), prefixFlag, "Static route prefix") + cmd.Flags().String(nexthopFlag, "", "Next hop IP address. Must be a valid IPv4") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag, prefixFlag, nexthopFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + Prefix: flags.FlagToStringPointer(p, cmd, prefixFlag), + Nexthop: flags.FlagToStringPointer(p, cmd, nexthopFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRouteRequest { + req := apiClient.CreateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId) + payload := iaas.CreateNetworkAreaRoutePayload{ + Ipv4: &[]iaas.Route{ + { + Prefix: model.Prefix, + Nexthop: model.Nexthop, + }, + }, + } + return req.CreateNetworkAreaRoutePayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, route iaas.Route) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(route, "", " ") + if err != nil { + return fmt.Errorf("marshal static route: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal static route: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, *route.RouteId) + return nil + } +} diff --git a/internal/cmd/beta/network-area/routes/create/create_test.go b/internal/cmd/beta/network-area/routes/create/create_test.go new file mode 100644 index 000000000..03a3a7bb0 --- /dev/null +++ b/internal/cmd/beta/network-area/routes/create/create_test.go @@ -0,0 +1,242 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrgId, + networkAreaIdFlag: testNetworkAreaId, + prefixFlag: "1.1.1.0/24", + nexthopFlag: "1.1.1.1", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: utils.Ptr(testOrgId), + NetworkAreaId: utils.Ptr(testNetworkAreaId), + Prefix: utils.Ptr("1.1.1.0/24"), + Nexthop: utils.Ptr("1.1.1.1"), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkAreaRouteRequest)) iaas.ApiCreateNetworkAreaRouteRequest { + request := testClient.CreateNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId) + request = request.CreateNetworkAreaRoutePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaRoutePayload)) iaas.CreateNetworkAreaRoutePayload { + payload := iaas.CreateNetworkAreaRoutePayload{ + Ipv4: &[]iaas.Route{ + { + Prefix: utils.Ptr("1.1.1.0/24"), + Nexthop: utils.Ptr("1.1.1.1"), + }, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + + { + description: "next hop missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nexthopFlag) + }), + isValid: false, + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "prefix missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, prefixFlag) + }), + isValid: false, + }, + { + description: "prefix invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[prefixFlag] = "" + }), + isValid: false, + }, + { + description: "prefix invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[prefixFlag] = "invalid-prefix" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateNetworkAreaRouteRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/routes/delete/delete.go b/internal/cmd/beta/network-area/routes/delete/delete.go new file mode 100644 index 000000000..53c8c1d1b --- /dev/null +++ b/internal/cmd/beta/network-area/routes/delete/delete.go @@ -0,0 +1,122 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + routeIdArg = "ROUTE_ID" + + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + NetworkAreaId *string + RouteId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a static route in a STACKIT Network Area (SNA)", + Long: "Deletes a static route in a STACKIT Network Area (SNA).", + Args: args.SingleArg(routeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, + "$ stackit beta network-area routes delete xxx --organization-id zzz --network-area-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + if err != nil { + p.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = *model.NetworkAreaId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete static route %q on STACKIT Network Area (SNA) %q?", model.RouteId, networkAreaLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete static route: %w", err) + } + + p.Info("Deleted static route %q on SNA %q\n", model.RouteId, networkAreaLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area ID") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + routeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + RouteId: routeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNetworkAreaRouteRequest { + req := apiClient.DeleteNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.RouteId) + return req +} diff --git a/internal/cmd/beta/network-area/routes/delete/delete_test.go b/internal/cmd/beta/network-area/routes/delete/delete_test.go new file mode 100644 index 000000000..8a63e08c7 --- /dev/null +++ b/internal/cmd/beta/network-area/routes/delete/delete_test.go @@ -0,0 +1,236 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() +var testRouteId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testRouteId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrgId, + networkAreaIdFlag: testNetworkAreaId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: utils.Ptr(testOrgId), + NetworkAreaId: utils.Ptr(testNetworkAreaId), + RouteId: testRouteId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteNetworkAreaRouteRequest)) iaas.ApiDeleteNetworkAreaRouteRequest { + request := testClient.DeleteNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRouteId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "route id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, routeIdArg) + }), + isValid: false, + }, + { + description: "route id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[routeIdArg] = "" + }), + isValid: false, + }, + { + description: "route id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[routeIdArg] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteNetworkAreaRouteRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/routes/describe/describe.go b/internal/cmd/beta/network-area/routes/describe/describe.go new file mode 100644 index 000000000..e9e77e906 --- /dev/null +++ b/internal/cmd/beta/network-area/routes/describe/describe.go @@ -0,0 +1,147 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + routeIdArg = "ROUTE_ID" + + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + NetworkAreaId *string + RouteId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a static route in a STACKIT Network Area (SNA)", + Long: "Shows details of a static route in a STACKIT Network Area (SNA).", + Args: args.SingleArg(routeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, + `$ stackit beta network-area routes describe xxx --network-area-id yyy --organization-id zzz`, + ), + examples.NewExample( + `Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" in JSON format`, + `$ stackit beta network-area routes describe xxx --network-area-id yyy --organization-id zzz --output-format json`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("describe static route: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area ID") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + routeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + RouteId: routeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNetworkAreaRouteRequest { + req := apiClient.GetNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.RouteId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, route *iaas.Route) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(route, "", " ") + if err != nil { + return fmt.Errorf("marshal static route: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal static route: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *route.RouteId) + table.AddSeparator() + table.AddRow("Prefix", *route.Prefix) + table.AddSeparator() + table.AddRow("Nexthop", *route.Nexthop) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/network-area/routes/describe/describe_test.go b/internal/cmd/beta/network-area/routes/describe/describe_test.go new file mode 100644 index 000000000..08fba5d5f --- /dev/null +++ b/internal/cmd/beta/network-area/routes/describe/describe_test.go @@ -0,0 +1,236 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() +var testRouteId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testRouteId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrgId, + networkAreaIdFlag: testNetworkAreaId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: utils.Ptr(testOrgId), + NetworkAreaId: utils.Ptr(testNetworkAreaId), + RouteId: testRouteId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetNetworkAreaRouteRequest)) iaas.ApiGetNetworkAreaRouteRequest { + request := testClient.GetNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRouteId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network route id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, routeIdArg) + }), + isValid: false, + }, + { + description: "network route id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[routeIdArg] = "" + }), + isValid: false, + }, + { + description: "network route id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[routeIdArg] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetNetworkAreaRouteRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/routes/list/list.go b/internal/cmd/beta/network-area/routes/list/list.go new file mode 100644 index 000000000..f8d9c9bcf --- /dev/null +++ b/internal/cmd/beta/network-area/routes/list/list.go @@ -0,0 +1,171 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + OrganizationId *string + NetworkAreaId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all static routes in a STACKIT Network Area (SNA)", + Long: "Lists all static routes in a STACKIT Network Area (SNA).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + "$ stackit beta network-area routes list --network-area-id xxx --organization-id yyy", + ), + examples.NewExample( + `Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format`, + "$ stackit beta network-area routes list --network-area-id xxx --organization-id yyy --output-format json", + ), + examples.NewExample( + `Lists up to 10 static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + "$ stackit beta network-area routes list --network-area-id xxx --organization-id yyy --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list static routes: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + var networkAreaLabel string + networkAreaLabel, err = iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + if err != nil { + p.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = *model.NetworkAreaId + } + p.Info("No static routes found for STACKIT Network Area %q\n", networkAreaLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area ID") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworkAreaRoutesRequest { + return apiClient.ListNetworkAreaRoutes(ctx, *model.OrganizationId, *model.NetworkAreaId) +} + +func outputResult(p *print.Printer, outputFormat string, routes []iaas.Route) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(routes, "", " ") + if err != nil { + return fmt.Errorf("marshal static routes: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(routes, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal static routes: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("Static Route ID", "Next Hop", "Prefix") + + for _, route := range routes { + table.AddRow(*route.RouteId, *route.Nexthop, *route.Prefix) + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/network-area/routes/list/list_test.go b/internal/cmd/beta/network-area/routes/list/list_test.go new file mode 100644 index 000000000..929ed0543 --- /dev/null +++ b/internal/cmd/beta/network-area/routes/list/list_test.go @@ -0,0 +1,212 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testOrganizationId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrganizationId, + networkAreaIdFlag: testNetworkAreaId, + limitFlag: "10", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: &testOrganizationId, + NetworkAreaId: &testNetworkAreaId, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreaRoutesRequest)) iaas.ApiListNetworkAreaRoutesRequest { + request := testClient.ListNetworkAreaRoutes(testCtx, testOrganizationId, testNetworkAreaId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "organization id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "organization id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "organization id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListNetworkAreaRoutesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/routes/routes.go b/internal/cmd/beta/network-area/routes/routes.go new file mode 100644 index 000000000..4671b3487 --- /dev/null +++ b/internal/cmd/beta/network-area/routes/routes.go @@ -0,0 +1,32 @@ +package routes + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "routes", + Short: "Provides functionality for static routes in STACKIT Network Areas", + Long: "Provides functionality for static routes in STACKIT Network Areas.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} diff --git a/internal/cmd/beta/network-area/update/update.go b/internal/cmd/beta/network-area/update/update.go new file mode 100644 index 000000000..5c595ab15 --- /dev/null +++ b/internal/cmd/beta/network-area/update/update.go @@ -0,0 +1,185 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" + rmUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + areaIdArg = "AREA_ID" + + nameFlag = "name" + organizationIdFlag = "organization-id" + areaIdFlag = "area-id" + dnsNameServersFlag = "dns-name-servers" + defaultPrefixLengthFlag = "default-prefix-length" + maxPrefixLengthFlag = "max-prefix-length" + minPrefixLengthFlag = "min-prefix-length" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + AreaId string + Name *string + OrganizationId *string + DnsNameServers *[]string + DefaultPrefixLength *int64 + MaxPrefixLength *int64 + MinPrefixLength *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a STACKIT Network Area (SNA)", + Long: "Updates a STACKIT Network Area (SNA) in an organization.", + Args: args.SingleArg(areaIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update network area with ID "xxx" in organization with ID "yyy" with new name "network-area-1-new"`, + "$ stackit beta network-area update xxx --organization-id yyy --name network-area-1-new", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + var orgLabel string + rmApiClient, err := rmClient.ConfigureClient(p) + if err == nil { + orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) + if err != nil { + p.Debug(print.ErrorLevel, "get organization name: %v", err) + orgLabel = *model.OrganizationId + } + } else { + p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update a network area for organization %q?", orgLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update network area: %w", err) + } + + return outputResult(p, model, orgLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(nameFlag, "n", "", "Network area name") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().StringSlice(dnsNameServersFlag, nil, "List of DNS name server IPs") + cmd.Flags().Int64(defaultPrefixLengthFlag, 0, "The default prefix length for networks in the network area") + cmd.Flags().Int64(maxPrefixLengthFlag, 0, "The maximum prefix length for networks in the network area") + cmd.Flags().Int64(minPrefixLengthFlag, 0, "The minimum prefix length for networks in the network area") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + areaId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + AreaId: areaId, + DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, dnsNameServersFlag), + DefaultPrefixLength: flags.FlagToInt64Pointer(p, cmd, defaultPrefixLengthFlag), + MaxPrefixLength: flags.FlagToInt64Pointer(p, cmd, maxPrefixLengthFlag), + MinPrefixLength: flags.FlagToInt64Pointer(p, cmd, minPrefixLengthFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiPartialUpdateNetworkAreaRequest { + req := apiClient.PartialUpdateNetworkArea(ctx, *model.OrganizationId, model.AreaId) + + payload := iaas.PartialUpdateNetworkAreaPayload{ + Name: model.Name, + AddressFamily: &iaas.UpdateAreaAddressFamily{ + Ipv4: &iaas.UpdateAreaIPv4{ + DefaultNameservers: model.DnsNameServers, + DefaultPrefixLen: model.DefaultPrefixLength, + MaxPrefixLen: model.MaxPrefixLength, + MinPrefixLen: model.MinPrefixLength, + }, + }, + } + + return req.PartialUpdateNetworkAreaPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, networkArea *iaas.NetworkArea) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(networkArea, "", " ") + if err != nil { + return fmt.Errorf("marshal network area: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network area: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Updated STACKIT Network Area for project %q.\n", projectLabel) + return nil + } +} diff --git a/internal/cmd/beta/network-area/update/update_test.go b/internal/cmd/beta/network-area/update/update_test.go new file mode 100644 index 000000000..f91e0b583 --- /dev/null +++ b/internal/cmd/beta/network-area/update/update_test.go @@ -0,0 +1,268 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() +var testAreaId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testAreaId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + nameFlag: "example-network-area-name", + organizationIdFlag: testOrgId, + dnsNameServersFlag: "1.1.1.0,1.1.2.0", + defaultPrefixLengthFlag: "24", + maxPrefixLengthFlag: "24", + minPrefixLengthFlag: "24", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example-network-area-name"), + OrganizationId: utils.Ptr(testOrgId), + AreaId: testAreaId, + DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + DefaultPrefixLength: utils.Ptr(int64(24)), + MaxPrefixLength: utils.Ptr(int64(24)), + MinPrefixLength: utils.Ptr(int64(24)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiPartialUpdateNetworkAreaRequest)) iaas.ApiPartialUpdateNetworkAreaRequest { + request := testClient.PartialUpdateNetworkArea(testCtx, testOrgId, testAreaId) + request = request.PartialUpdateNetworkAreaPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.PartialUpdateNetworkAreaPayload)) iaas.PartialUpdateNetworkAreaPayload { + payload := iaas.PartialUpdateNetworkAreaPayload{ + Name: utils.Ptr("example-network-area-name"), + AddressFamily: &iaas.UpdateAreaAddressFamily{ + Ipv4: &iaas.UpdateAreaIPv4{ + DefaultNameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + DefaultPrefixLen: utils.Ptr(int64(24)), + MaxPrefixLen: utils.Ptr(int64(24)), + MinPrefixLen: utils.Ptr(int64(24)), + }, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "required only", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, dnsNameServersFlag) + delete(flagValues, defaultPrefixLengthFlag) + delete(flagValues, maxPrefixLengthFlag) + delete(flagValues, minPrefixLengthFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.DnsNameServers = nil + model.DefaultPrefixLength = nil + model.MaxPrefixLength = nil + model.MinPrefixLength = nil + }), + }, + + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "area id missing", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "area id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[areaIdFlag] = "" + }), + isValid: false, + }, + { + description: "area id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[areaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiPartialUpdateNetworkAreaRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index e62407792..ab59637c7 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -39,6 +39,7 @@ const ( serviceEnablementCustomEndpointFlag = "service-enablement-custom-endpoint" skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" + iaasCustomEndpointFlag = "iaas-custom-endpoint" ) type inputModel struct { @@ -146,6 +147,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(serverBackupCustomEndpointFlag, "", "Server Backup API base URL, used in calls to this API") cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") + cmd.Flags().String(iaasCustomEndpointFlag, "", "IaaS API base URL, used in calls to this API") err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) cobra.CheckErr(err) @@ -190,6 +192,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.SQLServerFlexCustomEndpointKey, cmd.Flags().Lookup(sqlServerFlexCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.IaaSCustomEndpointKey, cmd.Flags().Lookup(iaasCustomEndpointFlag)) + cobra.CheckErr(err) } func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 46c541af5..58f985dfe 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -42,6 +42,7 @@ const ( serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" + iaasCustomEndpointFlag = "iaas-custom-endpoint" ) type inputModel struct { @@ -72,6 +73,7 @@ type inputModel struct { ServiceEnablementCustomEndpoint bool SKECustomEndpoint bool SQLServerFlexCustomEndpoint bool + IaaSCustomEndpoint bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -171,6 +173,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.SQLServerFlexCustomEndpoint { viper.Set(config.SQLServerFlexCustomEndpointKey, "") } + if model.IaaSCustomEndpoint { + viper.Set(config.IaaSCustomEndpointKey, "") + } err := config.Write() if err != nil { @@ -211,6 +216,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(serverBackupCustomEndpointFlag, false, "Server Backup base URL. If unset, uses the default base URL") cmd.Flags().Bool(skeCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(iaasCustomEndpointFlag, false, "IaaS API base URL. If unset, uses the default base URL") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { @@ -242,6 +248,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { ServerBackupCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverBackupCustomEndpointFlag), SKECustomEndpoint: flags.FlagToBoolValue(p, cmd, skeCustomEndpointFlag), SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), + IaaSCustomEndpoint: flags.FlagToBoolValue(p, cmd, iaasCustomEndpointFlag), } if p.IsVerbosityDebug() { diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index c1e87f48c..ba5989f3b 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -35,6 +35,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool serverBackupCustomEndpointFlag: true, skeCustomEndpointFlag: true, sqlServerFlexCustomEndpointFlag: true, + iaasCustomEndpointFlag: true, } for _, mod := range mods { mod(flagValues) @@ -68,6 +69,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { ServerBackupCustomEndpoint: true, SKECustomEndpoint: true, SQLServerFlexCustomEndpoint: true, + IaaSCustomEndpoint: true, } for _, mod := range mods { mod(model) @@ -117,6 +119,7 @@ func TestParseInput(t *testing.T) { model.ServerBackupCustomEndpoint = false model.SKECustomEndpoint = false model.SQLServerFlexCustomEndpoint = false + model.IaaSCustomEndpoint = false }), }, { diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index aa68e5290..1564b47e1 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -22,28 +22,37 @@ import ( ) const ( - parentIdFlag = "parent-id" - nameFlag = "name" - labelFlag = "label" - - ownerRole = "project.owner" - labelKeyRegex = `[A-ZÄÜÖa-zäüöß0-9_-]{1,64}` - labelValueRegex = `^$|[A-ZÄÜÖa-zäüöß0-9_-]{1,64}` + parentIdFlag = "parent-id" + nameFlag = "name" + labelFlag = "label" + networkAreaIdFlag = "network-area-id" + + ownerRole = "project.owner" + labelKeyRegex = `[A-ZÄÜÖa-zäüöß0-9_-]{1,64}` + labelValueRegex = `^$|[A-ZÄÜÖa-zäüöß0-9_-]{1,64}` + networkAreaLabel = "networkArea" ) type inputModel struct { *globalflags.GlobalFlagModel - ParentId *string - Name *string - Labels *map[string]string + ParentId *string + Name *string + Labels *map[string]string + NetworkAreaId *string } func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a STACKIT project", - Long: "Creates a STACKIT project.", - Args: args.NoArgs, + Long: fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n", + "Creates a STACKIT project.", + "You can associate a project with a STACKIT Network Area (SNA) by providing the ID of the SNA.", + "The STACKIT Network Area (SNA) allows projects within an organization to be connected to each other on a network level.", + "This makes it possible to connect various resources of the projects within an SNA and also simplifies the connection with on-prem environments (hybrid cloud).", + "The network type can no longer be changed after the project has been created. If you require a different network type, you must create a new project.", + ), + Args: args.NoArgs, Example: examples.Build( examples.NewExample( `Create a STACKIT project`, @@ -51,6 +60,9 @@ func NewCmd(p *print.Printer) *cobra.Command { examples.NewExample( `Create a STACKIT project with a set of labels`, "$ stackit project create --parent-id xxxx --name my-project --label key=value --label foo=bar"), + examples.NewExample( + `Create a STACKIT project with a network area`, + "$ stackit project create --parent-id xxxx --name my-project --network-area-id yyyy"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -94,6 +106,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(parentIdFlag, "", "Parent resource identifier. Both container ID (user-friendly) and UUID are supported") cmd.Flags().String(nameFlag, "", "Project name") cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a project. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "ID of a STACKIT Network Area (SNA) to associate with the project.") err := flags.MarkFlagsRequired(cmd, parentIdFlag, nameFlag) cobra.CheckErr(err) @@ -128,6 +141,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ParentId: flags.FlagToStringPointer(p, cmd, parentIdFlag), Name: flags.FlagToStringPointer(p, cmd, nameFlag), Labels: labels, + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), } if p.IsVerbosityDebug() { @@ -174,10 +188,19 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *resourceman return req, fmt.Errorf("the authenticated subject email cannot be empty, please report this issue") } + labels := model.Labels + + if model.NetworkAreaId != nil { + if labels == nil { + labels = &map[string]string{} + } + (*labels)[networkAreaLabel] = *model.NetworkAreaId + } + req = req.CreateProjectPayload(resourcemanager.CreateProjectPayload{ ContainerParentId: model.ParentId, Name: model.Name, - Labels: model.Labels, + Labels: labels, Members: &[]resourcemanager.Member{ { Role: utils.Ptr(ownerRole), diff --git a/internal/cmd/project/create/create_test.go b/internal/cmd/project/create/create_test.go index e1e6365ad..43fa09b92 100644 --- a/internal/cmd/project/create/create_test.go +++ b/internal/cmd/project/create/create_test.go @@ -21,13 +21,15 @@ type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &resourcemanager.APIClient{} var testParentId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() var testEmail = "email" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - parentIdFlag: testParentId, - nameFlag: "name", - labelFlag: "key=value", + parentIdFlag: testParentId, + nameFlag: "name", + labelFlag: "key=value", + networkAreaIdFlag: testNetworkAreaId, } for _, mod := range mods { mod(flagValues) @@ -43,6 +45,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Labels: utils.Ptr(map[string]string{ "key": "value", }), + NetworkAreaId: utils.Ptr(testNetworkAreaId), } for _, mod := range mods { mod(model) @@ -50,13 +53,13 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *resourcemanager.ApiCreateProjectRequest)) resourcemanager.ApiCreateProjectRequest { - request := testClient.CreateProject(testCtx) - request = request.CreateProjectPayload(resourcemanager.CreateProjectPayload{ +func fixturePayload(mods ...func(payload *resourcemanager.CreateProjectPayload)) resourcemanager.CreateProjectPayload { + payload := resourcemanager.CreateProjectPayload{ ContainerParentId: utils.Ptr(testParentId), Name: utils.Ptr(nameFlag), Labels: utils.Ptr(map[string]string{ - "key": "value", + "key": "value", + networkAreaLabel: testNetworkAreaId, }), Members: &[]resourcemanager.Member{ { @@ -64,7 +67,16 @@ func fixtureRequest(mods ...func(request *resourcemanager.ApiCreateProjectReques Subject: utils.Ptr(testEmail), }, }, - }) + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *resourcemanager.ApiCreateProjectRequest)) resourcemanager.ApiCreateProjectRequest { + request := testClient.CreateProject(testCtx) + request = request.CreateProjectPayload(fixturePayload()) for _, mod := range mods { mod(&request) } @@ -136,6 +148,31 @@ func TestParseInput(t *testing.T) { labelValues: []string{"key"}, isValid: false, }, + { + description: "network_area_id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: true, + expectedModel: fixtureInputModel( + func(model *inputModel) { + model.NetworkAreaId = nil + }), + }, + { + description: "network_area_id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network_area_id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, } for _, tt := range tests { @@ -228,6 +265,51 @@ func TestBuildRequest(t *testing.T) { expectedRequest: fixtureRequest(), isValid: true, }, + { + description: "missing_network_area_id sa_key", + model: fixtureInputModel( + func(model *inputModel) { + model.NetworkAreaId = nil + }), + authFlow: auth.AUTH_FLOW_SERVICE_ACCOUNT_KEY, + sa_email: utils.Ptr(testEmail), + expectedRequest: fixtureRequest().CreateProjectPayload(fixturePayload( + func(payload *resourcemanager.CreateProjectPayload) { + delete((*payload.Labels), networkAreaLabel) + }), + ), + isValid: true, + }, + { + description: "missing_network_area_id sa_token", + model: fixtureInputModel( + func(model *inputModel) { + model.NetworkAreaId = nil + }), + authFlow: auth.AUTH_FLOW_SERVICE_ACCOUNT_TOKEN, + sa_email: utils.Ptr(testEmail), + expectedRequest: fixtureRequest().CreateProjectPayload(fixturePayload( + func(payload *resourcemanager.CreateProjectPayload) { + delete((*payload.Labels), networkAreaLabel) + }), + ), + isValid: true, + }, + { + description: "missing_network_area_id user", + model: fixtureInputModel( + func(model *inputModel) { + model.NetworkAreaId = nil + }), + authFlow: auth.AUTH_FLOW_USER_TOKEN, + user_email: utils.Ptr(testEmail), + expectedRequest: fixtureRequest().CreateProjectPayload(fixturePayload( + func(payload *resourcemanager.CreateProjectPayload) { + delete((*payload.Labels), networkAreaLabel) + }), + ), + isValid: true, + }, { description: "missing_auth_flow", model: fixtureInputModel(), diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 016b6248a..4b2d897ac 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -38,6 +38,7 @@ const ( ServerBackupCustomEndpointKey = "serverbackup_custom_endpoint" SKECustomEndpointKey = "ske_custom_endpoint" SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" + IaaSCustomEndpointKey = "iaas_custom_endpoint" ProjectNameKey = "project_name" DefaultProfileName = "default" @@ -86,6 +87,7 @@ var ConfigKeys = []string{ ServerBackupCustomEndpointKey, SKECustomEndpointKey, SQLServerFlexCustomEndpointKey, + IaaSCustomEndpointKey, } var defaultConfigFolderPath string @@ -158,6 +160,7 @@ func setConfigDefaults() { viper.SetDefault(ServerBackupCustomEndpointKey, "") viper.SetDefault(SKECustomEndpointKey, "") viper.SetDefault(SQLServerFlexCustomEndpointKey, "") + viper.SetDefault(IaaSCustomEndpointKey, "") } func getConfigFilePath(configFolder string) string { diff --git a/internal/pkg/projectname/project_name.go b/internal/pkg/projectname/project_name.go index 1c6532b48..b50239b9f 100644 --- a/internal/pkg/projectname/project_name.go +++ b/internal/pkg/projectname/project_name.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -33,12 +34,11 @@ func GetProjectName(ctx context.Context, p *print.Printer, cmd *cobra.Command) ( if err != nil { return "", fmt.Errorf("configure resource manager client: %w", err) } - req := apiClient.GetProject(ctx, projectId) - resp, err := req.Execute() + + projectName, err := utils.GetProjectName(ctx, apiClient, projectId) if err != nil { - return "", fmt.Errorf("read project details: %w", err) + return "", fmt.Errorf("get project name: %w", err) } - projectName := *resp.Name // If project ID is set in config, we store the project name in config // (So next time we can just pull it from there) diff --git a/internal/pkg/services/iaas/client/client.go b/internal/pkg/services/iaas/client/client.go new file mode 100644 index 000000000..c9301496b --- /dev/null +++ b/internal/pkg/services/iaas/client/client.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/spf13/viper" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +func ConfigureClient(p *print.Printer) (*iaas.APIClient, error) { + var err error + var apiClient *iaas.APIClient + var cfgOptions []sdkConfig.ConfigurationOption + + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return nil, &errors.AuthError{} + } + cfgOptions = append(cfgOptions, authCfgOption) + + customEndpoint := viper.GetString(config.IaaSCustomEndpointKey) + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } else { + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err = iaas.NewAPIClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return nil, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go new file mode 100644 index 000000000..7b8d103c0 --- /dev/null +++ b/internal/pkg/services/iaas/utils/utils.go @@ -0,0 +1,60 @@ +package utils + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type IaaSClient interface { + GetNetworkAreaExecute(ctx context.Context, organizationId, areaId string) (*iaas.NetworkArea, error) + ListNetworkAreaProjectsExecute(ctx context.Context, organizationId, areaId string) (*iaas.ProjectListResponse, error) + GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) +} + +func GetNetworkAreaName(ctx context.Context, apiClient IaaSClient, organizationId, areaId string) (string, error) { + resp, err := apiClient.GetNetworkAreaExecute(ctx, organizationId, areaId) + if err != nil { + return "", fmt.Errorf("get network area: %w", err) + } + return *resp.Name, nil +} + +func ListAttachedProjects(ctx context.Context, apiClient IaaSClient, organizationId, areaId string) ([]string, error) { + resp, err := apiClient.ListNetworkAreaProjectsExecute(ctx, organizationId, areaId) + if err != nil { + return nil, fmt.Errorf("list network area attached projects: %w", err) + } + return *resp.Items, nil +} + +func GetNetworkRangePrefix(ctx context.Context, apiClient IaaSClient, organizationId, areaId, networkRangeId string) (string, error) { + resp, err := apiClient.GetNetworkAreaRangeExecute(ctx, organizationId, areaId, networkRangeId) + if err != nil { + return "", fmt.Errorf("get network range: %w", err) + } + return *resp.Prefix, nil +} + +// GetRouteFromAPIResponse returns the static route from the API response that matches the prefix and nexthop +// This works because static routes are unique by prefix and nexthop +func GetRouteFromAPIResponse(prefix, nexthop string, routes *[]iaas.Route) (iaas.Route, error) { + for _, route := range *routes { + if *route.Prefix == prefix && *route.Nexthop == nexthop { + return route, nil + } + } + return iaas.Route{}, fmt.Errorf("new static route not found in API response") +} + +// GetNetworkRangeFromAPIResponse returns the network range from the API response that matches the given prefix +// This works because network range prefixes are unique in the same SNA +func GetNetworkRangeFromAPIResponse(prefix string, networkRanges *[]iaas.NetworkRange) (iaas.NetworkRange, error) { + for _, networkRange := range *networkRanges { + if *networkRange.Prefix == prefix { + return networkRange, nil + } + } + return iaas.NetworkRange{}, fmt.Errorf("new network range not found in API response") +} diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go new file mode 100644 index 000000000..d3165a4d6 --- /dev/null +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -0,0 +1,327 @@ +package utils + +import ( + "context" + "fmt" + "reflect" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type IaaSClientMocked struct { + GetNetworkAreaFails bool + GetNetworkAreaResp *iaas.NetworkArea + GetAttachedProjectsFails bool + GetAttachedProjectsResp *iaas.ProjectListResponse + GetNetworkAreaRangeFails bool + GetNetworkAreaRangeResp *iaas.NetworkRange +} + +func (m *IaaSClientMocked) GetNetworkAreaExecute(_ context.Context, _, _ string) (*iaas.NetworkArea, error) { + if m.GetNetworkAreaFails { + return nil, fmt.Errorf("could not get network area") + } + return m.GetNetworkAreaResp, nil +} + +func (m *IaaSClientMocked) ListNetworkAreaProjectsExecute(_ context.Context, _, _ string) (*iaas.ProjectListResponse, error) { + if m.GetAttachedProjectsFails { + return nil, fmt.Errorf("could not get attached projects") + } + return m.GetAttachedProjectsResp, nil +} + +func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _ string) (*iaas.NetworkRange, error) { + if m.GetNetworkAreaRangeFails { + return nil, fmt.Errorf("could not get network range") + } + return m.GetNetworkAreaRangeResp, nil +} + +func TestGetNetworkAreaName(t *testing.T) { + type args struct { + getInstanceFails bool + getInstanceResp *iaas.NetworkArea + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "base", + args: args{ + getInstanceResp: &iaas.NetworkArea{ + Name: utils.Ptr("test"), + }, + }, + want: "test", + }, + { + name: "get network area fails", + args: args{ + getInstanceFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetNetworkAreaFails: tt.args.getInstanceFails, + GetNetworkAreaResp: tt.args.getInstanceResp, + } + got, err := GetNetworkAreaName(context.Background(), m, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetNetworkAreaName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetNetworkAreaName() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestListAttachedProjects(t *testing.T) { + type args struct { + getAttachedProjectsFails bool + getAttachedProjectsResp *iaas.ProjectListResponse + } + tests := []struct { + name string + args args + want []string + wantErr bool + }{ + { + name: "base", + args: args{ + getAttachedProjectsResp: &iaas.ProjectListResponse{ + Items: &[]string{"test"}, + }, + }, + want: []string{"test"}, + }, + { + name: "get attached projects fails", + args: args{ + getAttachedProjectsFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetAttachedProjectsFails: tt.args.getAttachedProjectsFails, + GetAttachedProjectsResp: tt.args.getAttachedProjectsResp, + } + got, err := ListAttachedProjects(context.Background(), m, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetAttachedProjects() error = %v, wantErr %v", err, tt.wantErr) + return + } + if fmt.Sprintf("%v", got) != fmt.Sprintf("%v", tt.want) { + t.Errorf("GetAttachedProjects() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetNetworkRangePrefix(t *testing.T) { + type args struct { + getNetworkAreaRangeFails bool + getNetworkAreaRangeResp *iaas.NetworkRange + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "base", + args: args{ + getNetworkAreaRangeResp: &iaas.NetworkRange{ + Prefix: utils.Ptr("test"), + }, + }, + want: "test", + }, + { + name: "get network area range fails", + args: args{ + getNetworkAreaRangeFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetNetworkAreaRangeFails: tt.args.getNetworkAreaRangeFails, + GetNetworkAreaRangeResp: tt.args.getNetworkAreaRangeResp, + } + got, err := GetNetworkRangePrefix(context.Background(), m, "", "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetNetworkRangePrefix() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetNetworkRangePrefix() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetRouteFromAPIResponse(t *testing.T) { + type args struct { + prefix string + nexthop string + routes *[]iaas.Route + } + tests := []struct { + name string + args args + want iaas.Route + wantErr bool + }{ + { + name: "base", + args: args{ + prefix: "1.1.1.0/24", + nexthop: "1.1.1.1", + routes: &[]iaas.Route{ + { + Prefix: utils.Ptr("1.1.1.0/24"), + Nexthop: utils.Ptr("1.1.1.1"), + }, + { + Prefix: utils.Ptr("2.2.2.0/24"), + Nexthop: utils.Ptr("2.2.2.2"), + }, + { + Prefix: utils.Ptr("3.3.3.0/24"), + Nexthop: utils.Ptr("3.3.3.3"), + }, + }, + }, + want: iaas.Route{ + Prefix: utils.Ptr("1.1.1.0/24"), + Nexthop: utils.Ptr("1.1.1.1"), + }, + }, + { + name: "not found", + args: args{ + prefix: "1.1.1.0/24", + nexthop: "1.1.1.1", + routes: &[]iaas.Route{ + { + Prefix: utils.Ptr("2.2.2.0/24"), + Nexthop: utils.Ptr("2.2.2.2"), + }, + { + Prefix: utils.Ptr("3.3.3.0/24"), + Nexthop: utils.Ptr("3.3.3.3"), + }, + }, + }, + wantErr: true, + }, + { + name: "empty", + args: args{ + prefix: "1.1.1.0/24", + nexthop: "1.1.1.1", + routes: &[]iaas.Route{}, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetRouteFromAPIResponse(tt.args.prefix, tt.args.nexthop, tt.args.routes) + if (err != nil) != tt.wantErr { + t.Errorf("GetRouteFromAPIResponse() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetRouteFromAPIResponse() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetNetworkRangeFromAPIResponse(t *testing.T) { + type args struct { + prefix string + networkRanges *[]iaas.NetworkRange + } + tests := []struct { + name string + args args + want iaas.NetworkRange + wantErr bool + }{ + { + name: "base", + args: args{ + prefix: "1.1.1.0/24", + networkRanges: &[]iaas.NetworkRange{ + { + Prefix: utils.Ptr("1.1.1.0/24"), + }, + { + Prefix: utils.Ptr("2.2.2.0/24"), + }, + { + Prefix: utils.Ptr("3.3.3.0/24"), + }, + }, + }, + want: iaas.NetworkRange{ + Prefix: utils.Ptr("1.1.1.0/24"), + }, + }, + { + name: "not found", + args: args{ + prefix: "1.1.1.0/24", + networkRanges: &[]iaas.NetworkRange{ + { + Prefix: utils.Ptr("2.2.2.0/24"), + }, + { + Prefix: utils.Ptr("3.3.3.0/24"), + }, + }, + }, + wantErr: true, + }, + { + name: "empty", + args: args{ + prefix: "1.1.1.0/24", + networkRanges: &[]iaas.NetworkRange{}, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetNetworkRangeFromAPIResponse(tt.args.prefix, tt.args.networkRanges) + if (err != nil) != tt.wantErr { + t.Errorf("GetNetworkRangeFromAPIResponse() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetNetworkRangeFromAPIResponse() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/pkg/services/resourcemanager/utils/utils.go b/internal/pkg/services/resourcemanager/utils/utils.go new file mode 100644 index 000000000..bf8724b06 --- /dev/null +++ b/internal/pkg/services/resourcemanager/utils/utils.go @@ -0,0 +1,32 @@ +package utils + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" +) + +type ResourceManagerClient interface { + GetOrganizationExecute(ctx context.Context, organizationId string) (*resourcemanager.OrganizationResponse, error) + GetProjectExecute(ctx context.Context, projectId string) (*resourcemanager.GetProjectResponse, error) +} + +// GetOrganizationName returns the name of an organization by its ID. +func GetOrganizationName(ctx context.Context, apiClient ResourceManagerClient, orgId string) (string, error) { + resp, err := apiClient.GetOrganizationExecute(ctx, orgId) + if err != nil { + return "", fmt.Errorf("get organization details: %w", err) + } + + return *resp.Name, nil +} + +func GetProjectName(ctx context.Context, apiClient ResourceManagerClient, projectId string) (string, error) { + resp, err := apiClient.GetProjectExecute(ctx, projectId) + if err != nil { + return "", fmt.Errorf("get project details: %w", err) + } + + return *resp.Name, nil +} diff --git a/internal/pkg/services/resourcemanager/utils/utils_test.go b/internal/pkg/services/resourcemanager/utils/utils_test.go new file mode 100644 index 000000000..bcd0ad2d0 --- /dev/null +++ b/internal/pkg/services/resourcemanager/utils/utils_test.go @@ -0,0 +1,136 @@ +package utils + +import ( + "context" + "fmt" + "testing" + + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" +) + +var ( + testOrgId = uuid.NewString() +) + +const ( + testOrgName = "organization" +) + +type resourceManagerClientMocked struct { + getOrganizationFails bool + getOrganizationResp *resourcemanager.OrganizationResponse + getProjectFails bool + getProjectResp *resourcemanager.GetProjectResponse +} + +func (s *resourceManagerClientMocked) GetOrganizationExecute(_ context.Context, _ string) (*resourcemanager.OrganizationResponse, error) { + if s.getOrganizationFails { + return nil, fmt.Errorf("could not get organization") + } + return s.getOrganizationResp, nil +} + +func (s *resourceManagerClientMocked) GetProjectExecute(_ context.Context, _ string) (*resourcemanager.GetProjectResponse, error) { + if s.getProjectFails { + return nil, fmt.Errorf("could not get project") + } + return s.getProjectResp, nil +} + +func TestGetOrganizationName(t *testing.T) { + tests := []struct { + description string + getOrganizationFails bool + getOrganizationResp *resourcemanager.OrganizationResponse + isValid bool + expectedOutput string + }{ + { + description: "base", + getOrganizationResp: &resourcemanager.OrganizationResponse{ + Name: utils.Ptr(testOrgName), + }, + isValid: true, + expectedOutput: testOrgName, + }, + { + description: "get organization fails", + getOrganizationFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &resourceManagerClientMocked{ + getOrganizationFails: tt.getOrganizationFails, + getOrganizationResp: tt.getOrganizationResp, + } + + output, err := GetOrganizationName(context.Background(), client, testOrgId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %s, got %s", tt.expectedOutput, output) + } + }) + } +} + +func TestGetProjectName(t *testing.T) { + tests := []struct { + description string + getProjectFails bool + getProjectResp *resourcemanager.GetProjectResponse + isValid bool + expectedOutput string + }{ + { + description: "base", + getProjectResp: &resourcemanager.GetProjectResponse{ + Name: utils.Ptr("project"), + }, + isValid: true, + expectedOutput: "project", + }, + { + description: "get project fails", + getProjectFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &resourceManagerClientMocked{ + getProjectFails: tt.getProjectFails, + getProjectResp: tt.getProjectResp, + } + + output, err := GetProjectName(context.Background(), client, testOrgId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %s, got %s", tt.expectedOutput, output) + } + }) + } +} From e4272f08392e628d4f28ddd7e8f4c6e8273f2c1b Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 1 Aug 2024 17:47:11 +0200 Subject: [PATCH 029/619] change commands to singular form (#436) --- docs/stackit_beta_network-area.md | 4 ++-- ... => stackit_beta_network-area_network-range.md} | 14 +++++++------- ...ckit_beta_network-area_network-range_create.md} | 10 +++++----- ...ckit_beta_network-area_network-range_delete.md} | 10 +++++----- ...it_beta_network-area_network-range_describe.md} | 10 +++++----- ...tackit_beta_network-area_network-range_list.md} | 14 +++++++------- ...outes.md => stackit_beta_network-area_route.md} | 14 +++++++------- ...d => stackit_beta_network-area_route_create.md} | 10 +++++----- ...d => stackit_beta_network-area_route_delete.md} | 10 +++++----- ...=> stackit_beta_network-area_route_describe.md} | 12 ++++++------ ....md => stackit_beta_network-area_route_list.md} | 14 +++++++------- .../create/create.go | 2 +- .../create/create_test.go | 0 .../delete/delete.go | 2 +- .../delete/delete_test.go | 0 .../describe/describe.go | 2 +- .../describe/describe_test.go | 0 .../{network-ranges => network-range}/list/list.go | 6 +++--- .../list/list_test.go | 0 .../network_range.go} | 12 ++++++------ internal/cmd/beta/network-area/network_area.go | 8 ++++---- .../{routes => route}/create/create.go | 2 +- .../{routes => route}/create/create_test.go | 0 .../{routes => route}/delete/delete.go | 2 +- .../{routes => route}/delete/delete_test.go | 0 .../{routes => route}/describe/describe.go | 4 ++-- .../{routes => route}/describe/describe_test.go | 0 .../network-area/{routes => route}/list/list.go | 6 +++--- .../{routes => route}/list/list_test.go | 0 .../beta/network-area/{routes => route}/routes.go | 12 ++++++------ 30 files changed, 90 insertions(+), 90 deletions(-) rename docs/{stackit_beta_network-area_network-ranges.md => stackit_beta_network-area_network-range.md} (51%) rename docs/{stackit_beta_network-area_network-ranges_create.md => stackit_beta_network-area_network-range_create.md} (69%) rename docs/{stackit_beta_network-area_network-ranges_delete.md => stackit_beta_network-area_network-range_delete.md} (69%) rename docs/{stackit_beta_network-area_network-ranges_describe.md => stackit_beta_network-area_network-range_describe.md} (69%) rename docs/{stackit_beta_network-area_network-ranges_list.md => stackit_beta_network-area_network-range_list.md} (66%) rename docs/{stackit_beta_network-area_routes.md => stackit_beta_network-area_route.md} (50%) rename docs/{stackit_beta_network-area_routes_create.md => stackit_beta_network-area_route_create.md} (76%) rename docs/{stackit_beta_network-area_routes_delete.md => stackit_beta_network-area_route_delete.md} (72%) rename docs/{stackit_beta_network-area_routes_describe.md => stackit_beta_network-area_route_describe.md} (69%) rename docs/{stackit_beta_network-area_routes_list.md => stackit_beta_network-area_route_list.md} (68%) rename internal/cmd/beta/network-area/{network-ranges => network-range}/create/create.go (97%) rename internal/cmd/beta/network-area/{network-ranges => network-range}/create/create_test.go (100%) rename internal/cmd/beta/network-area/{network-ranges => network-range}/delete/delete.go (97%) rename internal/cmd/beta/network-area/{network-ranges => network-range}/delete/delete_test.go (100%) rename internal/cmd/beta/network-area/{network-ranges => network-range}/describe/describe.go (97%) rename internal/cmd/beta/network-area/{network-ranges => network-range}/describe/describe_test.go (100%) rename internal/cmd/beta/network-area/{network-ranges => network-range}/list/list.go (93%) rename internal/cmd/beta/network-area/{network-ranges => network-range}/list/list_test.go (100%) rename internal/cmd/beta/network-area/{network-ranges/network_ranges.go => network-range/network_range.go} (85%) rename internal/cmd/beta/network-area/{routes => route}/create/create.go (97%) rename internal/cmd/beta/network-area/{routes => route}/create/create_test.go (100%) rename internal/cmd/beta/network-area/{routes => route}/delete/delete.go (97%) rename internal/cmd/beta/network-area/{routes => route}/delete/delete_test.go (100%) rename internal/cmd/beta/network-area/{routes => route}/describe/describe.go (95%) rename internal/cmd/beta/network-area/{routes => route}/describe/describe_test.go (100%) rename internal/cmd/beta/network-area/{routes => route}/list/list.go (94%) rename internal/cmd/beta/network-area/{routes => route}/list/list_test.go (100%) rename internal/cmd/beta/network-area/{routes => route}/routes.go (89%) diff --git a/docs/stackit_beta_network-area.md b/docs/stackit_beta_network-area.md index 49859b4c1..793bb2cd4 100644 --- a/docs/stackit_beta_network-area.md +++ b/docs/stackit_beta_network-area.md @@ -33,7 +33,7 @@ stackit beta network-area [flags] * [stackit beta network-area delete](./stackit_beta_network-area_delete.md) - Deletes a STACKIT Network Area (SNA) * [stackit beta network-area describe](./stackit_beta_network-area_describe.md) - Shows details of a STACKIT Network Area * [stackit beta network-area list](./stackit_beta_network-area_list.md) - Lists all STACKIT Network Areas (SNA) of an organization -* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas -* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas * [stackit beta network-area update](./stackit_beta_network-area_update.md) - Updates a STACKIT Network Area (SNA) diff --git a/docs/stackit_beta_network-area_network-ranges.md b/docs/stackit_beta_network-area_network-range.md similarity index 51% rename from docs/stackit_beta_network-area_network-ranges.md rename to docs/stackit_beta_network-area_network-range.md index 2fa256f86..3c4ab566f 100644 --- a/docs/stackit_beta_network-area_network-ranges.md +++ b/docs/stackit_beta_network-area_network-range.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-ranges +## stackit beta network-area network-range Provides functionality for network ranges in STACKIT Network Areas @@ -7,13 +7,13 @@ Provides functionality for network ranges in STACKIT Network Areas Provides functionality for network ranges in STACKIT Network Areas. ``` -stackit beta network-area network-ranges [flags] +stackit beta network-area network-range [flags] ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-ranges" + -h, --help Help for "stackit beta network-area network-range" ``` ### Options inherited from parent commands @@ -29,8 +29,8 @@ stackit beta network-area network-ranges [flags] ### SEE ALSO * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) -* [stackit beta network-area network-ranges create](./stackit_beta_network-area_network-ranges_create.md) - Creates a network range in a STACKIT Network Area (SNA) -* [stackit beta network-area network-ranges delete](./stackit_beta_network-area_network-ranges_delete.md) - Deletes a network range in a STACKIT Network Area (SNA) -* [stackit beta network-area network-ranges describe](./stackit_beta_network-area_network-ranges_describe.md) - Shows details of a network range in a STACKIT Network Area (SNA) -* [stackit beta network-area network-ranges list](./stackit_beta_network-area_network-ranges_list.md) - Lists all network ranges in a STACKIT Network Area (SNA) +* [stackit beta network-area network-range create](./stackit_beta_network-area_network-range_create.md) - Creates a network range in a STACKIT Network Area (SNA) +* [stackit beta network-area network-range delete](./stackit_beta_network-area_network-range_delete.md) - Deletes a network range in a STACKIT Network Area (SNA) +* [stackit beta network-area network-range describe](./stackit_beta_network-area_network-range_describe.md) - Shows details of a network range in a STACKIT Network Area (SNA) +* [stackit beta network-area network-range list](./stackit_beta_network-area_network-range_list.md) - Lists all network ranges in a STACKIT Network Area (SNA) diff --git a/docs/stackit_beta_network-area_network-ranges_create.md b/docs/stackit_beta_network-area_network-range_create.md similarity index 69% rename from docs/stackit_beta_network-area_network-ranges_create.md rename to docs/stackit_beta_network-area_network-range_create.md index 1c2f86443..2bb284744 100644 --- a/docs/stackit_beta_network-area_network-ranges_create.md +++ b/docs/stackit_beta_network-area_network-range_create.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-ranges create +## stackit beta network-area network-range create Creates a network range in a STACKIT Network Area (SNA) @@ -7,20 +7,20 @@ Creates a network range in a STACKIT Network Area (SNA) Creates a network range in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-ranges create [flags] +stackit beta network-area network-range create [flags] ``` ### Examples ``` Create a network range in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area network-ranges create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24" + $ stackit beta network-area network-range create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24" ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-ranges create" + -h, --help Help for "stackit beta network-area network-range create" --network-area-id string STACKIT Network Area (SNA) ID --network-range string Network range to create in CIDR notation --organization-id string Organization ID @@ -38,5 +38,5 @@ stackit beta network-area network-ranges create [flags] ### SEE ALSO -* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_network-ranges_delete.md b/docs/stackit_beta_network-area_network-range_delete.md similarity index 69% rename from docs/stackit_beta_network-area_network-ranges_delete.md rename to docs/stackit_beta_network-area_network-range_delete.md index 3dfa26a05..1d8588478 100644 --- a/docs/stackit_beta_network-area_network-ranges_delete.md +++ b/docs/stackit_beta_network-area_network-range_delete.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-ranges delete +## stackit beta network-area network-range delete Deletes a network range in a STACKIT Network Area (SNA) @@ -7,20 +7,20 @@ Deletes a network range in a STACKIT Network Area (SNA) Deletes a network range in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-ranges delete [flags] +stackit beta network-area network-range delete [flags] ``` ### Examples ``` Delete network range with id "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area network-ranges delete xxx --network-area-id yyy --organization-id zzz + $ stackit beta network-area network-range delete xxx --network-area-id yyy --organization-id zzz ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-ranges delete" + -h, --help Help for "stackit beta network-area network-range delete" --network-area-id string STACKIT Network Area (SNA) ID --organization-id string Organization ID ``` @@ -37,5 +37,5 @@ stackit beta network-area network-ranges delete [flags] ### SEE ALSO -* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_network-ranges_describe.md b/docs/stackit_beta_network-area_network-range_describe.md similarity index 69% rename from docs/stackit_beta_network-area_network-ranges_describe.md rename to docs/stackit_beta_network-area_network-range_describe.md index 4d5b2442f..ef5244d0e 100644 --- a/docs/stackit_beta_network-area_network-ranges_describe.md +++ b/docs/stackit_beta_network-area_network-range_describe.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-ranges describe +## stackit beta network-area network-range describe Shows details of a network range in a STACKIT Network Area (SNA) @@ -7,20 +7,20 @@ Shows details of a network range in a STACKIT Network Area (SNA) Shows details of a network range in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-ranges describe [flags] +stackit beta network-area network-range describe [flags] ``` ### Examples ``` Show details of a network range with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area network-ranges describe xxx --network-area-id yyy --organization-id zzz + $ stackit beta network-area network-range describe xxx --network-area-id yyy --organization-id zzz ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-ranges describe" + -h, --help Help for "stackit beta network-area network-range describe" --network-area-id string STACKIT Network Area (SNA) ID --organization-id string Organization ID ``` @@ -37,5 +37,5 @@ stackit beta network-area network-ranges describe [flags] ### SEE ALSO -* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_network-ranges_list.md b/docs/stackit_beta_network-area_network-range_list.md similarity index 66% rename from docs/stackit_beta_network-area_network-ranges_list.md rename to docs/stackit_beta_network-area_network-range_list.md index e42a53e1b..0bd85ee5e 100644 --- a/docs/stackit_beta_network-area_network-ranges_list.md +++ b/docs/stackit_beta_network-area_network-range_list.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-ranges list +## stackit beta network-area network-range list Lists all network ranges in a STACKIT Network Area (SNA) @@ -7,26 +7,26 @@ Lists all network ranges in a STACKIT Network Area (SNA) Lists all network ranges in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-ranges list [flags] +stackit beta network-area network-range list [flags] ``` ### Examples ``` Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy + $ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format - $ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy --output-format json + $ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --output-format json Lists up to 10 network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy --limit 10 + $ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-ranges list" + -h, --help Help for "stackit beta network-area network-range list" --limit int Maximum number of entries to list --network-area-id string STACKIT Network Area (SNA) ID --organization-id string Organization ID @@ -44,5 +44,5 @@ stackit beta network-area network-ranges list [flags] ### SEE ALSO -* [stackit beta network-area network-ranges](./stackit_beta_network-area_network-ranges.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_routes.md b/docs/stackit_beta_network-area_route.md similarity index 50% rename from docs/stackit_beta_network-area_routes.md rename to docs/stackit_beta_network-area_route.md index d8d7bd82e..39efe6da8 100644 --- a/docs/stackit_beta_network-area_routes.md +++ b/docs/stackit_beta_network-area_route.md @@ -1,4 +1,4 @@ -## stackit beta network-area routes +## stackit beta network-area route Provides functionality for static routes in STACKIT Network Areas @@ -7,13 +7,13 @@ Provides functionality for static routes in STACKIT Network Areas Provides functionality for static routes in STACKIT Network Areas. ``` -stackit beta network-area routes [flags] +stackit beta network-area route [flags] ``` ### Options ``` - -h, --help Help for "stackit beta network-area routes" + -h, --help Help for "stackit beta network-area route" ``` ### Options inherited from parent commands @@ -29,8 +29,8 @@ stackit beta network-area routes [flags] ### SEE ALSO * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) -* [stackit beta network-area routes create](./stackit_beta_network-area_routes_create.md) - Creates a static route in a STACKIT Network Area (SNA) -* [stackit beta network-area routes delete](./stackit_beta_network-area_routes_delete.md) - Deletes a static route in a STACKIT Network Area (SNA) -* [stackit beta network-area routes describe](./stackit_beta_network-area_routes_describe.md) - Shows details of a static route in a STACKIT Network Area (SNA) -* [stackit beta network-area routes list](./stackit_beta_network-area_routes_list.md) - Lists all static routes in a STACKIT Network Area (SNA) +* [stackit beta network-area route create](./stackit_beta_network-area_route_create.md) - Creates a static route in a STACKIT Network Area (SNA) +* [stackit beta network-area route delete](./stackit_beta_network-area_route_delete.md) - Deletes a static route in a STACKIT Network Area (SNA) +* [stackit beta network-area route describe](./stackit_beta_network-area_route_describe.md) - Shows details of a static route in a STACKIT Network Area (SNA) +* [stackit beta network-area route list](./stackit_beta_network-area_route_list.md) - Lists all static routes in a STACKIT Network Area (SNA) diff --git a/docs/stackit_beta_network-area_routes_create.md b/docs/stackit_beta_network-area_route_create.md similarity index 76% rename from docs/stackit_beta_network-area_routes_create.md rename to docs/stackit_beta_network-area_route_create.md index 83b183f2a..f9fca71f2 100644 --- a/docs/stackit_beta_network-area_routes_create.md +++ b/docs/stackit_beta_network-area_route_create.md @@ -1,4 +1,4 @@ -## stackit beta network-area routes create +## stackit beta network-area route create Creates a static route in a STACKIT Network Area (SNA) @@ -9,20 +9,20 @@ This command is currently asynchonous only due to limitations in the waiting fun ``` -stackit beta network-area routes create [flags] +stackit beta network-area route create [flags] ``` ### Examples ``` Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area routes create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 + $ stackit beta network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 ``` ### Options ``` - -h, --help Help for "stackit beta network-area routes create" + -h, --help Help for "stackit beta network-area route create" --network-area-id string STACKIT Network Area ID --next-hop string Next hop IP address. Must be a valid IPv4 --organization-id string Organization ID @@ -41,5 +41,5 @@ stackit beta network-area routes create [flags] ### SEE ALSO -* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_routes_delete.md b/docs/stackit_beta_network-area_route_delete.md similarity index 72% rename from docs/stackit_beta_network-area_routes_delete.md rename to docs/stackit_beta_network-area_route_delete.md index 50edd02fc..9fa746057 100644 --- a/docs/stackit_beta_network-area_routes_delete.md +++ b/docs/stackit_beta_network-area_route_delete.md @@ -1,4 +1,4 @@ -## stackit beta network-area routes delete +## stackit beta network-area route delete Deletes a static route in a STACKIT Network Area (SNA) @@ -7,20 +7,20 @@ Deletes a static route in a STACKIT Network Area (SNA) Deletes a static route in a STACKIT Network Area (SNA). ``` -stackit beta network-area routes delete [flags] +stackit beta network-area route delete [flags] ``` ### Examples ``` Delete a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area routes delete xxx --organization-id zzz --network-area-id yyy + $ stackit beta network-area route delete xxx --organization-id zzz --network-area-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta network-area routes delete" + -h, --help Help for "stackit beta network-area route delete" --network-area-id string STACKIT Network Area ID --organization-id string Organization ID ``` @@ -37,5 +37,5 @@ stackit beta network-area routes delete [flags] ### SEE ALSO -* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_routes_describe.md b/docs/stackit_beta_network-area_route_describe.md similarity index 69% rename from docs/stackit_beta_network-area_routes_describe.md rename to docs/stackit_beta_network-area_route_describe.md index dbd6483ba..7561134ca 100644 --- a/docs/stackit_beta_network-area_routes_describe.md +++ b/docs/stackit_beta_network-area_route_describe.md @@ -1,4 +1,4 @@ -## stackit beta network-area routes describe +## stackit beta network-area route describe Shows details of a static route in a STACKIT Network Area (SNA) @@ -7,23 +7,23 @@ Shows details of a static route in a STACKIT Network Area (SNA) Shows details of a static route in a STACKIT Network Area (SNA). ``` -stackit beta network-area routes describe [flags] +stackit beta network-area route describe [flags] ``` ### Examples ``` Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area routes describe xxx --network-area-id yyy --organization-id zzz + $ stackit beta network-area route describe xxx --network-area-id yyy --organization-id zzz Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" in JSON format - $ stackit beta network-area routes describe xxx --network-area-id yyy --organization-id zzz --output-format json + $ stackit beta network-area route describe xxx --network-area-id yyy --organization-id zzz --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta network-area routes describe" + -h, --help Help for "stackit beta network-area route describe" --network-area-id string STACKIT Network Area ID --organization-id string Organization ID ``` @@ -40,5 +40,5 @@ stackit beta network-area routes describe [flags] ### SEE ALSO -* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_routes_list.md b/docs/stackit_beta_network-area_route_list.md similarity index 68% rename from docs/stackit_beta_network-area_routes_list.md rename to docs/stackit_beta_network-area_route_list.md index b38b34cfd..b4228f464 100644 --- a/docs/stackit_beta_network-area_routes_list.md +++ b/docs/stackit_beta_network-area_route_list.md @@ -1,4 +1,4 @@ -## stackit beta network-area routes list +## stackit beta network-area route list Lists all static routes in a STACKIT Network Area (SNA) @@ -7,26 +7,26 @@ Lists all static routes in a STACKIT Network Area (SNA) Lists all static routes in a STACKIT Network Area (SNA). ``` -stackit beta network-area routes list [flags] +stackit beta network-area route list [flags] ``` ### Examples ``` Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area routes list --network-area-id xxx --organization-id yyy + $ stackit beta network-area route list --network-area-id xxx --organization-id yyy Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format - $ stackit beta network-area routes list --network-area-id xxx --organization-id yyy --output-format json + $ stackit beta network-area route list --network-area-id xxx --organization-id yyy --output-format json Lists up to 10 static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area routes list --network-area-id xxx --organization-id yyy --limit 10 + $ stackit beta network-area route list --network-area-id xxx --organization-id yyy --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta network-area routes list" + -h, --help Help for "stackit beta network-area route list" --limit int Maximum number of entries to list --network-area-id string STACKIT Network Area ID --organization-id string Organization ID @@ -44,5 +44,5 @@ stackit beta network-area routes list [flags] ### SEE ALSO -* [stackit beta network-area routes](./stackit_beta_network-area_routes.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/internal/cmd/beta/network-area/network-ranges/create/create.go b/internal/cmd/beta/network-area/network-range/create/create.go similarity index 97% rename from internal/cmd/beta/network-area/network-ranges/create/create.go rename to internal/cmd/beta/network-area/network-range/create/create.go index 56aceb7dc..3e5d9639f 100644 --- a/internal/cmd/beta/network-area/network-ranges/create/create.go +++ b/internal/cmd/beta/network-area/network-range/create/create.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a network range in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - `$ stackit beta network-area network-ranges create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24"`, + `$ stackit beta network-area network-range create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24"`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/network-ranges/create/create_test.go b/internal/cmd/beta/network-area/network-range/create/create_test.go similarity index 100% rename from internal/cmd/beta/network-area/network-ranges/create/create_test.go rename to internal/cmd/beta/network-area/network-range/create/create_test.go diff --git a/internal/cmd/beta/network-area/network-ranges/delete/delete.go b/internal/cmd/beta/network-area/network-range/delete/delete.go similarity index 97% rename from internal/cmd/beta/network-area/network-ranges/delete/delete.go rename to internal/cmd/beta/network-area/network-range/delete/delete.go index ec439f87f..b42d26f4a 100644 --- a/internal/cmd/beta/network-area/network-ranges/delete/delete.go +++ b/internal/cmd/beta/network-area/network-range/delete/delete.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete network range with id "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - `$ stackit beta network-area network-ranges delete xxx --network-area-id yyy --organization-id zzz`, + `$ stackit beta network-area network-range delete xxx --network-area-id yyy --organization-id zzz`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/network-ranges/delete/delete_test.go b/internal/cmd/beta/network-area/network-range/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/network-area/network-ranges/delete/delete_test.go rename to internal/cmd/beta/network-area/network-range/delete/delete_test.go diff --git a/internal/cmd/beta/network-area/network-ranges/describe/describe.go b/internal/cmd/beta/network-area/network-range/describe/describe.go similarity index 97% rename from internal/cmd/beta/network-area/network-ranges/describe/describe.go rename to internal/cmd/beta/network-area/network-range/describe/describe.go index dbfaf1c24..aedc34a26 100644 --- a/internal/cmd/beta/network-area/network-ranges/describe/describe.go +++ b/internal/cmd/beta/network-area/network-range/describe/describe.go @@ -42,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a network range with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - `$ stackit beta network-area network-ranges describe xxx --network-area-id yyy --organization-id zzz`, + `$ stackit beta network-area network-range describe xxx --network-area-id yyy --organization-id zzz`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/network-ranges/describe/describe_test.go b/internal/cmd/beta/network-area/network-range/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/network-area/network-ranges/describe/describe_test.go rename to internal/cmd/beta/network-area/network-range/describe/describe_test.go diff --git a/internal/cmd/beta/network-area/network-ranges/list/list.go b/internal/cmd/beta/network-area/network-range/list/list.go similarity index 93% rename from internal/cmd/beta/network-area/network-ranges/list/list.go rename to internal/cmd/beta/network-area/network-range/list/list.go index fb815ec3b..6c0c98451 100644 --- a/internal/cmd/beta/network-area/network-ranges/list/list.go +++ b/internal/cmd/beta/network-area/network-range/list/list.go @@ -42,15 +42,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy", + "$ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy", ), examples.NewExample( `Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format`, - "$ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy --output-format json", + "$ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --output-format json", ), examples.NewExample( `Lists up to 10 network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area network-ranges list --network-area-id xxx --organization-id yyy --limit 10", + "$ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --limit 10", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/network-ranges/list/list_test.go b/internal/cmd/beta/network-area/network-range/list/list_test.go similarity index 100% rename from internal/cmd/beta/network-area/network-ranges/list/list_test.go rename to internal/cmd/beta/network-area/network-range/list/list_test.go diff --git a/internal/cmd/beta/network-area/network-ranges/network_ranges.go b/internal/cmd/beta/network-area/network-range/network_range.go similarity index 85% rename from internal/cmd/beta/network-area/network-ranges/network_ranges.go rename to internal/cmd/beta/network-area/network-range/network_range.go index 49c765198..889cc75a2 100644 --- a/internal/cmd/beta/network-area/network-ranges/network_ranges.go +++ b/internal/cmd/beta/network-area/network-range/network_range.go @@ -1,10 +1,10 @@ package networkranges import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -14,8 +14,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "network-ranges", - Aliases: []string{"ranges"}, + Use: "network-range", + Aliases: []string{"range"}, Short: "Provides functionality for network ranges in STACKIT Network Areas", Long: "Provides functionality for network ranges in STACKIT Network Areas.", Args: args.NoArgs, diff --git a/internal/cmd/beta/network-area/network_area.go b/internal/cmd/beta/network-area/network_area.go index 21abd15a6..fd0bdd739 100644 --- a/internal/cmd/beta/network-area/network_area.go +++ b/internal/cmd/beta/network-area/network_area.go @@ -5,8 +5,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/list" - networkranges "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-ranges" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes" + networkrange "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -32,7 +32,7 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(delete.NewCmd(p)) cmd.AddCommand(describe.NewCmd(p)) cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(networkranges.NewCmd(p)) - cmd.AddCommand(routes.NewCmd(p)) + cmd.AddCommand(networkrange.NewCmd(p)) + cmd.AddCommand(route.NewCmd(p)) cmd.AddCommand(update.NewCmd(p)) } diff --git a/internal/cmd/beta/network-area/routes/create/create.go b/internal/cmd/beta/network-area/route/create/create.go similarity index 97% rename from internal/cmd/beta/network-area/routes/create/create.go rename to internal/cmd/beta/network-area/route/create/create.go index 5f61c3677..b354d7d91 100644 --- a/internal/cmd/beta/network-area/routes/create/create.go +++ b/internal/cmd/beta/network-area/route/create/create.go @@ -45,7 +45,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area routes create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", + "$ stackit beta network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/routes/create/create_test.go b/internal/cmd/beta/network-area/route/create/create_test.go similarity index 100% rename from internal/cmd/beta/network-area/routes/create/create_test.go rename to internal/cmd/beta/network-area/route/create/create_test.go diff --git a/internal/cmd/beta/network-area/routes/delete/delete.go b/internal/cmd/beta/network-area/route/delete/delete.go similarity index 97% rename from internal/cmd/beta/network-area/routes/delete/delete.go rename to internal/cmd/beta/network-area/route/delete/delete.go index 53c8c1d1b..b927be8c9 100644 --- a/internal/cmd/beta/network-area/routes/delete/delete.go +++ b/internal/cmd/beta/network-area/route/delete/delete.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - "$ stackit beta network-area routes delete xxx --organization-id zzz --network-area-id yyy", + "$ stackit beta network-area route delete xxx --organization-id zzz --network-area-id yyy", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/routes/delete/delete_test.go b/internal/cmd/beta/network-area/route/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/network-area/routes/delete/delete_test.go rename to internal/cmd/beta/network-area/route/delete/delete_test.go diff --git a/internal/cmd/beta/network-area/routes/describe/describe.go b/internal/cmd/beta/network-area/route/describe/describe.go similarity index 95% rename from internal/cmd/beta/network-area/routes/describe/describe.go rename to internal/cmd/beta/network-area/route/describe/describe.go index e9e77e906..793d9b96f 100644 --- a/internal/cmd/beta/network-area/routes/describe/describe.go +++ b/internal/cmd/beta/network-area/route/describe/describe.go @@ -42,11 +42,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - `$ stackit beta network-area routes describe xxx --network-area-id yyy --organization-id zzz`, + `$ stackit beta network-area route describe xxx --network-area-id yyy --organization-id zzz`, ), examples.NewExample( `Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" in JSON format`, - `$ stackit beta network-area routes describe xxx --network-area-id yyy --organization-id zzz --output-format json`, + `$ stackit beta network-area route describe xxx --network-area-id yyy --organization-id zzz --output-format json`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/routes/describe/describe_test.go b/internal/cmd/beta/network-area/route/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/network-area/routes/describe/describe_test.go rename to internal/cmd/beta/network-area/route/describe/describe_test.go diff --git a/internal/cmd/beta/network-area/routes/list/list.go b/internal/cmd/beta/network-area/route/list/list.go similarity index 94% rename from internal/cmd/beta/network-area/routes/list/list.go rename to internal/cmd/beta/network-area/route/list/list.go index f8d9c9bcf..a3e71d19e 100644 --- a/internal/cmd/beta/network-area/routes/list/list.go +++ b/internal/cmd/beta/network-area/route/list/list.go @@ -42,15 +42,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area routes list --network-area-id xxx --organization-id yyy", + "$ stackit beta network-area route list --network-area-id xxx --organization-id yyy", ), examples.NewExample( `Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format`, - "$ stackit beta network-area routes list --network-area-id xxx --organization-id yyy --output-format json", + "$ stackit beta network-area route list --network-area-id xxx --organization-id yyy --output-format json", ), examples.NewExample( `Lists up to 10 static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area routes list --network-area-id xxx --organization-id yyy --limit 10", + "$ stackit beta network-area route list --network-area-id xxx --organization-id yyy --limit 10", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/routes/list/list_test.go b/internal/cmd/beta/network-area/route/list/list_test.go similarity index 100% rename from internal/cmd/beta/network-area/routes/list/list_test.go rename to internal/cmd/beta/network-area/route/list/list_test.go diff --git a/internal/cmd/beta/network-area/routes/routes.go b/internal/cmd/beta/network-area/route/routes.go similarity index 89% rename from internal/cmd/beta/network-area/routes/routes.go rename to internal/cmd/beta/network-area/route/routes.go index 4671b3487..f4b5bfac9 100644 --- a/internal/cmd/beta/network-area/routes/routes.go +++ b/internal/cmd/beta/network-area/route/routes.go @@ -1,10 +1,10 @@ -package routes +package route import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/routes/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -14,7 +14,7 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "routes", + Use: "route", Short: "Provides functionality for static routes in STACKIT Network Areas", Long: "Provides functionality for static routes in STACKIT Network Areas.", Args: args.NoArgs, From 39eac626814f229c515b56f88bcb56fc2715bab7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 5 Aug 2024 18:16:04 +0200 Subject: [PATCH 030/619] fix(deps): update module golang.org/x/oauth2 to v0.22.0 (#440) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f11f6a752..514632102 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.4.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.19.0 - golang.org/x/oauth2 v0.21.0 + golang.org/x/oauth2 v0.22.0 golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 k8s.io/apimachinery v0.29.2 diff --git a/go.sum b/go.sum index eeb74d819..05229fc3f 100644 --- a/go.sum +++ b/go.sum @@ -201,8 +201,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From d2d869cca1a986369fdd7f70c9140df896278920 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:39:08 +0200 Subject: [PATCH 031/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.6.0 (#441) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 514632102..e4413abe2 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.4.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 diff --git a/go.sum b/go.sum index 05229fc3f..046f679f6 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.4.0 h1:W6Zxyq487RpWfEIb6GL7tGTt5SsBzxHPeYTzmB11GtY= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.4.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.6.0 h1:bOUmdso7RuVgswGaVgDRpNWXizSAwihDP77DcZHkkO8= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.6.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 h1:/GwkGMD7ID5hSjdZs1l/Mj8waceCt7oj3TxHgBfEMDQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 h1:S8UZYBu2lHmKCPTR17jZetIal8X7cHO1gVRv101UdPw= From 49db4ca0bc80968e281e3a0ec6a2a28346abd688 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:40:51 +0200 Subject: [PATCH 032/619] fix(deps): update module golang.org/x/mod to v0.20.0 (#439) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e4413abe2..4e089d0e8 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.4.0 github.com/zalando/go-keyring v0.2.5 - golang.org/x/mod v0.19.0 + golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.22.0 golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 diff --git a/go.sum b/go.sum index 046f679f6..eaf7c34b3 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,8 @@ golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRj golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From 4221f8826cdfa0d881e9461e98a6088cd7167b05 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:41:20 +0200 Subject: [PATCH 033/619] fix(deps): update module golang.org/x/term to v0.23.0 (#442) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 4e089d0e8..1177be464 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.22.0 - golang.org/x/term v0.22.0 + golang.org/x/term v0.23.0 golang.org/x/text v0.16.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 @@ -86,7 +86,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/sys v0.22.0 // indirect + golang.org/x/sys v0.23.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index eaf7c34b3..955bb1574 100644 --- a/go.sum +++ b/go.sum @@ -211,10 +211,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= From d5aa4d32124a6c14b5164497ffa2c63a9c768cf1 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:18:46 +0200 Subject: [PATCH 034/619] fix(deps): update module golang.org/x/text to v0.17.0 (#443) Co-authored-by: Renovate Bot Co-authored-by: GokceGK <161626272+GokceGK@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1177be464..d472b8649 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.22.0 golang.org/x/term v0.23.0 - golang.org/x/text v0.16.0 + golang.org/x/text v0.17.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 ) diff --git a/go.sum b/go.sum index 955bb1574..174ecd081 100644 --- a/go.sum +++ b/go.sum @@ -217,8 +217,8 @@ golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From a3054cfd99d6e41fe62c3527df0007b314a2109a Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:50:44 +0200 Subject: [PATCH 035/619] Onboard IaaS network (#438) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * onboard iaas network commands * add unit tests * generate docs * fix linter issues * update iaas sdk version * Update internal/cmd/beta/network/update/update.go Co-authored-by: João Palet * Update internal/cmd/beta/network/describe/describe.go Co-authored-by: João Palet * Update internal/cmd/beta/network/describe/describe.go Co-authored-by: João Palet * Update internal/cmd/beta/network/create/create.go Co-authored-by: João Palet * rename dns servers as dns name servers * change description for prefix length * add ipv6 fields --------- Co-authored-by: João Palet --- docs/stackit_beta.md | 1 + docs/stackit_beta_network.md | 37 +++ docs/stackit_beta_network_create.md | 50 ++++ docs/stackit_beta_network_delete.md | 41 +++ docs/stackit_beta_network_describe.md | 42 +++ docs/stackit_beta_network_list.md | 46 +++ docs/stackit_beta_network_update.md | 48 ++++ internal/cmd/beta/beta.go | 2 + internal/cmd/beta/network/create/create.go | 194 +++++++++++++ .../cmd/beta/network/create/create_test.go | 244 ++++++++++++++++ internal/cmd/beta/network/delete/delete.go | 129 +++++++++ .../cmd/beta/network/delete/delete_test.go | 218 ++++++++++++++ .../cmd/beta/network/describe/describe.go | 174 ++++++++++++ .../beta/network/describe/describe_test.go | 218 ++++++++++++++ internal/cmd/beta/network/list/list.go | 164 +++++++++++ internal/cmd/beta/network/list/list_test.go | 190 +++++++++++++ internal/cmd/beta/network/network.go | 34 +++ internal/cmd/beta/network/update/update.go | 168 +++++++++++ .../cmd/beta/network/update/update_test.go | 267 ++++++++++++++++++ internal/pkg/services/iaas/utils/utils.go | 9 + .../pkg/services/iaas/utils/utils_test.go | 55 ++++ 21 files changed, 2331 insertions(+) create mode 100644 docs/stackit_beta_network.md create mode 100644 docs/stackit_beta_network_create.md create mode 100644 docs/stackit_beta_network_delete.md create mode 100644 docs/stackit_beta_network_describe.md create mode 100644 docs/stackit_beta_network_list.md create mode 100644 docs/stackit_beta_network_update.md create mode 100644 internal/cmd/beta/network/create/create.go create mode 100644 internal/cmd/beta/network/create/create_test.go create mode 100644 internal/cmd/beta/network/delete/delete.go create mode 100644 internal/cmd/beta/network/delete/delete_test.go create mode 100644 internal/cmd/beta/network/describe/describe.go create mode 100644 internal/cmd/beta/network/describe/describe_test.go create mode 100644 internal/cmd/beta/network/list/list.go create mode 100644 internal/cmd/beta/network/list/list_test.go create mode 100644 internal/cmd/beta/network/network.go create mode 100644 internal/cmd/beta/network/update/update.go create mode 100644 internal/cmd/beta/network/update/update_test.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 5d56bcd5c..bf3beb0aa 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -40,6 +40,7 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) * [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_network.md b/docs/stackit_beta_network.md new file mode 100644 index 000000000..cfde2f0c7 --- /dev/null +++ b/docs/stackit_beta_network.md @@ -0,0 +1,37 @@ +## stackit beta network + +Provides functionality for Network + +### Synopsis + +Provides functionality for Network. + +``` +stackit beta network [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta network" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta network create](./stackit_beta_network_create.md) - Creates a network +* [stackit beta network delete](./stackit_beta_network_delete.md) - Deletes a network +* [stackit beta network describe](./stackit_beta_network_describe.md) - Shows details of a network +* [stackit beta network list](./stackit_beta_network_list.md) - Lists all networks of a project +* [stackit beta network update](./stackit_beta_network_update.md) - Updates a network + diff --git a/docs/stackit_beta_network_create.md b/docs/stackit_beta_network_create.md new file mode 100644 index 000000000..ff4177c6b --- /dev/null +++ b/docs/stackit_beta_network_create.md @@ -0,0 +1,50 @@ +## stackit beta network create + +Creates a network + +### Synopsis + +Creates a network. + +``` +stackit beta network create [flags] +``` + +### Examples + +``` + Create a network with name "network-1" + $ stackit beta network create --name network-1 + + Create an IPv4 network with name "network-1" with DNS name servers and a prefix length + $ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix-length 25 + + Create an IPv6 network with name "network-1" with DNS name servers and a prefix length + $ stackit beta network create --name network-1 --ipv6-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv6-prefix-length 25 +``` + +### Options + +``` + -h, --help Help for "stackit beta network create" + --ipv4-dns-name-servers strings List of DNS name servers for IPv4 + --ipv4-prefix-length int The prefix length of the IPv4 network + --ipv6-dns-name-servers strings List of DNS name servers for IPv6 + --ipv6-prefix-length int The prefix length of the IPv6 network + -n, --name string Network name +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network + diff --git a/docs/stackit_beta_network_delete.md b/docs/stackit_beta_network_delete.md new file mode 100644 index 000000000..1e42ed58c --- /dev/null +++ b/docs/stackit_beta_network_delete.md @@ -0,0 +1,41 @@ +## stackit beta network delete + +Deletes a network + +### Synopsis + +Deletes a network. +If the network is still in use, the deletion will fail + + +``` +stackit beta network delete [flags] +``` + +### Examples + +``` + Delete network with ID "xxx" + $ stackit beta network delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta network delete" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network + diff --git a/docs/stackit_beta_network_describe.md b/docs/stackit_beta_network_describe.md new file mode 100644 index 000000000..5c8a15752 --- /dev/null +++ b/docs/stackit_beta_network_describe.md @@ -0,0 +1,42 @@ +## stackit beta network describe + +Shows details of a network + +### Synopsis + +Shows details of a network. + +``` +stackit beta network describe [flags] +``` + +### Examples + +``` + Show details of a network with ID "xxx" + $ stackit beta network describe xxx + + Show details of a network with ID "xxx" in JSON format + $ stackit beta network describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta network 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network + diff --git a/docs/stackit_beta_network_list.md b/docs/stackit_beta_network_list.md new file mode 100644 index 000000000..14f19bd40 --- /dev/null +++ b/docs/stackit_beta_network_list.md @@ -0,0 +1,46 @@ +## stackit beta network list + +Lists all networks of a project + +### Synopsis + +Lists all network of a project. + +``` +stackit beta network list [flags] +``` + +### Examples + +``` + Lists all networks + $ stackit beta network list + + Lists all networks in JSON format + $ stackit beta network list --output-format json + + Lists up to 10 networks + $ stackit beta network list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta network list" + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network + diff --git a/docs/stackit_beta_network_update.md b/docs/stackit_beta_network_update.md new file mode 100644 index 000000000..1ef6e8192 --- /dev/null +++ b/docs/stackit_beta_network_update.md @@ -0,0 +1,48 @@ +## stackit beta network update + +Updates a network + +### Synopsis + +Updates a network. + +``` +stackit beta network update [flags] +``` + +### Examples + +``` + Update network with ID "xxx" with new name "network-1-new" + $ stackit beta network update xxx --name network-1-new + + Update IPv4 network with ID "xxx" with new name "network-1-new" and new DNS name servers + $ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" + + Update IPv6 network with ID "xxx" with new name "network-1-new" and new DNS name servers + $ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2.2.2.2" +``` + +### Options + +``` + -h, --help Help for "stackit beta network update" + --ipv4-dns-name-servers strings List of DNS name servers IPv4 + --ipv6-dns-name-servers strings List of DNS name servers for IPv6 + -n, --name string Network name +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network + diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 0a53bac25..348118936 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,6 +3,7 @@ package beta import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network" networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" @@ -40,4 +41,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(sqlserverflex.NewCmd(p)) cmd.AddCommand(server.NewCmd(p)) cmd.AddCommand(networkArea.NewCmd(p)) + cmd.AddCommand(network.NewCmd(p)) } diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go new file mode 100644 index 000000000..6ca6297d6 --- /dev/null +++ b/internal/cmd/beta/network/create/create.go @@ -0,0 +1,194 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + nameFlag = "name" + ipv4DnsNameServersFlag = "ipv4-dns-name-servers" + ipv4PrefixLengthFlag = "ipv4-prefix-length" + ipv6DnsNameServersFlag = "ipv6-dns-name-servers" + ipv6PrefixLengthFlag = "ipv6-prefix-length" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name *string + IPv4DnsNameServers *[]string + IPv4PrefixLength *int64 + IPv6DnsNameServers *[]string + IPv6PrefixLength *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a network", + Long: "Creates a network.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a network with name "network-1"`, + `$ stackit beta network create --name network-1`, + ), + examples.NewExample( + `Create an IPv4 network with name "network-1" with DNS name servers and a prefix length`, + `$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix-length 25`, + ), + examples.NewExample( + `Create an IPv6 network with name "network-1" with DNS name servers and a prefix length`, + `$ stackit beta network create --name network-1 --ipv6-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv6-prefix-length 25`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a network for project %q?", projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create network : %w", err) + } + networkId := *resp.NetworkId + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Creating network") + _, err = wait.CreateNetworkWaitHandler(ctx, apiClient, model.ProjectId, networkId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for network creation: %w", err) + } + s.Stop() + } + + return outputResult(p, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(nameFlag, "n", "", "Network name") + cmd.Flags().StringSlice(ipv4DnsNameServersFlag, []string{}, "List of DNS name servers for IPv4") + cmd.Flags().Int64(ipv4PrefixLengthFlag, 0, "The prefix length of the IPv4 network") + cmd.Flags().StringSlice(ipv6DnsNameServersFlag, []string{}, "List of DNS name servers for IPv6") + cmd.Flags().Int64(ipv6PrefixLengthFlag, 0, "The prefix length of the IPv6 network") + + err := flags.MarkFlagsRequired(cmd, nameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + IPv4DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv4DnsNameServersFlag), + IPv4PrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4PrefixLengthFlag), + IPv6DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv6DnsNameServersFlag), + IPv6PrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv6PrefixLengthFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkRequest { + req := apiClient.CreateNetwork(ctx, model.ProjectId) + + payload := iaas.CreateNetworkPayload{ + Name: model.Name, + AddressFamily: &iaas.CreateNetworkAddressFamily{ + Ipv4: &iaas.CreateNetworkIPv4{ + Nameservers: model.IPv4DnsNameServers, + PrefixLength: model.IPv4PrefixLength, + }, + Ipv6: &iaas.V1CreateNetworkIPv6{ + Nameservers: model.IPv6DnsNameServers, + PrefixLength: model.IPv6PrefixLength, + }, + }, + } + + return req.CreateNetworkPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, network *iaas.Network) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(network, "", " ") + if err != nil { + return fmt.Errorf("marshal network: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(network, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created network for project %q.\nNetwork ID: %s\n", projectLabel, *network.NetworkId) + return nil + } +} diff --git a/internal/cmd/beta/network/create/create_test.go b/internal/cmd/beta/network/create/create_test.go new file mode 100644 index 000000000..496b7d2ed --- /dev/null +++ b/internal/cmd/beta/network/create/create_test.go @@ -0,0 +1,244 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + nameFlag: "example-network-name", + ipv4DnsNameServersFlag: "1.1.1.0,1.1.2.0", + ipv4PrefixLengthFlag: "24", + ipv6DnsNameServersFlag: "2001:4860:4860::8888,2001:4860:4860::8844", + ipv6PrefixLengthFlag: "24", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example-network-name"), + IPv4DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + IPv4PrefixLength: utils.Ptr(int64(24)), + IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), + IPv6PrefixLength: utils.Ptr(int64(24)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.ApiCreateNetworkRequest { + request := testClient.CreateNetwork(testCtx, testProjectId) + request = request.CreateNetworkPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.CreateNetworkPayload { + payload := iaas.CreateNetworkPayload{ + Name: utils.Ptr("example-network-name"), + AddressFamily: &iaas.CreateNetworkAddressFamily{ + Ipv4: &iaas.CreateNetworkIPv4{ + Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + PrefixLength: utils.Ptr(int64(24)), + }, + Ipv6: &iaas.V1CreateNetworkIPv6{ + Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), + PrefixLength: utils.Ptr(int64(24)), + }, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipv4DnsNameServersFlag) + delete(flagValues, ipv4PrefixLengthFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IPv4DnsNameServers = nil + model.IPv4PrefixLength = nil + }), + }, + { + description: "name missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "use dns servers and prefix", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4DnsNameServersFlag] = "1.1.1.1" + flagValues[ipv4PrefixLengthFlag] = "25" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IPv4DnsNameServers = utils.Ptr([]string{"1.1.1.1"}) + model.IPv4PrefixLength = utils.Ptr(int64(25)) + }), + }, + { + description: "use ipv6 dns servers and prefix", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv6DnsNameServersFlag] = "2001:4860:4860::8888" + flagValues[ipv6PrefixLengthFlag] = "25" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IPv6DnsNameServers = utils.Ptr([]string{"2001:4860:4860::8888"}) + model.IPv6PrefixLength = utils.Ptr(int64(25)) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateNetworkRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network/delete/delete.go b/internal/cmd/beta/network/delete/delete.go new file mode 100644 index 000000000..f612e923c --- /dev/null +++ b/internal/cmd/beta/network/delete/delete.go @@ -0,0 +1,129 @@ +package delete + +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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + networkIdArg = "NETWORK_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + NetworkId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a network", + Long: fmt.Sprintf("%s\n%s\n", + "Deletes a network.", + "If the network is still in use, the deletion will fail", + ), + Args: args.SingleArg(networkIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete network with ID "xxx"`, + "$ stackit beta network delete xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.NetworkId) + if err != nil { + p.Debug(print.ErrorLevel, "get network name: %v", err) + networkLabel = model.NetworkId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete network %q?", networkLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete network: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Deleting network") + _, err = wait.DeleteNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.NetworkId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for network deletion: %w", err) + } + s.Stop() + } + + operationState := "Deleted" + if model.Async { + operationState = "Triggered deletion of" + } + p.Info("%s network %q\n", operationState, networkLabel) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + networkId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkId: networkId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNetworkRequest { + return apiClient.DeleteNetwork(ctx, model.ProjectId, model.NetworkId) +} diff --git a/internal/cmd/beta/network/delete/delete_test.go b/internal/cmd/beta/network/delete/delete_test.go new file mode 100644 index 000000000..726364502 --- /dev/null +++ b/internal/cmd/beta/network/delete/delete_test.go @@ -0,0 +1,218 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testNetworkId = uuid.NewString() +var testProjectId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNetworkId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + NetworkId: testNetworkId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteNetworkRequest)) iaas.ApiDeleteNetworkRequest { + request := testClient.DeleteNetwork(testCtx, testProjectId, testNetworkId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "network id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteNetworkRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/beta/network/describe/describe.go new file mode 100644 index 000000000..d9a991388 --- /dev/null +++ b/internal/cmd/beta/network/describe/describe.go @@ -0,0 +1,174 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + networkIdArg = "NETWORK_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + NetworkId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a network", + Long: "Shows details of a network.", + Args: args.SingleArg(networkIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Show details of a network with ID "xxx"`, + "$ stackit beta network describe xxx", + ), + examples.NewExample( + `Show details of a network with ID "xxx" in JSON format`, + "$ stackit beta network describe xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read network: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + networkId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkId: networkId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNetworkRequest { + return apiClient.GetNetwork(ctx, model.ProjectId, model.NetworkId) +} + +func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(network, "", " ") + if err != nil { + return fmt.Errorf("marshal network: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(network, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + var ipv4nameservers []string + if network.Nameservers != nil { + ipv4nameservers = append(ipv4nameservers, *network.Nameservers...) + } + + var ipv4prefixes []string + if network.Prefixes != nil { + ipv4prefixes = append(ipv4prefixes, *network.Prefixes...) + } + + var ipv6nameservers []string + if network.NameserversV6 != nil { + ipv6nameservers = append(ipv6nameservers, *network.NameserversV6...) + } + + var ipv6prefixes []string + if network.PrefixesV6 != nil { + ipv6prefixes = append(ipv6prefixes, *network.PrefixesV6...) + } + + table := tables.NewTable() + table.AddRow("ID", *network.NetworkId) + table.AddSeparator() + table.AddRow("NAME", *network.Name) + table.AddSeparator() + table.AddRow("STATE", *network.State) + table.AddSeparator() + table.AddRow("PUBLIC IP", *network.PublicIp) + table.AddSeparator() + if len(ipv4nameservers) > 0 { + table.AddRow("IPv4 NAME SERVERS", strings.Join(ipv4nameservers, ", ")) + } + table.AddSeparator() + if len(ipv4prefixes) > 0 { + table.AddRow("IPv4 PREFIXES", strings.Join(ipv4prefixes, ", ")) + } + table.AddSeparator() + if len(ipv6nameservers) > 0 { + table.AddRow("IPv6 NAME SERVERS", strings.Join(ipv6nameservers, ", ")) + } + table.AddSeparator() + if len(ipv6prefixes) > 0 { + table.AddRow("IPv6 PREFIXES", strings.Join(ipv6prefixes, ", ")) + } + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/network/describe/describe_test.go b/internal/cmd/beta/network/describe/describe_test.go new file mode 100644 index 000000000..b0fb47c6a --- /dev/null +++ b/internal/cmd/beta/network/describe/describe_test.go @@ -0,0 +1,218 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testNetworkId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNetworkId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + NetworkId: testNetworkId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetNetworkRequest)) iaas.ApiGetNetworkRequest { + request := testClient.GetNetwork(testCtx, testProjectId, testNetworkId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "network id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetNetworkRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go new file mode 100644 index 000000000..a6584a05b --- /dev/null +++ b/internal/cmd/beta/network/list/list.go @@ -0,0 +1,164 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all networks of a project", + Long: "Lists all network of a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all networks`, + "$ stackit beta network list", + ), + examples.NewExample( + `Lists all networks in JSON format`, + "$ stackit beta network list --output-format json", + ), + examples.NewExample( + `Lists up to 10 networks`, + "$ stackit beta network list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list networks: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + p.Info("No networks found for organization %q\n", projectLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworksRequest { + return apiClient.ListNetworks(ctx, model.ProjectId) +} + +func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(networks, "", " ") + if err != nil { + return fmt.Errorf("marshal network: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(networks, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "Name", "Status", "Public IP") + + for _, network := range networks { + table.AddRow(*network.NetworkId, *network.Name, *network.State, *network.PublicIp) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/network/list/list_test.go b/internal/cmd/beta/network/list/list_test.go new file mode 100644 index 000000000..22de7baea --- /dev/null +++ b/internal/cmd/beta/network/list/list_test.go @@ -0,0 +1,190 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListNetworksRequest)) iaas.ApiListNetworksRequest { + request := testClient.ListNetworks(testCtx, testProjectId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListNetworksRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network/network.go b/internal/cmd/beta/network/network.go new file mode 100644 index 000000000..cf4ccdd4d --- /dev/null +++ b/internal/cmd/beta/network/network.go @@ -0,0 +1,34 @@ +package network + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "network", + Short: "Provides functionality for Network", + Long: "Provides functionality for Network.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) +} diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/beta/network/update/update.go new file mode 100644 index 000000000..e8d66e8bf --- /dev/null +++ b/internal/cmd/beta/network/update/update.go @@ -0,0 +1,168 @@ +package update + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + networkIdArg = "NETWORK_ID" + + nameFlag = "name" + ipv4DnsNameServersFlag = "ipv4-dns-name-servers" + ipv6DnsNameServersFlag = "ipv6-dns-name-servers" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + NetworkId string + Name *string + IPv4DnsNameServers *[]string + IPv6DnsNameServers *[]string + IPv6PrefixLength *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a network", + Long: "Updates a network.", + Args: args.SingleArg(networkIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update network with ID "xxx" with new name "network-1-new"`, + `$ stackit beta network update xxx --name network-1-new`, + ), + examples.NewExample( + `Update IPv4 network with ID "xxx" with new name "network-1-new" and new DNS name servers`, + `$ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2"`, + ), + examples.NewExample( + `Update IPv6 network with ID "xxx" with new name "network-1-new" and new DNS name servers`, + `$ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2.2.2.2"`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.NetworkId) + if err != nil { + p.Debug(print.ErrorLevel, "get network name: %v", err) + networkLabel = model.NetworkId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update network %q?", networkLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("update network area: %w", err) + } + networkId := model.NetworkId + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Updating network") + _, err = wait.UpdateNetworkWaitHandler(ctx, apiClient, model.ProjectId, networkId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for network update: %w", err) + } + s.Stop() + } + + operationState := "Updated" + if model.Async { + operationState = "Triggered update of" + } + p.Info("%s network %q\n", operationState, networkLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(nameFlag, "n", "", "Network name") + cmd.Flags().StringSlice(ipv4DnsNameServersFlag, nil, "List of DNS name servers IPv4") + cmd.Flags().StringSlice(ipv6DnsNameServersFlag, nil, "List of DNS name servers for IPv6") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + networkId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + NetworkId: networkId, + IPv4DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv4DnsNameServersFlag), + IPv6DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv6DnsNameServersFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiPartialUpdateNetworkRequest { + req := apiClient.PartialUpdateNetwork(ctx, model.ProjectId, model.NetworkId) + + payload := iaas.PartialUpdateNetworkPayload{ + Name: model.Name, + AddressFamily: &iaas.UpdateNetworkAddressFamily{ + Ipv4: &iaas.UpdateNetworkIPv4{ + Nameservers: model.IPv4DnsNameServers, + }, + Ipv6: &iaas.V1UpdateNetworkIPv6{ + Nameservers: model.IPv6DnsNameServers, + }, + }, + } + + return req.PartialUpdateNetworkPayload(payload) +} diff --git a/internal/cmd/beta/network/update/update_test.go b/internal/cmd/beta/network/update/update_test.go new file mode 100644 index 000000000..356af7a2b --- /dev/null +++ b/internal/cmd/beta/network/update/update_test.go @@ -0,0 +1,267 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testNetworkId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNetworkId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + nameFlag: "example-network-name", + projectIdFlag: testProjectId, + ipv4DnsNameServersFlag: "1.1.1.0,1.1.2.0", + ipv6DnsNameServersFlag: "2001:4860:4860::8888,2001:4860:4860::8844", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example-network-name"), + NetworkId: testNetworkId, + IPv4DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiPartialUpdateNetworkRequest)) iaas.ApiPartialUpdateNetworkRequest { + request := testClient.PartialUpdateNetwork(testCtx, testProjectId, testNetworkId) + request = request.PartialUpdateNetworkPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.PartialUpdateNetworkPayload)) iaas.PartialUpdateNetworkPayload { + payload := iaas.PartialUpdateNetworkPayload{ + Name: utils.Ptr("example-network-name"), + AddressFamily: &iaas.UpdateNetworkAddressFamily{ + Ipv4: &iaas.UpdateNetworkIPv4{ + Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + }, + Ipv6: &iaas.V1UpdateNetworkIPv6{ + Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), + }, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "required only", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipv4DnsNameServersFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IPv4DnsNameServers = nil + }), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network id invalid 1", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "network id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "use dns servers and prefix", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4DnsNameServersFlag] = "1.1.1.1" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IPv4DnsNameServers = utils.Ptr([]string{"1.1.1.1"}) + }), + }, + { + description: "use ipv6 dns servers and prefix", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv6DnsNameServersFlag] = "2001:4860:4860::8888" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IPv6DnsNameServers = utils.Ptr([]string{"2001:4860:4860::8888"}) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiPartialUpdateNetworkRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index 7b8d103c0..44807a4fc 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -8,11 +8,20 @@ import ( ) type IaaSClient interface { + GetNetworkExecute(ctx context.Context, projectId, networkId string) (*iaas.Network, error) GetNetworkAreaExecute(ctx context.Context, organizationId, areaId string) (*iaas.NetworkArea, error) ListNetworkAreaProjectsExecute(ctx context.Context, organizationId, areaId string) (*iaas.ProjectListResponse, error) GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) } +func GetNetworkName(ctx context.Context, apiClient IaaSClient, projectId, networkId string) (string, error) { + resp, err := apiClient.GetNetworkExecute(ctx, projectId, networkId) + if err != nil { + return "", fmt.Errorf("get network: %w", err) + } + return *resp.Name, nil +} + func GetNetworkAreaName(ctx context.Context, apiClient IaaSClient, organizationId, areaId string) (string, error) { resp, err := apiClient.GetNetworkAreaExecute(ctx, organizationId, areaId) if err != nil { diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index d3165a4d6..4caa3c7fc 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -11,6 +11,8 @@ import ( ) type IaaSClientMocked struct { + GetNetworkFails bool + GetNetworkResp *iaas.Network GetNetworkAreaFails bool GetNetworkAreaResp *iaas.NetworkArea GetAttachedProjectsFails bool @@ -19,6 +21,13 @@ type IaaSClientMocked struct { GetNetworkAreaRangeResp *iaas.NetworkRange } +func (m *IaaSClientMocked) GetNetworkExecute(_ context.Context, _, _ string) (*iaas.Network, error) { + if m.GetNetworkFails { + return nil, fmt.Errorf("could not get network") + } + return m.GetNetworkResp, nil +} + func (m *IaaSClientMocked) GetNetworkAreaExecute(_ context.Context, _, _ string) (*iaas.NetworkArea, error) { if m.GetNetworkAreaFails { return nil, fmt.Errorf("could not get network area") @@ -40,6 +49,52 @@ func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _ return m.GetNetworkAreaRangeResp, nil } +func TestGetNetworkName(t *testing.T) { + type args struct { + getInstanceFails bool + getInstanceResp *iaas.Network + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "base", + args: args{ + getInstanceResp: &iaas.Network{ + Name: utils.Ptr("test"), + }, + }, + want: "test", + }, + { + name: "get network fails", + args: args{ + getInstanceFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetNetworkFails: tt.args.getInstanceFails, + GetNetworkResp: tt.args.getInstanceResp, + } + got, err := GetNetworkName(context.Background(), m, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetNetworkName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetNetworkName() = %v, want %v", got, tt.want) + } + }) + } +} + func TestGetNetworkAreaName(t *testing.T) { type args struct { getInstanceFails bool From fce9c0686442bff9094fa171286d8fda59568780 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 8 Aug 2024 09:02:15 +0200 Subject: [PATCH 036/619] Change network payload handling (#444) * change network payload handling * apply pr suggestions --- docs/stackit_beta_network_create.md | 2 +- docs/stackit_beta_network_update.md | 2 +- internal/cmd/beta/network/create/create.go | 30 +++++++++++++--------- internal/cmd/beta/network/update/update.go | 26 +++++++++++-------- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/docs/stackit_beta_network_create.md b/docs/stackit_beta_network_create.md index ff4177c6b..e9ac60921 100644 --- a/docs/stackit_beta_network_create.md +++ b/docs/stackit_beta_network_create.md @@ -20,7 +20,7 @@ stackit beta network create [flags] $ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix-length 25 Create an IPv6 network with name "network-1" with DNS name servers and a prefix length - $ stackit beta network create --name network-1 --ipv6-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv6-prefix-length 25 + $ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix-length 56 ``` ### Options diff --git a/docs/stackit_beta_network_update.md b/docs/stackit_beta_network_update.md index 1ef6e8192..b14bc9a8d 100644 --- a/docs/stackit_beta_network_update.md +++ b/docs/stackit_beta_network_update.md @@ -20,7 +20,7 @@ stackit beta network update [flags] $ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" Update IPv6 network with ID "xxx" with new name "network-1-new" and new DNS name servers - $ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2.2.2.2" + $ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" ``` ### Options diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go index 6ca6297d6..b5666acd3 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/beta/network/create/create.go @@ -55,7 +55,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), examples.NewExample( `Create an IPv6 network with name "network-1" with DNS name servers and a prefix length`, - `$ stackit beta network create --name network-1 --ipv6-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv6-prefix-length 25`, + `$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix-length 56`, ), ), RunE: func(cmd *cobra.Command, args []string) error { @@ -151,19 +151,25 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkRequest { req := apiClient.CreateNetwork(ctx, model.ProjectId) + addressFamily := &iaas.CreateNetworkAddressFamily{} + + if model.IPv6DnsNameServers != nil { + addressFamily.Ipv6 = &iaas.V1CreateNetworkIPv6{ + Nameservers: model.IPv6DnsNameServers, + PrefixLength: model.IPv6PrefixLength, + } + } + + if model.IPv4DnsNameServers != nil { + addressFamily.Ipv4 = &iaas.CreateNetworkIPv4{ + Nameservers: model.IPv4DnsNameServers, + PrefixLength: model.IPv4PrefixLength, + } + } payload := iaas.CreateNetworkPayload{ - Name: model.Name, - AddressFamily: &iaas.CreateNetworkAddressFamily{ - Ipv4: &iaas.CreateNetworkIPv4{ - Nameservers: model.IPv4DnsNameServers, - PrefixLength: model.IPv4PrefixLength, - }, - Ipv6: &iaas.V1CreateNetworkIPv6{ - Nameservers: model.IPv6DnsNameServers, - PrefixLength: model.IPv6PrefixLength, - }, - }, + Name: model.Name, + AddressFamily: addressFamily, } return req.CreateNetworkPayload(payload) diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/beta/network/update/update.go index e8d66e8bf..5a5cd44bf 100644 --- a/internal/cmd/beta/network/update/update.go +++ b/internal/cmd/beta/network/update/update.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), examples.NewExample( `Update IPv6 network with ID "xxx" with new name "network-1-new" and new DNS name servers`, - `$ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2.2.2.2"`, + `$ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888"`, ), ), RunE: func(cmd *cobra.Command, args []string) error { @@ -151,17 +151,23 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiPartialUpdateNetworkRequest { req := apiClient.PartialUpdateNetwork(ctx, model.ProjectId, model.NetworkId) + addressFamily := &iaas.UpdateNetworkAddressFamily{} + + if model.IPv6DnsNameServers != nil { + addressFamily.Ipv6 = &iaas.V1UpdateNetworkIPv6{ + Nameservers: model.IPv6DnsNameServers, + } + } + + if model.IPv4DnsNameServers != nil { + addressFamily.Ipv4 = &iaas.UpdateNetworkIPv4{ + Nameservers: model.IPv4DnsNameServers, + } + } payload := iaas.PartialUpdateNetworkPayload{ - Name: model.Name, - AddressFamily: &iaas.UpdateNetworkAddressFamily{ - Ipv4: &iaas.UpdateNetworkIPv4{ - Nameservers: model.IPv4DnsNameServers, - }, - Ipv6: &iaas.V1UpdateNetworkIPv6{ - Nameservers: model.IPv6DnsNameServers, - }, - }, + Name: model.Name, + AddressFamily: addressFamily, } return req.PartialUpdateNetworkPayload(payload) From 8701c9bd866f7b9caf3d27317b74130f206fa49c Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Fri, 9 Aug 2024 12:39:04 +0200 Subject: [PATCH 037/619] Fix acc test findings (#445) * remove extra space in prompt message * fix info message --- internal/cmd/beta/network/delete/delete.go | 2 +- internal/cmd/beta/network/list/list.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/beta/network/delete/delete.go b/internal/cmd/beta/network/delete/delete.go index f612e923c..1e399e17c 100644 --- a/internal/cmd/beta/network/delete/delete.go +++ b/internal/cmd/beta/network/delete/delete.go @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete network %q?", networkLabel) + prompt := fmt.Sprintf("Are you sure you want to delete network %q?", networkLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index a6584a05b..3ed188fd2 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -75,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { p.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No networks found for organization %q\n", projectLabel) + p.Info("No networks found for project %q\n", projectLabel) return nil } From 935aee980858086b29bf5e37c8a684f8a2e391b6 Mon Sep 17 00:00:00 2001 From: a_nackov Date: Wed, 14 Aug 2024 12:07:20 +0300 Subject: [PATCH 038/619] ref 644499 - server command (#421) Signed-off-by: Adrian Nackov --- docs/stackit_beta_server.md | 1 + docs/stackit_beta_server_command.md | 36 +++ docs/stackit_beta_server_command_create.md | 45 ++++ docs/stackit_beta_server_command_describe.md | 43 ++++ docs/stackit_beta_server_command_list.md | 44 ++++ docs/stackit_beta_server_command_template.md | 34 +++ ...t_beta_server_command_template_describe.md | 43 ++++ ...ackit_beta_server_command_template_list.md | 43 ++++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 2 + internal/cmd/beta/server/command/command.go | 32 +++ .../cmd/beta/server/command/create/create.go | 162 ++++++++++++ .../beta/server/command/create/create_test.go | 203 +++++++++++++++ .../beta/server/command/describe/describe.go | 156 ++++++++++++ .../server/command/describe/describe_test.go | 241 ++++++++++++++++++ internal/cmd/beta/server/command/list/list.go | 160 ++++++++++++ .../cmd/beta/server/command/list/list_test.go | 188 ++++++++++++++ .../command/template/describe/describe.go | 153 +++++++++++ .../template/describe/describe_test.go | 241 ++++++++++++++++++ .../beta/server/command/template/list/list.go | 154 +++++++++++ .../server/command/template/list/list_test.go | 185 ++++++++++++++ .../beta/server/command/template/template.go | 28 ++ internal/cmd/beta/server/server.go | 2 + internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 13 + internal/pkg/config/config.go | 3 + .../pkg/services/runcommand/client/client.go | 46 ++++ .../pkg/services/runcommand/utils/utils.go | 25 ++ .../services/runcommand/utils/utils_test.go | 46 ++++ 32 files changed, 2343 insertions(+) create mode 100644 docs/stackit_beta_server_command.md create mode 100644 docs/stackit_beta_server_command_create.md create mode 100644 docs/stackit_beta_server_command_describe.md create mode 100644 docs/stackit_beta_server_command_list.md create mode 100644 docs/stackit_beta_server_command_template.md create mode 100644 docs/stackit_beta_server_command_template_describe.md create mode 100644 docs/stackit_beta_server_command_template_list.md create mode 100644 internal/cmd/beta/server/command/command.go create mode 100644 internal/cmd/beta/server/command/create/create.go create mode 100644 internal/cmd/beta/server/command/create/create_test.go create mode 100644 internal/cmd/beta/server/command/describe/describe.go create mode 100644 internal/cmd/beta/server/command/describe/describe_test.go create mode 100644 internal/cmd/beta/server/command/list/list.go create mode 100644 internal/cmd/beta/server/command/list/list_test.go create mode 100644 internal/cmd/beta/server/command/template/describe/describe.go create mode 100644 internal/cmd/beta/server/command/template/describe/describe_test.go create mode 100644 internal/cmd/beta/server/command/template/list/list.go create mode 100644 internal/cmd/beta/server/command/template/list/list_test.go create mode 100644 internal/cmd/beta/server/command/template/template.go create mode 100644 internal/pkg/services/runcommand/client/client.go create mode 100644 internal/pkg/services/runcommand/utils/utils.go create mode 100644 internal/pkg/services/runcommand/utils/utils_test.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index d06925458..1a2b67b25 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -30,4 +30,5 @@ stackit beta server [flags] * [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands * [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command diff --git a/docs/stackit_beta_server_command.md b/docs/stackit_beta_server_command.md new file mode 100644 index 000000000..228a29930 --- /dev/null +++ b/docs/stackit_beta_server_command.md @@ -0,0 +1,36 @@ +## stackit beta server command + +Provides functionality for Server Command + +### Synopsis + +Provides functionality for Server Command. + +``` +stackit beta server command [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server command" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server command create](./stackit_beta_server_command_create.md) - Creates a Server Command +* [stackit beta server command describe](./stackit_beta_server_command_describe.md) - Shows details of a Server Command +* [stackit beta server command list](./stackit_beta_server_command_list.md) - Lists all server commands +* [stackit beta server command template](./stackit_beta_server_command_template.md) - Provides functionality for Server Command Template + diff --git a/docs/stackit_beta_server_command_create.md b/docs/stackit_beta_server_command_create.md new file mode 100644 index 000000000..4bc354e96 --- /dev/null +++ b/docs/stackit_beta_server_command_create.md @@ -0,0 +1,45 @@ +## stackit beta server command create + +Creates a Server Command + +### Synopsis + +Creates a Server Command. + +``` +stackit beta server command create [flags] +``` + +### Examples + +``` + Create a server command for server with ID "xxx", template name "RunShellScript" and a script from a file (using the @{...} format) + $ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='@{/path/to/script.sh}' + + Create a server command for server with ID "xxx", template name "RunShellScript" and a script provided on the command line + $ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='echo hello' +``` + +### Options + +``` + -h, --help Help for "stackit beta server command create" + -r, --params stringToString Params can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) + -s, --server-id string Server ID + -n, --template-name string Template name +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command + diff --git a/docs/stackit_beta_server_command_describe.md b/docs/stackit_beta_server_command_describe.md new file mode 100644 index 000000000..fc1311adb --- /dev/null +++ b/docs/stackit_beta_server_command_describe.md @@ -0,0 +1,43 @@ +## stackit beta server command describe + +Shows details of a Server Command + +### Synopsis + +Shows details of a Server Command. + +``` +stackit beta server command describe COMMAND_ID [flags] +``` + +### Examples + +``` + Get details of a Server Command with ID "xxx" for server with ID "yyy" + $ stackit beta server command describe xxx --server-id=yyy + + Get details of a Server Command with ID "xxx" for server with ID "yyy" in JSON format + $ stackit beta server command describe xxx --server-id=yyy --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server command describe" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command + diff --git a/docs/stackit_beta_server_command_list.md b/docs/stackit_beta_server_command_list.md new file mode 100644 index 000000000..b5a866aff --- /dev/null +++ b/docs/stackit_beta_server_command_list.md @@ -0,0 +1,44 @@ +## stackit beta server command list + +Lists all server commands + +### Synopsis + +Lists all server commands. + +``` +stackit beta server command list [flags] +``` + +### Examples + +``` + List all commands for a server with ID "xxx" + $ stackit beta server command list --server-id xxx + + List all commands for a server with ID "xxx" in JSON format + $ stackit beta server command list --server-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server command list" + --limit int Maximum number of entries to list + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command + diff --git a/docs/stackit_beta_server_command_template.md b/docs/stackit_beta_server_command_template.md new file mode 100644 index 000000000..0d5de8aa6 --- /dev/null +++ b/docs/stackit_beta_server_command_template.md @@ -0,0 +1,34 @@ +## stackit beta server command template + +Provides functionality for Server Command Template + +### Synopsis + +Provides functionality for Server Command Template. + +``` +stackit beta server command template [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server command template" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command +* [stackit beta server command template describe](./stackit_beta_server_command_template_describe.md) - Shows details of a Server Command Template +* [stackit beta server command template list](./stackit_beta_server_command_template_list.md) - Lists all server command templates + diff --git a/docs/stackit_beta_server_command_template_describe.md b/docs/stackit_beta_server_command_template_describe.md new file mode 100644 index 000000000..629d1855a --- /dev/null +++ b/docs/stackit_beta_server_command_template_describe.md @@ -0,0 +1,43 @@ +## stackit beta server command template describe + +Shows details of a Server Command Template + +### Synopsis + +Shows details of a Server Command Template. + +``` +stackit beta server command template describe COMMAND_TEMPLATE_NAME [flags] +``` + +### Examples + +``` + Get details of a Server Command Template with name "RunShellScript" for server with ID "xxx" + $ stackit beta server command template describe RunShellScript --server-id=xxx + + Get details of a Server Command Template with name "RunShellScript" for server with ID "xxx" in JSON format + $ stackit beta server command template describe RunShellScript --server-id=xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server command template describe" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server command template](./stackit_beta_server_command_template.md) - Provides functionality for Server Command Template + diff --git a/docs/stackit_beta_server_command_template_list.md b/docs/stackit_beta_server_command_template_list.md new file mode 100644 index 000000000..db7f59e44 --- /dev/null +++ b/docs/stackit_beta_server_command_template_list.md @@ -0,0 +1,43 @@ +## stackit beta server command template list + +Lists all server command templates + +### Synopsis + +Lists all server command templates. + +``` +stackit beta server command template list [flags] +``` + +### Examples + +``` + List all command templates + $ stackit beta server command template list + + List all commands templates in JSON format + $ stackit beta server command template list --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server command template list" + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server command template](./stackit_beta_server_command_template.md) - Provides functionality for Server Command Template + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 3b3d666a7..0ca92d5a9 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -45,6 +45,7 @@ stackit config set [flags] --rabbitmq-custom-endpoint string RabbitMQ API base URL, used in calls to this API --redis-custom-endpoint string Redis API base URL, used in calls to this API --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API + --runcommand-custom-endpoint string Run Command API base URL, used in calls to this API --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API --service-account-custom-endpoint string Service Account API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index b4edb27d7..0a05047a3 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -45,6 +45,7 @@ stackit config unset [flags] --rabbitmq-custom-endpoint RabbitMQ API base URL. If unset, uses the default base URL --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL + --runcommand-custom-endpoint Server Command base URL. If unset, uses the default base URL --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL --service-account-custom-endpoint Service Account API base URL. If unset, uses the default base URL diff --git a/go.mod b/go.mod index d472b8649..6bd226ae2 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 diff --git a/go.sum b/go.sum index 174ecd081..78b924ae3 100644 --- a/go.sum +++ b/go.sum @@ -153,6 +153,8 @@ github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0 h1:jnApmhchW5FYNWs github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0/go.mod h1:3LhiTR/DMbKR2HuleTzlFHltR1MT1KD0DeW46X6K2GE= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 h1:qCbvGqdG9saRB++UlhXt5ieCCDCITROqL5K2nm38efU= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0/go.mod h1:p16qz/pAW8b1gEhqMpIgJfutRPeDPqQLlbVGyCo3f8o= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0 h1:4EApay9ceTTmIG7bI1XWN1zcevkAiCyAvHrS4sp7s5g= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0/go.mod h1:pSDRPhmRYgRmKoQKL+tzgOmnin90sXUjfnc9jaTir8c= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 h1:pJBG455kmtbQFpCxcBfBK8wOuEnmsMv3h90LFcdj3q0= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0/go.mod h1:LX0Mcyr7/QP77zf7e05fHCJO38RMuTxr7nEDUDZ3oPQ= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 h1:fYCBNvh4tqE+DXYDfbJEjC3n/I78zTZajdcPTPB/yig= diff --git a/internal/cmd/beta/server/command/command.go b/internal/cmd/beta/server/command/command.go new file mode 100644 index 000000000..6d51137f2 --- /dev/null +++ b/internal/cmd/beta/server/command/command.go @@ -0,0 +1,32 @@ +package command + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/template" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "command", + Short: "Provides functionality for Server Command", + Long: "Provides functionality for Server Command.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(template.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/command/create/create.go b/internal/cmd/beta/server/command/create/create.go new file mode 100644 index 000000000..ff593276e --- /dev/null +++ b/internal/cmd/beta/server/command/create/create.go @@ -0,0 +1,162 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" + runcommandUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +const ( + serverIdFlag = "server-id" + commandTemplateNameFlag = "template-name" + paramsFlag = "params" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + + ServerId string + CommandTemplateName string + Params *map[string]string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a Server Command", + Long: "Creates a Server Command.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a server command for server with ID "xxx", template name "RunShellScript" and a script from a file (using the @{...} format)`, + `$ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='@{/path/to/script.sh}'`), + examples.NewExample( + `Create a server command for server with ID "xxx", template name "RunShellScript" and a script provided on the command line`, + `$ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='echo hello'`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a Command for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create Server Command: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().StringP(commandTemplateNameFlag, "n", "", "Template name") + cmd.Flags().StringToStringP(paramsFlag, "r", nil, "Params can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag, commandTemplateNameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + CommandTemplateName: flags.FlagToStringValue(p, cmd, commandTemplateNameFlag), + Params: flags.FlagToStringToStringPointer(p, cmd, paramsFlag), + } + parsedParams, err := runcommandUtils.ParseScriptParams(*model.Params) + if err != nil { + return nil, &cliErr.FlagValidationError{ + Flag: paramsFlag, + Details: err.Error(), + } + } + model.Params = &parsedParams + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand.APIClient) (runcommand.ApiCreateCommandRequest, error) { + req := apiClient.CreateCommand(ctx, model.ProjectId, model.ServerId) + req = req.CreateCommandPayload(runcommand.CreateCommandPayload{ + CommandTemplateName: &model.CommandTemplateName, + Parameters: model.Params, + }) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *runcommand.NewCommandResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal server command: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server command: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created server command for server %s. Command ID: %d\n", model.ServerId, *resp.Id) + return nil + } +} diff --git a/internal/cmd/beta/server/command/create/create_test.go b/internal/cmd/beta/server/command/create/create_test.go new file mode 100644 index 000000000..31ea154bf --- /dev/null +++ b/internal/cmd/beta/server/command/create/create_test.go @@ -0,0 +1,203 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &runcommand.APIClient{} + +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + commandTemplateNameFlag: "RunShellScript", + paramsFlag: `script='echo hello'`, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + CommandTemplateName: "RunShellScript", + Params: &map[string]string{"script": "'echo hello'"}, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *runcommand.ApiCreateCommandRequest)) runcommand.ApiCreateCommandRequest { + request := testClient.CreateCommand(testCtx, testProjectId, testServerId) + request = request.CreateCommandPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *runcommand.CreateCommandPayload)) runcommand.CreateCommandPayload { + payload := runcommand.CreateCommandPayload{ + CommandTemplateName: utils.Ptr("RunShellScript"), + Parameters: &map[string]string{"script": "'echo hello'"}, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "with defaults", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest runcommand.ApiCreateCommandRequest + isValid bool + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/describe/describe.go b/internal/cmd/beta/server/command/describe/describe.go new file mode 100644 index 000000000..70db7e791 --- /dev/null +++ b/internal/cmd/beta/server/command/describe/describe.go @@ -0,0 +1,156 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +const ( + commandIdArg = "COMMAND_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + CommandId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", commandIdArg), + Short: "Shows details of a Server Command", + Long: "Shows details of a Server Command.", + Args: args.SingleArg(commandIdArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details of a Server Command with ID "xxx" for server with ID "yyy"`, + "$ stackit beta server command describe xxx --server-id=yyy"), + examples.NewExample( + `Get details of a Server Command with ID "xxx" for server with ID "yyy" in JSON format`, + "$ stackit beta server command describe xxx --server-id=yyy --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read server command: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + commandId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + CommandId: commandId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand.APIClient) runcommand.ApiGetCommandRequest { + req := apiClient.GetCommand(ctx, model.ProjectId, model.ServerId, model.CommandId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, command *runcommand.CommandDetails) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(command, "", " ") + if err != nil { + return fmt.Errorf("marshal server command: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(command, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server command: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *command.Id) + table.AddSeparator() + table.AddRow("COMMAND TEMPLATE NAME", *command.CommandTemplateName) + table.AddSeparator() + table.AddRow("COMMAND TEMPLATE TITLE", *command.CommandTemplateTitle) + table.AddSeparator() + table.AddRow("STATUS", *command.Status) + table.AddSeparator() + table.AddRow("STARTED AT", *command.StartedAt) + table.AddSeparator() + table.AddRow("FINISHED AT", *command.FinishedAt) + table.AddSeparator() + table.AddRow("EXIT CODE", *command.ExitCode) + table.AddSeparator() + table.AddRow("COMMAND SCRIPT", *command.Script) + table.AddSeparator() + table.AddRow("COMMAND OUTPUT", *command.Output) + table.AddSeparator() + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/server/command/describe/describe_test.go b/internal/cmd/beta/server/command/describe/describe_test.go new file mode 100644 index 000000000..46fac2707 --- /dev/null +++ b/internal/cmd/beta/server/command/describe/describe_test.go @@ -0,0 +1,241 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &runcommand.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testCommandId = "5" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testCommandId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + CommandId: testCommandId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *runcommand.ApiGetCommandRequest)) runcommand.ApiGetCommandRequest { + request := testClient.GetCommand(testCtx, testProjectId, testServerId, testCommandId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "command id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + isValid bool + expectedRequest runcommand.ApiGetCommandRequest + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/list/list.go b/internal/cmd/beta/server/command/list/list.go new file mode 100644 index 000000000..475cd6328 --- /dev/null +++ b/internal/cmd/beta/server/command/list/list.go @@ -0,0 +1,160 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +const ( + limitFlag = "limit" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all server commands", + Long: "Lists all server commands.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all commands for a server with ID "xxx"`, + "$ stackit beta server command list --server-id xxx"), + examples.NewExample( + `List all commands for a server with ID "xxx" in JSON format`, + "$ stackit beta server command list --server-id xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list server commands: %w", err) + } + commands := *resp.Items + if len(commands) == 0 { + p.Info("No commands found for server %s\n", model.ServerId) + return nil + } + + // Truncate output + if model.Limit != nil && len(commands) > int(*model.Limit) { + commands = commands[:*model.Limit] + } + return outputResult(p, model.OutputFormat, commands) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand.APIClient) runcommand.ApiListCommandsRequest { + req := apiClient.ListCommands(ctx, model.ProjectId, model.ServerId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, commands []runcommand.Commands) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(commands, "", " ") + if err != nil { + return fmt.Errorf("marshal server command list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(commands, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server command list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "TEMPLATE NAME", "TEMPLATE TITLE", "STATUS", "STARTED_AT", "FINISHED_AT") + for i := range commands { + s := commands[i] + table.AddRow(*s.Id, *s.CommandTemplateName, *s.CommandTemplateTitle, *s.Status, *s.StartedAt, *s.FinishedAt) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/command/list/list_test.go b/internal/cmd/beta/server/command/list/list_test.go new file mode 100644 index 000000000..e49a614c7 --- /dev/null +++ b/internal/cmd/beta/server/command/list/list_test.go @@ -0,0 +1,188 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &runcommand.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(int64(10)), + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *runcommand.ApiListCommandsRequest)) runcommand.ApiListCommandsRequest { + request := testClient.ListCommands(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest runcommand.ApiListCommandsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/template/describe/describe.go b/internal/cmd/beta/server/command/template/describe/describe.go new file mode 100644 index 000000000..c393b1892 --- /dev/null +++ b/internal/cmd/beta/server/command/template/describe/describe.go @@ -0,0 +1,153 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +const ( + commandTemplateNameArg = "COMMAND_TEMPLATE_NAME" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + CommandTemplateName string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", commandTemplateNameArg), + Short: "Shows details of a Server Command Template", + Long: "Shows details of a Server Command Template.", + Args: args.SingleArg(commandTemplateNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details of a Server Command Template with name "RunShellScript" for server with ID "xxx"`, + "$ stackit beta server command template describe RunShellScript --server-id=xxx"), + examples.NewExample( + `Get details of a Server Command Template with name "RunShellScript" for server with ID "xxx" in JSON format`, + "$ stackit beta server command template describe RunShellScript --server-id=xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read server command template: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + commandTemplateName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + CommandTemplateName: commandTemplateName, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand.APIClient) runcommand.ApiGetCommandTemplateRequest { + req := apiClient.GetCommandTemplate(ctx, model.ProjectId, model.ServerId, model.CommandTemplateName) + return req +} + +func outputResult(p *print.Printer, outputFormat string, commandTemplate *runcommand.CommandTemplateSchema) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(commandTemplate, "", " ") + if err != nil { + return fmt.Errorf("marshal server command template: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(commandTemplate, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server command template: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("NAME", *commandTemplate.Name) + table.AddSeparator() + table.AddRow("TITLE", *commandTemplate.Title) + table.AddSeparator() + table.AddRow("DESCRIPTION", *commandTemplate.Description) + table.AddSeparator() + table.AddRow("OS TYPE", strings.Join(*commandTemplate.OsType, "\n")) + table.AddSeparator() + if commandTemplate.ParameterSchema != nil { + table.AddRow("PARAMS", *commandTemplate.ParameterSchema) + } else { + table.AddRow("PARAMS", "") + } + table.AddSeparator() + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/server/command/template/describe/describe_test.go b/internal/cmd/beta/server/command/template/describe/describe_test.go new file mode 100644 index 000000000..560d0ee93 --- /dev/null +++ b/internal/cmd/beta/server/command/template/describe/describe_test.go @@ -0,0 +1,241 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &runcommand.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testCommandTemplateName = "RunShellScript" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testCommandTemplateName, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + CommandTemplateName: testCommandTemplateName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *runcommand.ApiGetCommandTemplateRequest)) runcommand.ApiGetCommandTemplateRequest { + request := testClient.GetCommandTemplate(testCtx, testProjectId, testServerId, testCommandTemplateName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "command template name invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + isValid bool + expectedRequest runcommand.ApiGetCommandTemplateRequest + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/template/list/list.go b/internal/cmd/beta/server/command/template/list/list.go new file mode 100644 index 000000000..dc14573d9 --- /dev/null +++ b/internal/cmd/beta/server/command/template/list/list.go @@ -0,0 +1,154 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +const ( + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all server command templates", + Long: "Lists all server command templates.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all command templates`, + "$ stackit beta server command template list"), + examples.NewExample( + `List all commands templates in JSON format`, + "$ stackit beta server command template list --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list server command templates: %w", err) + } + templates := *resp.Items + if len(templates) == 0 { + p.Info("No commands templates found\n") + return nil + } + + // Truncate output + if model.Limit != nil && len(templates) > int(*model.Limit) { + templates = templates[:*model.Limit] + } + return outputResult(p, model.OutputFormat, templates) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, _ *inputModel, apiClient *runcommand.APIClient) runcommand.ApiListCommandTemplatesRequest { + req := apiClient.ListCommandTemplates(ctx) + return req +} + +func outputResult(p *print.Printer, outputFormat string, templates []runcommand.CommandTemplate) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(templates, "", " ") + if err != nil { + return fmt.Errorf("marshal server command template list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(templates, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server command template list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("NAME", "OS TYPE", "TITLE") + for i := range templates { + s := templates[i] + table.AddRow(*s.Name, strings.Join(*s.OsType, ","), *s.Title) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/command/template/list/list_test.go b/internal/cmd/beta/server/command/template/list/list_test.go new file mode 100644 index 000000000..119302574 --- /dev/null +++ b/internal/cmd/beta/server/command/template/list/list_test.go @@ -0,0 +1,185 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &runcommand.APIClient{} +var testProjectId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *runcommand.ApiListCommandTemplatesRequest)) runcommand.ApiListCommandTemplatesRequest { + request := testClient.ListCommandTemplates(testCtx) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest runcommand.ApiListCommandTemplatesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/template/template.go b/internal/cmd/beta/server/command/template/template.go new file mode 100644 index 000000000..a1f0d7b20 --- /dev/null +++ b/internal/cmd/beta/server/command/template/template.go @@ -0,0 +1,28 @@ +package template + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/template/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/template/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "template", + Short: "Provides functionality for Server Command Template", + Long: "Provides functionality for Server Command Template.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 8208d5b5d..4a0d70559 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -2,6 +2,7 @@ package server import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -23,4 +24,5 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(backup.NewCmd(p)) + cmd.AddCommand(command.NewCmd(p)) } diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index ab59637c7..e0b9ada9e 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -35,6 +35,7 @@ const ( resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" + runCommandCustomEndpointFlag = "runcommand-custom-endpoint" serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" serviceEnablementCustomEndpointFlag = "service-enablement-custom-endpoint" skeCustomEndpointFlag = "ske-custom-endpoint" @@ -145,6 +146,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(serviceAccountCustomEndpointFlag, "", "Service Account API base URL, used in calls to this API") cmd.Flags().String(serviceEnablementCustomEndpointFlag, "", "Service Enablement API base URL, used in calls to this API") cmd.Flags().String(serverBackupCustomEndpointFlag, "", "Server Backup API base URL, used in calls to this API") + cmd.Flags().String(runCommandCustomEndpointFlag, "", "Run Command API base URL, used in calls to this API") cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") cmd.Flags().String(iaasCustomEndpointFlag, "", "IaaS API base URL, used in calls to this API") @@ -184,6 +186,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.ServerBackupCustomEndpointKey, cmd.Flags().Lookup(serverBackupCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.RunCommandCustomEndpointKey, cmd.Flags().Lookup(runCommandCustomEndpointFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.ServiceAccountCustomEndpointKey, cmd.Flags().Lookup(serviceAccountCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.ServiceEnablementCustomEndpointKey, cmd.Flags().Lookup(serviceEnablementCustomEndpointFlag)) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 58f985dfe..9c6d95328 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -40,6 +40,7 @@ const ( serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" serviceEnablementCustomEndpointFlag = "service-enablement-custom-endpoint" serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" + runCommandCustomEndpointFlag = "runcommand-custom-endpoint" skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" iaasCustomEndpointFlag = "iaas-custom-endpoint" @@ -69,6 +70,7 @@ type inputModel struct { ResourceManagerCustomEndpoint bool SecretsManagerCustomEndpoint bool ServerBackupCustomEndpoint bool + RunCommandCustomEndpoint bool ServiceAccountCustomEndpoint bool ServiceEnablementCustomEndpoint bool SKECustomEndpoint bool @@ -167,6 +169,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.ServerBackupCustomEndpoint { viper.Set(config.ServerBackupCustomEndpointKey, "") } + if model.RunCommandCustomEndpoint { + viper.Set(config.RunCommandCustomEndpointKey, "") + } if model.SKECustomEndpoint { viper.Set(config.SKECustomEndpointKey, "") } @@ -214,6 +219,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(serviceAccountCustomEndpointFlag, false, "Service Account API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serviceEnablementCustomEndpointFlag, false, "Service Enablement API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serverBackupCustomEndpointFlag, false, "Server Backup base URL. If unset, uses the default base URL") + cmd.Flags().Bool(runCommandCustomEndpointFlag, false, "Server Command base URL. If unset, uses the default base URL") cmd.Flags().Bool(skeCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") cmd.Flags().Bool(iaasCustomEndpointFlag, false, "IaaS API base URL. If unset, uses the default base URL") @@ -246,6 +252,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { ServiceAccountCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceAccountCustomEndpointFlag), ServiceEnablementCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceEnablementCustomEndpointFlag), ServerBackupCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverBackupCustomEndpointFlag), + RunCommandCustomEndpoint: flags.FlagToBoolValue(p, cmd, runCommandCustomEndpointFlag), SKECustomEndpoint: flags.FlagToBoolValue(p, cmd, skeCustomEndpointFlag), SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), IaaSCustomEndpoint: flags.FlagToBoolValue(p, cmd, iaasCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index ba5989f3b..ad3d75199 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -33,6 +33,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool secretsManagerCustomEndpointFlag: true, serviceAccountCustomEndpointFlag: true, serverBackupCustomEndpointFlag: true, + runCommandCustomEndpointFlag: true, skeCustomEndpointFlag: true, sqlServerFlexCustomEndpointFlag: true, iaasCustomEndpointFlag: true, @@ -67,6 +68,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { SecretsManagerCustomEndpoint: true, ServiceAccountCustomEndpoint: true, ServerBackupCustomEndpoint: true, + RunCommandCustomEndpoint: true, SKECustomEndpoint: true, SQLServerFlexCustomEndpoint: true, IaaSCustomEndpoint: true, @@ -117,6 +119,7 @@ func TestParseInput(t *testing.T) { model.SecretsManagerCustomEndpoint = false model.ServiceAccountCustomEndpoint = false model.ServerBackupCustomEndpoint = false + model.RunCommandCustomEndpoint = false model.SKECustomEndpoint = false model.SQLServerFlexCustomEndpoint = false model.IaaSCustomEndpoint = false @@ -222,6 +225,16 @@ func TestParseInput(t *testing.T) { model.ServerBackupCustomEndpoint = false }), }, + { + description: "runcommand custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[runCommandCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.RunCommandCustomEndpoint = false + }), + }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 4b2d897ac..a898d957d 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -36,6 +36,7 @@ const ( ServiceAccountCustomEndpointKey = "service_account_custom_endpoint" ServiceEnablementCustomEndpointKey = "service_enablement_custom_endpoint" ServerBackupCustomEndpointKey = "serverbackup_custom_endpoint" + RunCommandCustomEndpointKey = "runcommand_custom_endpoint" SKECustomEndpointKey = "ske_custom_endpoint" SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" IaaSCustomEndpointKey = "iaas_custom_endpoint" @@ -85,6 +86,7 @@ var ConfigKeys = []string{ ServiceAccountCustomEndpointKey, ServiceEnablementCustomEndpointKey, ServerBackupCustomEndpointKey, + RunCommandCustomEndpointKey, SKECustomEndpointKey, SQLServerFlexCustomEndpointKey, IaaSCustomEndpointKey, @@ -158,6 +160,7 @@ func setConfigDefaults() { viper.SetDefault(ServiceAccountCustomEndpointKey, "") viper.SetDefault(ServiceEnablementCustomEndpointKey, "") viper.SetDefault(ServerBackupCustomEndpointKey, "") + viper.SetDefault(RunCommandCustomEndpointKey, "") viper.SetDefault(SKECustomEndpointKey, "") viper.SetDefault(SQLServerFlexCustomEndpointKey, "") viper.SetDefault(IaaSCustomEndpointKey, "") diff --git a/internal/pkg/services/runcommand/client/client.go b/internal/pkg/services/runcommand/client/client.go new file mode 100644 index 000000000..e9ef53cb5 --- /dev/null +++ b/internal/pkg/services/runcommand/client/client.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/spf13/viper" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/runcommand" +) + +func ConfigureClient(p *print.Printer) (*runcommand.APIClient, error) { + var err error + var apiClient *runcommand.APIClient + var cfgOptions []sdkConfig.ConfigurationOption + + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return nil, &errors.AuthError{} + } + cfgOptions = append(cfgOptions, authCfgOption) + + customEndpoint := viper.GetString(config.RunCommandCustomEndpointKey) + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } else { + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err = runcommand.NewAPIClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return nil, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/internal/pkg/services/runcommand/utils/utils.go b/internal/pkg/services/runcommand/utils/utils.go new file mode 100644 index 000000000..d6775f373 --- /dev/null +++ b/internal/pkg/services/runcommand/utils/utils.go @@ -0,0 +1,25 @@ +package utils + +import ( + "os" + "strings" +) + +func ParseScriptParams(params map[string]string) (map[string]string, error) { + if params == nil { + return nil, nil + } + parsed := map[string]string{} + for k, v := range params { + parsed[k] = v + if k == "script" && strings.HasPrefix(v, "@{") && strings.HasSuffix(v, "}") { + // Check if a script file path was specified, like: --params script=@{/tmp/test.sh} + fileContents, err := os.ReadFile(v[2 : len(v)-1]) + if err != nil { + return nil, err + } + parsed[k] = string(fileContents) + } + } + return parsed, nil +} diff --git a/internal/pkg/services/runcommand/utils/utils_test.go b/internal/pkg/services/runcommand/utils/utils_test.go new file mode 100644 index 000000000..5b1d1c69f --- /dev/null +++ b/internal/pkg/services/runcommand/utils/utils_test.go @@ -0,0 +1,46 @@ +package utils + +import ( + "testing" +) + +func TestParseScriptParams(t *testing.T) { + tests := []struct { + description string + input map[string]string + expectedOutput map[string]string + isValid bool + }{ + { + "base-ok", + map[string]string{"script": "ls /"}, + map[string]string{"script": "ls /"}, + true, + }, + { + "not-ok-nonexistant-file-specified-for-script", + map[string]string{"script": "@{/some/file/which/does/not/exist/and/thus/fails}"}, + nil, + false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + output, err := ParseScriptParams(tt.input) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output["script"] != tt.expectedOutput["script"] { + t.Errorf("expected output to be %s, got %s", tt.expectedOutput["script"], output["script"]) + } + }) + } +} From 259118c488b660ea8e51558e7240d1d978aaded4 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:44:05 +0200 Subject: [PATCH 039/619] update github-action to 40.2.6 (#448) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 982f43403..b44e7a13b 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v40.2.3 + uses: renovatebot/github-action@v40.2.6 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From faf5e5f43af96de834985364e6c6f280ace60b76 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:46:41 +0200 Subject: [PATCH 040/619] update readme (#447) --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6c9a9eb1d..0bad6336a 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ Help is available for any command by specifying the special flag `--help` (or si Below you can find a list of the STACKIT services already available in the CLI (along with their respective command names) and the ones that are currently planned to be integrated. | Service | CLI Commands | Status | -| ---------------------------------- |---------------------------|---------------------------| +|------------------------------------|---------------------------|---------------------------| | Argus | `argus` | :white_check_mark: | | Infrastructure as a Service (IaaS) | `beta network-area` | :white_check_mark: (beta) | | Authorization | `project`, `organization` | :white_check_mark: | @@ -83,7 +83,8 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Redis | `redis` | :white_check_mark: | | Resource Manager | `project` | :white_check_mark: | | Secrets Manager | `secrets-manager` | :white_check_mark: | -| Server Backup Management | `beta server backup` | :white_check_mark: | +| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | +| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | | Service Account | `service-account` | :white_check_mark: | | SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | From a645d6d83001ee939853fb88e9312682b465a1b5 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Fri, 16 Aug 2024 12:32:42 +0200 Subject: [PATCH 041/619] Implement client ID as config option (#449) * implement client ID as config option * clean up comment --- docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + internal/cmd/config/set/set.go | 4 +++ internal/cmd/config/unset/unset.go | 7 +++++ internal/cmd/config/unset/unset_test.go | 13 ++++++++ internal/pkg/auth/user_login.go | 19 ++++++++++-- internal/pkg/auth/user_token_flow.go | 7 ++++- internal/pkg/auth/utils.go | 11 +++++++ internal/pkg/auth/utils_test.go | 41 +++++++++++++++++++++++++ internal/pkg/config/config.go | 3 ++ 10 files changed, 103 insertions(+), 4 deletions(-) diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 0ca92d5a9..be39928f8 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -34,6 +34,7 @@ stackit config set [flags] --dns-custom-endpoint string DNS API base URL, used in calls to this API -h, --help Help for "stackit config set" --iaas-custom-endpoint string IaaS API base URL, used in calls to this API + --identity-provider-custom-client-id string Identity Provider client ID, used for user authentication --identity-provider-custom-endpoint string Identity Provider base URL, used for user authentication --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API --logme-custom-endpoint string LogMe API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 0a05047a3..11c9c459a 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -32,6 +32,7 @@ stackit config unset [flags] --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL -h, --help Help for "stackit config unset" --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL + --identity-provider-custom-client-id Identity Provider client ID, used for user authentication --identity-provider-custom-endpoint Identity Provider base URL. If unset, uses the default base URL --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index e0b9ada9e..e44372455 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -19,6 +19,7 @@ import ( const ( sessionTimeLimitFlag = "session-time-limit" identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" + identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" @@ -129,6 +130,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e func configureFlags(cmd *cobra.Command) { cmd.Flags().String(sessionTimeLimitFlag, "", "Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect)") cmd.Flags().String(identityProviderCustomEndpointFlag, "", "Identity Provider base URL, used for user authentication") + cmd.Flags().String(identityProviderCustomClientIdFlag, "", "Identity Provider client ID, used for user authentication") cmd.Flags().String(argusCustomEndpointFlag, "", "Argus API base URL, used in calls to this API") cmd.Flags().String(authorizationCustomEndpointFlag, "", "Authorization API base URL, used in calls to this API") cmd.Flags().String(dnsCustomEndpointFlag, "", "DNS API base URL, used in calls to this API") @@ -155,6 +157,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.IdentityProviderCustomEndpointKey, cmd.Flags().Lookup(identityProviderCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.IdentityProviderCustomClientIdKey, cmd.Flags().Lookup(identityProviderCustomClientIdFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.ArgusCustomEndpointKey, cmd.Flags().Lookup(argusCustomEndpointFlag)) cobra.CheckErr(err) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 9c6d95328..a879dd5b0 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -22,6 +22,7 @@ const ( sessionTimeLimitFlag = "session-time-limit" identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" + identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" @@ -54,6 +55,7 @@ type inputModel struct { SessionTimeLimit bool IdentityProviderCustomEndpoint bool + IdentityProviderCustomClientID bool ArgusCustomEndpoint bool AuthorizationCustomEndpoint bool @@ -117,6 +119,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.IdentityProviderCustomEndpoint { viper.Set(config.IdentityProviderCustomEndpointKey, "") } + if model.IdentityProviderCustomClientID { + viper.Set(config.IdentityProviderCustomClientIdKey, "") + } if model.ArgusCustomEndpoint { viper.Set(config.ArgusCustomEndpointKey, "") @@ -201,6 +206,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(sessionTimeLimitFlag, false, fmt.Sprintf("Maximum time before authentication is required again. If unset, defaults to %s", config.SessionTimeLimitDefault)) cmd.Flags().Bool(identityProviderCustomEndpointFlag, false, "Identity Provider base URL. If unset, uses the default base URL") + cmd.Flags().Bool(identityProviderCustomClientIdFlag, false, "Identity Provider client ID, used for user authentication") cmd.Flags().Bool(argusCustomEndpointFlag, false, "Argus API base URL. If unset, uses the default base URL") cmd.Flags().Bool(authorizationCustomEndpointFlag, false, "Authorization API base URL. If unset, uses the default base URL") @@ -234,6 +240,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { SessionTimeLimit: flags.FlagToBoolValue(p, cmd, sessionTimeLimitFlag), IdentityProviderCustomEndpoint: flags.FlagToBoolValue(p, cmd, identityProviderCustomEndpointFlag), + IdentityProviderCustomClientID: flags.FlagToBoolValue(p, cmd, identityProviderCustomClientIdFlag), ArgusCustomEndpoint: flags.FlagToBoolValue(p, cmd, argusCustomEndpointFlag), AuthorizationCustomEndpoint: flags.FlagToBoolValue(p, cmd, authorizationCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index ad3d75199..9f64136f5 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -18,6 +18,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool sessionTimeLimitFlag: true, identityProviderCustomEndpointFlag: true, + identityProviderCustomClientIdFlag: true, argusCustomEndpointFlag: true, authorizationCustomEndpointFlag: true, @@ -53,6 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { SessionTimeLimit: true, IdentityProviderCustomEndpoint: true, + IdentityProviderCustomClientID: true, ArgusCustomEndpoint: true, AuthorizationCustomEndpoint: true, @@ -104,6 +106,7 @@ func TestParseInput(t *testing.T) { model.SessionTimeLimit = false model.IdentityProviderCustomEndpoint = false + model.IdentityProviderCustomClientID = false model.ArgusCustomEndpoint = false model.AuthorizationCustomEndpoint = false @@ -155,6 +158,16 @@ func TestParseInput(t *testing.T) { model.IdentityProviderCustomEndpoint = false }), }, + { + description: "identity provider custom client id empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[identityProviderCustomClientIdFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IdentityProviderCustomClientID = false + }), + }, { description: "argus custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index ad519f628..d2d767fd1 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -24,7 +24,7 @@ import ( const ( defaultIDPEndpoint = "https://accounts.stackit.cloud/oauth/v2" - cliClientID = "stackit-cli-0000-0000-000000000001" + defaultCLIClientID = "stackit-cli-0000-0000-000000000001" loginSuccessPath = "/login-successful" stackitLandingPage = "https://www.stackit.de" @@ -58,6 +58,18 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { } } + idpClientID, err := getIDPClientID() + if err != nil { + return err + } + if idpClientID != defaultCLIClientID { + p.Warn("You are using a custom client ID (%s) for authentication.\n", idpClientID) + err := p.PromptForEnter("Press Enter to proceed with the login...") + if err != nil { + return err + } + } + if isReauthentication { err := p.PromptForEnter("Your session has expired, press Enter to login again...") if err != nil { @@ -86,7 +98,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { } conf := &oauth2.Config{ - ClientID: cliClientID, + ClientID: idpClientID, Endpoint: oauth2.Endpoint{ AuthURL: fmt.Sprintf("%s/authorize", idpEndpoint), }, @@ -131,7 +143,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { p.Debug(print.DebugLevel, "trading authorization code for access and refresh tokens") // Trade the authorization code and the code verifier for access and refresh tokens - accessToken, refreshToken, err := getUserAccessAndRefreshTokens(idpEndpoint, cliClientID, codeVerifier, code, redirectURL) + accessToken, refreshToken, err := getUserAccessAndRefreshTokens(idpEndpoint, idpClientID, codeVerifier, code, redirectURL) if err != nil { errServer = fmt.Errorf("retrieve tokens: %w", err) return @@ -207,6 +219,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { p.Debug(print.DebugLevel, "opening browser for authentication") p.Debug(print.DebugLevel, "using authentication server on %s", idpEndpoint) + p.Debug(print.DebugLevel, "using client ID %s for authentication ", idpClientID) // Open a browser window to the authorizationURL err = openBrowser(authorizationURL) diff --git a/internal/pkg/auth/user_token_flow.go b/internal/pkg/auth/user_token_flow.go index a15c33c17..530672882 100644 --- a/internal/pkg/auth/user_token_flow.go +++ b/internal/pkg/auth/user_token_flow.go @@ -161,6 +161,11 @@ func buildRequestToRefreshTokens(utf *userTokenFlow) (*http.Request, error) { return nil, err } + idpClientID, err := getIDPClientID() + if err != nil { + return nil, err + } + req, err := http.NewRequest( http.MethodPost, fmt.Sprintf("%s/token", idpEndpoint), @@ -171,7 +176,7 @@ func buildRequestToRefreshTokens(utf *userTokenFlow) (*http.Request, error) { } reqQuery := url.Values{} reqQuery.Set("grant_type", "refresh_token") - reqQuery.Set("client_id", cliClientID) + reqQuery.Set("client_id", idpClientID) reqQuery.Set("refresh_token", utf.refreshToken) reqQuery.Set("token_format", "jwt") req.URL.RawQuery = reqQuery.Encode() diff --git a/internal/pkg/auth/utils.go b/internal/pkg/auth/utils.go index cdb38c137..a60e25a5c 100644 --- a/internal/pkg/auth/utils.go +++ b/internal/pkg/auth/utils.go @@ -22,3 +22,14 @@ func getIDPEndpoint() (string, error) { return idpEndpoint, nil } + +func getIDPClientID() (string, error) { + idpClientID := defaultCLIClientID + + customIDPClientID := viper.GetString(config.IdentityProviderCustomClientIdKey) + if customIDPClientID != "" { + idpClientID = customIDPClientID + } + + return idpClientID, nil +} diff --git a/internal/pkg/auth/utils_test.go b/internal/pkg/auth/utils_test.go index 375bd8462..c345c4d82 100644 --- a/internal/pkg/auth/utils_test.go +++ b/internal/pkg/auth/utils_test.go @@ -52,3 +52,44 @@ func TestGetIDPEndpoint(t *testing.T) { }) } } + +func TestGetIDPClientID(t *testing.T) { + tests := []struct { + name string + idpCustomClientID string + isValid bool + expected string + }{ + { + name: "custom client ID specified", + idpCustomClientID: "custom-client-id", + isValid: true, + expected: "custom-client-id", + }, + { + name: "custom client ID not specified", + idpCustomClientID: "", + isValid: true, + expected: defaultCLIClientID, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + viper.Reset() + viper.Set(config.IdentityProviderCustomClientIdKey, tt.idpCustomClientID) + + got, err := getIDPClientID() + + if tt.isValid && err != nil { + t.Fatalf("expected no error, got %v", err) + } + if !tt.isValid && err == nil { + t.Fatalf("expected error, got none") + } + + if got != tt.expected { + t.Fatalf("expected idp client ID %q, got %q", tt.expected, got) + } + }) + } +} diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index a898d957d..548827ddb 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -18,6 +18,7 @@ const ( VerbosityKey = "verbosity" IdentityProviderCustomEndpointKey = "identity_provider_custom_endpoint" + IdentityProviderCustomClientIdKey = "identity_provider_custom_client_id" ArgusCustomEndpointKey = "argus_custom_endpoint" AuthorizationCustomEndpointKey = "authorization_custom_endpoint" @@ -67,6 +68,7 @@ var ConfigKeys = []string{ VerbosityKey, IdentityProviderCustomEndpointKey, + IdentityProviderCustomClientIdKey, DNSCustomEndpointKey, LoadBalancerCustomEndpointKey, @@ -148,6 +150,7 @@ func setConfigDefaults() { viper.SetDefault(ProjectIdKey, "") viper.SetDefault(SessionTimeLimitKey, SessionTimeLimitDefault) viper.SetDefault(IdentityProviderCustomEndpointKey, "") + viper.SetDefault(IdentityProviderCustomClientIdKey, "") viper.SetDefault(DNSCustomEndpointKey, "") viper.SetDefault(ArgusCustomEndpointKey, "") viper.SetDefault(AuthorizationCustomEndpointKey, "") From 50b5aa9509ad7525fca163d30d92c06170938838 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Tue, 20 Aug 2024 10:47:11 +0200 Subject: [PATCH 042/619] Add error description to output (#452) * add error description to output * add empty check for err description * Update internal/pkg/auth/user_login.go Co-authored-by: Vicente Pinto --------- Co-authored-by: Vicente Pinto --- internal/pkg/auth/user_login.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index d2d767fd1..f35c8cc75 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -135,8 +135,12 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { // Get the authorization code code := r.URL.Query().Get("code") + errDescription := r.URL.Query().Get("error_description") if code == "" { errServer = fmt.Errorf("could not find 'code' URL parameter") + if errDescription != "" { + errServer = fmt.Errorf("%w: %s", errServer, errDescription) + } return } From 303a20117328cab6e772e3b56986dfbd2715152d Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 21 Aug 2024 09:12:53 +0200 Subject: [PATCH 043/619] fix(deps): update stackit sdk modules (#450) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update stackit sdk modules * update function names --------- Co-authored-by: Renovate Bot Co-authored-by: Gökçe Gök Klingel --- go.mod | 6 +++--- go.sum | 12 ++++++------ internal/cmd/beta/network/create/create.go | 4 ++-- internal/cmd/beta/network/create/create_test.go | 4 ++-- internal/cmd/beta/network/update/update.go | 4 ++-- internal/cmd/beta/network/update/update_test.go | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 6bd226ae2..ef94341f6 100644 --- a/go.mod +++ b/go.mod @@ -18,18 +18,18 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.4.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.5.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.22.0 diff --git a/go.sum b/go.sum index 78b924ae3..3477d20ae 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.6.0 h1:bOUmdso7RuVgswGaVgDRpNWXizSAwihDP77DcZHkkO8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.6.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.7.0 h1:BnDF0RSW+gN2/AxC5TAkNMzVPGsbnCrURj755so6EBY= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.7.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 h1:/GwkGMD7ID5hSjdZs1l/Mj8waceCt7oj3TxHgBfEMDQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 h1:S8UZYBu2lHmKCPTR17jZetIal8X7cHO1gVRv101UdPw= @@ -155,8 +155,8 @@ github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 h1:qCbvGq github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0/go.mod h1:p16qz/pAW8b1gEhqMpIgJfutRPeDPqQLlbVGyCo3f8o= github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0 h1:4EApay9ceTTmIG7bI1XWN1zcevkAiCyAvHrS4sp7s5g= github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0/go.mod h1:pSDRPhmRYgRmKoQKL+tzgOmnin90sXUjfnc9jaTir8c= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 h1:pJBG455kmtbQFpCxcBfBK8wOuEnmsMv3h90LFcdj3q0= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0/go.mod h1:LX0Mcyr7/QP77zf7e05fHCJO38RMuTxr7nEDUDZ3oPQ= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.9.0 h1:Zzow6CUNFjM+gIPPR/onuR1yBeRqUOphDKf3zmefvFo= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.9.0/go.mod h1:LX0Mcyr7/QP77zf7e05fHCJO38RMuTxr7nEDUDZ3oPQ= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 h1:fYCBNvh4tqE+DXYDfbJEjC3n/I78zTZajdcPTPB/yig= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0/go.mod h1:ZYI3wj/NnhhWi25ugbdcniwnY/7mF6zN582c5HPe00o= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 h1:JB1O0E9+L50ZaO36uz7azurvUuB5JdX5s2ZXuIdb9t8= @@ -165,8 +165,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 h1:HAEF github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0/go.mod h1:z6XdA+ndaWzcPW/P0QrUIcTXJzKlajxgGZ5+EwXNS+c= github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 h1:vmkfa26HO1VA40pKPNnYMHkcNMxBEWAdYbX+5LVIo48= github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.4.0 h1:Ly8dDjjggO7udf5kyyQU6Lm6UPoWzJVJONYeaIDkFVM= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.4.0/go.mod h1:Qnn+06i21XtagtMQ4cTwOCR3OLnXX+t1n+Vf/HH49Yw= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.5.0 h1:Nil6gmhXik5FsnvvfagpHReFNg/uxeMS+8YHOkU5bRg= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.5.0/go.mod h1:Qnn+06i21XtagtMQ4cTwOCR3OLnXX+t1n+Vf/HH49Yw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go index b5666acd3..166f71526 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/beta/network/create/create.go @@ -154,14 +154,14 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli addressFamily := &iaas.CreateNetworkAddressFamily{} if model.IPv6DnsNameServers != nil { - addressFamily.Ipv6 = &iaas.V1CreateNetworkIPv6{ + addressFamily.Ipv6 = &iaas.CreateNetworkIPv6Body{ Nameservers: model.IPv6DnsNameServers, PrefixLength: model.IPv6PrefixLength, } } if model.IPv4DnsNameServers != nil { - addressFamily.Ipv4 = &iaas.CreateNetworkIPv4{ + addressFamily.Ipv4 = &iaas.CreateNetworkIPv4Body{ Nameservers: model.IPv4DnsNameServers, PrefixLength: model.IPv4PrefixLength, } diff --git a/internal/cmd/beta/network/create/create_test.go b/internal/cmd/beta/network/create/create_test.go index 496b7d2ed..0d8b23728 100644 --- a/internal/cmd/beta/network/create/create_test.go +++ b/internal/cmd/beta/network/create/create_test.go @@ -69,11 +69,11 @@ func fixturePayload(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.Creat payload := iaas.CreateNetworkPayload{ Name: utils.Ptr("example-network-name"), AddressFamily: &iaas.CreateNetworkAddressFamily{ - Ipv4: &iaas.CreateNetworkIPv4{ + Ipv4: &iaas.CreateNetworkIPv4Body{ Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), PrefixLength: utils.Ptr(int64(24)), }, - Ipv6: &iaas.V1CreateNetworkIPv6{ + Ipv6: &iaas.CreateNetworkIPv6Body{ Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), PrefixLength: utils.Ptr(int64(24)), }, diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/beta/network/update/update.go index 5a5cd44bf..67f7e5acd 100644 --- a/internal/cmd/beta/network/update/update.go +++ b/internal/cmd/beta/network/update/update.go @@ -154,13 +154,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli addressFamily := &iaas.UpdateNetworkAddressFamily{} if model.IPv6DnsNameServers != nil { - addressFamily.Ipv6 = &iaas.V1UpdateNetworkIPv6{ + addressFamily.Ipv6 = &iaas.UpdateNetworkIPv6Body{ Nameservers: model.IPv6DnsNameServers, } } if model.IPv4DnsNameServers != nil { - addressFamily.Ipv4 = &iaas.UpdateNetworkIPv4{ + addressFamily.Ipv4 = &iaas.UpdateNetworkIPv4Body{ Nameservers: model.IPv4DnsNameServers, } } diff --git a/internal/cmd/beta/network/update/update_test.go b/internal/cmd/beta/network/update/update_test.go index 356af7a2b..bc2c28e4e 100644 --- a/internal/cmd/beta/network/update/update_test.go +++ b/internal/cmd/beta/network/update/update_test.go @@ -77,10 +77,10 @@ func fixturePayload(mods ...func(payload *iaas.PartialUpdateNetworkPayload)) iaa payload := iaas.PartialUpdateNetworkPayload{ Name: utils.Ptr("example-network-name"), AddressFamily: &iaas.UpdateNetworkAddressFamily{ - Ipv4: &iaas.UpdateNetworkIPv4{ + Ipv4: &iaas.UpdateNetworkIPv4Body{ Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), }, - Ipv6: &iaas.V1UpdateNetworkIPv6{ + Ipv6: &iaas.UpdateNetworkIPv6Body{ Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), }, }, From 0edba2085585242031797120d07c6aa0fd4f24f2 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:03:23 +0200 Subject: [PATCH 044/619] Extend config options (#451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * implement allowed-url-domain config option * implement jwks and token endpoints in cfg command * Update internal/cmd/config/set/set.go Co-authored-by: João Palet * extend unset command for token and jwks * Change method name * Change endpoint handling * change default value handling for the allowed url domain * accept empty url domains and add warning * fix unit tests * Update internal/cmd/config/set/set.go Co-authored-by: Vicente Pinto --------- Co-authored-by: João Palet Co-authored-by: Vicente Pinto --- docs/stackit_auth_activate-service-account.md | 2 - docs/stackit_config_set.md | 3 + docs/stackit_config_unset.md | 3 + .../activate_service_account.go | 31 ++++--- .../activate_service_account_test.go | 83 +++++++++++-------- internal/cmd/config/set/set.go | 17 ++++ internal/cmd/config/unset/unset.go | 21 +++++ internal/cmd/config/unset/unset_test.go | 39 +++++++++ internal/cmd/curl/curl.go | 2 +- internal/cmd/curl/curl_test.go | 16 +++- internal/pkg/auth/utils.go | 2 +- internal/pkg/auth/utils_test.go | 25 ++++++ internal/pkg/config/config.go | 11 +++ internal/pkg/utils/utils.go | 11 ++- internal/pkg/utils/utils_test.go | 49 ++++++++--- 15 files changed, 241 insertions(+), 74 deletions(-) diff --git a/docs/stackit_auth_activate-service-account.md b/docs/stackit_auth_activate-service-account.md index 18feefe3d..e39102530 100644 --- a/docs/stackit_auth_activate-service-account.md +++ b/docs/stackit_auth_activate-service-account.md @@ -29,11 +29,9 @@ stackit auth activate-service-account [flags] ``` -h, --help Help for "stackit auth activate-service-account" - --jwks-custom-endpoint string Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated --private-key-path string RSA private key path. It takes precedence over the private key included in the service account key, if present --service-account-key-path string Service account key path --service-account-token string Service account long-lived access token - --token-custom-endpoint string Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated ``` ### Options inherited from parent commands diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index be39928f8..d739983cc 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -29,6 +29,7 @@ stackit config set [flags] ### Options ``` + --allowed-url-domain string Domain name, used for the verification of the URLs that are given in the custom identidy provider endpoint and "STACKIT curl" command --argus-custom-endpoint string Argus API base URL, used in calls to this API --authorization-custom-endpoint string Authorization API base URL, used in calls to this API --dns-custom-endpoint string DNS API base URL, used in calls to this API @@ -36,6 +37,7 @@ stackit config set [flags] --iaas-custom-endpoint string IaaS API base URL, used in calls to this API --identity-provider-custom-client-id string Identity Provider client ID, used for user authentication --identity-provider-custom-endpoint string Identity Provider base URL, used for user authentication + --jwks-custom-endpoint string Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API --logme-custom-endpoint string LogMe API base URL, used in calls to this API --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API @@ -54,6 +56,7 @@ stackit config set [flags] --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) --ske-custom-endpoint string SKE API base URL, used in calls to this API --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API + --token-custom-endpoint string Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated ``` ### Options inherited from parent commands diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 11c9c459a..fc68fe45a 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -26,6 +26,7 @@ stackit config unset [flags] ### Options ``` + --allowed-url-domain Domain name, used for the verification of the URLs that are given in the IDP endpoint and curl commands. If unset, defaults to stackit.cloud --argus-custom-endpoint Argus API base URL. If unset, uses the default base URL --async Configuration option to run commands asynchronously --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL @@ -34,6 +35,7 @@ stackit config unset [flags] --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL --identity-provider-custom-client-id Identity Provider client ID, used for user authentication --identity-provider-custom-endpoint Identity Provider base URL. If unset, uses the default base URL + --jwks-custom-endpoint Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL @@ -54,6 +56,7 @@ stackit config unset [flags] --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL + --token-custom-endpoint Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated --verbosity Verbosity of the CLI ``` diff --git a/internal/cmd/auth/activate-service-account/activate_service_account.go b/internal/cmd/auth/activate-service-account/activate_service_account.go index c0d806518..e49ec48df 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account.go @@ -4,8 +4,10 @@ import ( "errors" "fmt" + "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -20,16 +22,12 @@ const ( serviceAccountTokenFlag = "service-account-token" serviceAccountKeyPathFlag = "service-account-key-path" privateKeyPathFlag = "private-key-path" - tokenCustomEndpointFlag = "token-custom-endpoint" - jwksCustomEndpointFlag = "jwks-custom-endpoint" ) type inputModel struct { ServiceAccountToken string ServiceAccountKeyPath string PrivateKeyPath string - TokenCustomEndpoint string - JwksCustomEndpoint string } func NewCmd(p *print.Printer) *cobra.Command { @@ -56,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { model := parseInput(p, cmd) - err := storeFlags(model) + tokenCustomEndpoint, jwksCustomEndpoint, err := storeFlags() if err != nil { return err } @@ -65,8 +63,8 @@ func NewCmd(p *print.Printer) *cobra.Command { Token: model.ServiceAccountToken, ServiceAccountKeyPath: model.ServiceAccountKeyPath, PrivateKeyPath: model.PrivateKeyPath, - TokenCustomUrl: model.TokenCustomEndpoint, - JWKSCustomUrl: model.JwksCustomEndpoint, + TokenCustomUrl: tokenCustomEndpoint, + JWKSCustomUrl: jwksCustomEndpoint, } // Setup authentication based on the provided credentials and the environment @@ -100,8 +98,6 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(serviceAccountTokenFlag, "", "Service account long-lived access token") cmd.Flags().String(serviceAccountKeyPathFlag, "", "Service account key path") cmd.Flags().String(privateKeyPathFlag, "", "RSA private key path. It takes precedence over the private key included in the service account key, if present") - cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated") - cmd.Flags().String(jwksCustomEndpointFlag, "", "Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { @@ -109,8 +105,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { ServiceAccountToken: flags.FlagToStringValue(p, cmd, serviceAccountTokenFlag), ServiceAccountKeyPath: flags.FlagToStringValue(p, cmd, serviceAccountKeyPathFlag), PrivateKeyPath: flags.FlagToStringValue(p, cmd, privateKeyPathFlag), - TokenCustomEndpoint: flags.FlagToStringValue(p, cmd, tokenCustomEndpointFlag), - JwksCustomEndpoint: flags.FlagToStringValue(p, cmd, jwksCustomEndpointFlag), } if p.IsVerbosityDebug() { @@ -125,14 +119,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { return &model } -func storeFlags(model *inputModel) error { - err := auth.SetAuthField(auth.TOKEN_CUSTOM_ENDPOINT, model.TokenCustomEndpoint) +func storeFlags() (tokenCustomEndpoint, jwksCustomEndpoint string, err error) { + tokenCustomEndpoint = viper.GetString(config.TokenCustomEndpointKey) + jwksCustomEndpoint = viper.GetString(config.JwksCustomEndpointKey) + + err = auth.SetAuthField(auth.TOKEN_CUSTOM_ENDPOINT, tokenCustomEndpoint) if err != nil { - return fmt.Errorf("set %s: %w", auth.TOKEN_CUSTOM_ENDPOINT, err) + return "", "", fmt.Errorf("set %s: %w", auth.TOKEN_CUSTOM_ENDPOINT, err) } - err = auth.SetAuthField(auth.JWKS_CUSTOM_ENDPOINT, model.JwksCustomEndpoint) + err = auth.SetAuthField(auth.JWKS_CUSTOM_ENDPOINT, jwksCustomEndpoint) if err != nil { - return fmt.Errorf("set %s: %w", auth.JWKS_CUSTOM_ENDPOINT, err) + return "", "", fmt.Errorf("set %s: %w", auth.JWKS_CUSTOM_ENDPOINT, err) } - return nil + return tokenCustomEndpoint, jwksCustomEndpoint, nil } diff --git a/internal/cmd/auth/activate-service-account/activate_service_account_test.go b/internal/cmd/auth/activate-service-account/activate_service_account_test.go index a9e12b30c..6beadb0d6 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account_test.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account_test.go @@ -3,7 +3,9 @@ package activateserviceaccount import ( "testing" + "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/zalando/go-keyring" @@ -11,13 +13,14 @@ import ( "github.com/google/go-cmp/cmp" ) +var testTokenCustomEndpoint = "token_url" +var testJwksCustomEndpoint = "jwks_url" + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ serviceAccountTokenFlag: "token", serviceAccountKeyPathFlag: "sa_key", privateKeyPathFlag: "private_key", - tokenCustomEndpointFlag: "token_url", - jwksCustomEndpointFlag: "jwks_url", } for _, mod := range mods { mod(flagValues) @@ -30,8 +33,6 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { ServiceAccountToken: "token", ServiceAccountKeyPath: "sa_key", PrivateKeyPath: "private_key", - TokenCustomEndpoint: "token_url", - JwksCustomEndpoint: "jwks_url", } for _, mod := range mods { mod(model) @@ -41,27 +42,31 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func TestParseInput(t *testing.T) { tests := []struct { - description string - flagValues map[string]string - isValid bool - expectedModel *inputModel + description string + flagValues map[string]string + tokenCustomEndpoint string + jwksCustomEndpoint string + isValid bool + expectedModel *inputModel }{ { - description: "base", - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(), + description: "base", + flagValues: fixtureFlagValues(), + tokenCustomEndpoint: testTokenCustomEndpoint, + jwksCustomEndpoint: testJwksCustomEndpoint, + isValid: true, + expectedModel: fixtureInputModel(), }, { - description: "no values", - flagValues: map[string]string{}, - isValid: true, + description: "no values", + flagValues: map[string]string{}, + tokenCustomEndpoint: "", + jwksCustomEndpoint: "", + isValid: true, expectedModel: &inputModel{ ServiceAccountToken: "", ServiceAccountKeyPath: "", PrivateKeyPath: "", - TokenCustomEndpoint: "", - JwksCustomEndpoint: "", }, }, { @@ -70,16 +75,14 @@ func TestParseInput(t *testing.T) { serviceAccountTokenFlag: "", serviceAccountKeyPathFlag: "", privateKeyPathFlag: "", - tokenCustomEndpointFlag: "", - jwksCustomEndpointFlag: "", }, - isValid: true, + tokenCustomEndpoint: "", + jwksCustomEndpoint: "", + isValid: true, expectedModel: &inputModel{ ServiceAccountToken: "", ServiceAccountKeyPath: "", PrivateKeyPath: "", - TokenCustomEndpoint: "", - JwksCustomEndpoint: "", }, }, { @@ -125,14 +128,18 @@ func TestParseInput(t *testing.T) { func TestStoreFlags(t *testing.T) { tests := []struct { - description string - model *inputModel - isValid bool + description string + model *inputModel + tokenCustomEndpoint string + jwksCustomEndpoint string + isValid bool }{ { - description: "base", - model: fixtureInputModel(), - isValid: true, + description: "base", + model: fixtureInputModel(), + tokenCustomEndpoint: testTokenCustomEndpoint, + jwksCustomEndpoint: testJwksCustomEndpoint, + isValid: true, }, { description: "no values", @@ -140,10 +147,10 @@ func TestStoreFlags(t *testing.T) { ServiceAccountToken: "", ServiceAccountKeyPath: "", PrivateKeyPath: "", - TokenCustomEndpoint: "", - JwksCustomEndpoint: "", }, - isValid: true, + tokenCustomEndpoint: "", + jwksCustomEndpoint: "", + isValid: true, }, } @@ -152,7 +159,11 @@ func TestStoreFlags(t *testing.T) { // Initialize an empty keyring keyring.MockInit() - err := storeFlags(tt.model) + viper.Reset() + viper.Set(config.TokenCustomEndpointKey, tt.tokenCustomEndpoint) + viper.Set(config.JwksCustomEndpointKey, tt.jwksCustomEndpoint) + + tokenCustomEndpoint, jwksCustomEndpoint, err := storeFlags() if !tt.isValid { if err == nil { t.Fatalf("did not fail on invalid input") @@ -167,16 +178,16 @@ func TestStoreFlags(t *testing.T) { if err != nil { t.Errorf("Failed to get value of auth field: %v", err) } - if value != tt.model.TokenCustomEndpoint { - t.Errorf("Value of \"%s\" does not match: expected \"%s\", got \"%s\"", auth.TOKEN_CUSTOM_ENDPOINT, tt.model.TokenCustomEndpoint, value) + if value != tokenCustomEndpoint { + t.Errorf("Value of \"%s\" does not match: expected \"%s\", got \"%s\"", auth.TOKEN_CUSTOM_ENDPOINT, tokenCustomEndpoint, value) } value, err = auth.GetAuthField(auth.JWKS_CUSTOM_ENDPOINT) if err != nil { t.Errorf("Failed to get value of auth field: %v", err) } - if value != tt.model.JwksCustomEndpoint { - t.Errorf("Value of \"%s\" does not match: expected \"%s\", got \"%s\"", auth.JWKS_CUSTOM_ENDPOINT, tt.model.TokenCustomEndpoint, value) + if value != jwksCustomEndpoint { + t.Errorf("Value of \"%s\" does not match: expected \"%s\", got \"%s\"", auth.JWKS_CUSTOM_ENDPOINT, jwksCustomEndpoint, value) } }) } diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index e44372455..eb62d1053 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -20,6 +20,7 @@ const ( sessionTimeLimitFlag = "session-time-limit" identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" + allowedUrlDomainFlag = "allowed-url-domain" argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" @@ -42,6 +43,8 @@ const ( skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" iaasCustomEndpointFlag = "iaas-custom-endpoint" + tokenCustomEndpointFlag = "token-custom-endpoint" + jwksCustomEndpointFlag = "jwks-custom-endpoint" ) type inputModel struct { @@ -131,6 +134,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(sessionTimeLimitFlag, "", "Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect)") cmd.Flags().String(identityProviderCustomEndpointFlag, "", "Identity Provider base URL, used for user authentication") cmd.Flags().String(identityProviderCustomClientIdFlag, "", "Identity Provider client ID, used for user authentication") + cmd.Flags().String(allowedUrlDomainFlag, "", `Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command`) cmd.Flags().String(argusCustomEndpointFlag, "", "Argus API base URL, used in calls to this API") cmd.Flags().String(authorizationCustomEndpointFlag, "", "Authorization API base URL, used in calls to this API") cmd.Flags().String(dnsCustomEndpointFlag, "", "DNS API base URL, used in calls to this API") @@ -152,6 +156,8 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") cmd.Flags().String(iaasCustomEndpointFlag, "", "IaaS API base URL, used in calls to this API") + cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated") + cmd.Flags().String(jwksCustomEndpointFlag, "", "Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated") err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) cobra.CheckErr(err) @@ -159,6 +165,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.IdentityProviderCustomClientIdKey, cmd.Flags().Lookup(identityProviderCustomClientIdFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.AllowedUrlDomainKey, cmd.Flags().Lookup(allowedUrlDomainFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.ArgusCustomEndpointKey, cmd.Flags().Lookup(argusCustomEndpointFlag)) cobra.CheckErr(err) @@ -202,6 +210,10 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.IaaSCustomEndpointKey, cmd.Flags().Lookup(iaasCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.TokenCustomEndpointKey, cmd.Flags().Lookup(tokenCustomEndpointFlag)) + cobra.CheckErr(err) + err = viper.BindPFlag(config.JwksCustomEndpointKey, cmd.Flags().Lookup(jwksCustomEndpointFlag)) + cobra.CheckErr(err) } func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { @@ -222,6 +234,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { projectIdSet = true } + allowedUrlDomainFromFlag := flags.FlagToStringValue(p, cmd, allowedUrlDomainFlag) + if allowedUrlDomainFromFlag == "" { + p.Warn("The allowed URL domain is set to empty. All URLs will be accepted regardless of their domain.\n") + } + model := inputModel{ SessionTimeLimit: sessionTimeLimit, ProjectIdSet: projectIdSet, diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index a879dd5b0..44526ba4d 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -23,6 +23,7 @@ const ( sessionTimeLimitFlag = "session-time-limit" identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" + allowedUrlDomainFlag = "allowed-url-domain" argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" @@ -45,6 +46,8 @@ const ( skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" iaasCustomEndpointFlag = "iaas-custom-endpoint" + tokenCustomEndpointFlag = "token-custom-endpoint" + jwksCustomEndpointFlag = "jwks-custom-endpoint" ) type inputModel struct { @@ -56,6 +59,7 @@ type inputModel struct { SessionTimeLimit bool IdentityProviderCustomEndpoint bool IdentityProviderCustomClientID bool + AllowedUrlDomain bool ArgusCustomEndpoint bool AuthorizationCustomEndpoint bool @@ -78,6 +82,8 @@ type inputModel struct { SKECustomEndpoint bool SQLServerFlexCustomEndpoint bool IaaSCustomEndpoint bool + TokenCustomEndpoint bool + JwksCustomEndpoint bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -122,6 +128,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.IdentityProviderCustomClientID { viper.Set(config.IdentityProviderCustomClientIdKey, "") } + if model.AllowedUrlDomain { + viper.Set(config.AllowedUrlDomainKey, config.AllowedUrlDomainDefault) + } if model.ArgusCustomEndpoint { viper.Set(config.ArgusCustomEndpointKey, "") @@ -186,6 +195,12 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.IaaSCustomEndpoint { viper.Set(config.IaaSCustomEndpointKey, "") } + if model.TokenCustomEndpoint { + viper.Set(config.TokenCustomEndpointKey, "") + } + if model.JwksCustomEndpoint { + viper.Set(config.JwksCustomEndpointKey, "") + } err := config.Write() if err != nil { @@ -207,6 +222,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(sessionTimeLimitFlag, false, fmt.Sprintf("Maximum time before authentication is required again. If unset, defaults to %s", config.SessionTimeLimitDefault)) cmd.Flags().Bool(identityProviderCustomEndpointFlag, false, "Identity Provider base URL. If unset, uses the default base URL") cmd.Flags().Bool(identityProviderCustomClientIdFlag, false, "Identity Provider client ID, used for user authentication") + cmd.Flags().Bool(allowedUrlDomainFlag, false, fmt.Sprintf("Domain name, used for the verification of the URLs that are given in the IDP endpoint and curl commands. If unset, defaults to %s", config.AllowedUrlDomainDefault)) cmd.Flags().Bool(argusCustomEndpointFlag, false, "Argus API base URL. If unset, uses the default base URL") cmd.Flags().Bool(authorizationCustomEndpointFlag, false, "Authorization API base URL. If unset, uses the default base URL") @@ -229,6 +245,8 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(skeCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") cmd.Flags().Bool(iaasCustomEndpointFlag, false, "IaaS API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(tokenCustomEndpointFlag, false, "Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated") + cmd.Flags().Bool(jwksCustomEndpointFlag, false, "Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { @@ -241,6 +259,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { SessionTimeLimit: flags.FlagToBoolValue(p, cmd, sessionTimeLimitFlag), IdentityProviderCustomEndpoint: flags.FlagToBoolValue(p, cmd, identityProviderCustomEndpointFlag), IdentityProviderCustomClientID: flags.FlagToBoolValue(p, cmd, identityProviderCustomClientIdFlag), + AllowedUrlDomain: flags.FlagToBoolValue(p, cmd, allowedUrlDomainFlag), ArgusCustomEndpoint: flags.FlagToBoolValue(p, cmd, argusCustomEndpointFlag), AuthorizationCustomEndpoint: flags.FlagToBoolValue(p, cmd, authorizationCustomEndpointFlag), @@ -263,6 +282,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { SKECustomEndpoint: flags.FlagToBoolValue(p, cmd, skeCustomEndpointFlag), SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), IaaSCustomEndpoint: flags.FlagToBoolValue(p, cmd, iaasCustomEndpointFlag), + TokenCustomEndpoint: flags.FlagToBoolValue(p, cmd, tokenCustomEndpointFlag), + JwksCustomEndpoint: flags.FlagToBoolValue(p, cmd, jwksCustomEndpointFlag), } if p.IsVerbosityDebug() { diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 9f64136f5..5d33ae3ce 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -19,6 +19,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool sessionTimeLimitFlag: true, identityProviderCustomEndpointFlag: true, identityProviderCustomClientIdFlag: true, + allowedUrlDomainFlag: true, argusCustomEndpointFlag: true, authorizationCustomEndpointFlag: true, @@ -38,6 +39,8 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool skeCustomEndpointFlag: true, sqlServerFlexCustomEndpointFlag: true, iaasCustomEndpointFlag: true, + tokenCustomEndpointFlag: true, + jwksCustomEndpointFlag: true, } for _, mod := range mods { mod(flagValues) @@ -55,6 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { SessionTimeLimit: true, IdentityProviderCustomEndpoint: true, IdentityProviderCustomClientID: true, + AllowedUrlDomain: true, ArgusCustomEndpoint: true, AuthorizationCustomEndpoint: true, @@ -74,6 +78,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { SKECustomEndpoint: true, SQLServerFlexCustomEndpoint: true, IaaSCustomEndpoint: true, + TokenCustomEndpoint: true, + JwksCustomEndpoint: true, } for _, mod := range mods { mod(model) @@ -107,6 +113,7 @@ func TestParseInput(t *testing.T) { model.SessionTimeLimit = false model.IdentityProviderCustomEndpoint = false model.IdentityProviderCustomClientID = false + model.AllowedUrlDomain = false model.ArgusCustomEndpoint = false model.AuthorizationCustomEndpoint = false @@ -126,6 +133,8 @@ func TestParseInput(t *testing.T) { model.SKECustomEndpoint = false model.SQLServerFlexCustomEndpoint = false model.IaaSCustomEndpoint = false + model.TokenCustomEndpoint = false + model.JwksCustomEndpoint = false }), }, { @@ -168,6 +177,16 @@ func TestParseInput(t *testing.T) { model.IdentityProviderCustomClientID = false }), }, + { + description: "allowed url domain empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[allowedUrlDomainFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.AllowedUrlDomain = false + }), + }, { description: "argus custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { @@ -248,6 +267,26 @@ func TestParseInput(t *testing.T) { model.RunCommandCustomEndpoint = false }), }, + { + description: "token custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[tokenCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.TokenCustomEndpoint = false + }), + }, + { + description: "jwks custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[jwksCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.JwksCustomEndpoint = false + }), + }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index 05caa082c..e78accf1a 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -67,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones -X POST -H "Authorization: Bearer yyy" --fail`, ), ), - Args: args.SingleArg(urlArg, utils.ValidateSTACKITURL), + Args: args.SingleArg(urlArg, utils.ValidateURLDomain), RunE: func(cmd *cobra.Command, args []string) (err error) { model, err := parseInput(p, cmd, args) if err != nil { diff --git a/internal/cmd/curl/curl_test.go b/internal/cmd/curl/curl_test.go index b6e9faa30..62d70e607 100644 --- a/internal/cmd/curl/curl_test.go +++ b/internal/cmd/curl/curl_test.go @@ -7,6 +7,8 @@ import ( "net/http" "testing" + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -78,6 +80,7 @@ func TestParseInput(t *testing.T) { argValues []string flagValues map[string]string headerFlagValues []string + allowedURLDomain string isValid bool expectedModel *inputModel }{ @@ -123,10 +126,14 @@ func TestParseInput(t *testing.T) { { description: "URL outside STACKIT", argValues: []string{ - "https://www.very-suspicious-website.com/", + "https://www.example.website.com/", }, - flagValues: fixtureFlagValues(), - isValid: false, + flagValues: fixtureFlagValues(), + allowedURLDomain: "", + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.URL = "https://www.example.website.com/" + }), }, { description: "invalid method 1", @@ -213,6 +220,9 @@ func TestParseInput(t *testing.T) { t.Fatalf("configure global flags: %v", err) } + viper.Reset() + viper.Set(config.AllowedUrlDomainKey, tt.allowedURLDomain) + for flag, value := range tt.flagValues { err := cmd.Flags().Set(flag, value) if err != nil { diff --git a/internal/pkg/auth/utils.go b/internal/pkg/auth/utils.go index a60e25a5c..34f5cbf1b 100644 --- a/internal/pkg/auth/utils.go +++ b/internal/pkg/auth/utils.go @@ -15,7 +15,7 @@ func getIDPEndpoint() (string, error) { if customIDPEndpoint != "" { idpEndpoint = customIDPEndpoint } - err := utils.ValidateSTACKITURL(idpEndpoint) + err := utils.ValidateURLDomain(idpEndpoint) if err != nil { return "", fmt.Errorf("validate custom identity provider endpoint: %w", err) } diff --git a/internal/pkg/auth/utils_test.go b/internal/pkg/auth/utils_test.go index c345c4d82..bb9e5a633 100644 --- a/internal/pkg/auth/utils_test.go +++ b/internal/pkg/auth/utils_test.go @@ -11,23 +11,47 @@ func TestGetIDPEndpoint(t *testing.T) { tests := []struct { name string idpCustomEndpoint string + allowedUrlDomain string isValid bool expected string }{ { name: "custom endpoint specified", idpCustomEndpoint: "https://example.stackit.cloud", + allowedUrlDomain: "stackit.cloud", isValid: true, expected: "https://example.stackit.cloud", }, { name: "custom endpoint outside STACKIT", idpCustomEndpoint: "https://www.very-suspicious-website.com/", + allowedUrlDomain: "stackit.cloud", isValid: false, }, + { + name: "non-STACKIT custom endpoint invalid", + idpCustomEndpoint: "https://www.very-suspicious-website.com/", + allowedUrlDomain: "stackit.cloud", + isValid: false, + }, + { + name: "non-STACKIT custom endpoint valid", + idpCustomEndpoint: "https://www.test.example.com/", + allowedUrlDomain: "example.com", + isValid: true, + expected: "https://www.test.example.com/", + }, + { + name: "every URL valid", + idpCustomEndpoint: "https://www.test.example.com/", + allowedUrlDomain: "", + isValid: true, + expected: "https://www.test.example.com/", + }, { name: "custom endpoint not specified", idpCustomEndpoint: "", + allowedUrlDomain: "", isValid: true, expected: defaultIDPEndpoint, }, @@ -36,6 +60,7 @@ func TestGetIDPEndpoint(t *testing.T) { t.Run(tt.name, func(t *testing.T) { viper.Reset() viper.Set(config.IdentityProviderCustomEndpointKey, tt.idpCustomEndpoint) + viper.Set(config.AllowedUrlDomainKey, tt.allowedUrlDomain) got, err := getIDPEndpoint() diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 548827ddb..6ca8db9c9 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -19,6 +19,7 @@ const ( IdentityProviderCustomEndpointKey = "identity_provider_custom_endpoint" IdentityProviderCustomClientIdKey = "identity_provider_custom_client_id" + AllowedUrlDomainKey = "allowed_url_domain" ArgusCustomEndpointKey = "argus_custom_endpoint" AuthorizationCustomEndpointKey = "authorization_custom_endpoint" @@ -41,12 +42,16 @@ const ( SKECustomEndpointKey = "ske_custom_endpoint" SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" IaaSCustomEndpointKey = "iaas_custom_endpoint" + TokenCustomEndpointKey = "token_custom_endpoint" + JwksCustomEndpointKey = "jwks_custom_endpoint" ProjectNameKey = "project_name" DefaultProfileName = "default" AsyncDefault = false SessionTimeLimitDefault = "2h" + + AllowedUrlDomainDefault = "stackit.cloud" ) const ( @@ -69,6 +74,7 @@ var ConfigKeys = []string{ IdentityProviderCustomEndpointKey, IdentityProviderCustomClientIdKey, + AllowedUrlDomainKey, DNSCustomEndpointKey, LoadBalancerCustomEndpointKey, @@ -92,6 +98,8 @@ var ConfigKeys = []string{ SKECustomEndpointKey, SQLServerFlexCustomEndpointKey, IaaSCustomEndpointKey, + TokenCustomEndpointKey, + JwksCustomEndpointKey, } var defaultConfigFolderPath string @@ -151,6 +159,7 @@ func setConfigDefaults() { viper.SetDefault(SessionTimeLimitKey, SessionTimeLimitDefault) viper.SetDefault(IdentityProviderCustomEndpointKey, "") viper.SetDefault(IdentityProviderCustomClientIdKey, "") + viper.SetDefault(AllowedUrlDomainKey, AllowedUrlDomainDefault) viper.SetDefault(DNSCustomEndpointKey, "") viper.SetDefault(ArgusCustomEndpointKey, "") viper.SetDefault(AuthorizationCustomEndpointKey, "") @@ -167,6 +176,8 @@ func setConfigDefaults() { viper.SetDefault(SKECustomEndpointKey, "") viper.SetDefault(SQLServerFlexCustomEndpointKey, "") viper.SetDefault(IaaSCustomEndpointKey, "") + viper.SetDefault(TokenCustomEndpointKey, "") + viper.SetDefault(JwksCustomEndpointKey, "") } func getConfigFilePath(configFolder string) string { diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index c369b92d7..205bff1cf 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -7,6 +7,8 @@ import ( "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" ) // Ptr Returns the pointer to any type T @@ -51,7 +53,7 @@ func ConvertInt64PToFloat64P(i *int64) *float64 { return &f } -func ValidateSTACKITURL(value string) error { +func ValidateURLDomain(value string) error { urlStruct, err := url.Parse(value) if err != nil { return fmt.Errorf("parse url: %w", err) @@ -60,8 +62,11 @@ func ValidateSTACKITURL(value string) error { if urlHost == "" { return fmt.Errorf("bad url") } - if !strings.HasSuffix(urlHost, "stackit.cloud") { - return fmt.Errorf(`only urls belonging to STACKIT are allowed, hostname must end in "stackit.cloud"`) + + allowedUrlDomain := viper.GetString(config.AllowedUrlDomainKey) + + if !strings.HasSuffix(urlHost, allowedUrlDomain) { + return fmt.Errorf(`only urls belonging to domain %s are allowed`, allowedUrlDomain) } return nil } diff --git a/internal/pkg/utils/utils_test.go b/internal/pkg/utils/utils_test.go index 77f5cffef..6ef165d9b 100644 --- a/internal/pkg/utils/utils_test.go +++ b/internal/pkg/utils/utils_test.go @@ -2,6 +2,9 @@ package utils import ( "testing" + + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" ) func TestConvertInt64PToFloat64P(t *testing.T) { @@ -46,21 +49,42 @@ func TestConvertInt64PToFloat64P(t *testing.T) { } } -func TestValidateSTACKITURL(t *testing.T) { +func TestValidateURLDomain(t *testing.T) { tests := []struct { - name string - input string - isValid bool + name string + allowedUrlDomain string + isValid bool + input string }{ { - name: "STACKIT URL", - input: "https://example.stackit.cloud", - isValid: true, + name: "STACKIT URL valid", + allowedUrlDomain: "stackit.cloud", + input: "https://example.stackit.cloud", + isValid: true, }, { - name: "non-STACKIT URL", - input: "https://www.very-suspicious-website.com/", - isValid: false, + name: "STACKIT URL invalid", + allowedUrlDomain: "example.com", + input: "https://example.stackit.cloud", + isValid: false, + }, + { + name: "non-STACKIT URL invalid", + allowedUrlDomain: "stackit.cloud", + input: "https://www.very-suspicious-website.com/", + isValid: false, + }, + { + name: "non-STACKIT URL valid", + allowedUrlDomain: "example.com", + input: "https://www.test.example.com/", + isValid: true, + }, + { + name: "every URL valid", + allowedUrlDomain: "", + input: "https://www.test.example.com/", + isValid: true, }, { name: "invalid URL", @@ -71,7 +95,10 @@ func TestValidateSTACKITURL(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := ValidateSTACKITURL(tt.input) + viper.Reset() + viper.Set(config.AllowedUrlDomainKey, tt.allowedUrlDomain) + + err := ValidateURLDomain(tt.input) if tt.isValid && err != nil { t.Errorf("expected URL to be valid, got error: %v", err) } From f9f6382030cbbce0efb944c1bbff4dd00d2ff4d4 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 22 Aug 2024 09:39:46 +0200 Subject: [PATCH 045/619] Fix empty check for allowed url domain (#455) --- internal/cmd/config/set/set.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index eb62d1053..2f5341121 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -234,8 +234,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { projectIdSet = true } - allowedUrlDomainFromFlag := flags.FlagToStringValue(p, cmd, allowedUrlDomainFlag) - if allowedUrlDomainFromFlag == "" { + allowedUrlDomainFromFlag := flags.FlagToStringPointer(p, cmd, allowedUrlDomainFlag) + allowedUrlDomainFlagValue := flags.FlagToStringValue(p, cmd, allowedUrlDomainFlag) + if allowedUrlDomainFromFlag != nil && allowedUrlDomainFlagValue == "" { p.Warn("The allowed URL domain is set to empty. All URLs will be accepted regardless of their domain.\n") } From 5637766d64339f6dd13340ca069b27ba51f96dc1 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:44:53 +0200 Subject: [PATCH 046/619] rename argus to observability (#454) --- README.md | 9 +- docs/stackit.md | 2 +- docs/stackit_argus.md | 37 ---- docs/stackit_argus_credentials.md | 35 ---- docs/stackit_argus_credentials_create.md | 41 ----- docs/stackit_argus_credentials_delete.md | 40 ----- docs/stackit_argus_credentials_list.md | 47 ------ docs/stackit_argus_grafana.md | 35 ---- docs/stackit_argus_grafana_describe.md | 48 ------ ...tackit_argus_grafana_public-read-access.md | 35 ---- ...rgus_grafana_public-read-access_disable.md | 40 ----- ...argus_grafana_public-read-access_enable.md | 40 ----- docs/stackit_argus_grafana_single-sign-on.md | 35 ---- ...it_argus_grafana_single-sign-on_disable.md | 40 ----- ...kit_argus_grafana_single-sign-on_enable.md | 40 ----- docs/stackit_argus_instance.md | 37 ---- docs/stackit_argus_instance_create.md | 45 ----- docs/stackit_argus_instance_delete.md | 39 ----- docs/stackit_argus_instance_describe.md | 42 ----- docs/stackit_argus_instance_list.md | 46 ----- docs/stackit_argus_instance_update.md | 48 ------ docs/stackit_argus_plans.md | 46 ----- docs/stackit_argus_scrape-config.md | 38 ----- docs/stackit_argus_scrape-config_create.md | 55 ------ docs/stackit_argus_scrape-config_delete.md | 40 ----- docs/stackit_argus_scrape-config_describe.md | 43 ----- ...it_argus_scrape-config_generate-payload.md | 58 ------- docs/stackit_argus_scrape-config_list.md | 47 ------ docs/stackit_argus_scrape-config_update.md | 51 ------ docs/stackit_config_set.md | 4 +- docs/stackit_config_unset.md | 2 +- ...load-balancer_observability-credentials.md | 2 +- ...-balancer_observability-credentials_add.md | 2 +- ...lancer_observability-credentials_update.md | 2 +- go.mod | 2 +- go.sum | 4 +- internal/cmd/config/set/set.go | 6 +- internal/cmd/config/unset/unset.go | 12 +- internal/cmd/config/unset/unset_test.go | 12 +- .../observability-credentials/add/add.go | 2 +- .../observability-credentials.go | 2 +- .../update/update.go | 2 +- .../cmd/mariadb/credentials/create/create.go | 4 +- .../credentials/create/create.go | 31 ++-- .../credentials/create/create_test.go | 8 +- .../credentials/credentials.go | 10 +- .../credentials/delete/delete.go | 20 +-- .../credentials/delete/delete_test.go | 8 +- .../credentials/list/list.go | 34 ++-- .../credentials/list/list_test.go | 8 +- .../grafana/describe/describe.go | 26 +-- .../grafana/describe/describe_test.go | 12 +- .../grafana/grafana.go | 10 +- .../public-read-access/disable/disable.go | 20 +-- .../disable/disable_test.go | 42 ++--- .../public-read-access/enable/enable.go | 20 +-- .../public-read-access/enable/enable_test.go | 42 ++--- .../public-read-access/public_read_access.go | 8 +- .../grafana/single-sign-on/disable/disable.go | 20 +-- .../single-sign-on/disable/disable_test.go | 42 ++--- .../grafana/single-sign-on/enable/enable.go | 20 +-- .../single-sign-on/enable/enable_test.go | 42 ++--- .../grafana/single-sign-on/single_sign_on.go | 8 +- .../instance/create/create.go | 62 +++---- .../instance/create/create_test.go | 32 ++-- .../instance/delete/delete.go | 24 +-- .../instance/delete/delete_test.go | 8 +- .../instance/describe/describe.go | 26 +-- .../instance/describe/describe_test.go | 8 +- .../instance/instance.go | 14 +- .../instance/list/list.go | 30 ++-- .../instance/list/list_test.go | 8 +- .../instance/update/update.go | 66 ++++---- .../instance/update/update_test.go | 40 ++--- .../observability.go} | 23 +-- .../{argus => observability}/plans/plans.go | 30 ++-- .../plans/plans_test.go | 8 +- .../scrape-config/create/create.go | 46 ++--- .../scrape-config/create/create_test.go | 18 +- .../scrape-config/delete/delete.go | 24 +-- .../scrape-config/delete/delete_test.go | 8 +- .../scrape-config/describe/describe.go | 20 +-- .../scrape-config/describe/describe_test.go | 8 +- .../generate-payload/generate_payload.go | 36 ++-- .../generate-payload/generate_payload_test.go | 8 +- .../scrape-config/list/list.go | 28 ++-- .../scrape-config/list/list_test.go | 8 +- .../scrape-config/scrape_config.go | 16 +- .../scrape-config/update/update.go | 28 ++-- .../scrape-config/update/update_test.go | 14 +- internal/cmd/root.go | 4 +- internal/pkg/config/config.go | 6 +- internal/pkg/errors/errors.go | 16 +- internal/pkg/errors/errors_test.go | 18 +- .../{argus => observability}/client/client.go | 10 +- .../{argus => observability}/utils/utils.go | 71 ++++---- .../utils/utils_test.go | 158 +++++++++--------- 97 files changed, 715 insertions(+), 1857 deletions(-) delete mode 100644 docs/stackit_argus.md delete mode 100644 docs/stackit_argus_credentials.md delete mode 100644 docs/stackit_argus_credentials_create.md delete mode 100644 docs/stackit_argus_credentials_delete.md delete mode 100644 docs/stackit_argus_credentials_list.md delete mode 100644 docs/stackit_argus_grafana.md delete mode 100644 docs/stackit_argus_grafana_describe.md delete mode 100644 docs/stackit_argus_grafana_public-read-access.md delete mode 100644 docs/stackit_argus_grafana_public-read-access_disable.md delete mode 100644 docs/stackit_argus_grafana_public-read-access_enable.md delete mode 100644 docs/stackit_argus_grafana_single-sign-on.md delete mode 100644 docs/stackit_argus_grafana_single-sign-on_disable.md delete mode 100644 docs/stackit_argus_grafana_single-sign-on_enable.md delete mode 100644 docs/stackit_argus_instance.md delete mode 100644 docs/stackit_argus_instance_create.md delete mode 100644 docs/stackit_argus_instance_delete.md delete mode 100644 docs/stackit_argus_instance_describe.md delete mode 100644 docs/stackit_argus_instance_list.md delete mode 100644 docs/stackit_argus_instance_update.md delete mode 100644 docs/stackit_argus_plans.md delete mode 100644 docs/stackit_argus_scrape-config.md delete mode 100644 docs/stackit_argus_scrape-config_create.md delete mode 100644 docs/stackit_argus_scrape-config_delete.md delete mode 100644 docs/stackit_argus_scrape-config_describe.md delete mode 100644 docs/stackit_argus_scrape-config_generate-payload.md delete mode 100644 docs/stackit_argus_scrape-config_list.md delete mode 100644 docs/stackit_argus_scrape-config_update.md rename internal/cmd/{argus => observability}/credentials/create/create.go (74%) rename internal/cmd/{argus => observability}/credentials/create/create_test.go (93%) rename internal/cmd/{argus => observability}/credentials/credentials.go (60%) rename internal/cmd/{argus => observability}/credentials/delete/delete.go (76%) rename internal/cmd/{argus => observability}/credentials/delete/delete_test.go (94%) rename internal/cmd/{argus => observability}/credentials/list/list.go (72%) rename internal/cmd/{argus => observability}/credentials/list/list_test.go (94%) rename internal/cmd/{argus => observability}/grafana/describe/describe.go (80%) rename internal/cmd/{argus => observability}/grafana/describe/describe_test.go (92%) rename internal/cmd/{argus => observability}/grafana/grafana.go (79%) rename internal/cmd/{argus => observability}/grafana/public-read-access/disable/disable.go (75%) rename internal/cmd/{argus => observability}/grafana/public-read-access/disable/disable_test.go (79%) rename internal/cmd/{argus => observability}/grafana/public-read-access/enable/enable.go (75%) rename internal/cmd/{argus => observability}/grafana/public-read-access/enable/enable_test.go (79%) rename internal/cmd/{argus => observability}/grafana/public-read-access/public_read_access.go (66%) rename internal/cmd/{argus => observability}/grafana/single-sign-on/disable/disable.go (75%) rename internal/cmd/{argus => observability}/grafana/single-sign-on/disable/disable_test.go (79%) rename internal/cmd/{argus => observability}/grafana/single-sign-on/enable/enable.go (76%) rename internal/cmd/{argus => observability}/grafana/single-sign-on/enable/enable_test.go (79%) rename internal/cmd/{argus => observability}/grafana/single-sign-on/single_sign_on.go (67%) rename internal/cmd/{argus => observability}/instance/create/create.go (67%) rename internal/cmd/{argus => observability}/instance/create/create_test.go (86%) rename internal/cmd/{argus => observability}/instance/delete/delete.go (77%) rename internal/cmd/{argus => observability}/instance/delete/delete_test.go (94%) rename internal/cmd/{argus => observability}/instance/describe/describe.go (81%) rename internal/cmd/{argus => observability}/instance/describe/describe_test.go (94%) rename internal/cmd/{argus => observability}/instance/instance.go (54%) rename internal/cmd/{argus => observability}/instance/list/list.go (80%) rename internal/cmd/{argus => observability}/instance/list/list_test.go (93%) rename internal/cmd/{argus => observability}/instance/update/update.go (67%) rename internal/cmd/{argus => observability}/instance/update/update_test.go (87%) rename internal/cmd/{argus/argus.go => observability/observability.go} (52%) rename internal/cmd/{argus => observability}/plans/plans.go (81%) rename internal/cmd/{argus => observability}/plans/plans_test.go (93%) rename internal/cmd/{argus => observability}/scrape-config/create/create.go (68%) rename internal/cmd/{argus => observability}/scrape-config/create/create_test.go (91%) rename internal/cmd/{argus => observability}/scrape-config/delete/delete.go (75%) rename internal/cmd/{argus => observability}/scrape-config/delete/delete_test.go (94%) rename internal/cmd/{argus => observability}/scrape-config/describe/describe.go (87%) rename internal/cmd/{argus => observability}/scrape-config/describe/describe_test.go (94%) rename internal/cmd/{argus => observability}/scrape-config/generate-payload/generate_payload.go (76%) rename internal/cmd/{argus => observability}/scrape-config/generate-payload/generate_payload_test.go (95%) rename internal/cmd/{argus => observability}/scrape-config/list/list.go (78%) rename internal/cmd/{argus => observability}/scrape-config/list/list_test.go (94%) rename internal/cmd/{argus => observability}/scrape-config/scrape_config.go (54%) rename internal/cmd/{argus => observability}/scrape-config/update/update.go (73%) rename internal/cmd/{argus => observability}/scrape-config/update/update_test.go (93%) rename internal/pkg/services/{argus => observability}/client/client.go (77%) rename internal/pkg/services/{argus => observability}/utils/utils.go (65%) rename internal/pkg/services/{argus => observability}/utils/utils_test.go (79%) diff --git a/README.md b/README.md index 0bad6336a..571c5b6ba 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,13 @@ Your feedback is appreciated! +> [!WARNING] +> On August 26 2024, The STACKIT Argus service was renamed to STACKIT Observability. +> +> This means that there is a new command group `observability`, which offers the same functionality as the deprecated `argus` command. +> +> Please make sure to **update your STACKIT CLI to the latest version after August 26 2024** to ensure that you start using `observability` command. + > [!WARNING] > On July 9 2024, the new [STACKIT Identity Provider (IDP)](https://docs.stackit.cloud/stackit/en/release-notes-23101442.html#ReleaseNotes-2024-06-21-identity-provider) was released. We are happy to announce that on [v0.9.0](https://github.com/stackitcloud/stackit-cli/releases/tag/v0.9.0), the new IDP was integrated in the STACKIT CLI, where it is used for user authentication. > @@ -67,7 +74,7 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Service | CLI Commands | Status | |------------------------------------|---------------------------|---------------------------| -| Argus | `argus` | :white_check_mark: | +| Observability | `observability` | :white_check_mark: | | Infrastructure as a Service (IaaS) | `beta network-area` | :white_check_mark: (beta) | | Authorization | `project`, `organization` | :white_check_mark: | | DNS | `dns` | :white_check_mark: | diff --git a/docs/stackit.md b/docs/stackit.md index cb2915ace..8ec49c754 100644 --- a/docs/stackit.md +++ b/docs/stackit.md @@ -26,7 +26,6 @@ stackit [flags] ### SEE ALSO -* [stackit argus](./stackit_argus.md) - Provides functionality for Argus * [stackit auth](./stackit_auth.md) - Authenticates the STACKIT CLI * [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands * [stackit config](./stackit_config.md) - Provides functionality for CLI configuration options @@ -37,6 +36,7 @@ stackit [flags] * [stackit mariadb](./stackit_mariadb.md) - Provides functionality for MariaDB * [stackit mongodbflex](./stackit_mongodbflex.md) - Provides functionality for MongoDB Flex * [stackit object-storage](./stackit_object-storage.md) - Provides functionality for Object Storage +* [stackit observability](./stackit_observability.md) - Provides functionality for Observability * [stackit opensearch](./stackit_opensearch.md) - Provides functionality for OpenSearch * [stackit organization](./stackit_organization.md) - Manages organizations * [stackit postgresflex](./stackit_postgresflex.md) - Provides functionality for PostgreSQL Flex diff --git a/docs/stackit_argus.md b/docs/stackit_argus.md deleted file mode 100644 index b09e8d344..000000000 --- a/docs/stackit_argus.md +++ /dev/null @@ -1,37 +0,0 @@ -## stackit argus - -Provides functionality for Argus - -### Synopsis - -Provides functionality for Argus. - -``` -stackit argus [flags] -``` - -### Options - -``` - -h, --help Help for "stackit argus" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit](./stackit.md) - Manage STACKIT resources using the command line -* [stackit argus credentials](./stackit_argus_credentials.md) - Provides functionality for Argus credentials -* [stackit argus grafana](./stackit_argus_grafana.md) - Provides functionality for the Grafana configuration of Argus instances -* [stackit argus instance](./stackit_argus_instance.md) - Provides functionality for Argus instances -* [stackit argus plans](./stackit_argus_plans.md) - Lists all Argus service plans -* [stackit argus scrape-config](./stackit_argus_scrape-config.md) - Provides functionality for scrape configurations in Argus - diff --git a/docs/stackit_argus_credentials.md b/docs/stackit_argus_credentials.md deleted file mode 100644 index b8cb24b2d..000000000 --- a/docs/stackit_argus_credentials.md +++ /dev/null @@ -1,35 +0,0 @@ -## stackit argus credentials - -Provides functionality for Argus credentials - -### Synopsis - -Provides functionality for Argus credentials. - -``` -stackit argus credentials [flags] -``` - -### Options - -``` - -h, --help Help for "stackit argus credentials" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus](./stackit_argus.md) - Provides functionality for Argus -* [stackit argus credentials create](./stackit_argus_credentials_create.md) - Creates credentials for an Argus instance. -* [stackit argus credentials delete](./stackit_argus_credentials_delete.md) - Deletes credentials of an Argus instance -* [stackit argus credentials list](./stackit_argus_credentials_list.md) - Lists the usernames of all credentials for an Argus instance - diff --git a/docs/stackit_argus_credentials_create.md b/docs/stackit_argus_credentials_create.md deleted file mode 100644 index 9a5c0de17..000000000 --- a/docs/stackit_argus_credentials_create.md +++ /dev/null @@ -1,41 +0,0 @@ -## stackit argus credentials create - -Creates credentials for an Argus instance. - -### Synopsis - -Creates credentials (username and password) for an Argus instance. -The credentials will be generated and included in the response. You won't be able to retrieve the password later. - -``` -stackit argus credentials create [flags] -``` - -### Examples - -``` - Create credentials for Argus instance with ID "xxx" - $ stackit argus credentials create --instance-id xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus credentials create" - --instance-id string Instance ID -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus credentials](./stackit_argus_credentials.md) - Provides functionality for Argus credentials - diff --git a/docs/stackit_argus_credentials_delete.md b/docs/stackit_argus_credentials_delete.md deleted file mode 100644 index b88f82b44..000000000 --- a/docs/stackit_argus_credentials_delete.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit argus credentials delete - -Deletes credentials of an Argus instance - -### Synopsis - -Deletes credentials of an Argus instance. - -``` -stackit argus credentials delete USERNAME [flags] -``` - -### Examples - -``` - Delete credentials of username "xxx" for Argus instance with ID "yyy" - $ stackit argus credentials delete xxx --instance-id yyy -``` - -### Options - -``` - -h, --help Help for "stackit argus credentials delete" - --instance-id string Instance ID -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus credentials](./stackit_argus_credentials.md) - Provides functionality for Argus credentials - diff --git a/docs/stackit_argus_credentials_list.md b/docs/stackit_argus_credentials_list.md deleted file mode 100644 index 889f08e04..000000000 --- a/docs/stackit_argus_credentials_list.md +++ /dev/null @@ -1,47 +0,0 @@ -## stackit argus credentials list - -Lists the usernames of all credentials for an Argus instance - -### Synopsis - -Lists the usernames of all credentials for an Argus instance. - -``` -stackit argus credentials list [flags] -``` - -### Examples - -``` - List the usernames of all credentials for an Argus instance with ID "xxx" - $ stackit argus credentials list --instance-id xxx - - List the usernames of all credentials for an Argus instance in JSON format - $ stackit argus credentials list --instance-id xxx --output-format json - - List the usernames of up to 10 credentials for an Argus instance - $ stackit argus credentials list --instance-id xxx --limit 10 -``` - -### Options - -``` - -h, --help Help for "stackit argus credentials list" - --instance-id string Instance ID - --limit int Maximum number of entries to list -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus credentials](./stackit_argus_credentials.md) - Provides functionality for Argus credentials - diff --git a/docs/stackit_argus_grafana.md b/docs/stackit_argus_grafana.md deleted file mode 100644 index 3307c0b37..000000000 --- a/docs/stackit_argus_grafana.md +++ /dev/null @@ -1,35 +0,0 @@ -## stackit argus grafana - -Provides functionality for the Grafana configuration of Argus instances - -### Synopsis - -Provides functionality for the Grafana configuration of Argus instances. - -``` -stackit argus grafana [flags] -``` - -### Options - -``` - -h, --help Help for "stackit argus grafana" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus](./stackit_argus.md) - Provides functionality for Argus -* [stackit argus grafana describe](./stackit_argus_grafana_describe.md) - Shows details of the Grafana configuration of an Argus instance -* [stackit argus grafana public-read-access](./stackit_argus_grafana_public-read-access.md) - Enable or disable public read access for Grafana in Argus instances -* [stackit argus grafana single-sign-on](./stackit_argus_grafana_single-sign-on.md) - Enable or disable single sign-on for Grafana in Argus instances - diff --git a/docs/stackit_argus_grafana_describe.md b/docs/stackit_argus_grafana_describe.md deleted file mode 100644 index 53ea3812a..000000000 --- a/docs/stackit_argus_grafana_describe.md +++ /dev/null @@ -1,48 +0,0 @@ -## stackit argus grafana describe - -Shows details of the Grafana configuration of an Argus instance - -### Synopsis - -Shows details of the Grafana configuration of an Argus instance. -The Grafana dashboard URL and initial credentials (admin user and password) will be shown in the "pretty" output format. These credentials are only valid for first login. Please change the password after first login. After changing, the initial password is no longer valid. -The initial password is hidden by default, if you want to show it use the "--show-password" flag. - -``` -stackit argus grafana describe INSTANCE_ID [flags] -``` - -### Examples - -``` - Get details of the Grafana configuration of an Argus instance with ID "xxx" - $ stackit argus credentials describe xxx - - Get details of the Grafana configuration of an Argus instance with ID "xxx" and show the initial admin password - $ stackit argus credentials describe xxx --show-password - - Get details of the Grafana configuration of an Argus instance with ID "xxx" in JSON format - $ stackit argus credentials describe xxx --output-format json -``` - -### Options - -``` - -h, --help Help for "stackit argus grafana describe" - -s, --show-password Show password in output -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus grafana](./stackit_argus_grafana.md) - Provides functionality for the Grafana configuration of Argus instances - diff --git a/docs/stackit_argus_grafana_public-read-access.md b/docs/stackit_argus_grafana_public-read-access.md deleted file mode 100644 index 963dbec1d..000000000 --- a/docs/stackit_argus_grafana_public-read-access.md +++ /dev/null @@ -1,35 +0,0 @@ -## stackit argus grafana public-read-access - -Enable or disable public read access for Grafana in Argus instances - -### Synopsis - -Enable or disable public read access for Grafana in Argus instances. -When enabled, anyone can access the Grafana dashboards of the instance without logging in. Otherwise, a login is required. - -``` -stackit argus grafana public-read-access [flags] -``` - -### Options - -``` - -h, --help Help for "stackit argus grafana public-read-access" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus grafana](./stackit_argus_grafana.md) - Provides functionality for the Grafana configuration of Argus instances -* [stackit argus grafana public-read-access disable](./stackit_argus_grafana_public-read-access_disable.md) - Disables public read access for Grafana on Argus instances -* [stackit argus grafana public-read-access enable](./stackit_argus_grafana_public-read-access_enable.md) - Enables public read access for Grafana on Argus instances - diff --git a/docs/stackit_argus_grafana_public-read-access_disable.md b/docs/stackit_argus_grafana_public-read-access_disable.md deleted file mode 100644 index b2f232934..000000000 --- a/docs/stackit_argus_grafana_public-read-access_disable.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit argus grafana public-read-access disable - -Disables public read access for Grafana on Argus instances - -### Synopsis - -Disables public read access for Grafana on Argus instances. -When disabled, a login is required to access the Grafana dashboards of the instance. Otherwise, anyone can access the dashboards. - -``` -stackit argus grafana public-read-access disable INSTANCE_ID [flags] -``` - -### Examples - -``` - Disable public read access for Grafana on an Argus instance with ID "xxx" - $ stackit argus grafana public-read-access disable xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus grafana public-read-access disable" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus grafana public-read-access](./stackit_argus_grafana_public-read-access.md) - Enable or disable public read access for Grafana in Argus instances - diff --git a/docs/stackit_argus_grafana_public-read-access_enable.md b/docs/stackit_argus_grafana_public-read-access_enable.md deleted file mode 100644 index 1cbe9579a..000000000 --- a/docs/stackit_argus_grafana_public-read-access_enable.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit argus grafana public-read-access enable - -Enables public read access for Grafana on Argus instances - -### Synopsis - -Enables public read access for Grafana on Argus instances. -When enabled, anyone can access the Grafana dashboards of the instance without logging in. Otherwise, a login is required. - -``` -stackit argus grafana public-read-access enable INSTANCE_ID [flags] -``` - -### Examples - -``` - Enable public read access for Grafana on an Argus instance with ID "xxx" - $ stackit argus grafana public-read-access enable xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus grafana public-read-access enable" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus grafana public-read-access](./stackit_argus_grafana_public-read-access.md) - Enable or disable public read access for Grafana in Argus instances - diff --git a/docs/stackit_argus_grafana_single-sign-on.md b/docs/stackit_argus_grafana_single-sign-on.md deleted file mode 100644 index 37540150e..000000000 --- a/docs/stackit_argus_grafana_single-sign-on.md +++ /dev/null @@ -1,35 +0,0 @@ -## stackit argus grafana single-sign-on - -Enable or disable single sign-on for Grafana in Argus instances - -### Synopsis - -Enable or disable single sign-on for Grafana in Argus instances. -When enabled for an instance, overwrites the generic OAuth2 authentication and configures STACKIT single sign-on for that instance. - -``` -stackit argus grafana single-sign-on [flags] -``` - -### Options - -``` - -h, --help Help for "stackit argus grafana single-sign-on" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus grafana](./stackit_argus_grafana.md) - Provides functionality for the Grafana configuration of Argus instances -* [stackit argus grafana single-sign-on disable](./stackit_argus_grafana_single-sign-on_disable.md) - Disables single sign-on for Grafana on Argus instances -* [stackit argus grafana single-sign-on enable](./stackit_argus_grafana_single-sign-on_enable.md) - Enables single sign-on for Grafana on Argus instances - diff --git a/docs/stackit_argus_grafana_single-sign-on_disable.md b/docs/stackit_argus_grafana_single-sign-on_disable.md deleted file mode 100644 index 2766cb326..000000000 --- a/docs/stackit_argus_grafana_single-sign-on_disable.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit argus grafana single-sign-on disable - -Disables single sign-on for Grafana on Argus instances - -### Synopsis - -Disables single sign-on for Grafana on Argus instances. -When disabled for an instance, the generic OAuth2 authentication is used for that instance. - -``` -stackit argus grafana single-sign-on disable INSTANCE_ID [flags] -``` - -### Examples - -``` - Disable single sign-on for Grafana on an Argus instance with ID "xxx" - $ stackit argus grafana single-sign-on disable xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus grafana single-sign-on disable" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus grafana single-sign-on](./stackit_argus_grafana_single-sign-on.md) - Enable or disable single sign-on for Grafana in Argus instances - diff --git a/docs/stackit_argus_grafana_single-sign-on_enable.md b/docs/stackit_argus_grafana_single-sign-on_enable.md deleted file mode 100644 index 33b6ae4e1..000000000 --- a/docs/stackit_argus_grafana_single-sign-on_enable.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit argus grafana single-sign-on enable - -Enables single sign-on for Grafana on Argus instances - -### Synopsis - -Enables single sign-on for Grafana on Argus instances. -When enabled for an instance, overwrites the generic OAuth2 authentication and configures STACKIT single sign-on for that instance. - -``` -stackit argus grafana single-sign-on enable INSTANCE_ID [flags] -``` - -### Examples - -``` - Enable single sign-on for Grafana on an Argus instance with ID "xxx" - $ stackit argus grafana single-sign-on enable xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus grafana single-sign-on enable" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus grafana single-sign-on](./stackit_argus_grafana_single-sign-on.md) - Enable or disable single sign-on for Grafana in Argus instances - diff --git a/docs/stackit_argus_instance.md b/docs/stackit_argus_instance.md deleted file mode 100644 index 8683c76eb..000000000 --- a/docs/stackit_argus_instance.md +++ /dev/null @@ -1,37 +0,0 @@ -## stackit argus instance - -Provides functionality for Argus instances - -### Synopsis - -Provides functionality for Argus instances. - -``` -stackit argus instance [flags] -``` - -### Options - -``` - -h, --help Help for "stackit argus instance" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus](./stackit_argus.md) - Provides functionality for Argus -* [stackit argus instance create](./stackit_argus_instance_create.md) - Creates an Argus instance -* [stackit argus instance delete](./stackit_argus_instance_delete.md) - Deletes an Argus instance -* [stackit argus instance describe](./stackit_argus_instance_describe.md) - Shows details of an Argus instance -* [stackit argus instance list](./stackit_argus_instance_list.md) - Lists all Argus instances -* [stackit argus instance update](./stackit_argus_instance_update.md) - Updates an Argus instance - diff --git a/docs/stackit_argus_instance_create.md b/docs/stackit_argus_instance_create.md deleted file mode 100644 index ed63c92e0..000000000 --- a/docs/stackit_argus_instance_create.md +++ /dev/null @@ -1,45 +0,0 @@ -## stackit argus instance create - -Creates an Argus instance - -### Synopsis - -Creates an Argus instance. - -``` -stackit argus instance create [flags] -``` - -### Examples - -``` - Create an Argus instance with name "my-instance" and specify plan by name - $ stackit argus instance create --name my-instance --plan-name Monitoring-Starter-EU01 - - Create an Argus instance with name "my-instance" and specify plan by ID - $ stackit argus instance create --name my-instance --plan-id xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus instance create" - -n, --name string Instance name - --plan-id string Plan ID - --plan-name string Plan name -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus instance](./stackit_argus_instance.md) - Provides functionality for Argus instances - diff --git a/docs/stackit_argus_instance_delete.md b/docs/stackit_argus_instance_delete.md deleted file mode 100644 index b0c681607..000000000 --- a/docs/stackit_argus_instance_delete.md +++ /dev/null @@ -1,39 +0,0 @@ -## stackit argus instance delete - -Deletes an Argus instance - -### Synopsis - -Deletes an Argus instance. - -``` -stackit argus instance delete INSTANCE_ID [flags] -``` - -### Examples - -``` - Delete an Argus instance with ID "xxx" - $ stackit argus instance delete xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus instance delete" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus instance](./stackit_argus_instance.md) - Provides functionality for Argus instances - diff --git a/docs/stackit_argus_instance_describe.md b/docs/stackit_argus_instance_describe.md deleted file mode 100644 index 77d3c6546..000000000 --- a/docs/stackit_argus_instance_describe.md +++ /dev/null @@ -1,42 +0,0 @@ -## stackit argus instance describe - -Shows details of an Argus instance - -### Synopsis - -Shows details of an Argus instance. - -``` -stackit argus instance describe INSTANCE_ID [flags] -``` - -### Examples - -``` - Get details of an Argus instance with ID "xxx" - $ stackit argus instance describe xxx - - Get details of an Argus instance with ID "xxx" in JSON format - $ stackit argus instance describe xxx --output-format json -``` - -### Options - -``` - -h, --help Help for "stackit argus instance 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus instance](./stackit_argus_instance.md) - Provides functionality for Argus instances - diff --git a/docs/stackit_argus_instance_list.md b/docs/stackit_argus_instance_list.md deleted file mode 100644 index b91308146..000000000 --- a/docs/stackit_argus_instance_list.md +++ /dev/null @@ -1,46 +0,0 @@ -## stackit argus instance list - -Lists all Argus instances - -### Synopsis - -Lists all Argus instances. - -``` -stackit argus instance list [flags] -``` - -### Examples - -``` - List all Argus instances - $ stackit argus instance list - - List all Argus instances in JSON format - $ stackit argus instance list --output-format json - - List up to 10 Argus instances - $ stackit argus instance list --limit 10 -``` - -### Options - -``` - -h, --help Help for "stackit argus instance list" - --limit int Maximum number of entries to list -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus instance](./stackit_argus_instance.md) - Provides functionality for Argus instances - diff --git a/docs/stackit_argus_instance_update.md b/docs/stackit_argus_instance_update.md deleted file mode 100644 index 25155965e..000000000 --- a/docs/stackit_argus_instance_update.md +++ /dev/null @@ -1,48 +0,0 @@ -## stackit argus instance update - -Updates an Argus instance - -### Synopsis - -Updates an Argus instance. - -``` -stackit argus instance update INSTANCE_ID [flags] -``` - -### Examples - -``` - Update the plan of an Argus instance with ID "xxx" by specifying the plan ID - $ stackit argus instance update xxx --plan-id yyy - - Update the plan of an Argus instance with ID "xxx" by specifying the plan name - $ stackit argus instance update xxx --plan-name Frontend-Starter-EU01 - - Update the name of an Argus instance with ID "xxx" - $ stackit argus instance update xxx --name new-instance-name -``` - -### Options - -``` - -h, --help Help for "stackit argus instance update" - -n, --name string Instance name - --plan-id string Plan ID - --plan-name string Plan name -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus instance](./stackit_argus_instance.md) - Provides functionality for Argus instances - diff --git a/docs/stackit_argus_plans.md b/docs/stackit_argus_plans.md deleted file mode 100644 index bc65afb9e..000000000 --- a/docs/stackit_argus_plans.md +++ /dev/null @@ -1,46 +0,0 @@ -## stackit argus plans - -Lists all Argus service plans - -### Synopsis - -Lists all Argus service plans. - -``` -stackit argus plans [flags] -``` - -### Examples - -``` - List all Argus service plans - $ stackit argus plans - - List all Argus service plans in JSON format - $ stackit argus plans --output-format json - - List up to 10 Argus service plans - $ stackit argus plans --limit 10 -``` - -### Options - -``` - -h, --help Help for "stackit argus plans" - --limit int Maximum number of entries to list -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus](./stackit_argus.md) - Provides functionality for Argus - diff --git a/docs/stackit_argus_scrape-config.md b/docs/stackit_argus_scrape-config.md deleted file mode 100644 index 8a96ec535..000000000 --- a/docs/stackit_argus_scrape-config.md +++ /dev/null @@ -1,38 +0,0 @@ -## stackit argus scrape-config - -Provides functionality for scrape configurations in Argus - -### Synopsis - -Provides functionality for scrape configurations in Argus. - -``` -stackit argus scrape-config [flags] -``` - -### Options - -``` - -h, --help Help for "stackit argus scrape-config" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus](./stackit_argus.md) - Provides functionality for Argus -* [stackit argus scrape-config create](./stackit_argus_scrape-config_create.md) - Creates a scrape configuration for an Argus instance -* [stackit argus scrape-config delete](./stackit_argus_scrape-config_delete.md) - Deletes a scrape configuration from an Argus instance -* [stackit argus scrape-config describe](./stackit_argus_scrape-config_describe.md) - Shows details of a scrape configuration from an Argus instance -* [stackit argus scrape-config generate-payload](./stackit_argus_scrape-config_generate-payload.md) - Generates a payload to create/update scrape configurations for an Argus instance -* [stackit argus scrape-config list](./stackit_argus_scrape-config_list.md) - Lists all scrape configurations of an Argus instance -* [stackit argus scrape-config update](./stackit_argus_scrape-config_update.md) - Updates a scrape configuration of an Argus instance - diff --git a/docs/stackit_argus_scrape-config_create.md b/docs/stackit_argus_scrape-config_create.md deleted file mode 100644 index 0df2e91bd..000000000 --- a/docs/stackit_argus_scrape-config_create.md +++ /dev/null @@ -1,55 +0,0 @@ -## stackit argus scrape-config create - -Creates a scrape configuration for an Argus instance - -### Synopsis - -Creates a scrape configuration job for an Argus instance. -The payload can be provided as a JSON string or a file path prefixed with "@". -If no payload is provided, a default payload will be used. -See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_create for information regarding the payload structure. - -``` -stackit argus scrape-config create [flags] -``` - -### Examples - -``` - Create a scrape configuration on Argus instance "xxx" using default configuration - $ stackit argus scrape-config create - - Create a scrape configuration on Argus instance "xxx" using an API payload sourced from the file "./payload.json" - $ stackit argus scrape-config create --payload @./payload.json --instance-id xxx - - Create a scrape configuration on Argus instance "xxx" using an API payload provided as a JSON string - $ stackit argus scrape-config create --payload "{...}" --instance-id xxx - - Generate a payload with default values, and adapt it with custom values for the different configuration options - $ stackit argus scrape-config generate-payload > ./payload.json - - $ stackit argus scrape-config create --payload @./payload.json --instance-id xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus scrape-config create" - --instance-id string Instance ID - --payload string Request payload (JSON). Can be a string or a file path, if prefixed with "@" (example: @./payload.json). If unset, will use a default payload (you can check it by running "stackit argus scrape-config generate-payload") -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus scrape-config](./stackit_argus_scrape-config.md) - Provides functionality for scrape configurations in Argus - diff --git a/docs/stackit_argus_scrape-config_delete.md b/docs/stackit_argus_scrape-config_delete.md deleted file mode 100644 index 503433973..000000000 --- a/docs/stackit_argus_scrape-config_delete.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit argus scrape-config delete - -Deletes a scrape configuration from an Argus instance - -### Synopsis - -Deletes a scrape configuration from an Argus instance. - -``` -stackit argus scrape-config delete JOB_NAME [flags] -``` - -### Examples - -``` - Delete a scrape configuration job with name "my-config" from Argus instance "xxx" - $ stackit argus scrape-config delete my-config --instance-id xxx -``` - -### Options - -``` - -h, --help Help for "stackit argus scrape-config delete" - --instance-id string Instance ID -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus scrape-config](./stackit_argus_scrape-config.md) - Provides functionality for scrape configurations in Argus - diff --git a/docs/stackit_argus_scrape-config_describe.md b/docs/stackit_argus_scrape-config_describe.md deleted file mode 100644 index 565c8f65f..000000000 --- a/docs/stackit_argus_scrape-config_describe.md +++ /dev/null @@ -1,43 +0,0 @@ -## stackit argus scrape-config describe - -Shows details of a scrape configuration from an Argus instance - -### Synopsis - -Shows details of a scrape configuration from an Argus instance. - -``` -stackit argus scrape-config describe JOB_NAME [flags] -``` - -### Examples - -``` - Get details of a scrape configuration with name "my-config" from Argus instance "xxx" - $ stackit argus scrape-config describe my-config --instance-id xxx - - Get details of a scrape configuration with name "my-config" from Argus instance "xxx" in JSON format - $ stackit argus scrape-config describe my-config --output-format json -``` - -### Options - -``` - -h, --help Help for "stackit argus scrape-config describe" - --instance-id string Instance ID -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus scrape-config](./stackit_argus_scrape-config.md) - Provides functionality for scrape configurations in Argus - diff --git a/docs/stackit_argus_scrape-config_generate-payload.md b/docs/stackit_argus_scrape-config_generate-payload.md deleted file mode 100644 index a6d725a27..000000000 --- a/docs/stackit_argus_scrape-config_generate-payload.md +++ /dev/null @@ -1,58 +0,0 @@ -## stackit argus scrape-config generate-payload - -Generates a payload to create/update scrape configurations for an Argus instance - -### Synopsis - -Generates a JSON payload with values to be used as --payload input for scrape configurations creation or update. -This command can be used to generate a payload to update an existing scrape config or to create a new scrape config job. -To update an existing scrape config job, provide the job name and the instance ID of the Argus instance. -To obtain a default payload to create a new scrape config job, run the command with no flags. -Note that some of the default values provided, such as the job name, the metrics path and URL of the targets, should be adapted to your use case. -See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_create for information regarding the payload structure. - - -``` -stackit argus scrape-config generate-payload [flags] -``` - -### Examples - -``` - Generate a Create payload with default values, and adapt it with custom values for the different configuration options - $ stackit argus scrape-config generate-payload --file-path ./payload.json - - $ stackit argus scrape-config create my-config --payload @./payload.json - - Generate an Update payload with the values of an existing configuration named "my-config" for Argus instance xxx, and adapt it with custom values for the different configuration options - $ stackit argus scrape-config generate-payload --job-name my-config --instance-id xxx --file-path ./payload.json - - $ stackit argus scrape-config update my-config --payload @./payload.json - - Generate an Update payload with the values of an existing configuration named "my-config" for Argus instance xxx, and preview it in the terminal - $ stackit argus scrape-config generate-payload --job-name my-config --instance-id xxx -``` - -### Options - -``` - -f, --file-path string If set, writes the payload to the given file. If unset, writes the payload to the standard output - -h, --help Help for "stackit argus scrape-config generate-payload" - --instance-id string Instance ID - -n, --job-name string If set, generates an update payload with the current state of the given scrape config. If unset, generates a create payload with default values -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus scrape-config](./stackit_argus_scrape-config.md) - Provides functionality for scrape configurations in Argus - diff --git a/docs/stackit_argus_scrape-config_list.md b/docs/stackit_argus_scrape-config_list.md deleted file mode 100644 index a4ae284f4..000000000 --- a/docs/stackit_argus_scrape-config_list.md +++ /dev/null @@ -1,47 +0,0 @@ -## stackit argus scrape-config list - -Lists all scrape configurations of an Argus instance - -### Synopsis - -Lists all scrape configurations of an Argus instance. - -``` -stackit argus scrape-config list [flags] -``` - -### Examples - -``` - List all scrape configurations of Argus instance "xxx" - $ stackit argus scrape-config list --instance-id xxx - - List all scrape configurations of Argus instance "xxx" in JSON format - $ stackit argus scrape-config list --instance-id xxx --output-format json - - List up to 10 scrape configurations of Argus instance "xxx" - $ stackit argus scrape-config list --instance-id xxx --limit 10 -``` - -### Options - -``` - -h, --help Help for "stackit argus scrape-config list" - --instance-id string Instance ID - --limit int Maximum number of entries to list -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus scrape-config](./stackit_argus_scrape-config.md) - Provides functionality for scrape configurations in Argus - diff --git a/docs/stackit_argus_scrape-config_update.md b/docs/stackit_argus_scrape-config_update.md deleted file mode 100644 index f335fc673..000000000 --- a/docs/stackit_argus_scrape-config_update.md +++ /dev/null @@ -1,51 +0,0 @@ -## stackit argus scrape-config update - -Updates a scrape configuration of an Argus instance - -### Synopsis - -Updates a scrape configuration of an Argus instance. -The payload can be provided as a JSON string or a file path prefixed with "@". -See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_update for information regarding the payload structure. - -``` -stackit argus scrape-config update JOB_NAME [flags] -``` - -### Examples - -``` - Update a scrape configuration with name "my-config" from Argus instance "xxx", using an API payload sourced from the file "./payload.json" - $ stackit argus scrape-config update my-config --payload @./payload.json --instance-id xxx - - Update an scrape configuration with name "my-config" from Argus instance "xxx", using an API payload provided as a JSON string - $ stackit argus scrape-config update my-config --payload "{...}" --instance-id xxx - - Generate a payload with the current values of a scrape configuration, and adapt it with custom values for the different configuration options - $ stackit argus scrape-config generate-payload --job-name my-config > ./payload.json - - $ stackit argus scrape-configs update my-config --payload @./payload.json -``` - -### Options - -``` - -h, --help Help for "stackit argus scrape-config update" - --instance-id string Instance ID - --payload string Request payload (JSON). Can be a string or a file path, if prefixed with "@". Example: @./payload.json -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit argus scrape-config](./stackit_argus_scrape-config.md) - Provides functionality for scrape configurations in Argus - diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index d739983cc..6c7378e4d 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -29,8 +29,7 @@ stackit config set [flags] ### Options ``` - --allowed-url-domain string Domain name, used for the verification of the URLs that are given in the custom identidy provider endpoint and "STACKIT curl" command - --argus-custom-endpoint string Argus API base URL, used in calls to this API + --allowed-url-domain string Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command --authorization-custom-endpoint string Authorization API base URL, used in calls to this API --dns-custom-endpoint string DNS API base URL, used in calls to this API -h, --help Help for "stackit config set" @@ -43,6 +42,7 @@ stackit config set [flags] --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API --mongodbflex-custom-endpoint string MongoDB Flex API base URL, used in calls to this API --object-storage-custom-endpoint string Object Storage API base URL, used in calls to this API + --observability-custom-endpoint string Observability API base URL, used in calls to this API --opensearch-custom-endpoint string OpenSearch API base URL, used in calls to this API --postgresflex-custom-endpoint string PostgreSQL Flex API base URL, used in calls to this API --rabbitmq-custom-endpoint string RabbitMQ API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index fc68fe45a..3f6a4e508 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -27,7 +27,6 @@ stackit config unset [flags] ``` --allowed-url-domain Domain name, used for the verification of the URLs that are given in the IDP endpoint and curl commands. If unset, defaults to stackit.cloud - --argus-custom-endpoint Argus API base URL. If unset, uses the default base URL --async Configuration option to run commands asynchronously --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL @@ -41,6 +40,7 @@ stackit config unset [flags] --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL --mongodbflex-custom-endpoint MongoDB Flex API base URL. If unset, uses the default base URL --object-storage-custom-endpoint Object Storage API base URL. If unset, uses the default base URL + --observability-custom-endpoint Observability API base URL. If unset, uses the default base URL --opensearch-custom-endpoint OpenSearch API base URL. If unset, uses the default base URL --output-format Output format --postgresflex-custom-endpoint PostgreSQL Flex API base URL. If unset, uses the default base URL diff --git a/docs/stackit_load-balancer_observability-credentials.md b/docs/stackit_load-balancer_observability-credentials.md index 187047d14..6a9806d41 100644 --- a/docs/stackit_load-balancer_observability-credentials.md +++ b/docs/stackit_load-balancer_observability-credentials.md @@ -4,7 +4,7 @@ Provides functionality for Load Balancer observability credentials ### Synopsis -Provides functionality for Load Balancer observability credentials. These commands can be used to store and update existing credentials, which are valid to be used for Load Balancer observability. This means, e.g. when using Argus, first of all these credentials must be created for that Argus instance (by using "stackit argus credentials create") and then can be managed for a Load Balancer by using the commands in this group. +Provides functionality for Load Balancer observability credentials. These commands can be used to store and update existing credentials, which are valid to be used for Load Balancer observability. This means, e.g. when using Observability, first of all these credentials must be created for that Observability instance (by using "stackit observability credentials create") and then can be managed for a Load Balancer by using the commands in this group. ``` stackit load-balancer observability-credentials [flags] diff --git a/docs/stackit_load-balancer_observability-credentials_add.md b/docs/stackit_load-balancer_observability-credentials_add.md index 8abbc2fe9..8f86b2aad 100644 --- a/docs/stackit_load-balancer_observability-credentials_add.md +++ b/docs/stackit_load-balancer_observability-credentials_add.md @@ -4,7 +4,7 @@ Adds observability credentials to Load Balancer ### Synopsis -Adds existing observability credentials (username and password) to Load Balancer. The credentials can be for Argus or another monitoring tool. +Adds existing observability credentials (username and password) to Load Balancer. The credentials can be for Observability or another monitoring tool. ``` stackit load-balancer observability-credentials add [flags] diff --git a/docs/stackit_load-balancer_observability-credentials_update.md b/docs/stackit_load-balancer_observability-credentials_update.md index 2ef125bbc..53fa1cd02 100644 --- a/docs/stackit_load-balancer_observability-credentials_update.md +++ b/docs/stackit_load-balancer_observability-credentials_update.md @@ -4,7 +4,7 @@ Updates observability credentials for Load Balancer ### Synopsis -Updates existing observability credentials (username and password) for Load Balancer. The credentials can be for Argus or another monitoring tool. +Updates existing observability credentials (username and password) for Load Balancer. The credentials can be for Observability or another monitoring tool. ``` stackit load-balancer observability-credentials update [flags] diff --git a/go.mod b/go.mod index ef94341f6..d2be18fc3 100644 --- a/go.mod +++ b/go.mod @@ -77,11 +77,11 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/argus v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 3477d20ae..84bd7f50a 100644 --- a/go.sum +++ b/go.sum @@ -125,8 +125,6 @@ github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stackitcloud/stackit-sdk-go/core v0.12.0 h1:auIzUUNRuydKOScvpICP4MifGgvOajiDQd+ncGmBL0U= github.com/stackitcloud/stackit-sdk-go/core v0.12.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= -github.com/stackitcloud/stackit-sdk-go/services/argus v0.11.0 h1:JVEx/ouHB6PlwGzQa3ywyDym1HTWo3WgrxAyXprCnuM= -github.com/stackitcloud/stackit-sdk-go/services/argus v0.11.0/go.mod h1:nVllQfYODhX1q3bgwVTLO7wHOp+8NMLiKbn3u/Dg5nU= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd0rCm+2+xaWqtfibjWmkKlO+U+7qxqvtKpJ8= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= @@ -143,6 +141,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 h1:FaJYVfha+ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0/go.mod h1:iFerEzGmkg6R13ldFUyHUWHm0ac9cS4ftTDLhP0k/dU= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 h1:tn1MD1nu+gYEbT3lslRI6BrapKwuvHv5Wi2Zw9uVPPc= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0/go.mod h1:dkVMJI88eJ3Xs0ZV15r4tUpgitUGJXcvrX3RL4Zq2bQ= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0 h1:VdxYMJqGKUvk7/l2b83Z/bB0FUYuFbELK/ipTicJ5QY= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0/go.mod h1:cSnBZGdtx4jnn9HEefkQHDrm8+PuS0NCWvukVfuwP/8= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 h1:EEjhfIFiC4TsaFKB4mkxz6NFz4InfVs5STmWc+oEjgQ= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0/go.mod h1:ZecMIf9oYj2DGZqWh93l97WdVaRdLl+tW5Fq3YKGwBM= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 h1:05wQYhO37Z4y8xAD+4OTYz6rYu6eJEmwMfCG4tjETEc= diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 2f5341121..6231c9bb4 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -22,7 +22,6 @@ const ( identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" allowedUrlDomainFlag = "allowed-url-domain" - argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" dnsCustomEndpointFlag = "dns-custom-endpoint" loadBalancerCustomEndpointFlag = "load-balancer-custom-endpoint" @@ -30,6 +29,7 @@ const ( mariaDBCustomEndpointFlag = "mariadb-custom-endpoint" mongoDBFlexCustomEndpointFlag = "mongodbflex-custom-endpoint" objectStorageCustomEndpointFlag = "object-storage-custom-endpoint" + observabilityCustomEndpointFlag = "observability-custom-endpoint" openSearchCustomEndpointFlag = "opensearch-custom-endpoint" postgresFlexCustomEndpointFlag = "postgresflex-custom-endpoint" rabbitMQCustomEndpointFlag = "rabbitmq-custom-endpoint" @@ -135,7 +135,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(identityProviderCustomEndpointFlag, "", "Identity Provider base URL, used for user authentication") cmd.Flags().String(identityProviderCustomClientIdFlag, "", "Identity Provider client ID, used for user authentication") cmd.Flags().String(allowedUrlDomainFlag, "", `Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command`) - cmd.Flags().String(argusCustomEndpointFlag, "", "Argus API base URL, used in calls to this API") + cmd.Flags().String(observabilityCustomEndpointFlag, "", "Observability API base URL, used in calls to this API") cmd.Flags().String(authorizationCustomEndpointFlag, "", "Authorization API base URL, used in calls to this API") cmd.Flags().String(dnsCustomEndpointFlag, "", "DNS API base URL, used in calls to this API") cmd.Flags().String(loadBalancerCustomEndpointFlag, "", "Load Balancer API base URL, used in calls to this API") @@ -168,7 +168,7 @@ func configureFlags(cmd *cobra.Command) { err = viper.BindPFlag(config.AllowedUrlDomainKey, cmd.Flags().Lookup(allowedUrlDomainFlag)) cobra.CheckErr(err) - err = viper.BindPFlag(config.ArgusCustomEndpointKey, cmd.Flags().Lookup(argusCustomEndpointFlag)) + err = viper.BindPFlag(config.ObservabilityCustomEndpointKey, cmd.Flags().Lookup(observabilityCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.AuthorizationCustomEndpointKey, cmd.Flags().Lookup(authorizationCustomEndpointFlag)) cobra.CheckErr(err) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 44526ba4d..a73f452f6 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -25,7 +25,6 @@ const ( identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" allowedUrlDomainFlag = "allowed-url-domain" - argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" dnsCustomEndpointFlag = "dns-custom-endpoint" loadBalancerCustomEndpointFlag = "load-balancer-custom-endpoint" @@ -33,6 +32,7 @@ const ( mariaDBCustomEndpointFlag = "mariadb-custom-endpoint" mongoDBFlexCustomEndpointFlag = "mongodbflex-custom-endpoint" objectStorageCustomEndpointFlag = "object-storage-custom-endpoint" + observabilityCustomEndpointFlag = "observability-custom-endpoint" openSearchCustomEndpointFlag = "opensearch-custom-endpoint" postgresFlexCustomEndpointFlag = "postgresflex-custom-endpoint" rabbitMQCustomEndpointFlag = "rabbitmq-custom-endpoint" @@ -61,7 +61,6 @@ type inputModel struct { IdentityProviderCustomClientID bool AllowedUrlDomain bool - ArgusCustomEndpoint bool AuthorizationCustomEndpoint bool DNSCustomEndpoint bool LoadBalancerCustomEndpoint bool @@ -69,6 +68,7 @@ type inputModel struct { MariaDBCustomEndpoint bool MongoDBFlexCustomEndpoint bool ObjectStorageCustomEndpoint bool + ObservabilityCustomEndpoint bool OpenSearchCustomEndpoint bool PostgresFlexCustomEndpoint bool RabbitMQCustomEndpoint bool @@ -132,8 +132,8 @@ func NewCmd(p *print.Printer) *cobra.Command { viper.Set(config.AllowedUrlDomainKey, config.AllowedUrlDomainDefault) } - if model.ArgusCustomEndpoint { - viper.Set(config.ArgusCustomEndpointKey, "") + if model.ObservabilityCustomEndpoint { + viper.Set(config.ObservabilityCustomEndpointKey, "") } if model.AuthorizationCustomEndpoint { viper.Set(config.AuthorizationCustomEndpointKey, "") @@ -224,7 +224,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(identityProviderCustomClientIdFlag, false, "Identity Provider client ID, used for user authentication") cmd.Flags().Bool(allowedUrlDomainFlag, false, fmt.Sprintf("Domain name, used for the verification of the URLs that are given in the IDP endpoint and curl commands. If unset, defaults to %s", config.AllowedUrlDomainDefault)) - cmd.Flags().Bool(argusCustomEndpointFlag, false, "Argus API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(observabilityCustomEndpointFlag, false, "Observability API base URL. If unset, uses the default base URL") cmd.Flags().Bool(authorizationCustomEndpointFlag, false, "Authorization API base URL. If unset, uses the default base URL") cmd.Flags().Bool(dnsCustomEndpointFlag, false, "DNS API base URL. If unset, uses the default base URL") cmd.Flags().Bool(loadBalancerCustomEndpointFlag, false, "Load Balancer API base URL. If unset, uses the default base URL") @@ -261,7 +261,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { IdentityProviderCustomClientID: flags.FlagToBoolValue(p, cmd, identityProviderCustomClientIdFlag), AllowedUrlDomain: flags.FlagToBoolValue(p, cmd, allowedUrlDomainFlag), - ArgusCustomEndpoint: flags.FlagToBoolValue(p, cmd, argusCustomEndpointFlag), AuthorizationCustomEndpoint: flags.FlagToBoolValue(p, cmd, authorizationCustomEndpointFlag), DNSCustomEndpoint: flags.FlagToBoolValue(p, cmd, dnsCustomEndpointFlag), LoadBalancerCustomEndpoint: flags.FlagToBoolValue(p, cmd, loadBalancerCustomEndpointFlag), @@ -269,6 +268,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { MariaDBCustomEndpoint: flags.FlagToBoolValue(p, cmd, mariaDBCustomEndpointFlag), MongoDBFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, mongoDBFlexCustomEndpointFlag), ObjectStorageCustomEndpoint: flags.FlagToBoolValue(p, cmd, objectStorageCustomEndpointFlag), + ObservabilityCustomEndpoint: flags.FlagToBoolValue(p, cmd, observabilityCustomEndpointFlag), OpenSearchCustomEndpoint: flags.FlagToBoolValue(p, cmd, openSearchCustomEndpointFlag), PostgresFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, postgresFlexCustomEndpointFlag), RabbitMQCustomEndpoint: flags.FlagToBoolValue(p, cmd, rabbitMQCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 5d33ae3ce..b97766ae2 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -21,13 +21,13 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool identityProviderCustomClientIdFlag: true, allowedUrlDomainFlag: true, - argusCustomEndpointFlag: true, authorizationCustomEndpointFlag: true, dnsCustomEndpointFlag: true, loadBalancerCustomEndpointFlag: true, logMeCustomEndpointFlag: true, mariaDBCustomEndpointFlag: true, objectStorageCustomEndpointFlag: true, + observabilityCustomEndpointFlag: true, openSearchCustomEndpointFlag: true, rabbitMQCustomEndpointFlag: true, redisCustomEndpointFlag: true, @@ -60,13 +60,13 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { IdentityProviderCustomClientID: true, AllowedUrlDomain: true, - ArgusCustomEndpoint: true, AuthorizationCustomEndpoint: true, DNSCustomEndpoint: true, LoadBalancerCustomEndpoint: true, LogMeCustomEndpoint: true, MariaDBCustomEndpoint: true, ObjectStorageCustomEndpoint: true, + ObservabilityCustomEndpoint: true, OpenSearchCustomEndpoint: true, RabbitMQCustomEndpoint: true, RedisCustomEndpoint: true, @@ -115,13 +115,13 @@ func TestParseInput(t *testing.T) { model.IdentityProviderCustomClientID = false model.AllowedUrlDomain = false - model.ArgusCustomEndpoint = false model.AuthorizationCustomEndpoint = false model.DNSCustomEndpoint = false model.LoadBalancerCustomEndpoint = false model.LogMeCustomEndpoint = false model.MariaDBCustomEndpoint = false model.ObjectStorageCustomEndpoint = false + model.ObservabilityCustomEndpoint = false model.OpenSearchCustomEndpoint = false model.RabbitMQCustomEndpoint = false model.RedisCustomEndpoint = false @@ -188,13 +188,13 @@ func TestParseInput(t *testing.T) { }), }, { - description: "argus custom endpoint empty", + description: "observability custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { - flagValues[argusCustomEndpointFlag] = false + flagValues[observabilityCustomEndpointFlag] = false }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.ArgusCustomEndpoint = false + model.ObservabilityCustomEndpoint = false }), }, { diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index b1213eefd..96faa7a87 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "add", Short: "Adds observability credentials to Load Balancer", - Long: "Adds existing observability credentials (username and password) to Load Balancer. The credentials can be for Argus or another monitoring tool.", + Long: "Adds existing observability credentials (username and password) to Load Balancer. The credentials can be for Observability or another monitoring tool.", Args: args.NoArgs, Example: examples.Build( examples.NewExample( diff --git a/internal/cmd/load-balancer/observability-credentials/observability-credentials.go b/internal/cmd/load-balancer/observability-credentials/observability-credentials.go index 9ad8500d1..390b83caf 100644 --- a/internal/cmd/load-balancer/observability-credentials/observability-credentials.go +++ b/internal/cmd/load-balancer/observability-credentials/observability-credentials.go @@ -18,7 +18,7 @@ func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "observability-credentials", Short: "Provides functionality for Load Balancer observability credentials", - Long: `Provides functionality for Load Balancer observability credentials. These commands can be used to store and update existing credentials, which are valid to be used for Load Balancer observability. This means, e.g. when using Argus, first of all these credentials must be created for that Argus instance (by using "stackit argus credentials create") and then can be managed for a Load Balancer by using the commands in this group.`, + Long: `Provides functionality for Load Balancer observability credentials. These commands can be used to store and update existing credentials, which are valid to be used for Load Balancer observability. This means, e.g. when using Observability, first of all these credentials must be created for that Observability instance (by using "stackit observability credentials create") and then can be managed for a Load Balancer by using the commands in this group.`, Args: args.NoArgs, Aliases: []string{"credentials"}, Run: utils.CmdHelp, diff --git a/internal/cmd/load-balancer/observability-credentials/update/update.go b/internal/cmd/load-balancer/observability-credentials/update/update.go index 0f395139f..3372266d5 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update.go @@ -39,7 +39,7 @@ func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "Updates observability credentials for Load Balancer", - Long: "Updates existing observability credentials (username and password) for Load Balancer. The credentials can be for Argus or another monitoring tool.", + Long: "Updates existing observability credentials (username and password) for Load Balancer. The credentials can be for Observability or another monitoring tool.", Args: args.SingleArg(credentialsRefArg, nil), Example: examples.Build( examples.NewExample( diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 4373782ea..487c976b3 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -139,14 +139,14 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res case print.YAMLOutputFormat: details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) if err != nil { - return fmt.Errorf("marshal Argus credentials list: %w", err) + return fmt.Errorf("marshal MariaDB credentials list: %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 + // 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) diff --git a/internal/cmd/argus/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go similarity index 74% rename from internal/cmd/argus/credentials/create/create.go rename to internal/cmd/observability/credentials/create/create.go index 5e613a61d..844f25dda 100644 --- a/internal/cmd/argus/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -6,17 +6,16 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" - - "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -32,15 +31,15 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "create", - Short: "Creates credentials for an Argus instance.", + Short: "Creates credentials for an Observability instance.", Long: fmt.Sprintf("%s\n%s", - "Creates credentials (username and password) for an Argus instance.", + "Creates credentials (username and password) for an Observability instance.", "The credentials will be generated and included in the response. You won't be able to retrieve the password later."), Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `Create credentials for Argus instance with ID "xxx"`, - "$ stackit argus credentials create --instance-id xxx"), + `Create credentials for Observability instance with ID "xxx"`, + "$ stackit observability credentials create --instance-id xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -55,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -76,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } resp, err := req.Execute() if err != nil { - return fmt.Errorf("create credentials for Argus instance: %w", err) + return fmt.Errorf("create credentials for Observability instance: %w", err) } return outputResult(p, model, instanceLabel, resp) @@ -105,17 +104,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiCreateCredentialsRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiCreateCredentialsRequest { req := apiClient.CreateCredentials(ctx, model.InstanceId, model.ProjectId) return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *argus.CreateCredentialsResponse) error { +func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *observability.CreateCredentialsResponse) error { switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { - return fmt.Errorf("marshal Argus credentials: %w", err) + return fmt.Errorf("marshal Observability credentials: %w", err) } p.Outputln(string(details)) @@ -123,14 +122,14 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res case print.YAMLOutputFormat: details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) if err != nil { - return fmt.Errorf("marshal Argus credentials: %w", err) + return fmt.Errorf("marshal Observability credentials: %w", err) } p.Outputln(string(details)) return nil default: p.Outputf("Created credentials for instance %q.\n\n", instanceLabel) - // The username field cannot be set by the user so we only display it if it's not returned empty + // The username field cannot be set by the user, so we only display it if it's not returned empty username := *resp.Credentials.Username if username != "" { p.Outputf("Username: %s\n", username) diff --git a/internal/cmd/argus/credentials/create/create_test.go b/internal/cmd/observability/credentials/create/create_test.go similarity index 93% rename from internal/cmd/argus/credentials/create/create_test.go rename to internal/cmd/observability/credentials/create/create_test.go index 6bc528545..395876a4f 100644 --- a/internal/cmd/argus/credentials/create/create_test.go +++ b/internal/cmd/observability/credentials/create/create_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -17,7 +17,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() @@ -46,7 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiCreateCredentialsRequest)) argus.ApiCreateCredentialsRequest { +func fixtureRequest(mods ...func(request *observability.ApiCreateCredentialsRequest)) observability.ApiCreateCredentialsRequest { request := testClient.CreateCredentials(testCtx, testInstanceId, testProjectId) for _, mod := range mods { mod(&request) @@ -165,7 +165,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiCreateCredentialsRequest + expectedRequest observability.ApiCreateCredentialsRequest }{ { description: "base", diff --git a/internal/cmd/argus/credentials/credentials.go b/internal/cmd/observability/credentials/credentials.go similarity index 60% rename from internal/cmd/argus/credentials/credentials.go rename to internal/cmd/observability/credentials/credentials.go index b5a64b94c..fb84cf9d6 100644 --- a/internal/cmd/argus/credentials/credentials.go +++ b/internal/cmd/observability/credentials/credentials.go @@ -1,9 +1,9 @@ package credentials import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/credentials/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/credentials/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/credentials/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -14,8 +14,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", - Short: "Provides functionality for Argus credentials", - Long: "Provides functionality for Argus credentials.", + Short: "Provides functionality for Observability credentials", + Long: "Provides functionality for Observability credentials.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/cmd/argus/credentials/delete/delete.go b/internal/cmd/observability/credentials/delete/delete.go similarity index 76% rename from internal/cmd/argus/credentials/delete/delete.go rename to internal/cmd/observability/credentials/delete/delete.go index b81ab3ddb..a501b949a 100644 --- a/internal/cmd/argus/credentials/delete/delete.go +++ b/internal/cmd/observability/credentials/delete/delete.go @@ -10,11 +10,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -32,13 +32,13 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", usernameArg), - Short: "Deletes credentials of an Argus instance", - Long: "Deletes credentials of an Argus instance.", + Short: "Deletes credentials of an Observability instance", + Long: "Deletes credentials of an Observability instance.", Args: args.SingleArg(usernameArg, nil), Example: examples.Build( examples.NewExample( - `Delete credentials of username "xxx" for Argus instance with ID "yyy"`, - "$ stackit argus credentials delete xxx --instance-id yyy"), + `Delete credentials of username "xxx" for Observability instance with ID "yyy"`, + "$ stackit observability credentials delete xxx --instance-id yyy"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -53,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -71,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { req := buildRequest(ctx, model, apiClient) _, err = req.Execute() if err != nil { - return fmt.Errorf("delete Argus credentials: %w", err) + return fmt.Errorf("delete Observability credentials: %w", err) } p.Info("Deleted credentials for username %q of instance %q\n", model.Username, instanceLabel) @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiDeleteCredentialsRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiDeleteCredentialsRequest { req := apiClient.DeleteCredentials(ctx, model.InstanceId, model.ProjectId, model.Username) return req } diff --git a/internal/cmd/argus/credentials/delete/delete_test.go b/internal/cmd/observability/credentials/delete/delete_test.go similarity index 94% rename from internal/cmd/argus/credentials/delete/delete_test.go rename to internal/cmd/observability/credentials/delete/delete_test.go index 28034e8d9..21965e75c 100644 --- a/internal/cmd/argus/credentials/delete/delete_test.go +++ b/internal/cmd/observability/credentials/delete/delete_test.go @@ -9,7 +9,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -17,7 +17,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() @@ -59,7 +59,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiDeleteCredentialsRequest)) argus.ApiDeleteCredentialsRequest { +func fixtureRequest(mods ...func(request *observability.ApiDeleteCredentialsRequest)) observability.ApiDeleteCredentialsRequest { request := testClient.DeleteCredentials(testCtx, testInstanceId, testProjectId, testUsername) for _, mod := range mods { mod(&request) @@ -213,7 +213,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiDeleteCredentialsRequest + expectedRequest observability.ApiDeleteCredentialsRequest }{ { description: "base", diff --git a/internal/cmd/argus/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go similarity index 72% rename from internal/cmd/argus/credentials/list/list.go rename to internal/cmd/observability/credentials/list/list.go index 795b4278e..2fb435bb1 100644 --- a/internal/cmd/argus/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -12,12 +12,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/stackitcloud/stackit-sdk-go/services/argus" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -34,19 +34,19 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "list", - Short: "Lists the usernames of all credentials for an Argus instance", - Long: "Lists the usernames of all credentials for an Argus instance.", + Short: "Lists the usernames of all credentials for an Observability instance", + Long: "Lists the usernames of all credentials for an Observability instance.", Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `List the usernames of all credentials for an Argus instance with ID "xxx"`, - "$ stackit argus credentials list --instance-id xxx"), + `List the usernames of all credentials for an Observability instance with ID "xxx"`, + "$ stackit observability credentials list --instance-id xxx"), examples.NewExample( - `List the usernames of all credentials for an Argus instance in JSON format`, - "$ stackit argus credentials list --instance-id xxx --output-format json"), + `List the usernames of all credentials for an Observability instance in JSON format`, + "$ stackit observability credentials list --instance-id xxx --output-format json"), examples.NewExample( - `List the usernames of up to 10 credentials for an Argus instance`, - "$ stackit argus credentials list --instance-id xxx --limit 10"), + `List the usernames of up to 10 credentials for an Observability instance`, + "$ stackit observability credentials list --instance-id xxx --limit 10"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -65,11 +65,11 @@ func NewCmd(p *print.Printer) *cobra.Command { req := buildRequest(ctx, model, apiClient) resp, err := req.Execute() if err != nil { - return fmt.Errorf("list Argus credentials: %w", err) + return fmt.Errorf("list Observability credentials: %w", err) } credentials := *resp.Credentials if len(credentials) == 0 { - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -118,17 +118,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiListCredentialsRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiListCredentialsRequest { req := apiClient.ListCredentials(ctx, model.InstanceId, model.ProjectId) return req } -func outputResult(p *print.Printer, outputFormat string, credentials []argus.ServiceKeysList) error { +func outputResult(p *print.Printer, outputFormat string, credentials []observability.ServiceKeysList) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(credentials, "", " ") if err != nil { - return fmt.Errorf("marshal Argus credentials list: %w", err) + return fmt.Errorf("marshal Observability credentials list: %w", err) } p.Outputln(string(details)) @@ -136,7 +136,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []argus.Ser case print.YAMLOutputFormat: details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) if err != nil { - return fmt.Errorf("marshal Argus credentials list: %w", err) + return fmt.Errorf("marshal Observability credentials list: %w", err) } p.Outputln(string(details)) diff --git a/internal/cmd/argus/credentials/list/list_test.go b/internal/cmd/observability/credentials/list/list_test.go similarity index 94% rename from internal/cmd/argus/credentials/list/list_test.go rename to internal/cmd/observability/credentials/list/list_test.go index 14509ec68..3d188dba3 100644 --- a/internal/cmd/argus/credentials/list/list_test.go +++ b/internal/cmd/observability/credentials/list/list_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -18,7 +18,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() @@ -49,7 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiListCredentialsRequest)) argus.ApiListCredentialsRequest { +func fixtureRequest(mods ...func(request *observability.ApiListCredentialsRequest)) observability.ApiListCredentialsRequest { request := testClient.ListCredentials(testCtx, testInstanceId, testProjectId) for _, mod := range mods { mod(&request) @@ -182,7 +182,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiListCredentialsRequest + expectedRequest observability.ApiListCredentialsRequest }{ { description: "base", diff --git a/internal/cmd/argus/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go similarity index 80% rename from internal/cmd/argus/grafana/describe/describe.go rename to internal/cmd/observability/grafana/describe/describe.go index 4c8f930b7..46e7f60ee 100644 --- a/internal/cmd/argus/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -12,12 +12,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -34,23 +34,23 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), - Short: "Shows details of the Grafana configuration of an Argus instance", + Short: "Shows details of the Grafana configuration of an Observability instance", Long: fmt.Sprintf("%s\n%s\n%s", - "Shows details of the Grafana configuration of an Argus instance.", + "Shows details of the Grafana configuration of an Observability instance.", `The Grafana dashboard URL and initial credentials (admin user and password) will be shown in the "pretty" output format. These credentials are only valid for first login. Please change the password after first login. After changing, the initial password is no longer valid.`, `The initial password is hidden by default, if you want to show it use the "--show-password" flag.`, ), Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `Get details of the Grafana configuration of an Argus instance with ID "xxx"`, - "$ stackit argus credentials describe xxx"), + `Get details of the Grafana configuration of an Observability instance with ID "xxx"`, + "$ stackit observability credentials describe xxx"), examples.NewExample( - `Get details of the Grafana configuration of an Argus instance with ID "xxx" and show the initial admin password`, - "$ stackit argus credentials describe xxx --show-password"), + `Get details of the Grafana configuration of an Observability instance with ID "xxx" and show the initial admin password`, + "$ stackit observability credentials describe xxx --show-password"), examples.NewExample( - `Get details of the Grafana configuration of an Argus instance with ID "xxx" in JSON format`, - "$ stackit argus credentials describe xxx --output-format json"), + `Get details of the Grafana configuration of an Observability instance with ID "xxx" in JSON format`, + "$ stackit observability credentials describe xxx --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -114,17 +114,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func buildGetGrafanaConfigRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiGetGrafanaConfigsRequest { +func buildGetGrafanaConfigRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiGetGrafanaConfigsRequest { req := apiClient.GetGrafanaConfigs(ctx, model.InstanceId, model.ProjectId) return req } -func buildGetInstanceRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiGetInstanceRequest { +func buildGetInstanceRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiGetInstanceRequest { req := apiClient.GetInstance(ctx, model.InstanceId, model.ProjectId) return req } -func outputResult(p *print.Printer, inputModel *inputModel, grafanaConfigs *argus.GrafanaConfigs, instance *argus.GetInstanceResponse) error { +func outputResult(p *print.Printer, inputModel *inputModel, grafanaConfigs *observability.GrafanaConfigs, instance *observability.GetInstanceResponse) error { switch inputModel.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(grafanaConfigs, "", " ") diff --git a/internal/cmd/argus/grafana/describe/describe_test.go b/internal/cmd/observability/grafana/describe/describe_test.go similarity index 92% rename from internal/cmd/argus/grafana/describe/describe_test.go rename to internal/cmd/observability/grafana/describe/describe_test.go index 2bc97589b..d2b2daec0 100644 --- a/internal/cmd/argus/grafana/describe/describe_test.go +++ b/internal/cmd/observability/grafana/describe/describe_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -18,7 +18,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() @@ -56,7 +56,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureGetGrafanaConfigsRequest(mods ...func(request *argus.ApiGetGrafanaConfigsRequest)) argus.ApiGetGrafanaConfigsRequest { +func fixtureGetGrafanaConfigsRequest(mods ...func(request *observability.ApiGetGrafanaConfigsRequest)) observability.ApiGetGrafanaConfigsRequest { request := testClient.GetGrafanaConfigs(testCtx, testInstanceId, testProjectId) for _, mod := range mods { mod(&request) @@ -64,7 +64,7 @@ func fixtureGetGrafanaConfigsRequest(mods ...func(request *argus.ApiGetGrafanaCo return request } -func fixtureGetInstanceRequest(mods ...func(request *argus.ApiGetInstanceRequest)) argus.ApiGetInstanceRequest { +func fixtureGetInstanceRequest(mods ...func(request *observability.ApiGetInstanceRequest)) observability.ApiGetInstanceRequest { request := testClient.GetInstance(testCtx, testInstanceId, testProjectId) for _, mod := range mods { mod(&request) @@ -225,7 +225,7 @@ func TestBuildGetGrafanaConfigsRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiGetGrafanaConfigsRequest + expectedRequest observability.ApiGetGrafanaConfigsRequest }{ { description: "base", @@ -253,7 +253,7 @@ func TestBuildGetInstanceRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiGetInstanceRequest + expectedRequest observability.ApiGetInstanceRequest }{ { description: "base", diff --git a/internal/cmd/argus/grafana/grafana.go b/internal/cmd/observability/grafana/grafana.go similarity index 79% rename from internal/cmd/argus/grafana/grafana.go rename to internal/cmd/observability/grafana/grafana.go index 19ed4368a..e9ad230d1 100644 --- a/internal/cmd/argus/grafana/grafana.go +++ b/internal/cmd/observability/grafana/grafana.go @@ -1,9 +1,9 @@ package grafana import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/grafana/describe" - publicreadaccess "github.com/stackitcloud/stackit-cli/internal/cmd/argus/grafana/public-read-access" - singlesignon "github.com/stackitcloud/stackit-cli/internal/cmd/argus/grafana/single-sign-on" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/describe" + publicreadaccess "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access" + singlesignon "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -14,8 +14,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "grafana", - Short: "Provides functionality for the Grafana configuration of Argus instances", - Long: "Provides functionality for the Grafana configuration of Argus instances.", + Short: "Provides functionality for the Grafana configuration of Observability instances", + Long: "Provides functionality for the Grafana configuration of Observability instances.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable.go b/internal/cmd/observability/grafana/public-read-access/disable/disable.go similarity index 75% rename from internal/cmd/argus/grafana/public-read-access/disable/disable.go rename to internal/cmd/observability/grafana/public-read-access/disable/disable.go index fe5383380..ac6cd80a4 100644 --- a/internal/cmd/argus/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable.go @@ -9,12 +9,12 @@ import ( "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/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/observability" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" ) const ( @@ -29,16 +29,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disable %s", instanceIdArg), - Short: "Disables public read access for Grafana on Argus instances", + Short: "Disables public read access for Grafana on Observability instances", Long: fmt.Sprintf("%s\n%s", - "Disables public read access for Grafana on Argus instances.", + "Disables public read access for Grafana on Observability instances.", "When disabled, a login is required to access the Grafana dashboards of the instance. Otherwise, anyone can access the dashboards.", ), Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `Disable public read access for Grafana on an Argus instance with ID "xxx"`, - "$ stackit argus grafana public-read-access disable xxx"), + `Disable public read access for Grafana on an Observability instance with ID "xxx"`, + "$ stackit observability grafana public-read-access disable xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -53,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil || instanceLabel == "" { instanceLabel = model.InstanceId } @@ -108,9 +108,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient argusUtils.ArgusClient) (argus.ApiUpdateGrafanaConfigsRequest, error) { +func buildRequest(ctx context.Context, model *inputModel, apiClient observabilityUtils.ObservabilityClient) (observability.ApiUpdateGrafanaConfigsRequest, error) { req := apiClient.UpdateGrafanaConfigs(ctx, model.InstanceId, model.ProjectId) - payload, err := argusUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, nil, utils.Ptr(false)) + payload, err := observabilityUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, nil, utils.Ptr(false)) if err != nil { return req, fmt.Errorf("build request payload: %w", err) } diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go b/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go similarity index 79% rename from internal/cmd/argus/grafana/public-read-access/disable/disable_test.go rename to internal/cmd/observability/grafana/public-read-access/disable/disable_test.go index b52ba7223..7e08ac647 100644 --- a/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go @@ -7,13 +7,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -21,24 +21,24 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -type argusClientMocked struct { +type observabilityClientMocked struct { getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs } -func (c *argusClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error) { +func (c *observabilityClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*observability.GetInstanceResponse, error) { return testClient.GetInstanceExecute(ctx, instanceId, projectId) } -func (c *argusClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) argus.ApiUpdateGrafanaConfigsRequest { +func (c *observabilityClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) observability.ApiUpdateGrafanaConfigsRequest { return testClient.UpdateGrafanaConfigs(ctx, instanceId, projectId) } -func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*argus.GrafanaConfigs, error) { +func (c *observabilityClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*observability.GrafanaConfigs, error) { if c.getGrafanaConfigsFails { return nil, fmt.Errorf("get payload failed") } @@ -79,9 +79,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.GrafanaConfigs { - gc := argus.GrafanaConfigs{ - GenericOauth: &argus.GrafanaOauth{ +func fixtureGrafanaConfigs(mods ...func(gc *observability.GrafanaConfigs)) *observability.GrafanaConfigs { + gc := observability.GrafanaConfigs{ + GenericOauth: &observability.GrafanaOauth{ ApiUrl: utils.Ptr("apiUrl"), AuthUrl: utils.Ptr("authUrl"), Enabled: utils.Ptr(true), @@ -103,9 +103,9 @@ func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.Grafan return &gc } -func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *argus.UpdateGrafanaConfigsPayload { - payload := &argus.UpdateGrafanaConfigsPayload{ - GenericOauth: argusUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), +func fixturePayload(mods ...func(payload *observability.UpdateGrafanaConfigsPayload)) *observability.UpdateGrafanaConfigsPayload { + payload := &observability.UpdateGrafanaConfigsPayload{ + GenericOauth: observabilityUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), PublicReadAccess: utils.Ptr(false), UseStackitSso: fixtureGrafanaConfigs().UseStackitSso, } @@ -115,7 +115,7 @@ func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *a return payload } -func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) argus.ApiUpdateGrafanaConfigsRequest { +func fixtureRequest(mods ...func(request *observability.ApiUpdateGrafanaConfigsRequest)) observability.ApiUpdateGrafanaConfigsRequest { request := testClient.UpdateGrafanaConfigs(testCtx, testInstanceId, testProjectId) request = request.UpdateGrafanaConfigsPayload(*fixturePayload()) for _, mod := range mods { @@ -242,9 +242,9 @@ func TestBuildRequest(t *testing.T) { description string model *inputModel getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs isValid bool - expectedRequest argus.ApiUpdateGrafanaConfigsRequest + expectedRequest observability.ApiUpdateGrafanaConfigsRequest }{ { description: "base", @@ -256,12 +256,12 @@ func TestBuildRequest(t *testing.T) { { description: "nil generic oauth", model: fixtureInputModel(), - getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) { + getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *observability.GrafanaConfigs) { gc.GenericOauth = nil }), isValid: true, - expectedRequest: fixtureRequest(func(request *argus.ApiUpdateGrafanaConfigsRequest) { - *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *argus.UpdateGrafanaConfigsPayload) { + expectedRequest: fixtureRequest(func(request *observability.ApiUpdateGrafanaConfigsRequest) { + *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { payload.GenericOauth = nil })) }), @@ -282,7 +282,7 @@ func TestBuildRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &argusClientMocked{ + client := &observabilityClientMocked{ getGrafanaConfigsFails: tt.getGrafanaConfigsFails, getGrafanaConfigsResp: tt.getGrafanaConfigsResp, } diff --git a/internal/cmd/argus/grafana/public-read-access/enable/enable.go b/internal/cmd/observability/grafana/public-read-access/enable/enable.go similarity index 75% rename from internal/cmd/argus/grafana/public-read-access/enable/enable.go rename to internal/cmd/observability/grafana/public-read-access/enable/enable.go index 07c105fb4..9296a1f24 100644 --- a/internal/cmd/argus/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable.go @@ -9,12 +9,12 @@ import ( "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/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -29,16 +29,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("enable %s", instanceIdArg), - Short: "Enables public read access for Grafana on Argus instances", + Short: "Enables public read access for Grafana on Observability instances", Long: fmt.Sprintf("%s\n%s", - "Enables public read access for Grafana on Argus instances.", + "Enables public read access for Grafana on Observability instances.", "When enabled, anyone can access the Grafana dashboards of the instance without logging in. Otherwise, a login is required.", ), Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `Enable public read access for Grafana on an Argus instance with ID "xxx"`, - "$ stackit argus grafana public-read-access enable xxx"), + `Enable public read access for Grafana on an Observability instance with ID "xxx"`, + "$ stackit observability grafana public-read-access enable xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -53,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil || instanceLabel == "" { instanceLabel = model.InstanceId } @@ -108,9 +108,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient argusUtils.ArgusClient) (argus.ApiUpdateGrafanaConfigsRequest, error) { +func buildRequest(ctx context.Context, model *inputModel, apiClient observabilityUtils.ObservabilityClient) (observability.ApiUpdateGrafanaConfigsRequest, error) { req := apiClient.UpdateGrafanaConfigs(ctx, model.InstanceId, model.ProjectId) - payload, err := argusUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, nil, utils.Ptr(true)) + payload, err := observabilityUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, nil, utils.Ptr(true)) if err != nil { return req, fmt.Errorf("build request payload: %w", err) } diff --git a/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go b/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go similarity index 79% rename from internal/cmd/argus/grafana/public-read-access/enable/enable_test.go rename to internal/cmd/observability/grafana/public-read-access/enable/enable_test.go index 04d80e287..57ebc5bc3 100644 --- a/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go @@ -7,13 +7,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -21,24 +21,24 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -type argusClientMocked struct { +type observabilityClientMocked struct { getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs } -func (c *argusClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error) { +func (c *observabilityClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*observability.GetInstanceResponse, error) { return testClient.GetInstanceExecute(ctx, instanceId, projectId) } -func (c *argusClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) argus.ApiUpdateGrafanaConfigsRequest { +func (c *observabilityClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) observability.ApiUpdateGrafanaConfigsRequest { return testClient.UpdateGrafanaConfigs(ctx, instanceId, projectId) } -func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*argus.GrafanaConfigs, error) { +func (c *observabilityClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*observability.GrafanaConfigs, error) { if c.getGrafanaConfigsFails { return nil, fmt.Errorf("get payload failed") } @@ -79,9 +79,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.GrafanaConfigs { - gc := argus.GrafanaConfigs{ - GenericOauth: &argus.GrafanaOauth{ +func fixtureGrafanaConfigs(mods ...func(gc *observability.GrafanaConfigs)) *observability.GrafanaConfigs { + gc := observability.GrafanaConfigs{ + GenericOauth: &observability.GrafanaOauth{ ApiUrl: utils.Ptr("apiUrl"), AuthUrl: utils.Ptr("authUrl"), Enabled: utils.Ptr(true), @@ -103,9 +103,9 @@ func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.Grafan return &gc } -func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *argus.UpdateGrafanaConfigsPayload { - payload := &argus.UpdateGrafanaConfigsPayload{ - GenericOauth: argusUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), +func fixturePayload(mods ...func(payload *observability.UpdateGrafanaConfigsPayload)) *observability.UpdateGrafanaConfigsPayload { + payload := &observability.UpdateGrafanaConfigsPayload{ + GenericOauth: observabilityUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), PublicReadAccess: utils.Ptr(true), UseStackitSso: fixtureGrafanaConfigs().UseStackitSso, } @@ -115,7 +115,7 @@ func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *a return payload } -func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) argus.ApiUpdateGrafanaConfigsRequest { +func fixtureRequest(mods ...func(request *observability.ApiUpdateGrafanaConfigsRequest)) observability.ApiUpdateGrafanaConfigsRequest { request := testClient.UpdateGrafanaConfigs(testCtx, testInstanceId, testProjectId) request = request.UpdateGrafanaConfigsPayload(*fixturePayload()) for _, mod := range mods { @@ -242,9 +242,9 @@ func TestBuildRequest(t *testing.T) { description string model *inputModel getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs isValid bool - expectedRequest argus.ApiUpdateGrafanaConfigsRequest + expectedRequest observability.ApiUpdateGrafanaConfigsRequest }{ { description: "base", @@ -256,12 +256,12 @@ func TestBuildRequest(t *testing.T) { { description: "nil generic oauth", model: fixtureInputModel(), - getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) { + getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *observability.GrafanaConfigs) { gc.GenericOauth = nil }), isValid: true, - expectedRequest: fixtureRequest(func(request *argus.ApiUpdateGrafanaConfigsRequest) { - *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *argus.UpdateGrafanaConfigsPayload) { + expectedRequest: fixtureRequest(func(request *observability.ApiUpdateGrafanaConfigsRequest) { + *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { payload.GenericOauth = nil })) }), @@ -282,7 +282,7 @@ func TestBuildRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &argusClientMocked{ + client := &observabilityClientMocked{ getGrafanaConfigsFails: tt.getGrafanaConfigsFails, getGrafanaConfigsResp: tt.getGrafanaConfigsResp, } diff --git a/internal/cmd/argus/grafana/public-read-access/public_read_access.go b/internal/cmd/observability/grafana/public-read-access/public_read_access.go similarity index 66% rename from internal/cmd/argus/grafana/public-read-access/public_read_access.go rename to internal/cmd/observability/grafana/public-read-access/public_read_access.go index 736a6e265..8844e1279 100644 --- a/internal/cmd/argus/grafana/public-read-access/public_read_access.go +++ b/internal/cmd/observability/grafana/public-read-access/public_read_access.go @@ -3,8 +3,8 @@ package publicreadaccess import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/grafana/public-read-access/disable" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/grafana/public-read-access/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access/disable" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access/enable" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -15,9 +15,9 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "public-read-access", - Short: "Enable or disable public read access for Grafana in Argus instances", + Short: "Enable or disable public read access for Grafana in Observability instances", Long: fmt.Sprintf("%s\n%s", - "Enable or disable public read access for Grafana in Argus instances.", + "Enable or disable public read access for Grafana in Observability instances.", "When enabled, anyone can access the Grafana dashboards of the instance without logging in. Otherwise, a login is required.", ), Args: args.NoArgs, diff --git a/internal/cmd/argus/grafana/single-sign-on/disable/disable.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go similarity index 75% rename from internal/cmd/argus/grafana/single-sign-on/disable/disable.go rename to internal/cmd/observability/grafana/single-sign-on/disable/disable.go index d41b1461d..018d7827d 100644 --- a/internal/cmd/argus/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go @@ -9,12 +9,12 @@ import ( "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/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -29,16 +29,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disable %s", instanceIdArg), - Short: "Disables single sign-on for Grafana on Argus instances", + Short: "Disables single sign-on for Grafana on Observability instances", Long: fmt.Sprintf("%s\n%s", - "Disables single sign-on for Grafana on Argus instances.", + "Disables single sign-on for Grafana on Observability instances.", "When disabled for an instance, the generic OAuth2 authentication is used for that instance.", ), Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `Disable single sign-on for Grafana on an Argus instance with ID "xxx"`, - "$ stackit argus grafana single-sign-on disable xxx"), + `Disable single sign-on for Grafana on an Observability instance with ID "xxx"`, + "$ stackit observability grafana single-sign-on disable xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -53,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil || instanceLabel == "" { instanceLabel = model.InstanceId } @@ -108,9 +108,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient argusUtils.ArgusClient) (argus.ApiUpdateGrafanaConfigsRequest, error) { +func buildRequest(ctx context.Context, model *inputModel, apiClient observabilityUtils.ObservabilityClient) (observability.ApiUpdateGrafanaConfigsRequest, error) { req := apiClient.UpdateGrafanaConfigs(ctx, model.InstanceId, model.ProjectId) - payload, err := argusUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, utils.Ptr(false), nil) + payload, err := observabilityUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, utils.Ptr(false), nil) if err != nil { return req, fmt.Errorf("build request payload: %w", err) } diff --git a/internal/cmd/argus/grafana/single-sign-on/disable/disable_test.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go similarity index 79% rename from internal/cmd/argus/grafana/single-sign-on/disable/disable_test.go rename to internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go index e4f9f3f4b..79653608e 100644 --- a/internal/cmd/argus/grafana/single-sign-on/disable/disable_test.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go @@ -7,13 +7,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -21,24 +21,24 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -type argusClientMocked struct { +type observabilityClientMocked struct { getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs } -func (c *argusClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error) { +func (c *observabilityClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*observability.GetInstanceResponse, error) { return testClient.GetInstanceExecute(ctx, instanceId, projectId) } -func (c *argusClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) argus.ApiUpdateGrafanaConfigsRequest { +func (c *observabilityClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) observability.ApiUpdateGrafanaConfigsRequest { return testClient.UpdateGrafanaConfigs(ctx, instanceId, projectId) } -func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*argus.GrafanaConfigs, error) { +func (c *observabilityClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*observability.GrafanaConfigs, error) { if c.getGrafanaConfigsFails { return nil, fmt.Errorf("get payload failed") } @@ -79,9 +79,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.GrafanaConfigs { - gc := argus.GrafanaConfigs{ - GenericOauth: &argus.GrafanaOauth{ +func fixtureGrafanaConfigs(mods ...func(gc *observability.GrafanaConfigs)) *observability.GrafanaConfigs { + gc := observability.GrafanaConfigs{ + GenericOauth: &observability.GrafanaOauth{ ApiUrl: utils.Ptr("apiUrl"), AuthUrl: utils.Ptr("authUrl"), Enabled: utils.Ptr(true), @@ -103,9 +103,9 @@ func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.Grafan return &gc } -func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *argus.UpdateGrafanaConfigsPayload { - payload := &argus.UpdateGrafanaConfigsPayload{ - GenericOauth: argusUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), +func fixturePayload(mods ...func(payload *observability.UpdateGrafanaConfigsPayload)) *observability.UpdateGrafanaConfigsPayload { + payload := &observability.UpdateGrafanaConfigsPayload{ + GenericOauth: observabilityUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess, UseStackitSso: utils.Ptr(false), } @@ -115,7 +115,7 @@ func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *a return payload } -func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) argus.ApiUpdateGrafanaConfigsRequest { +func fixtureRequest(mods ...func(request *observability.ApiUpdateGrafanaConfigsRequest)) observability.ApiUpdateGrafanaConfigsRequest { request := testClient.UpdateGrafanaConfigs(testCtx, testInstanceId, testProjectId) request = request.UpdateGrafanaConfigsPayload(*fixturePayload()) for _, mod := range mods { @@ -242,9 +242,9 @@ func TestBuildRequest(t *testing.T) { description string model *inputModel getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs isValid bool - expectedRequest argus.ApiUpdateGrafanaConfigsRequest + expectedRequest observability.ApiUpdateGrafanaConfigsRequest }{ { description: "base", @@ -256,12 +256,12 @@ func TestBuildRequest(t *testing.T) { { description: "nil generic oauth", model: fixtureInputModel(), - getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) { + getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *observability.GrafanaConfigs) { gc.GenericOauth = nil }), isValid: true, - expectedRequest: fixtureRequest(func(request *argus.ApiUpdateGrafanaConfigsRequest) { - *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *argus.UpdateGrafanaConfigsPayload) { + expectedRequest: fixtureRequest(func(request *observability.ApiUpdateGrafanaConfigsRequest) { + *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { payload.GenericOauth = nil })) }), @@ -282,7 +282,7 @@ func TestBuildRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &argusClientMocked{ + client := &observabilityClientMocked{ getGrafanaConfigsFails: tt.getGrafanaConfigsFails, getGrafanaConfigsResp: tt.getGrafanaConfigsResp, } diff --git a/internal/cmd/argus/grafana/single-sign-on/enable/enable.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go similarity index 76% rename from internal/cmd/argus/grafana/single-sign-on/enable/enable.go rename to internal/cmd/observability/grafana/single-sign-on/enable/enable.go index 4fa204fb3..9a002b9f9 100644 --- a/internal/cmd/argus/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go @@ -9,12 +9,12 @@ import ( "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/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -29,16 +29,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("enable %s", instanceIdArg), - Short: "Enables single sign-on for Grafana on Argus instances", + Short: "Enables single sign-on for Grafana on Observability instances", Long: fmt.Sprintf("%s\n%s", - "Enables single sign-on for Grafana on Argus instances.", + "Enables single sign-on for Grafana on Observability instances.", "When enabled for an instance, overwrites the generic OAuth2 authentication and configures STACKIT single sign-on for that instance.", ), Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `Enable single sign-on for Grafana on an Argus instance with ID "xxx"`, - "$ stackit argus grafana single-sign-on enable xxx"), + `Enable single sign-on for Grafana on an Observability instance with ID "xxx"`, + "$ stackit observability grafana single-sign-on enable xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -53,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil || instanceLabel == "" { instanceLabel = model.InstanceId } @@ -108,9 +108,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient argusUtils.ArgusClient) (argus.ApiUpdateGrafanaConfigsRequest, error) { +func buildRequest(ctx context.Context, model *inputModel, apiClient observabilityUtils.ObservabilityClient) (observability.ApiUpdateGrafanaConfigsRequest, error) { req := apiClient.UpdateGrafanaConfigs(ctx, model.InstanceId, model.ProjectId) - payload, err := argusUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, utils.Ptr(true), nil) + payload, err := observabilityUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, utils.Ptr(true), nil) if err != nil { return req, fmt.Errorf("build request payload: %w", err) } diff --git a/internal/cmd/argus/grafana/single-sign-on/enable/enable_test.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go similarity index 79% rename from internal/cmd/argus/grafana/single-sign-on/enable/enable_test.go rename to internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go index 9b2c6b1d2..e59f23828 100644 --- a/internal/cmd/argus/grafana/single-sign-on/enable/enable_test.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go @@ -7,13 +7,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -21,24 +21,24 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -type argusClientMocked struct { +type observabilityClientMocked struct { getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs } -func (c *argusClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error) { +func (c *observabilityClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*observability.GetInstanceResponse, error) { return testClient.GetInstanceExecute(ctx, instanceId, projectId) } -func (c *argusClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) argus.ApiUpdateGrafanaConfigsRequest { +func (c *observabilityClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) observability.ApiUpdateGrafanaConfigsRequest { return testClient.UpdateGrafanaConfigs(ctx, instanceId, projectId) } -func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*argus.GrafanaConfigs, error) { +func (c *observabilityClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*observability.GrafanaConfigs, error) { if c.getGrafanaConfigsFails { return nil, fmt.Errorf("get payload failed") } @@ -79,9 +79,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.GrafanaConfigs { - gc := argus.GrafanaConfigs{ - GenericOauth: &argus.GrafanaOauth{ +func fixtureGrafanaConfigs(mods ...func(gc *observability.GrafanaConfigs)) *observability.GrafanaConfigs { + gc := observability.GrafanaConfigs{ + GenericOauth: &observability.GrafanaOauth{ ApiUrl: utils.Ptr("apiUrl"), AuthUrl: utils.Ptr("authUrl"), Enabled: utils.Ptr(true), @@ -103,9 +103,9 @@ func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.Grafan return &gc } -func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *argus.UpdateGrafanaConfigsPayload { - payload := &argus.UpdateGrafanaConfigsPayload{ - GenericOauth: argusUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), +func fixturePayload(mods ...func(payload *observability.UpdateGrafanaConfigsPayload)) *observability.UpdateGrafanaConfigsPayload { + payload := &observability.UpdateGrafanaConfigsPayload{ + GenericOauth: observabilityUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess, UseStackitSso: utils.Ptr(true), } @@ -115,7 +115,7 @@ func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *a return payload } -func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) argus.ApiUpdateGrafanaConfigsRequest { +func fixtureRequest(mods ...func(request *observability.ApiUpdateGrafanaConfigsRequest)) observability.ApiUpdateGrafanaConfigsRequest { request := testClient.UpdateGrafanaConfigs(testCtx, testInstanceId, testProjectId) request = request.UpdateGrafanaConfigsPayload(*fixturePayload()) for _, mod := range mods { @@ -242,9 +242,9 @@ func TestBuildRequest(t *testing.T) { description string model *inputModel getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs isValid bool - expectedRequest argus.ApiUpdateGrafanaConfigsRequest + expectedRequest observability.ApiUpdateGrafanaConfigsRequest }{ { description: "base", @@ -256,12 +256,12 @@ func TestBuildRequest(t *testing.T) { { description: "nil generic oauth", model: fixtureInputModel(), - getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) { + getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *observability.GrafanaConfigs) { gc.GenericOauth = nil }), isValid: true, - expectedRequest: fixtureRequest(func(request *argus.ApiUpdateGrafanaConfigsRequest) { - *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *argus.UpdateGrafanaConfigsPayload) { + expectedRequest: fixtureRequest(func(request *observability.ApiUpdateGrafanaConfigsRequest) { + *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { payload.GenericOauth = nil })) }), @@ -282,7 +282,7 @@ func TestBuildRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &argusClientMocked{ + client := &observabilityClientMocked{ getGrafanaConfigsFails: tt.getGrafanaConfigsFails, getGrafanaConfigsResp: tt.getGrafanaConfigsResp, } diff --git a/internal/cmd/argus/grafana/single-sign-on/single_sign_on.go b/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go similarity index 67% rename from internal/cmd/argus/grafana/single-sign-on/single_sign_on.go rename to internal/cmd/observability/grafana/single-sign-on/single_sign_on.go index c19147473..c53c4a5cf 100644 --- a/internal/cmd/argus/grafana/single-sign-on/single_sign_on.go +++ b/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go @@ -3,8 +3,8 @@ package singlesignon import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/grafana/single-sign-on/disable" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/grafana/single-sign-on/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on/disable" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on/enable" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -16,9 +16,9 @@ func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "single-sign-on", Aliases: []string{"sso"}, - Short: "Enable or disable single sign-on for Grafana in Argus instances", + Short: "Enable or disable single sign-on for Grafana in Observability instances", Long: fmt.Sprintf("%s\n%s", - "Enable or disable single sign-on for Grafana in Argus instances.", + "Enable or disable single sign-on for Grafana in Observability instances.", "When enabled for an instance, overwrites the generic OAuth2 authentication and configures STACKIT single sign-on for that instance.", ), Args: args.NoArgs, diff --git a/internal/cmd/argus/instance/create/create.go b/internal/cmd/observability/instance/create/create.go similarity index 67% rename from internal/cmd/argus/instance/create/create.go rename to internal/cmd/observability/instance/create/create.go index b37396bb7..0f1bd2714 100644 --- a/internal/cmd/argus/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -14,13 +14,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" - "github.com/stackitcloud/stackit-sdk-go/services/argus/wait" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-sdk-go/services/observability" + "github.com/stackitcloud/stackit-sdk-go/services/observability/wait" ) const ( @@ -40,16 +40,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "create", - Short: "Creates an Argus instance", - Long: "Creates an Argus instance.", + Short: "Creates an Observability instance", + Long: "Creates an Observability instance.", Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `Create an Argus instance with name "my-instance" and specify plan by name`, - "$ stackit argus instance create --name my-instance --plan-name Monitoring-Starter-EU01"), + `Create an Observability instance with name "my-instance" and specify plan by name`, + "$ stackit observability instance create --name my-instance --plan-name Monitoring-Starter-EU01"), examples.NewExample( - `Create an Argus instance with name "my-instance" and specify plan by ID`, - "$ stackit argus instance create --name my-instance --plan-id xxx"), + `Create an Observability instance with name "my-instance" and specify plan by ID`, + "$ stackit observability instance create --name my-instance --plan-id xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -71,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create an Argus instance for project %q?", projectLabel) + prompt := fmt.Sprintf("Are you sure you want to create an Observability instance for project %q?", projectLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -81,15 +81,15 @@ func NewCmd(p *print.Printer) *cobra.Command { // Call API req, err := buildRequest(ctx, model, apiClient) if err != nil { - var argusInvalidPlanError *cliErr.ArgusInvalidPlanError - if !errors.As(err, &argusInvalidPlanError) { - return fmt.Errorf("build Argus instance creation request: %w", err) + var observabilityInvalidPlanError *cliErr.ObservabilityInvalidPlanError + if !errors.As(err, &observabilityInvalidPlanError) { + return fmt.Errorf("build Observability instance creation request: %w", err) } return err } resp, err := req.Execute() if err != nil { - return fmt.Errorf("create Argus instance: %w", err) + return fmt.Errorf("create Observability instance: %w", err) } instanceId := *resp.InstanceId @@ -99,7 +99,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx) if err != nil { - return fmt.Errorf("wait for Argus instance creation: %w", err) + return fmt.Errorf("wait for Observability instance creation: %w", err) } s.Stop() } @@ -130,12 +130,12 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { planName := flags.FlagToStringValue(p, cmd, planNameFlag) if planId == nil && (planName == "") { - return nil, &cliErr.ArgusInputPlanError{ + return nil, &cliErr.ObservabilityInputPlanError{ Cmd: cmd, } } if planId != nil && (planName != "") { - return nil, &cliErr.ArgusInputPlanError{ + return nil, &cliErr.ObservabilityInputPlanError{ Cmd: cmd, } } @@ -159,12 +159,12 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -type argusClient interface { - CreateInstance(ctx context.Context, projectId string) argus.ApiCreateInstanceRequest - ListPlansExecute(ctx context.Context, projectId string) (*argus.PlansResponse, error) +type observabilityClient interface { + CreateInstance(ctx context.Context, projectId string) observability.ApiCreateInstanceRequest + ListPlansExecute(ctx context.Context, projectId string) (*observability.PlansResponse, error) } -func buildRequest(ctx context.Context, model *inputModel, apiClient argusClient) (argus.ApiCreateInstanceRequest, error) { +func buildRequest(ctx context.Context, model *inputModel, apiClient observabilityClient) (observability.ApiCreateInstanceRequest, error) { req := apiClient.CreateInstance(ctx, model.ProjectId) var planId *string @@ -172,39 +172,39 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient argusClient) plans, err := apiClient.ListPlansExecute(ctx, model.ProjectId) if err != nil { - return req, fmt.Errorf("get Argus plans: %w", err) + return req, fmt.Errorf("get Observability plans: %w", err) } if model.PlanId == nil { - planId, err = argusUtils.LoadPlanId(model.PlanName, plans) + planId, err = observabilityUtils.LoadPlanId(model.PlanName, plans) if err != nil { - var argusInvalidPlanError *cliErr.ArgusInvalidPlanError - if !errors.As(err, &argusInvalidPlanError) { + var observabilityInvalidPlanError *cliErr.ObservabilityInvalidPlanError + if !errors.As(err, &observabilityInvalidPlanError) { return req, fmt.Errorf("load plan ID: %w", err) } return req, err } } else { - err := argusUtils.ValidatePlanId(*model.PlanId, plans) + err := observabilityUtils.ValidatePlanId(*model.PlanId, plans) if err != nil { return req, err } planId = model.PlanId } - req = req.CreateInstancePayload(argus.CreateInstancePayload{ + req = req.CreateInstancePayload(observability.CreateInstancePayload{ Name: model.InstanceName, PlanId: planId, }) return req, nil } -func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *argus.CreateInstanceResponse) error { +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *observability.CreateInstanceResponse) error { switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { - return fmt.Errorf("marshal Argus instance: %w", err) + return fmt.Errorf("marshal Observability instance: %w", err) } p.Outputln(string(details)) @@ -212,7 +212,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp case print.YAMLOutputFormat: details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) if err != nil { - return fmt.Errorf("marshal Argus instance: %w", err) + return fmt.Errorf("marshal Observability instance: %w", err) } p.Outputln(string(details)) diff --git a/internal/cmd/argus/instance/create/create_test.go b/internal/cmd/observability/instance/create/create_test.go similarity index 86% rename from internal/cmd/argus/instance/create/create_test.go rename to internal/cmd/observability/instance/create/create_test.go index eb4b3c2c1..505a03be5 100644 --- a/internal/cmd/argus/instance/create/create_test.go +++ b/internal/cmd/observability/instance/create/create_test.go @@ -12,7 +12,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -20,18 +20,18 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} -type argusClientMocked struct { +type observabilityClientMocked struct { returnError bool - listPlansResponse *argus.PlansResponse + listPlansResponse *observability.PlansResponse } -func (c *argusClientMocked) CreateInstance(ctx context.Context, projectId string) argus.ApiCreateInstanceRequest { +func (c *observabilityClientMocked) CreateInstance(ctx context.Context, projectId string) observability.ApiCreateInstanceRequest { return testClient.CreateInstance(ctx, projectId) } -func (c *argusClientMocked) ListPlansExecute(_ context.Context, _ string) (*argus.PlansResponse, error) { +func (c *observabilityClientMocked) ListPlansExecute(_ context.Context, _ string) (*observability.PlansResponse, error) { if c.returnError { return nil, fmt.Errorf("list plans failed") } @@ -68,9 +68,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiCreateInstanceRequest)) argus.ApiCreateInstanceRequest { +func fixtureRequest(mods ...func(request *observability.ApiCreateInstanceRequest)) observability.ApiCreateInstanceRequest { request := testClient.CreateInstance(testCtx, testProjectId) - request = request.CreateInstancePayload(argus.CreateInstancePayload{ + request = request.CreateInstancePayload(observability.CreateInstancePayload{ Name: utils.Ptr("example-name"), PlanId: utils.Ptr(testPlanId), }) @@ -80,9 +80,9 @@ func fixtureRequest(mods ...func(request *argus.ApiCreateInstanceRequest)) argus return request } -func fixturePlansResponse(mods ...func(response *argus.PlansResponse)) *argus.PlansResponse { - response := &argus.PlansResponse{ - Plans: &[]argus.Plan{ +func fixturePlansResponse(mods ...func(response *observability.PlansResponse)) *observability.PlansResponse { + response := &observability.PlansResponse{ + Plans: &[]observability.Plan{ { Name: utils.Ptr("example-plan-name"), Id: utils.Ptr(testPlanId), @@ -222,9 +222,9 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiCreateInstanceRequest + expectedRequest observability.ApiCreateInstanceRequest getPlansFails bool - getPlansResponse *argus.PlansResponse + getPlansResponse *observability.PlansResponse isValid bool }{ { @@ -287,7 +287,7 @@ func TestBuildRequest(t *testing.T) { ), getPlansResponse: fixturePlansResponse(), expectedRequest: testClient.CreateInstance(testCtx, testProjectId). - CreateInstancePayload(argus.CreateInstancePayload{PlanId: utils.Ptr(testPlanId)}), + CreateInstancePayload(observability.CreateInstancePayload{PlanId: utils.Ptr(testPlanId)}), isValid: true, }, { @@ -301,14 +301,14 @@ func TestBuildRequest(t *testing.T) { ), getPlansResponse: fixturePlansResponse(), expectedRequest: testClient.CreateInstance(testCtx, testProjectId). - CreateInstancePayload(argus.CreateInstancePayload{PlanId: utils.Ptr(testPlanId)}), + CreateInstancePayload(observability.CreateInstancePayload{PlanId: utils.Ptr(testPlanId)}), isValid: true, }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &argusClientMocked{ + client := &observabilityClientMocked{ returnError: tt.getPlansFails, listPlansResponse: tt.getPlansResponse, } diff --git a/internal/cmd/argus/instance/delete/delete.go b/internal/cmd/observability/instance/delete/delete.go similarity index 77% rename from internal/cmd/argus/instance/delete/delete.go rename to internal/cmd/observability/instance/delete/delete.go index bb361c570..abe93e2a0 100644 --- a/internal/cmd/argus/instance/delete/delete.go +++ b/internal/cmd/observability/instance/delete/delete.go @@ -9,14 +9,14 @@ import ( "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/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" - "github.com/stackitcloud/stackit-sdk-go/services/argus/wait" + "github.com/stackitcloud/stackit-sdk-go/services/observability" + "github.com/stackitcloud/stackit-sdk-go/services/observability/wait" ) const ( @@ -31,13 +31,13 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), - Short: "Deletes an Argus instance", - Long: "Deletes an Argus instance.", + Short: "Deletes an Observability instance", + Long: "Deletes an Observability instance.", Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `Delete an Argus instance with ID "xxx"`, - "$ stackit argus instance delete xxx"), + `Delete an Observability instance with ID "xxx"`, + "$ stackit Observability instance delete xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -52,7 +52,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -70,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { req := buildRequest(ctx, model, apiClient) _, err = req.Execute() if err != nil { - return fmt.Errorf("delete Argus instance: %w", err) + return fmt.Errorf("delete Observability instance: %w", err) } // Wait for async operation, if async mode not enabled @@ -79,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.InstanceId, model.ProjectId).WaitWithContext(ctx) if err != nil { - return fmt.Errorf("wait for Argus instance deletion: %w", err) + return fmt.Errorf("wait for Observability instance deletion: %w", err) } s.Stop() } @@ -120,7 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiDeleteInstanceRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiDeleteInstanceRequest { req := apiClient.DeleteInstance(ctx, model.InstanceId, model.ProjectId) return req } diff --git a/internal/cmd/argus/instance/delete/delete_test.go b/internal/cmd/observability/instance/delete/delete_test.go similarity index 94% rename from internal/cmd/argus/instance/delete/delete_test.go rename to internal/cmd/observability/instance/delete/delete_test.go index 0510769ee..8375214bb 100644 --- a/internal/cmd/argus/instance/delete/delete_test.go +++ b/internal/cmd/observability/instance/delete/delete_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -18,7 +18,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() @@ -56,7 +56,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiDeleteInstanceRequest)) argus.ApiDeleteInstanceRequest { +func fixtureRequest(mods ...func(request *observability.ApiDeleteInstanceRequest)) observability.ApiDeleteInstanceRequest { request := testClient.DeleteInstance(testCtx, testInstanceId, testProjectId) for _, mod := range mods { mod(&request) @@ -193,7 +193,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiDeleteInstanceRequest + expectedRequest observability.ApiDeleteInstanceRequest }{ { description: "base", diff --git a/internal/cmd/argus/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go similarity index 81% rename from internal/cmd/argus/instance/describe/describe.go rename to internal/cmd/observability/instance/describe/describe.go index c6e8bc197..9f3764e00 100644 --- a/internal/cmd/argus/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -11,12 +11,12 @@ import ( "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/argus/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -31,16 +31,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), - Short: "Shows details of an Argus instance", - Long: "Shows details of an Argus instance.", + Short: "Shows details of an Observability instance", + Long: "Shows details of an Observability instance.", Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `Get details of an Argus instance with ID "xxx"`, - "$ stackit argus instance describe xxx"), + `Get details of an Observability instance with ID "xxx"`, + "$ stackit observability instance describe xxx"), examples.NewExample( - `Get details of an Argus instance with ID "xxx" in JSON format`, - "$ stackit argus instance describe xxx --output-format json"), + `Get details of an Observability instance with ID "xxx" in JSON format`, + "$ stackit observability instance describe xxx --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -58,7 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { req := buildRequest(ctx, model, apiClient) resp, err := req.Execute() if err != nil { - return fmt.Errorf("read Argus instance: %w", err) + return fmt.Errorf("read Observability instance: %w", err) } return outputResult(p, model.OutputFormat, resp) @@ -92,17 +92,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiGetInstanceRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiGetInstanceRequest { req := apiClient.GetInstance(ctx, model.InstanceId, model.ProjectId) return req } -func outputResult(p *print.Printer, outputFormat string, instance *argus.GetInstanceResponse) error { +func outputResult(p *print.Printer, outputFormat string, instance *observability.GetInstanceResponse) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") if err != nil { - return fmt.Errorf("marshal Argus instance: %w", err) + return fmt.Errorf("marshal Observability instance: %w", err) } p.Outputln(string(details)) @@ -110,7 +110,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *argus.GetInst case print.YAMLOutputFormat: details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) if err != nil { - return fmt.Errorf("marshal Argus instance: %w", err) + return fmt.Errorf("marshal Observability instance: %w", err) } p.Outputln(string(details)) diff --git a/internal/cmd/argus/instance/describe/describe_test.go b/internal/cmd/observability/instance/describe/describe_test.go similarity index 94% rename from internal/cmd/argus/instance/describe/describe_test.go rename to internal/cmd/observability/instance/describe/describe_test.go index fd9b429b2..f2eea2b4d 100644 --- a/internal/cmd/argus/instance/describe/describe_test.go +++ b/internal/cmd/observability/instance/describe/describe_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -18,7 +18,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() @@ -56,7 +56,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiGetInstanceRequest)) argus.ApiGetInstanceRequest { +func fixtureRequest(mods ...func(request *observability.ApiGetInstanceRequest)) observability.ApiGetInstanceRequest { request := testClient.GetInstance(testCtx, testInstanceId, testProjectId) for _, mod := range mods { mod(&request) @@ -193,7 +193,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiGetInstanceRequest + expectedRequest observability.ApiGetInstanceRequest }{ { description: "base", diff --git a/internal/cmd/argus/instance/instance.go b/internal/cmd/observability/instance/instance.go similarity index 54% rename from internal/cmd/argus/instance/instance.go rename to internal/cmd/observability/instance/instance.go index af10b9a7c..efd7d4974 100644 --- a/internal/cmd/argus/instance/instance.go +++ b/internal/cmd/observability/instance/instance.go @@ -1,11 +1,11 @@ package instance import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/instance/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/instance/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/instance/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/instance/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/instance/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -16,8 +16,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "instance", - Short: "Provides functionality for Argus instances", - Long: "Provides functionality for Argus instances.", + Short: "Provides functionality for Observability instances", + Long: "Provides functionality for Observability instances.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/cmd/argus/instance/list/list.go b/internal/cmd/observability/instance/list/list.go similarity index 80% rename from internal/cmd/argus/instance/list/list.go rename to internal/cmd/observability/instance/list/list.go index 98a8e74d5..d87fcdf0c 100644 --- a/internal/cmd/argus/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -13,11 +13,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -32,19 +32,19 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "list", - Short: "Lists all Argus instances", - Long: "Lists all Argus instances.", + Short: "Lists all Observability instances", + Long: "Lists all Observability instances.", Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `List all Argus instances`, - "$ stackit argus instance list"), + `List all Observability instances`, + "$ stackit observability instance list"), examples.NewExample( - `List all Argus instances in JSON format`, - "$ stackit argus instance list --output-format json"), + `List all Observability instances in JSON format`, + "$ stackit observability instance list --output-format json"), examples.NewExample( - `List up to 10 Argus instances`, - "$ stackit argus instance list --limit 10"), + `List up to 10 Observability instances`, + "$ stackit observability instance list --limit 10"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { req := buildRequest(ctx, model, apiClient) resp, err := req.Execute() if err != nil { - return fmt.Errorf("get Argus instances: %w", err) + return fmt.Errorf("get Observability instances: %w", err) } instances := *resp.Instances if len(instances) == 0 { @@ -124,17 +124,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiListInstancesRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiListInstancesRequest { req := apiClient.ListInstances(ctx, model.ProjectId) return req } -func outputResult(p *print.Printer, outputFormat string, instances []argus.ProjectInstanceFull) error { +func outputResult(p *print.Printer, outputFormat string, instances []observability.ProjectInstanceFull) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instances, "", " ") if err != nil { - return fmt.Errorf("marshal Argus instance list: %w", err) + return fmt.Errorf("marshal Observability instance list: %w", err) } p.Outputln(string(details)) @@ -142,7 +142,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []argus.Proje case print.YAMLOutputFormat: details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) if err != nil { - return fmt.Errorf("marshal Argus instance list: %w", err) + return fmt.Errorf("marshal Observability instance list: %w", err) } p.Outputln(string(details)) diff --git a/internal/cmd/argus/instance/list/list_test.go b/internal/cmd/observability/instance/list/list_test.go similarity index 93% rename from internal/cmd/argus/instance/list/list_test.go rename to internal/cmd/observability/instance/list/list_test.go index 5e6e9cb9d..649f70e55 100644 --- a/internal/cmd/argus/instance/list/list_test.go +++ b/internal/cmd/observability/instance/list/list_test.go @@ -12,7 +12,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -20,7 +20,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { @@ -48,7 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiListInstancesRequest)) argus.ApiListInstancesRequest { +func fixtureRequest(mods ...func(request *observability.ApiListInstancesRequest)) observability.ApiListInstancesRequest { request := testClient.ListInstances(testCtx, testProjectId) for _, mod := range mods { mod(&request) @@ -162,7 +162,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiListInstancesRequest + expectedRequest observability.ApiListInstancesRequest }{ { description: "base", diff --git a/internal/cmd/argus/instance/update/update.go b/internal/cmd/observability/instance/update/update.go similarity index 67% rename from internal/cmd/argus/instance/update/update.go rename to internal/cmd/observability/instance/update/update.go index dbfe4bc13..192c84366 100644 --- a/internal/cmd/argus/instance/update/update.go +++ b/internal/cmd/observability/instance/update/update.go @@ -11,14 +11,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" - "github.com/stackitcloud/stackit-sdk-go/services/argus/wait" + "github.com/stackitcloud/stackit-sdk-go/services/observability" + "github.com/stackitcloud/stackit-sdk-go/services/observability/wait" ) const ( @@ -41,19 +41,19 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), - Short: "Updates an Argus instance", - Long: "Updates an Argus instance.", + Short: "Updates an Observability instance", + Long: "Updates an Observability instance.", Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `Update the plan of an Argus instance with ID "xxx" by specifying the plan ID`, - "$ stackit argus instance update xxx --plan-id yyy"), + `Update the plan of an Observability instance with ID "xxx" by specifying the plan ID`, + "$ stackit observability instance update xxx --plan-id yyy"), examples.NewExample( - `Update the plan of an Argus instance with ID "xxx" by specifying the plan name`, - "$ stackit argus instance update xxx --plan-name Frontend-Starter-EU01"), + `Update the plan of an Observability instance with ID "xxx" by specifying the plan name`, + "$ stackit observability instance update xxx --plan-name Frontend-Starter-EU01"), examples.NewExample( - `Update the name of an Argus instance with ID "xxx"`, - "$ stackit argus instance update xxx --name new-instance-name"), + `Update the name of an Observability instance with ID "xxx"`, + "$ stackit observability instance update xxx --name new-instance-name"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -68,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil || instanceLabel == "" { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -85,16 +85,16 @@ func NewCmd(p *print.Printer) *cobra.Command { // Call API req, err := buildRequest(ctx, model, apiClient) if err != nil { - var argusInvalidPlanError *cliErr.ArgusInvalidPlanError - if !errors.As(err, &argusInvalidPlanError) { - return fmt.Errorf("build Argus instance update request: %w", err) + var observabilityInvalidPlanError *cliErr.ObservabilityInvalidPlanError + if !errors.As(err, &observabilityInvalidPlanError) { + return fmt.Errorf("build Observability instance update request: %w", err) } return err } _, err = req.Execute() if err != nil { - return fmt.Errorf("update Argus instance: %w", err) + return fmt.Errorf("update Observability instance: %w", err) } instanceId := model.InstanceId @@ -104,7 +104,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Start("Updating instance") _, err = wait.UpdateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx) if err != nil { - return fmt.Errorf("wait for Argus instance update: %w", err) + return fmt.Errorf("wait for Observability instance update: %w", err) } s.Stop() } @@ -140,7 +140,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu instanceName := flags.FlagToStringPointer(p, cmd, instanceNameFlag) if planId != nil && (planName != "") { - return nil, &cliErr.ArgusInputPlanError{ + return nil, &cliErr.ObservabilityInputPlanError{ Cmd: cmd, } } @@ -169,46 +169,46 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -type argusClient interface { - UpdateInstance(ctx context.Context, instanceId, projectId string) argus.ApiUpdateInstanceRequest - ListPlansExecute(ctx context.Context, projectId string) (*argus.PlansResponse, error) - GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error) +type observabilityClient interface { + UpdateInstance(ctx context.Context, instanceId, projectId string) observability.ApiUpdateInstanceRequest + ListPlansExecute(ctx context.Context, projectId string) (*observability.PlansResponse, error) + GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*observability.GetInstanceResponse, error) } -func buildRequest(ctx context.Context, model *inputModel, apiClient argusClient) (argus.ApiUpdateInstanceRequest, error) { +func buildRequest(ctx context.Context, model *inputModel, apiClient observabilityClient) (observability.ApiUpdateInstanceRequest, error) { req := apiClient.UpdateInstance(ctx, model.InstanceId, model.ProjectId) var err error plans, err := apiClient.ListPlansExecute(ctx, model.ProjectId) if err != nil { - return req, fmt.Errorf("get Argus plans: %w", err) + return req, fmt.Errorf("get Observability plans: %w", err) } currentInstance, err := apiClient.GetInstanceExecute(ctx, model.InstanceId, model.ProjectId) if err != nil { - return req, fmt.Errorf("get Argus instance: %w", err) + return req, fmt.Errorf("get Observability instance: %w", err) } - payload := argus.UpdateInstancePayload{ + payload := observability.UpdateInstancePayload{ PlanId: currentInstance.PlanId, Name: currentInstance.Name, } if model.PlanId == nil && model.PlanName != "" { - payload.PlanId, err = argusUtils.LoadPlanId(model.PlanName, plans) + payload.PlanId, err = observabilityUtils.LoadPlanId(model.PlanName, plans) if err != nil { - var argusInvalidPlanError *cliErr.ArgusInvalidPlanError - if !errors.As(err, &argusInvalidPlanError) { + var observabilityInvalidPlanError *cliErr.ObservabilityInvalidPlanError + if !errors.As(err, &observabilityInvalidPlanError) { return req, fmt.Errorf("load plan ID: %w", err) } return req, err } } else if model.PlanId != nil && model.PlanName == "" { - err := argusUtils.ValidatePlanId(*model.PlanId, plans) + err := observabilityUtils.ValidatePlanId(*model.PlanId, plans) if err != nil { - var argusInvalidPlanError *cliErr.ArgusInvalidPlanError - if !errors.As(err, &argusInvalidPlanError) { + var observabilityInvalidPlanError *cliErr.ObservabilityInvalidPlanError + if !errors.As(err, &observabilityInvalidPlanError) { return req, fmt.Errorf("validate plan ID: %w", err) } return req, err diff --git a/internal/cmd/argus/instance/update/update_test.go b/internal/cmd/observability/instance/update/update_test.go similarity index 87% rename from internal/cmd/argus/instance/update/update_test.go rename to internal/cmd/observability/instance/update/update_test.go index 89a7f99ca..0b5177b27 100644 --- a/internal/cmd/argus/instance/update/update_test.go +++ b/internal/cmd/observability/instance/update/update_test.go @@ -12,7 +12,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -20,27 +20,27 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} -type argusClientMocked struct { +type observabilityClientMocked struct { listPlansError bool - listPlansResponse *argus.PlansResponse + listPlansResponse *observability.PlansResponse getInstanceError bool - getInstanceResponse *argus.GetInstanceResponse + getInstanceResponse *observability.GetInstanceResponse } -func (c *argusClientMocked) UpdateInstance(ctx context.Context, instanceId, projectId string) argus.ApiUpdateInstanceRequest { +func (c *observabilityClientMocked) UpdateInstance(ctx context.Context, instanceId, projectId string) observability.ApiUpdateInstanceRequest { return testClient.UpdateInstance(ctx, instanceId, projectId) } -func (c *argusClientMocked) ListPlansExecute(_ context.Context, _ string) (*argus.PlansResponse, error) { +func (c *observabilityClientMocked) ListPlansExecute(_ context.Context, _ string) (*observability.PlansResponse, error) { if c.listPlansError { return nil, fmt.Errorf("list flavors failed") } return c.listPlansResponse, nil } -func (c *argusClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*argus.GetInstanceResponse, error) { +func (c *observabilityClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*observability.GetInstanceResponse, error) { if c.getInstanceError { return nil, fmt.Errorf("get instance failed") } @@ -94,9 +94,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiUpdateInstanceRequest)) argus.ApiUpdateInstanceRequest { +func fixtureRequest(mods ...func(request *observability.ApiUpdateInstanceRequest)) observability.ApiUpdateInstanceRequest { request := testClient.UpdateInstance(testCtx, testInstanceId, testProjectId) - request = request.UpdateInstancePayload(argus.UpdateInstancePayload{ + request = request.UpdateInstancePayload(observability.UpdateInstancePayload{ PlanId: utils.Ptr(testNewPlanId), Name: utils.Ptr(testInstanceName), }) @@ -106,9 +106,9 @@ func fixtureRequest(mods ...func(request *argus.ApiUpdateInstanceRequest)) argus return request } -func fixturePlansResponse(mods ...func(response *argus.PlansResponse)) *argus.PlansResponse { - response := &argus.PlansResponse{ - Plans: &[]argus.Plan{ +func fixturePlansResponse(mods ...func(response *observability.PlansResponse)) *observability.PlansResponse { + response := &observability.PlansResponse{ + Plans: &[]observability.Plan{ { Name: utils.Ptr("example-plan-name"), Id: utils.Ptr(testNewPlanId), @@ -121,8 +121,8 @@ func fixturePlansResponse(mods ...func(response *argus.PlansResponse)) *argus.Pl return response } -func fixtureGetInstanceResponse(mods ...func(response *argus.GetInstanceResponse)) *argus.GetInstanceResponse { - response := &argus.GetInstanceResponse{ +func fixtureGetInstanceResponse(mods ...func(response *observability.GetInstanceResponse)) *observability.GetInstanceResponse { + response := &observability.GetInstanceResponse{ PlanId: utils.Ptr(testPlanId), Name: utils.Ptr(testInstanceName), } @@ -295,11 +295,11 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiUpdateInstanceRequest + expectedRequest observability.ApiUpdateInstanceRequest getPlansFails bool - getPlansResponse *argus.PlansResponse + getPlansResponse *observability.PlansResponse getInstanceFails bool - getInstanceResponse *argus.GetInstanceResponse + getInstanceResponse *observability.GetInstanceResponse isValid bool }{ { @@ -394,7 +394,7 @@ func TestBuildRequest(t *testing.T) { ), getInstanceResponse: fixtureGetInstanceResponse(), expectedRequest: fixtureRequest(). - UpdateInstancePayload(argus.UpdateInstancePayload{ + UpdateInstancePayload(observability.UpdateInstancePayload{ PlanId: utils.Ptr(testPlanId), Name: utils.Ptr("new-instance-name"), }), @@ -416,7 +416,7 @@ func TestBuildRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &argusClientMocked{ + client := &observabilityClientMocked{ listPlansError: tt.getPlansFails, listPlansResponse: tt.getPlansResponse, getInstanceError: tt.getInstanceFails, diff --git a/internal/cmd/argus/argus.go b/internal/cmd/observability/observability.go similarity index 52% rename from internal/cmd/argus/argus.go rename to internal/cmd/observability/observability.go index 4bf46ccaa..c6a000568 100644 --- a/internal/cmd/argus/argus.go +++ b/internal/cmd/observability/observability.go @@ -1,11 +1,11 @@ -package argus +package observability import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/credentials" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/grafana" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/instance" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/plans" - scrapeconfig "github.com/stackitcloud/stackit-cli/internal/cmd/argus/scrape-config" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/plans" + scrapeconfig "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -15,11 +15,12 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "argus", - Short: "Provides functionality for Argus", - Long: "Provides functionality for Argus.", - Args: args.NoArgs, - Run: utils.CmdHelp, + Use: "observability", + Aliases: []string{"argus"}, + Short: "Provides functionality for Observability", + Long: "Provides functionality for Observability.", + Args: args.NoArgs, + Run: utils.CmdHelp, } addSubcommands(cmd, p) return cmd diff --git a/internal/cmd/argus/plans/plans.go b/internal/cmd/observability/plans/plans.go similarity index 81% rename from internal/cmd/argus/plans/plans.go rename to internal/cmd/observability/plans/plans.go index a80800177..14baeaec3 100644 --- a/internal/cmd/argus/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -13,11 +13,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -32,19 +32,19 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "plans", - Short: "Lists all Argus service plans", - Long: "Lists all Argus service plans.", + Short: "Lists all Observability service plans", + Long: "Lists all Observability service plans.", Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `List all Argus service plans`, - "$ stackit argus plans"), + `List all Observability service plans`, + "$ stackit observability plans"), examples.NewExample( - `List all Argus service plans in JSON format`, - "$ stackit argus plans --output-format json"), + `List all Observability service plans in JSON format`, + "$ stackit observability plans --output-format json"), examples.NewExample( - `List up to 10 Argus service plans`, - "$ stackit argus plans --limit 10"), + `List up to 10 Observability service plans`, + "$ stackit observability plans --limit 10"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { req := buildRequest(ctx, model, apiClient) resp, err := req.Execute() if err != nil { - return fmt.Errorf("get Argus service plans: %w", err) + return fmt.Errorf("get Observability service plans: %w", err) } plans := *resp.Plans if len(plans) == 0 { @@ -124,17 +124,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiListPlansRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiListPlansRequest { req := apiClient.ListPlans(ctx, model.ProjectId) return req } -func outputResult(p *print.Printer, outputFormat string, plans []argus.Plan) error { +func outputResult(p *print.Printer, outputFormat string, plans []observability.Plan) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(plans, "", " ") if err != nil { - return fmt.Errorf("marshal Argus plans: %w", err) + return fmt.Errorf("marshal Observability plans: %w", err) } p.Outputln(string(details)) @@ -142,7 +142,7 @@ func outputResult(p *print.Printer, outputFormat string, plans []argus.Plan) err case print.YAMLOutputFormat: details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true)) if err != nil { - return fmt.Errorf("marshal Argus plans: %w", err) + return fmt.Errorf("marshal Observability plans: %w", err) } p.Outputln(string(details)) diff --git a/internal/cmd/argus/plans/plans_test.go b/internal/cmd/observability/plans/plans_test.go similarity index 93% rename from internal/cmd/argus/plans/plans_test.go rename to internal/cmd/observability/plans/plans_test.go index d23fe8ec1..3c978a3a7 100644 --- a/internal/cmd/argus/plans/plans_test.go +++ b/internal/cmd/observability/plans/plans_test.go @@ -12,7 +12,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -20,7 +20,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { @@ -48,7 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiListPlansRequest)) argus.ApiListPlansRequest { +func fixtureRequest(mods ...func(request *observability.ApiListPlansRequest)) observability.ApiListPlansRequest { request := testClient.ListPlans(testCtx, testProjectId) for _, mod := range mods { mod(&request) @@ -163,7 +163,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiListPlansRequest + expectedRequest observability.ApiListPlansRequest }{ { description: "base", diff --git a/internal/cmd/argus/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go similarity index 68% rename from internal/cmd/argus/scrape-config/create/create.go rename to internal/cmd/observability/scrape-config/create/create.go index a2c4d02e5..dd7eba557 100644 --- a/internal/cmd/argus/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -11,13 +11,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" - "github.com/stackitcloud/stackit-sdk-go/services/argus/wait" + "github.com/stackitcloud/stackit-sdk-go/services/observability" + "github.com/stackitcloud/stackit-sdk-go/services/observability/wait" ) const ( @@ -28,15 +28,15 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel InstanceId string - Payload *argus.CreateScrapeConfigPayload + Payload *observability.CreateScrapeConfigPayload } func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "create", - Short: "Creates a scrape configuration for an Argus instance", + Short: "Creates a scrape configuration for an Observability instance", Long: fmt.Sprintf("%s\n%s\n%s\n%s", - "Creates a scrape configuration job for an Argus instance.", + "Creates a scrape configuration job for an Observability instance.", "The payload can be provided as a JSON string or a file path prefixed with \"@\".", "If no payload is provided, a default payload will be used.", "See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_create for information regarding the payload structure.", @@ -44,19 +44,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `Create a scrape configuration on Argus instance "xxx" using default configuration`, - "$ stackit argus scrape-config create"), + `Create a scrape configuration on Observability instance "xxx" using default configuration`, + "$ stackit observability scrape-config create"), examples.NewExample( - `Create a scrape configuration on Argus instance "xxx" using an API payload sourced from the file "./payload.json"`, - "$ stackit argus scrape-config create --payload @./payload.json --instance-id xxx"), + `Create a scrape configuration on Observability instance "xxx" using an API payload sourced from the file "./payload.json"`, + "$ stackit observability scrape-config create --payload @./payload.json --instance-id xxx"), examples.NewExample( - `Create a scrape configuration on Argus instance "xxx" using an API payload provided as a JSON string`, - `$ stackit argus scrape-config create --payload "{...}" --instance-id xxx`), + `Create a scrape configuration on Observability instance "xxx" using an API payload provided as a JSON string`, + `$ stackit observability scrape-config create --payload "{...}" --instance-id xxx`), examples.NewExample( `Generate a payload with default values, and adapt it with custom values for the different configuration options`, - `$ stackit argus scrape-config generate-payload > ./payload.json`, + `$ stackit observability scrape-config generate-payload > ./payload.json`, ``, - `$ stackit argus scrape-config create --payload @./payload.json --instance-id xxx`), + `$ stackit observability scrape-config create --payload @./payload.json --instance-id xxx`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -71,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -79,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Fill in default payload, if needed if model.Payload == nil { - defaultPayload := argusUtils.DefaultCreateScrapeConfigPayload + defaultPayload := observabilityUtils.DefaultCreateScrapeConfigPayload if err != nil { return fmt.Errorf("get default payload: %w", err) } @@ -87,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create scrape configuration %q on Argus instance %q?", *model.Payload.JobName, instanceLabel) + prompt := fmt.Sprintf("Are you sure you want to create scrape configuration %q on Observability instance %q?", *model.Payload.JobName, instanceLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -118,7 +118,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s scrape configuration with name %q for Argus instance %q\n", operationState, *jobName, instanceLabel) + p.Outputf("%s scrape configuration with name %q for Observability instance %q\n", operationState, *jobName, instanceLabel) return nil }, } @@ -127,7 +127,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } func configureFlags(cmd *cobra.Command) { - cmd.Flags().Var(flags.ReadFromFileFlag(), payloadFlag, `Request payload (JSON). Can be a string or a file path, if prefixed with "@" (example: @./payload.json). If unset, will use a default payload (you can check it by running "stackit argus scrape-config generate-payload")`) + cmd.Flags().Var(flags.ReadFromFileFlag(), payloadFlag, `Request payload (JSON). Can be a string or a file path, if prefixed with "@" (example: @./payload.json). If unset, will use a default payload (you can check it by running "stackit observability scrape-config generate-payload")`) cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "Instance ID") err := flags.MarkFlagsRequired(cmd, instanceIdFlag) @@ -141,9 +141,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } payloadValue := flags.FlagToStringPointer(p, cmd, payloadFlag) - var payload *argus.CreateScrapeConfigPayload + var payload *observability.CreateScrapeConfigPayload if payloadValue != nil { - payload = &argus.CreateScrapeConfigPayload{} + payload = &observability.CreateScrapeConfigPayload{} err := json.Unmarshal([]byte(*payloadValue), payload) if err != nil { return nil, fmt.Errorf("encode payload: %w", err) @@ -157,7 +157,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiCreateScrapeConfigRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiCreateScrapeConfigRequest { req := apiClient.CreateScrapeConfig(ctx, model.InstanceId, model.ProjectId) req = req.CreateScrapeConfigPayload(*model.Payload) diff --git a/internal/cmd/argus/scrape-config/create/create_test.go b/internal/cmd/observability/scrape-config/create/create_test.go similarity index 91% rename from internal/cmd/argus/scrape-config/create/create_test.go rename to internal/cmd/observability/scrape-config/create/create_test.go index a9ca561b4..54c0573e3 100644 --- a/internal/cmd/argus/scrape-config/create/create_test.go +++ b/internal/cmd/observability/scrape-config/create/create_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -18,12 +18,12 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -var testPayload = &argus.CreateScrapeConfigPayload{ - BasicAuth: &argus.CreateScrapeConfigPayloadBasicAuth{ +var testPayload = &observability.CreateScrapeConfigPayload{ + BasicAuth: &observability.CreateScrapeConfigPayloadBasicAuth{ Username: utils.Ptr("username"), Password: utils.Ptr("password"), }, @@ -32,7 +32,7 @@ var testPayload = &argus.CreateScrapeConfigPayload{ HonorTimeStamps: utils.Ptr(true), MetricsPath: utils.Ptr("/metrics"), JobName: utils.Ptr("default-name"), - MetricsRelabelConfigs: &[]argus.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ + MetricsRelabelConfigs: &[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ { Action: utils.Ptr("replace"), Modulus: utils.Ptr(1.0), @@ -51,7 +51,7 @@ var testPayload = &argus.CreateScrapeConfigPayload{ Scheme: utils.Ptr("scheme"), ScrapeInterval: utils.Ptr("interval"), ScrapeTimeout: utils.Ptr("timeout"), - StaticConfigs: &[]argus.CreateScrapeConfigPayloadStaticConfigsInner{ + StaticConfigs: &[]observability.CreateScrapeConfigPayloadStaticConfigsInner{ { Labels: &map[string]interface{}{ "label": "value", @@ -60,7 +60,7 @@ var testPayload = &argus.CreateScrapeConfigPayload{ Targets: &[]string{"target"}, }, }, - TlsConfig: &argus.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{ + TlsConfig: &observability.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{ InsecureSkipVerify: utils.Ptr(true), }, } @@ -133,7 +133,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiCreateScrapeConfigRequest)) argus.ApiCreateScrapeConfigRequest { +func fixtureRequest(mods ...func(request *observability.ApiCreateScrapeConfigRequest)) observability.ApiCreateScrapeConfigRequest { request := testClient.CreateScrapeConfig(testCtx, testInstanceId, testProjectId) request = request.CreateScrapeConfigPayload(*testPayload) for _, mod := range mods { @@ -286,7 +286,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiCreateScrapeConfigRequest + expectedRequest observability.ApiCreateScrapeConfigRequest isValid bool }{ { diff --git a/internal/cmd/argus/scrape-config/delete/delete.go b/internal/cmd/observability/scrape-config/delete/delete.go similarity index 75% rename from internal/cmd/argus/scrape-config/delete/delete.go rename to internal/cmd/observability/scrape-config/delete/delete.go index 31cc6d855..de04c6fcc 100644 --- a/internal/cmd/argus/scrape-config/delete/delete.go +++ b/internal/cmd/observability/scrape-config/delete/delete.go @@ -10,13 +10,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" - "github.com/stackitcloud/stackit-sdk-go/services/argus/wait" + "github.com/stackitcloud/stackit-sdk-go/services/observability" + "github.com/stackitcloud/stackit-sdk-go/services/observability/wait" ) const ( @@ -34,13 +34,13 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", jobNameArg), - Short: "Deletes a scrape configuration from an Argus instance", - Long: "Deletes a scrape configuration from an Argus instance.", + Short: "Deletes a scrape configuration from an Observability instance", + Long: "Deletes a scrape configuration from an Observability instance.", Args: args.SingleArg(jobNameArg, nil), Example: examples.Build( examples.NewExample( - `Delete a scrape configuration job with name "my-config" from Argus instance "xxx"`, - "$ stackit argus scrape-config delete my-config --instance-id xxx"), + `Delete a scrape configuration job with name "my-config" from Observability instance "xxx"`, + "$ stackit observability scrape-config delete my-config --instance-id xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -55,14 +55,14 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete scrape configuration %q on Argus instance %q? (This cannot be undone)", model.JobName, instanceLabel) + prompt := fmt.Sprintf("Are you sure you want to delete scrape configuration %q on Observability instance %q? (This cannot be undone)", model.JobName, instanceLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -91,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s scrape configuration with name %q for Argus instance %q\n", operationState, model.JobName, instanceLabel) + p.Info("%s scrape configuration with name %q for Observability instance %q\n", operationState, model.JobName, instanceLabel) return nil }, } @@ -121,7 +121,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiDeleteScrapeConfigRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiDeleteScrapeConfigRequest { req := apiClient.DeleteScrapeConfig(ctx, model.InstanceId, model.JobName, model.ProjectId) return req } diff --git a/internal/cmd/argus/scrape-config/delete/delete_test.go b/internal/cmd/observability/scrape-config/delete/delete_test.go similarity index 94% rename from internal/cmd/argus/scrape-config/delete/delete_test.go rename to internal/cmd/observability/scrape-config/delete/delete_test.go index 21d1b79c9..c9549964d 100644 --- a/internal/cmd/argus/scrape-config/delete/delete_test.go +++ b/internal/cmd/observability/scrape-config/delete/delete_test.go @@ -9,7 +9,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -17,7 +17,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testJobName = "my-config" @@ -58,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiDeleteScrapeConfigRequest)) argus.ApiDeleteScrapeConfigRequest { +func fixtureRequest(mods ...func(request *observability.ApiDeleteScrapeConfigRequest)) observability.ApiDeleteScrapeConfigRequest { request := testClient.DeleteScrapeConfig(testCtx, testInstanceId, testJobName, testProjectId) for _, mod := range mods { mod(&request) @@ -207,7 +207,7 @@ func TestBuildRequest(t *testing.T) { description string model *inputModel isValid bool - expectedRequest argus.ApiDeleteScrapeConfigRequest + expectedRequest observability.ApiDeleteScrapeConfigRequest }{ { description: "base", diff --git a/internal/cmd/argus/scrape-config/describe/describe.go b/internal/cmd/observability/scrape-config/describe/describe.go similarity index 87% rename from internal/cmd/argus/scrape-config/describe/describe.go rename to internal/cmd/observability/scrape-config/describe/describe.go index 2b9d1fb99..9a94c8fd6 100644 --- a/internal/cmd/argus/scrape-config/describe/describe.go +++ b/internal/cmd/observability/scrape-config/describe/describe.go @@ -13,9 +13,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" "github.com/spf13/cobra" ) @@ -35,16 +35,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", jobNameArg), - Short: "Shows details of a scrape configuration from an Argus instance", - Long: "Shows details of a scrape configuration from an Argus instance.", + Short: "Shows details of a scrape configuration from an Observability instance", + Long: "Shows details of a scrape configuration from an Observability instance.", Args: args.SingleArg(jobNameArg, nil), Example: examples.Build( examples.NewExample( - `Get details of a scrape configuration with name "my-config" from Argus instance "xxx"`, - "$ stackit argus scrape-config describe my-config --instance-id xxx"), + `Get details of a scrape configuration with name "my-config" from Observability instance "xxx"`, + "$ stackit observability scrape-config describe my-config --instance-id xxx"), examples.NewExample( - `Get details of a scrape configuration with name "my-config" from Argus instance "xxx" in JSON format`, - "$ stackit argus scrape-config describe my-config --output-format json"), + `Get details of a scrape configuration with name "my-config" from Observability instance "xxx" in JSON format`, + "$ stackit observability scrape-config describe my-config --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -94,12 +94,12 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiGetScrapeConfigRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiGetScrapeConfigRequest { req := apiClient.GetScrapeConfig(ctx, model.InstanceId, model.JobName, model.ProjectId) return req } -func outputResult(p *print.Printer, outputFormat string, config *argus.Job) error { +func outputResult(p *print.Printer, outputFormat string, config *observability.Job) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(config, "", " ") diff --git a/internal/cmd/argus/scrape-config/describe/describe_test.go b/internal/cmd/observability/scrape-config/describe/describe_test.go similarity index 94% rename from internal/cmd/argus/scrape-config/describe/describe_test.go rename to internal/cmd/observability/scrape-config/describe/describe_test.go index 962d373a9..f496da426 100644 --- a/internal/cmd/argus/scrape-config/describe/describe_test.go +++ b/internal/cmd/observability/scrape-config/describe/describe_test.go @@ -9,7 +9,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -17,7 +17,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testJobName = "my-config" @@ -58,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiGetScrapeConfigRequest)) argus.ApiGetScrapeConfigRequest { +func fixtureRequest(mods ...func(request *observability.ApiGetScrapeConfigRequest)) observability.ApiGetScrapeConfigRequest { request := testClient.GetScrapeConfig(testCtx, testInstanceId, testJobName, testProjectId) for _, mod := range mods { mod(&request) @@ -207,7 +207,7 @@ func TestBuildRequest(t *testing.T) { description string model *inputModel isValid bool - expectedRequest argus.ApiGetScrapeConfigRequest + expectedRequest observability.ApiGetScrapeConfigRequest }{ { description: "base", diff --git a/internal/cmd/argus/scrape-config/generate-payload/generate_payload.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go similarity index 76% rename from internal/cmd/argus/scrape-config/generate-payload/generate_payload.go rename to internal/cmd/observability/scrape-config/generate-payload/generate_payload.go index 9d5e720f2..cdd20cd9f 100644 --- a/internal/cmd/argus/scrape-config/generate-payload/generate_payload.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go @@ -11,11 +11,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -34,11 +34,11 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "generate-payload", - Short: "Generates a payload to create/update scrape configurations for an Argus instance ", + Short: "Generates a payload to create/update scrape configurations for an Observability instance ", Long: fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n", "Generates a JSON payload with values to be used as --payload input for scrape configurations creation or update.", "This command can be used to generate a payload to update an existing scrape config or to create a new scrape config job.", - "To update an existing scrape config job, provide the job name and the instance ID of the Argus instance.", + "To update an existing scrape config job, provide the job name and the instance ID of the Observability instance.", "To obtain a default payload to create a new scrape config job, run the command with no flags.", "Note that some of the default values provided, such as the job name, the metrics path and URL of the targets, should be adapted to your use case.", "See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_create for information regarding the payload structure.", @@ -47,17 +47,17 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Generate a Create payload with default values, and adapt it with custom values for the different configuration options`, - `$ stackit argus scrape-config generate-payload --file-path ./payload.json`, + `$ stackit observability scrape-config generate-payload --file-path ./payload.json`, ``, - `$ stackit argus scrape-config create my-config --payload @./payload.json`), + `$ stackit observability scrape-config create my-config --payload @./payload.json`), examples.NewExample( - `Generate an Update payload with the values of an existing configuration named "my-config" for Argus instance xxx, and adapt it with custom values for the different configuration options`, - `$ stackit argus scrape-config generate-payload --job-name my-config --instance-id xxx --file-path ./payload.json`, + `Generate an Update payload with the values of an existing configuration named "my-config" for Observability instance xxx, and adapt it with custom values for the different configuration options`, + `$ stackit observability scrape-config generate-payload --job-name my-config --instance-id xxx --file-path ./payload.json`, ``, - `$ stackit argus scrape-config update my-config --payload @./payload.json`), + `$ stackit observability scrape-config update my-config --payload @./payload.json`), examples.NewExample( - `Generate an Update payload with the values of an existing configuration named "my-config" for Argus instance xxx, and preview it in the terminal`, - `$ stackit argus scrape-config generate-payload --job-name my-config --instance-id xxx`), + `Generate an Update payload with the values of an existing configuration named "my-config" for Observability instance xxx, and preview it in the terminal`, + `$ stackit observability scrape-config generate-payload --job-name my-config --instance-id xxx`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -73,17 +73,17 @@ func NewCmd(p *print.Printer) *cobra.Command { } if model.JobName == nil { - createPayload := argusUtils.DefaultCreateScrapeConfigPayload + createPayload := observabilityUtils.DefaultCreateScrapeConfigPayload return outputCreateResult(p, model.FilePath, &createPayload) } req := buildRequest(ctx, model, apiClient) resp, err := req.Execute() if err != nil { - return fmt.Errorf("read Argus scrape config: %w", err) + return fmt.Errorf("read Observability scrape config: %w", err) } - payload, err := argusUtils.MapToUpdateScrapeConfigPayload(resp) + payload, err := observabilityUtils.MapToUpdateScrapeConfigPayload(resp) if err != nil { return fmt.Errorf("map update scrape config payloads: %w", err) } @@ -119,12 +119,12 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiGetScrapeConfigRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiGetScrapeConfigRequest { req := apiClient.GetScrapeConfig(ctx, model.InstanceId, *model.JobName, model.ProjectId) return req } -func outputCreateResult(p *print.Printer, filePath *string, payload *argus.CreateScrapeConfigPayload) error { +func outputCreateResult(p *print.Printer, filePath *string, payload *observability.CreateScrapeConfigPayload) error { payloadBytes, err := json.MarshalIndent(*payload, "", " ") if err != nil { return fmt.Errorf("marshal payload: %w", err) @@ -142,7 +142,7 @@ func outputCreateResult(p *print.Printer, filePath *string, payload *argus.Creat return nil } -func outputUpdateResult(p *print.Printer, filePath *string, payload *argus.UpdateScrapeConfigPayload) error { +func outputUpdateResult(p *print.Printer, filePath *string, payload *observability.UpdateScrapeConfigPayload) error { payloadBytes, err := json.MarshalIndent(*payload, "", " ") if err != nil { return fmt.Errorf("marshal payload: %w", err) diff --git a/internal/cmd/argus/scrape-config/generate-payload/generate_payload_test.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go similarity index 95% rename from internal/cmd/argus/scrape-config/generate-payload/generate_payload_test.go rename to internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go index 5c04abd5c..e23f4fabc 100644 --- a/internal/cmd/argus/scrape-config/generate-payload/generate_payload_test.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -18,7 +18,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() @@ -56,7 +56,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiGetScrapeConfigRequest)) argus.ApiGetScrapeConfigRequest { +func fixtureRequest(mods ...func(request *observability.ApiGetScrapeConfigRequest)) observability.ApiGetScrapeConfigRequest { request := testClient.GetScrapeConfig(testCtx, testInstanceId, testJobName, testProjectId) for _, mod := range mods { mod(&request) @@ -224,7 +224,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiGetScrapeConfigRequest + expectedRequest observability.ApiGetScrapeConfigRequest isValid bool }{ { diff --git a/internal/cmd/argus/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go similarity index 78% rename from internal/cmd/argus/scrape-config/list/list.go rename to internal/cmd/observability/scrape-config/list/list.go index 60f6598a0..f535db051 100644 --- a/internal/cmd/argus/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -12,13 +12,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -35,19 +35,19 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "list", - Short: "Lists all scrape configurations of an Argus instance", - Long: "Lists all scrape configurations of an Argus instance.", + Short: "Lists all scrape configurations of an Observability instance", + Long: "Lists all scrape configurations of an Observability instance.", Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `List all scrape configurations of Argus instance "xxx"`, - "$ stackit argus scrape-config list --instance-id xxx"), + `List all scrape configurations of Observability instance "xxx"`, + "$ stackit observability scrape-config list --instance-id xxx"), examples.NewExample( - `List all scrape configurations of Argus instance "xxx" in JSON format`, - "$ stackit argus scrape-config list --instance-id xxx --output-format json"), + `List all scrape configurations of Observability instance "xxx" in JSON format`, + "$ stackit observability scrape-config list --instance-id xxx --output-format json"), examples.NewExample( - `List up to 10 scrape configurations of Argus instance "xxx"`, - "$ stackit argus scrape-config list --instance-id xxx --limit 10"), + `List up to 10 scrape configurations of Observability instance "xxx"`, + "$ stackit observability scrape-config list --instance-id xxx --limit 10"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -70,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } configs := *resp.Data if len(configs) == 0 { - instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -121,12 +121,12 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiListScrapeConfigsRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiListScrapeConfigsRequest { req := apiClient.ListScrapeConfigs(ctx, model.InstanceId, model.ProjectId) return req } -func outputResult(p *print.Printer, outputFormat string, configs []argus.Job) error { +func outputResult(p *print.Printer, outputFormat string, configs []observability.Job) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(configs, "", " ") diff --git a/internal/cmd/argus/scrape-config/list/list_test.go b/internal/cmd/observability/scrape-config/list/list_test.go similarity index 94% rename from internal/cmd/argus/scrape-config/list/list_test.go rename to internal/cmd/observability/scrape-config/list/list_test.go index a62605da2..86836fc84 100644 --- a/internal/cmd/argus/scrape-config/list/list_test.go +++ b/internal/cmd/observability/scrape-config/list/list_test.go @@ -11,7 +11,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -19,7 +19,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() @@ -50,7 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiListScrapeConfigsRequest)) argus.ApiListScrapeConfigsRequest { +func fixtureRequest(mods ...func(request *observability.ApiListScrapeConfigsRequest)) observability.ApiListScrapeConfigsRequest { request := testClient.ListScrapeConfigs(testCtx, testInstanceId, testProjectId) for _, mod := range mods { mod(&request) @@ -185,7 +185,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiListScrapeConfigsRequest + expectedRequest observability.ApiListScrapeConfigsRequest }{ { description: "base", diff --git a/internal/cmd/argus/scrape-config/scrape_config.go b/internal/cmd/observability/scrape-config/scrape_config.go similarity index 54% rename from internal/cmd/argus/scrape-config/scrape_config.go rename to internal/cmd/observability/scrape-config/scrape_config.go index 781569aa9..f056c6e60 100644 --- a/internal/cmd/argus/scrape-config/scrape_config.go +++ b/internal/cmd/observability/scrape-config/scrape_config.go @@ -1,12 +1,12 @@ package scrapeconfig import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/scrape-config/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/scrape-config/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/scrape-config/describe" - generatepayload "github.com/stackitcloud/stackit-cli/internal/cmd/argus/scrape-config/generate-payload" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/scrape-config/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus/scrape-config/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/describe" + generatepayload "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/generate-payload" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -17,8 +17,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "scrape-config", - Short: "Provides functionality for scrape configurations in Argus", - Long: "Provides functionality for scrape configurations in Argus.", + Short: "Provides functionality for scrape configurations in Observability", + Long: "Provides functionality for scrape configurations in Observability.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/cmd/argus/scrape-config/update/update.go b/internal/cmd/observability/scrape-config/update/update.go similarity index 73% rename from internal/cmd/argus/scrape-config/update/update.go rename to internal/cmd/observability/scrape-config/update/update.go index ef92943ce..d07e97e1b 100644 --- a/internal/cmd/argus/scrape-config/update/update.go +++ b/internal/cmd/observability/scrape-config/update/update.go @@ -11,10 +11,10 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( @@ -28,31 +28,31 @@ type inputModel struct { *globalflags.GlobalFlagModel JobName string InstanceId string - Payload argus.UpdateScrapeConfigPayload + Payload observability.UpdateScrapeConfigPayload } func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", jobNameArg), - Short: "Updates a scrape configuration of an Argus instance", + Short: "Updates a scrape configuration of an Observability instance", Long: fmt.Sprintf("%s\n%s\n%s", - "Updates a scrape configuration of an Argus instance.", + "Updates a scrape configuration of an Observability instance.", "The payload can be provided as a JSON string or a file path prefixed with \"@\".", "See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_update for information regarding the payload structure.", ), Args: args.SingleArg(jobNameArg, nil), Example: examples.Build( examples.NewExample( - `Update a scrape configuration with name "my-config" from Argus instance "xxx", using an API payload sourced from the file "./payload.json"`, - "$ stackit argus scrape-config update my-config --payload @./payload.json --instance-id xxx"), + `Update a scrape configuration with name "my-config" from Observability instance "xxx", using an API payload sourced from the file "./payload.json"`, + "$ stackit observability scrape-config update my-config --payload @./payload.json --instance-id xxx"), examples.NewExample( - `Update an scrape configuration with name "my-config" from Argus instance "xxx", using an API payload provided as a JSON string`, - `$ stackit argus scrape-config update my-config --payload "{...}" --instance-id xxx`), + `Update an scrape configuration with name "my-config" from Observability instance "xxx", using an API payload provided as a JSON string`, + `$ stackit observability scrape-config update my-config --payload "{...}" --instance-id xxx`), examples.NewExample( `Generate a payload with the current values of a scrape configuration, and adapt it with custom values for the different configuration options`, - `$ stackit argus scrape-config generate-payload --job-name my-config > ./payload.json`, + `$ stackit observability scrape-config generate-payload --job-name my-config > ./payload.json`, ``, - `$ stackit argus scrape-configs update my-config --payload @./payload.json`), + `$ stackit observability scrape-configs update my-config --payload @./payload.json`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -83,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // The API has no status to wait on, so async mode is default - p.Info("Updated Argus scrape configuration with name %q\n", model.JobName) + p.Info("Updated Observability scrape configuration with name %q\n", model.JobName) return nil }, } @@ -108,7 +108,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } payloadString := flags.FlagToStringValue(p, cmd, payloadFlag) - var payload argus.UpdateScrapeConfigPayload + var payload observability.UpdateScrapeConfigPayload err := json.Unmarshal([]byte(payloadString), &payload) if err != nil { return nil, fmt.Errorf("encode payload: %w", err) @@ -122,7 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiUpdateScrapeConfigRequest { +func buildRequest(ctx context.Context, model *inputModel, apiClient *observability.APIClient) observability.ApiUpdateScrapeConfigRequest { req := apiClient.UpdateScrapeConfig(ctx, model.InstanceId, model.JobName, model.ProjectId) req = req.UpdateScrapeConfigPayload(model.Payload) diff --git a/internal/cmd/argus/scrape-config/update/update_test.go b/internal/cmd/observability/scrape-config/update/update_test.go similarity index 93% rename from internal/cmd/argus/scrape-config/update/update_test.go rename to internal/cmd/observability/scrape-config/update/update_test.go index 232d798c5..ad5870231 100644 --- a/internal/cmd/argus/scrape-config/update/update_test.go +++ b/internal/cmd/observability/scrape-config/update/update_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -18,13 +18,13 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &argus.APIClient{} +var testClient = &observability.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testJobName = "my-config" -var testPayload = argus.UpdateScrapeConfigPayload{ - BasicAuth: &argus.CreateScrapeConfigPayloadBasicAuth{ +var testPayload = observability.UpdateScrapeConfigPayload{ + BasicAuth: &observability.CreateScrapeConfigPayloadBasicAuth{ Username: utils.Ptr("username"), Password: utils.Ptr("password"), }, @@ -32,7 +32,7 @@ var testPayload = argus.UpdateScrapeConfigPayload{ HonorLabels: utils.Ptr(true), HonorTimeStamps: utils.Ptr(true), MetricsPath: utils.Ptr("/metrics"), - MetricsRelabelConfigs: &[]argus.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ + MetricsRelabelConfigs: &[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ { Action: utils.Ptr("replace"), Modulus: utils.Ptr(1.0), @@ -111,7 +111,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *argus.ApiUpdateScrapeConfigRequest)) argus.ApiUpdateScrapeConfigRequest { +func fixtureRequest(mods ...func(request *observability.ApiUpdateScrapeConfigRequest)) observability.ApiUpdateScrapeConfigRequest { request := testClient.UpdateScrapeConfig(testCtx, testInstanceId, testJobName, testProjectId) request = request.UpdateScrapeConfigPayload(testPayload) for _, mod := range mods { @@ -274,7 +274,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest argus.ApiUpdateScrapeConfigRequest + expectedRequest observability.ApiUpdateScrapeConfigRequest isValid bool }{ { diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 97384911f..e1385befb 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -6,7 +6,6 @@ import ( "strings" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/argus" "github.com/stackitcloud/stackit-cli/internal/cmd/auth" "github.com/stackitcloud/stackit-cli/internal/cmd/beta" configCmd "github.com/stackitcloud/stackit-cli/internal/cmd/config" @@ -17,6 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex" objectstorage "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch" "github.com/stackitcloud/stackit-cli/internal/cmd/organization" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex" @@ -144,7 +144,6 @@ func configureFlags(cmd *cobra.Command) error { } func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(argus.NewCmd(p)) cmd.AddCommand(auth.NewCmd(p)) cmd.AddCommand(configCmd.NewCmd(p)) cmd.AddCommand(beta.NewCmd(p)) @@ -155,6 +154,7 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(mariadb.NewCmd(p)) cmd.AddCommand(mongodbflex.NewCmd(p)) cmd.AddCommand(objectstorage.NewCmd(p)) + cmd.AddCommand(observability.NewCmd(p)) cmd.AddCommand(opensearch.NewCmd(p)) cmd.AddCommand(organization.NewCmd(p)) cmd.AddCommand(postgresflex.NewCmd(p)) diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 6ca8db9c9..8132254a4 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -21,7 +21,6 @@ const ( IdentityProviderCustomClientIdKey = "identity_provider_custom_client_id" AllowedUrlDomainKey = "allowed_url_domain" - ArgusCustomEndpointKey = "argus_custom_endpoint" AuthorizationCustomEndpointKey = "authorization_custom_endpoint" DNSCustomEndpointKey = "dns_custom_endpoint" LoadBalancerCustomEndpointKey = "load_balancer_custom_endpoint" @@ -29,6 +28,7 @@ const ( MariaDBCustomEndpointKey = "mariadb_custom_endpoint" MongoDBFlexCustomEndpointKey = "mongodbflex_custom_endpoint" ObjectStorageCustomEndpointKey = "object_storage_custom_endpoint" + ObservabilityCustomEndpointKey = "observability_custom_endpoint" OpenSearchCustomEndpointKey = "opensearch_custom_endpoint" PostgresFlexCustomEndpointKey = "postgresflex_custom_endpoint" RabbitMQCustomEndpointKey = "rabbitmq_custom_endpoint" @@ -84,7 +84,7 @@ var ConfigKeys = []string{ OpenSearchCustomEndpointKey, PostgresFlexCustomEndpointKey, ResourceManagerEndpointKey, - ArgusCustomEndpointKey, + ObservabilityCustomEndpointKey, AuthorizationCustomEndpointKey, MongoDBFlexCustomEndpointKey, RabbitMQCustomEndpointKey, @@ -161,7 +161,7 @@ func setConfigDefaults() { viper.SetDefault(IdentityProviderCustomClientIdKey, "") viper.SetDefault(AllowedUrlDomainKey, AllowedUrlDomainDefault) viper.SetDefault(DNSCustomEndpointKey, "") - viper.SetDefault(ArgusCustomEndpointKey, "") + viper.SetDefault(ObservabilityCustomEndpointKey, "") viper.SetDefault(AuthorizationCustomEndpointKey, "") viper.SetDefault(MongoDBFlexCustomEndpointKey, "") viper.SetDefault(ObjectStorageCustomEndpointKey, "") diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index 463fcf533..92af7ab83 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -50,7 +50,7 @@ To list all profiles, run: DELETE_DEFAULT_PROFILE = `the default configuration profile %q cannot be deleted.` - ARGUS_INVALID_INPUT_PLAN = `the instance plan was not correctly provided. + OBSERVABILITY_INVALID_INPUT_PLAN = `the instance plan was not correctly provided. Either provide the plan ID: $ %[1]s --plan-id [flags] @@ -61,7 +61,7 @@ or provide plan name: For more details on the available plans, run: $ stackit %[2]s plans` - ARGUS_INVALID_PLAN = `the provided instance plan is not valid. + OBSERVABILITY_INVALID_PLAN = `the provided instance plan is not valid. %s @@ -188,12 +188,12 @@ func (e *DeleteDefaultProfile) Error() string { return fmt.Sprintf(DELETE_DEFAULT_PROFILE, e.DefaultProfile) } -type ArgusInputPlanError struct { +type ObservabilityInputPlanError struct { Cmd *cobra.Command Args []string } -func (e *ArgusInputPlanError) Error() string { +func (e *ObservabilityInputPlanError) Error() string { fullCommandPath := e.Cmd.CommandPath() if len(e.Args) > 0 { fullCommandPath = fmt.Sprintf("%s %s", fullCommandPath, strings.Join(e.Args, " ")) @@ -201,16 +201,16 @@ func (e *ArgusInputPlanError) Error() string { // Assumes a structure of the form "stackit " service := e.Cmd.Parent().Parent().Use - return fmt.Sprintf(ARGUS_INVALID_INPUT_PLAN, fullCommandPath, service) + return fmt.Sprintf(OBSERVABILITY_INVALID_INPUT_PLAN, fullCommandPath, service) } -type ArgusInvalidPlanError struct { +type ObservabilityInvalidPlanError struct { Service string Details string } -func (e *ArgusInvalidPlanError) Error() string { - return fmt.Sprintf(ARGUS_INVALID_PLAN, e.Details, e.Service) +func (e *ObservabilityInvalidPlanError) Error() string { + return fmt.Sprintf(OBSERVABILITY_INVALID_PLAN, e.Details, e.Service) } type DSAInputPlanError struct { diff --git a/internal/pkg/errors/errors_test.go b/internal/pkg/errors/errors_test.go index 67c37b775..d2942e87f 100644 --- a/internal/pkg/errors/errors_test.go +++ b/internal/pkg/errors/errors_test.go @@ -90,7 +90,7 @@ func TestSimpleErrors(t *testing.T) { } } -func TestArgusInputPlanError(t *testing.T) { +func TestObservabilityInputPlanError(t *testing.T) { tests := []struct { description string args []string @@ -99,19 +99,19 @@ func TestArgusInputPlanError(t *testing.T) { { description: "base", args: []string{"arg1", "arg2"}, - expectedMsg: fmt.Sprintf(ARGUS_INVALID_INPUT_PLAN, "stackit service resource operation arg1 arg2", "service"), + expectedMsg: fmt.Sprintf(OBSERVABILITY_INVALID_INPUT_PLAN, "stackit service resource operation arg1 arg2", "service"), }, { description: "no args", args: []string{}, - expectedMsg: fmt.Sprintf(ARGUS_INVALID_INPUT_PLAN, "stackit service resource operation", "service"), + expectedMsg: fmt.Sprintf(OBSERVABILITY_INVALID_INPUT_PLAN, "stackit service resource operation", "service"), }, } setupCmd() for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - err := &ArgusInputPlanError{ + err := &ObservabilityInputPlanError{ Cmd: operation, Args: tt.args, } @@ -149,7 +149,7 @@ func TestSetInexistentProfile(t *testing.T) { } } -func TestArgusInvalidPlanError(t *testing.T) { +func TestObservabilityInvalidPlanError(t *testing.T) { tests := []struct { description string details string @@ -160,25 +160,25 @@ func TestArgusInvalidPlanError(t *testing.T) { description: "base", details: "details", service: "service", - expectedMsg: fmt.Sprintf(ARGUS_INVALID_PLAN, "details", "service"), + expectedMsg: fmt.Sprintf(OBSERVABILITY_INVALID_PLAN, "details", "service"), }, { description: "no details", details: "", service: "service", - expectedMsg: fmt.Sprintf(ARGUS_INVALID_PLAN, "", "service"), + expectedMsg: fmt.Sprintf(OBSERVABILITY_INVALID_PLAN, "", "service"), }, { description: "no service", details: "details", service: "", - expectedMsg: fmt.Sprintf(ARGUS_INVALID_PLAN, "details", ""), + expectedMsg: fmt.Sprintf(OBSERVABILITY_INVALID_PLAN, "details", ""), }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - err := &ArgusInvalidPlanError{ + err := &ObservabilityInvalidPlanError{ Service: tt.service, Details: tt.details, } diff --git a/internal/pkg/services/argus/client/client.go b/internal/pkg/services/observability/client/client.go similarity index 77% rename from internal/pkg/services/argus/client/client.go rename to internal/pkg/services/observability/client/client.go index c2f3a11da..a2af05d56 100644 --- a/internal/pkg/services/argus/client/client.go +++ b/internal/pkg/services/observability/client/client.go @@ -5,15 +5,15 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/observability" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" - "github.com/stackitcloud/stackit-sdk-go/services/argus" ) -func ConfigureClient(p *print.Printer) (*argus.APIClient, error) { +func ConfigureClient(p *print.Printer) (*observability.APIClient, error) { var err error - var apiClient *argus.APIClient + var apiClient *observability.APIClient var cfgOptions []sdkConfig.ConfigurationOption authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) @@ -23,7 +23,7 @@ func ConfigureClient(p *print.Printer) (*argus.APIClient, error) { } cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) - customEndpoint := viper.GetString(config.ArgusCustomEndpointKey) + customEndpoint := viper.GetString(config.ObservabilityCustomEndpointKey) if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) @@ -35,7 +35,7 @@ func ConfigureClient(p *print.Printer) (*argus.APIClient, error) { ) } - apiClient, err = argus.NewAPIClient(cfgOptions...) + apiClient, err = observability.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/argus/utils/utils.go b/internal/pkg/services/observability/utils/utils.go similarity index 65% rename from internal/pkg/services/argus/utils/utils.go rename to internal/pkg/services/observability/utils/utils.go index 556c3b7d2..fef48457e 100644 --- a/internal/pkg/services/argus/utils/utils.go +++ b/internal/pkg/services/observability/utils/utils.go @@ -7,29 +7,28 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) const ( - service = "argus" + service = "observability" ) -type ArgusClient interface { - GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error) - GetGrafanaConfigsExecute(ctx context.Context, instanceId, projectId string) (*argus.GrafanaConfigs, error) - UpdateGrafanaConfigs(ctx context.Context, instanceId string, projectId string) argus.ApiUpdateGrafanaConfigsRequest +type ObservabilityClient interface { + GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*observability.GetInstanceResponse, error) + GetGrafanaConfigsExecute(ctx context.Context, instanceId, projectId string) (*observability.GrafanaConfigs, error) + UpdateGrafanaConfigs(ctx context.Context, instanceId string, projectId string) observability.ApiUpdateGrafanaConfigsRequest } var ( - defaultStaticConfigs = []argus.CreateScrapeConfigPayloadStaticConfigsInner{ + defaultStaticConfigs = []observability.CreateScrapeConfigPayloadStaticConfigsInner{ { Targets: utils.Ptr([]string{ "url-target", }), }, } - DefaultCreateScrapeConfigPayload = argus.CreateScrapeConfigPayload{ + DefaultCreateScrapeConfigPayload = observability.CreateScrapeConfigPayload{ JobName: utils.Ptr("default-name"), MetricsPath: utils.Ptr("/metrics"), Scheme: utils.Ptr("https"), @@ -39,9 +38,9 @@ var ( } ) -func ValidatePlanId(planId string, resp *argus.PlansResponse) error { +func ValidatePlanId(planId string, resp *observability.PlansResponse) error { if resp == nil { - return fmt.Errorf("no Argus plans provided") + return fmt.Errorf("no Observability plans provided") } for i := range *resp.Plans { @@ -51,16 +50,16 @@ func ValidatePlanId(planId string, resp *argus.PlansResponse) error { } } - return &errors.ArgusInvalidPlanError{ + return &errors.ObservabilityInvalidPlanError{ Service: service, Details: fmt.Sprintf("You provided plan ID %q, which is invalid.", planId), } } -func LoadPlanId(planName string, resp *argus.PlansResponse) (*string, error) { +func LoadPlanId(planName string, resp *observability.PlansResponse) (*string, error) { availablePlanNames := "" if resp == nil { - return nil, fmt.Errorf("no Argus plans provided") + return nil, fmt.Errorf("no Observability plans provided") } for i := range *resp.Plans { @@ -75,15 +74,15 @@ func LoadPlanId(planName string, resp *argus.PlansResponse) (*string, error) { } details := fmt.Sprintf("You provided plan name %q, which is invalid. Available plan names are: %s", planName, availablePlanNames) - return nil, &errors.ArgusInvalidPlanError{ + return nil, &errors.ObservabilityInvalidPlanError{ Service: service, Details: details, } } -func MapToUpdateScrapeConfigPayload(resp *argus.GetScrapeConfigResponse) (*argus.UpdateScrapeConfigPayload, error) { +func MapToUpdateScrapeConfigPayload(resp *observability.GetScrapeConfigResponse) (*observability.UpdateScrapeConfigPayload, error) { if resp == nil || resp.Data == nil { - return nil, fmt.Errorf("no Argus scrape config provided") + return nil, fmt.Errorf("no Observability scrape config provided") } data := resp.Data @@ -98,7 +97,7 @@ func MapToUpdateScrapeConfigPayload(resp *argus.GetScrapeConfigResponse) (*argus params = utils.Ptr(mapParams(*data.Params)) } - payload := argus.UpdateScrapeConfigPayload{ + payload := observability.UpdateScrapeConfigPayload{ BasicAuth: basicAuth, BearerToken: data.BearerToken, HonorLabels: data.HonorLabels, @@ -114,20 +113,20 @@ func MapToUpdateScrapeConfigPayload(resp *argus.GetScrapeConfigResponse) (*argus TlsConfig: tlsConfig, } - if payload == (argus.UpdateScrapeConfigPayload{}) { - return nil, fmt.Errorf("the provided Argus scrape config payload is empty") + if payload == (observability.UpdateScrapeConfigPayload{}) { + return nil, fmt.Errorf("the provided Observability scrape config payload is empty") } return &payload, nil } -func mapMetricsRelabelConfig(metricsRelabelConfigs *[]argus.MetricsRelabelConfig) *[]argus.CreateScrapeConfigPayloadMetricsRelabelConfigsInner { +func mapMetricsRelabelConfig(metricsRelabelConfigs *[]observability.MetricsRelabelConfig) *[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner { if metricsRelabelConfigs == nil { return nil } - var mappedConfigs []argus.CreateScrapeConfigPayloadMetricsRelabelConfigsInner + var mappedConfigs []observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner for _, config := range *metricsRelabelConfigs { - mappedConfig := argus.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ + mappedConfig := observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ Action: config.Action, Modulus: utils.ConvertInt64PToFloat64P(config.Modulus), Regex: config.Regex, @@ -141,17 +140,17 @@ func mapMetricsRelabelConfig(metricsRelabelConfigs *[]argus.MetricsRelabelConfig return &mappedConfigs } -func mapStaticConfig(staticConfigs *[]argus.StaticConfigs) *[]argus.UpdateScrapeConfigPayloadStaticConfigsInner { +func mapStaticConfig(staticConfigs *[]observability.StaticConfigs) *[]observability.UpdateScrapeConfigPayloadStaticConfigsInner { if staticConfigs == nil { return nil } - var mappedConfigs []argus.UpdateScrapeConfigPayloadStaticConfigsInner + var mappedConfigs []observability.UpdateScrapeConfigPayloadStaticConfigsInner for _, config := range *staticConfigs { var labels *map[string]interface{} if config.Labels != nil { labels = utils.Ptr(mapStaticConfigLabels(*config.Labels)) } - mappedConfig := argus.UpdateScrapeConfigPayloadStaticConfigsInner{ + mappedConfig := observability.UpdateScrapeConfigPayloadStaticConfigsInner{ Labels: labels, Targets: config.Targets, } @@ -161,23 +160,23 @@ func mapStaticConfig(staticConfigs *[]argus.StaticConfigs) *[]argus.UpdateScrape return &mappedConfigs } -func mapBasicAuth(basicAuth *argus.BasicAuth) *argus.CreateScrapeConfigPayloadBasicAuth { +func mapBasicAuth(basicAuth *observability.BasicAuth) *observability.CreateScrapeConfigPayloadBasicAuth { if basicAuth == nil { return nil } - return &argus.CreateScrapeConfigPayloadBasicAuth{ + return &observability.CreateScrapeConfigPayloadBasicAuth{ Password: basicAuth.Password, Username: basicAuth.Username, } } -func mapTlsConfig(tlsConfig *argus.TLSConfig) *argus.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig { +func mapTlsConfig(tlsConfig *observability.TLSConfig) *observability.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig { if tlsConfig == nil { return nil } - return &argus.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{ + return &observability.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{ InsecureSkipVerify: tlsConfig.InsecureSkipVerify, } } @@ -198,19 +197,19 @@ func mapStaticConfigLabels(labels map[string]string) map[string]interface{} { return labelsMap } -func GetInstanceName(ctx context.Context, apiClient ArgusClient, instanceId, projectId string) (string, error) { +func GetInstanceName(ctx context.Context, apiClient ObservabilityClient, instanceId, projectId string) (string, error) { resp, err := apiClient.GetInstanceExecute(ctx, instanceId, projectId) if err != nil { - return "", fmt.Errorf("get Argus instance: %w", err) + return "", fmt.Errorf("get Observability instance: %w", err) } return *resp.Name, nil } -func ToPayloadGenericOAuth(respOAuth *argus.GrafanaOauth) *argus.UpdateGrafanaConfigsPayloadGenericOauth { +func ToPayloadGenericOAuth(respOAuth *observability.GrafanaOauth) *observability.UpdateGrafanaConfigsPayloadGenericOauth { if respOAuth == nil { return nil } - return &argus.UpdateGrafanaConfigsPayloadGenericOauth{ + return &observability.UpdateGrafanaConfigsPayloadGenericOauth{ ApiUrl: respOAuth.ApiUrl, AuthUrl: respOAuth.AuthUrl, Enabled: respOAuth.Enabled, @@ -225,7 +224,7 @@ func ToPayloadGenericOAuth(respOAuth *argus.GrafanaOauth) *argus.UpdateGrafanaCo } } -func GetPartialUpdateGrafanaConfigsPayload(ctx context.Context, apiClient ArgusClient, instanceId, projectId string, singleSignOn, publicReadAccess *bool) (*argus.UpdateGrafanaConfigsPayload, error) { +func GetPartialUpdateGrafanaConfigsPayload(ctx context.Context, apiClient ObservabilityClient, instanceId, projectId string, singleSignOn, publicReadAccess *bool) (*observability.UpdateGrafanaConfigsPayload, error) { currentConfigs, err := apiClient.GetGrafanaConfigsExecute(ctx, instanceId, projectId) if err != nil { return nil, fmt.Errorf("get current Grafana configs: %w", err) @@ -234,7 +233,7 @@ func GetPartialUpdateGrafanaConfigsPayload(ctx context.Context, apiClient ArgusC return nil, fmt.Errorf("no Grafana configs found for instance %q", instanceId) } - payload := &argus.UpdateGrafanaConfigsPayload{ + payload := &observability.UpdateGrafanaConfigsPayload{ GenericOauth: ToPayloadGenericOAuth(currentConfigs.GenericOauth), PublicReadAccess: currentConfigs.PublicReadAccess, UseStackitSso: currentConfigs.UseStackitSso, diff --git a/internal/pkg/services/argus/utils/utils_test.go b/internal/pkg/services/observability/utils/utils_test.go similarity index 79% rename from internal/pkg/services/argus/utils/utils_test.go rename to internal/pkg/services/observability/utils/utils_test.go index d36c572f3..36484e547 100644 --- a/internal/pkg/services/argus/utils/utils_test.go +++ b/internal/pkg/services/observability/utils/utils_test.go @@ -10,11 +10,11 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/argus" + "github.com/stackitcloud/stackit-sdk-go/services/observability" ) var ( - testClient = &argus.APIClient{} + testClient = &observability.APIClient{} testProjectId = uuid.NewString() testInstanceId = uuid.NewString() testPlanId = uuid.NewString() @@ -25,8 +25,8 @@ const ( testPlanName = "Plan-Name-01" ) -var testPlansResponse = argus.PlansResponse{ - Plans: &[]argus.Plan{ +var testPlansResponse = observability.PlansResponse{ + Plans: &[]observability.Plan{ { Id: utils.Ptr(testPlanId), Name: utils.Ptr(testPlanName), @@ -34,11 +34,11 @@ var testPlansResponse = argus.PlansResponse{ }, } -func fixtureGetScrapeConfigResponse(mods ...func(*argus.GetScrapeConfigResponse)) *argus.GetScrapeConfigResponse { +func fixtureGetScrapeConfigResponse(mods ...func(*observability.GetScrapeConfigResponse)) *observability.GetScrapeConfigResponse { number := int64(1) - resp := &argus.GetScrapeConfigResponse{ - Data: &argus.Job{ - BasicAuth: &argus.BasicAuth{ + resp := &observability.GetScrapeConfigResponse{ + Data: &observability.Job{ + BasicAuth: &observability.BasicAuth{ Username: utils.Ptr("username"), Password: utils.Ptr("password"), }, @@ -46,7 +46,7 @@ func fixtureGetScrapeConfigResponse(mods ...func(*argus.GetScrapeConfigResponse) HonorLabels: utils.Ptr(true), HonorTimeStamps: utils.Ptr(true), MetricsPath: utils.Ptr("/metrics"), - MetricsRelabelConfigs: &[]argus.MetricsRelabelConfig{ + MetricsRelabelConfigs: &[]observability.MetricsRelabelConfig{ { Action: utils.Ptr("replace"), Modulus: &number, @@ -65,7 +65,7 @@ func fixtureGetScrapeConfigResponse(mods ...func(*argus.GetScrapeConfigResponse) Scheme: utils.Ptr("scheme"), ScrapeInterval: utils.Ptr("interval"), ScrapeTimeout: utils.Ptr("timeout"), - StaticConfigs: &[]argus.StaticConfigs{ + StaticConfigs: &[]observability.StaticConfigs{ { Labels: &map[string]string{ "label": "value", @@ -74,7 +74,7 @@ func fixtureGetScrapeConfigResponse(mods ...func(*argus.GetScrapeConfigResponse) Targets: &[]string{"target"}, }, }, - TlsConfig: &argus.TLSConfig{ + TlsConfig: &observability.TLSConfig{ InsecureSkipVerify: utils.Ptr(true), }, }, @@ -87,9 +87,9 @@ func fixtureGetScrapeConfigResponse(mods ...func(*argus.GetScrapeConfigResponse) return resp } -func fixtureUpdateScrapeConfigPayload(mods ...func(*argus.UpdateScrapeConfigPayload)) *argus.UpdateScrapeConfigPayload { - payload := &argus.UpdateScrapeConfigPayload{ - BasicAuth: &argus.CreateScrapeConfigPayloadBasicAuth{ +func fixtureUpdateScrapeConfigPayload(mods ...func(*observability.UpdateScrapeConfigPayload)) *observability.UpdateScrapeConfigPayload { + payload := &observability.UpdateScrapeConfigPayload{ + BasicAuth: &observability.CreateScrapeConfigPayloadBasicAuth{ Username: utils.Ptr("username"), Password: utils.Ptr("password"), }, @@ -97,7 +97,7 @@ func fixtureUpdateScrapeConfigPayload(mods ...func(*argus.UpdateScrapeConfigPayl HonorLabels: utils.Ptr(true), HonorTimeStamps: utils.Ptr(true), MetricsPath: utils.Ptr("/metrics"), - MetricsRelabelConfigs: &[]argus.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ + MetricsRelabelConfigs: &[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ { Action: utils.Ptr("replace"), Modulus: utils.Ptr(1.0), @@ -116,7 +116,7 @@ func fixtureUpdateScrapeConfigPayload(mods ...func(*argus.UpdateScrapeConfigPayl Scheme: utils.Ptr("scheme"), ScrapeInterval: utils.Ptr("interval"), ScrapeTimeout: utils.Ptr("timeout"), - StaticConfigs: &[]argus.UpdateScrapeConfigPayloadStaticConfigsInner{ + StaticConfigs: &[]observability.UpdateScrapeConfigPayloadStaticConfigsInner{ { Labels: &map[string]interface{}{ "label": "value", @@ -125,7 +125,7 @@ func fixtureUpdateScrapeConfigPayload(mods ...func(*argus.UpdateScrapeConfigPayl Targets: &[]string{"target"}, }, }, - TlsConfig: &argus.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{ + TlsConfig: &observability.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{ InsecureSkipVerify: utils.Ptr(true), }, } @@ -137,34 +137,34 @@ func fixtureUpdateScrapeConfigPayload(mods ...func(*argus.UpdateScrapeConfigPayl return payload } -type argusClientMocked struct { +type observabilityClientMocked struct { getInstanceFails bool - getInstanceResp *argus.GetInstanceResponse + getInstanceResp *observability.GetInstanceResponse getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs } -func (m *argusClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*argus.GetInstanceResponse, error) { +func (m *observabilityClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*observability.GetInstanceResponse, error) { if m.getInstanceFails { return nil, fmt.Errorf("could not get instance") } return m.getInstanceResp, nil } -func (m *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*argus.GrafanaConfigs, error) { +func (m *observabilityClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*observability.GrafanaConfigs, error) { if m.getGrafanaConfigsFails { return nil, fmt.Errorf("could not get grafana configs") } return m.getGrafanaConfigsResp, nil } -func (c *argusClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) argus.ApiUpdateGrafanaConfigsRequest { +func (c *observabilityClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) observability.ApiUpdateGrafanaConfigsRequest { return testClient.UpdateGrafanaConfigs(ctx, instanceId, projectId) } -func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.GrafanaConfigs { - gc := argus.GrafanaConfigs{ - GenericOauth: &argus.GrafanaOauth{ +func fixtureGrafanaConfigs(mods ...func(gc *observability.GrafanaConfigs)) *observability.GrafanaConfigs { + gc := observability.GrafanaConfigs{ + GenericOauth: &observability.GrafanaOauth{ ApiUrl: utils.Ptr("apiUrl"), AuthUrl: utils.Ptr("authUrl"), Enabled: utils.Ptr(true), @@ -190,13 +190,13 @@ func TestGetInstanceName(t *testing.T) { tests := []struct { description string getInstanceFails bool - getInstanceResp *argus.GetInstanceResponse + getInstanceResp *observability.GetInstanceResponse isValid bool expectedOutput string }{ { description: "base", - getInstanceResp: &argus.GetInstanceResponse{ + getInstanceResp: &observability.GetInstanceResponse{ Name: utils.Ptr(testInstanceName), }, isValid: true, @@ -211,7 +211,7 @@ func TestGetInstanceName(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &argusClientMocked{ + client := &observabilityClientMocked{ getInstanceFails: tt.getInstanceFails, getInstanceResp: tt.getInstanceResp, } @@ -238,7 +238,7 @@ func TestLoadPlanId(t *testing.T) { tests := []struct { description string planName string - plansResponse *argus.PlansResponse + plansResponse *observability.PlansResponse isValid bool expectedOutput string }{ @@ -275,8 +275,8 @@ func TestLoadPlanId(t *testing.T) { { description: "no available plans", planName: testPlanName, - plansResponse: &argus.PlansResponse{ - Plans: &[]argus.Plan{}, + plansResponse: &observability.PlansResponse{ + Plans: &[]observability.Plan{}, }, isValid: false, }, @@ -306,7 +306,7 @@ func TestValidatePlanId(t *testing.T) { tests := []struct { description string planId string - plansResponse *argus.PlansResponse + plansResponse *observability.PlansResponse isValid bool }{ { @@ -340,8 +340,8 @@ func TestValidatePlanId(t *testing.T) { { description: "no available plans", planId: testPlanId, - plansResponse: &argus.PlansResponse{ - Plans: &[]argus.Plan{}, + plansResponse: &observability.PlansResponse{ + Plans: &[]observability.Plan{}, }, isValid: false, }, @@ -367,8 +367,8 @@ func TestValidatePlanId(t *testing.T) { func TestMapToUpdateScrapeConfigPayload(t *testing.T) { tests := []struct { description string - resp *argus.GetScrapeConfigResponse - expectedPayload *argus.UpdateScrapeConfigPayload + resp *observability.GetScrapeConfigResponse + expectedPayload *observability.UpdateScrapeConfigPayload isValid bool }{ { @@ -384,15 +384,15 @@ func TestMapToUpdateScrapeConfigPayload(t *testing.T) { }, { description: "nil data", - resp: &argus.GetScrapeConfigResponse{ + resp: &observability.GetScrapeConfigResponse{ Data: nil, }, isValid: false, }, { description: "empty data", - resp: &argus.GetScrapeConfigResponse{ - Data: &argus.Job{}, + resp: &observability.GetScrapeConfigResponse{ + Data: &observability.Job{}, }, isValid: false, }, @@ -425,12 +425,12 @@ func TestMapToUpdateScrapeConfigPayload(t *testing.T) { func TestMapMetricsRelabelConfig(t *testing.T) { tests := []struct { description string - config *[]argus.MetricsRelabelConfig - expected *[]argus.CreateScrapeConfigPayloadMetricsRelabelConfigsInner + config *[]observability.MetricsRelabelConfig + expected *[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner }{ { description: "base case", - config: &[]argus.MetricsRelabelConfig{ + config: &[]observability.MetricsRelabelConfig{ { Action: utils.Ptr("replace"), Modulus: utils.Int64Ptr(1), @@ -441,7 +441,7 @@ func TestMapMetricsRelabelConfig(t *testing.T) { TargetLabel: utils.Ptr("targetLabel"), }, }, - expected: &[]argus.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ + expected: &[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ { Action: utils.Ptr("replace"), Modulus: utils.Float64Ptr(1.0), @@ -455,7 +455,7 @@ func TestMapMetricsRelabelConfig(t *testing.T) { }, { description: "empty data", - config: &[]argus.MetricsRelabelConfig{}, + config: &[]observability.MetricsRelabelConfig{}, expected: nil, }, { @@ -484,12 +484,12 @@ func TestMapMetricsRelabelConfig(t *testing.T) { func TestMapStaticConfig(t *testing.T) { tests := []struct { description string - config *[]argus.StaticConfigs - expected *[]argus.UpdateScrapeConfigPayloadStaticConfigsInner + config *[]observability.StaticConfigs + expected *[]observability.UpdateScrapeConfigPayloadStaticConfigsInner }{ { description: "base case", - config: &[]argus.StaticConfigs{ + config: &[]observability.StaticConfigs{ { Labels: &map[string]string{ "label": "value", @@ -498,7 +498,7 @@ func TestMapStaticConfig(t *testing.T) { Targets: &[]string{"target", "target2"}, }, }, - expected: &[]argus.UpdateScrapeConfigPayloadStaticConfigsInner{ + expected: &[]observability.UpdateScrapeConfigPayloadStaticConfigsInner{ { Labels: utils.Ptr(map[string]interface{}{ "label": "value", @@ -510,7 +510,7 @@ func TestMapStaticConfig(t *testing.T) { }, { description: "empty data", - config: &[]argus.StaticConfigs{}, + config: &[]observability.StaticConfigs{}, expected: nil, }, { @@ -539,24 +539,24 @@ func TestMapStaticConfig(t *testing.T) { func TestMapBasicAuth(t *testing.T) { tests := []struct { description string - auth *argus.BasicAuth - expected *argus.CreateScrapeConfigPayloadBasicAuth + auth *observability.BasicAuth + expected *observability.CreateScrapeConfigPayloadBasicAuth }{ { description: "base case", - auth: &argus.BasicAuth{ + auth: &observability.BasicAuth{ Username: utils.Ptr("username"), Password: utils.Ptr("password"), }, - expected: &argus.CreateScrapeConfigPayloadBasicAuth{ + expected: &observability.CreateScrapeConfigPayloadBasicAuth{ Username: utils.Ptr("username"), Password: utils.Ptr("password"), }, }, { description: "empty data", - auth: &argus.BasicAuth{}, - expected: &argus.CreateScrapeConfigPayloadBasicAuth{}, + auth: &observability.BasicAuth{}, + expected: &observability.CreateScrapeConfigPayloadBasicAuth{}, }, { description: "nil", @@ -584,22 +584,22 @@ func TestMapBasicAuth(t *testing.T) { func TestMapTlsConfig(t *testing.T) { tests := []struct { description string - config *argus.TLSConfig - expected *argus.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig + config *observability.TLSConfig + expected *observability.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig }{ { description: "base case", - config: &argus.TLSConfig{ + config: &observability.TLSConfig{ InsecureSkipVerify: utils.Ptr(true), }, - expected: &argus.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{ + expected: &observability.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{ InsecureSkipVerify: utils.Ptr(true), }, }, { description: "empty data", - config: &argus.TLSConfig{}, - expected: &argus.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{}, + config: &observability.TLSConfig{}, + expected: &observability.CreateScrapeConfigPayloadHttpSdConfigsInnerOauth2TlsConfig{}, }, { description: "nil", @@ -703,12 +703,12 @@ func TestMapStaticConfigLabels(t *testing.T) { func TestToPayloadGenericOAuth(t *testing.T) { tests := []struct { description string - response *argus.GrafanaOauth - expected *argus.UpdateGrafanaConfigsPayloadGenericOauth + response *observability.GrafanaOauth + expected *observability.UpdateGrafanaConfigsPayloadGenericOauth }{ { description: "base", - response: &argus.GrafanaOauth{ + response: &observability.GrafanaOauth{ ApiUrl: utils.Ptr("apiUrl"), AuthUrl: utils.Ptr("authUrl"), Enabled: utils.Ptr(true), @@ -721,7 +721,7 @@ func TestToPayloadGenericOAuth(t *testing.T) { TokenUrl: utils.Ptr("tokenUrl"), UsePkce: utils.Ptr(true), }, - expected: &argus.UpdateGrafanaConfigsPayloadGenericOauth{ + expected: &observability.UpdateGrafanaConfigsPayloadGenericOauth{ ApiUrl: utils.Ptr("apiUrl"), AuthUrl: utils.Ptr("authUrl"), Enabled: utils.Ptr(true), @@ -760,9 +760,9 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { singleSignOn *bool publicReadAccess *bool getGrafanaConfigsFails bool - getGrafanaConfigsResp *argus.GrafanaConfigs + getGrafanaConfigsResp *observability.GrafanaConfigs isValid bool - expectedPayload *argus.UpdateGrafanaConfigsPayload + expectedPayload *observability.UpdateGrafanaConfigsPayload }{ { description: "enable both", @@ -770,7 +770,7 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { publicReadAccess: utils.Ptr(true), getGrafanaConfigsResp: fixtureGrafanaConfigs(), isValid: true, - expectedPayload: &argus.UpdateGrafanaConfigsPayload{ + expectedPayload: &observability.UpdateGrafanaConfigsPayload{ GenericOauth: ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), UseStackitSso: utils.Ptr(true), PublicReadAccess: utils.Ptr(true), @@ -782,7 +782,7 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { publicReadAccess: utils.Ptr(false), getGrafanaConfigsResp: fixtureGrafanaConfigs(), isValid: true, - expectedPayload: &argus.UpdateGrafanaConfigsPayload{ + expectedPayload: &observability.UpdateGrafanaConfigsPayload{ GenericOauth: ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), UseStackitSso: utils.Ptr(false), PublicReadAccess: utils.Ptr(false), @@ -794,7 +794,7 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { publicReadAccess: nil, getGrafanaConfigsResp: fixtureGrafanaConfigs(), isValid: true, - expectedPayload: &argus.UpdateGrafanaConfigsPayload{ + expectedPayload: &observability.UpdateGrafanaConfigsPayload{ GenericOauth: ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), UseStackitSso: utils.Ptr(true), PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess, @@ -806,7 +806,7 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { publicReadAccess: utils.Ptr(true), getGrafanaConfigsResp: fixtureGrafanaConfigs(), isValid: true, - expectedPayload: &argus.UpdateGrafanaConfigsPayload{ + expectedPayload: &observability.UpdateGrafanaConfigsPayload{ GenericOauth: ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), UseStackitSso: fixtureGrafanaConfigs().UseStackitSso, PublicReadAccess: utils.Ptr(true), @@ -816,11 +816,11 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { description: "disable single sign on", singleSignOn: utils.Ptr(false), publicReadAccess: nil, - getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) { + getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *observability.GrafanaConfigs) { gc.UseStackitSso = utils.Ptr(true) }), isValid: true, - expectedPayload: &argus.UpdateGrafanaConfigsPayload{ + expectedPayload: &observability.UpdateGrafanaConfigsPayload{ GenericOauth: ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), UseStackitSso: utils.Ptr(false), PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess, @@ -830,11 +830,11 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { description: "disable public read access", singleSignOn: nil, publicReadAccess: utils.Ptr(false), - getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) { + getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *observability.GrafanaConfigs) { gc.PublicReadAccess = utils.Ptr(true) }), isValid: true, - expectedPayload: &argus.UpdateGrafanaConfigsPayload{ + expectedPayload: &observability.UpdateGrafanaConfigsPayload{ GenericOauth: ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), UseStackitSso: fixtureGrafanaConfigs().UseStackitSso, PublicReadAccess: utils.Ptr(false), @@ -844,9 +844,9 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { description: "nil generic oauth", singleSignOn: utils.Ptr(true), publicReadAccess: utils.Ptr(true), - getGrafanaConfigsResp: &argus.GrafanaConfigs{}, + getGrafanaConfigsResp: &observability.GrafanaConfigs{}, isValid: true, - expectedPayload: &argus.UpdateGrafanaConfigsPayload{ + expectedPayload: &observability.UpdateGrafanaConfigsPayload{ GenericOauth: nil, UseStackitSso: utils.Ptr(true), PublicReadAccess: utils.Ptr(true), @@ -870,7 +870,7 @@ func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &argusClientMocked{ + client := &observabilityClientMocked{ getGrafanaConfigsFails: tt.getGrafanaConfigsFails, getGrafanaConfigsResp: tt.getGrafanaConfigsResp, } From 89b3ed0e909ea966729b22680722ab041221fad1 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:24:41 +0200 Subject: [PATCH 047/619] add observability docs (#456) --- docs/stackit_observability.md | 37 ++++++++++++ docs/stackit_observability_credentials.md | 35 +++++++++++ ...tackit_observability_credentials_create.md | 41 +++++++++++++ ...tackit_observability_credentials_delete.md | 40 +++++++++++++ .../stackit_observability_credentials_list.md | 47 +++++++++++++++ docs/stackit_observability_grafana.md | 35 +++++++++++ .../stackit_observability_grafana_describe.md | 48 +++++++++++++++ ...bservability_grafana_public-read-access.md | 35 +++++++++++ ...lity_grafana_public-read-access_disable.md | 40 +++++++++++++ ...ility_grafana_public-read-access_enable.md | 40 +++++++++++++ ...it_observability_grafana_single-sign-on.md | 35 +++++++++++ ...vability_grafana_single-sign-on_disable.md | 40 +++++++++++++ ...rvability_grafana_single-sign-on_enable.md | 40 +++++++++++++ docs/stackit_observability_instance.md | 37 ++++++++++++ docs/stackit_observability_instance_create.md | 45 ++++++++++++++ docs/stackit_observability_instance_delete.md | 39 +++++++++++++ ...stackit_observability_instance_describe.md | 42 ++++++++++++++ docs/stackit_observability_instance_list.md | 46 +++++++++++++++ docs/stackit_observability_instance_update.md | 48 +++++++++++++++ docs/stackit_observability_plans.md | 46 +++++++++++++++ docs/stackit_observability_scrape-config.md | 38 ++++++++++++ ...ckit_observability_scrape-config_create.md | 55 ++++++++++++++++++ ...ckit_observability_scrape-config_delete.md | 40 +++++++++++++ ...it_observability_scrape-config_describe.md | 43 ++++++++++++++ ...vability_scrape-config_generate-payload.md | 58 +++++++++++++++++++ ...tackit_observability_scrape-config_list.md | 47 +++++++++++++++ ...ckit_observability_scrape-config_update.md | 51 ++++++++++++++++ 27 files changed, 1148 insertions(+) create mode 100644 docs/stackit_observability.md create mode 100644 docs/stackit_observability_credentials.md create mode 100644 docs/stackit_observability_credentials_create.md create mode 100644 docs/stackit_observability_credentials_delete.md create mode 100644 docs/stackit_observability_credentials_list.md create mode 100644 docs/stackit_observability_grafana.md create mode 100644 docs/stackit_observability_grafana_describe.md create mode 100644 docs/stackit_observability_grafana_public-read-access.md create mode 100644 docs/stackit_observability_grafana_public-read-access_disable.md create mode 100644 docs/stackit_observability_grafana_public-read-access_enable.md create mode 100644 docs/stackit_observability_grafana_single-sign-on.md create mode 100644 docs/stackit_observability_grafana_single-sign-on_disable.md create mode 100644 docs/stackit_observability_grafana_single-sign-on_enable.md create mode 100644 docs/stackit_observability_instance.md create mode 100644 docs/stackit_observability_instance_create.md create mode 100644 docs/stackit_observability_instance_delete.md create mode 100644 docs/stackit_observability_instance_describe.md create mode 100644 docs/stackit_observability_instance_list.md create mode 100644 docs/stackit_observability_instance_update.md create mode 100644 docs/stackit_observability_plans.md create mode 100644 docs/stackit_observability_scrape-config.md create mode 100644 docs/stackit_observability_scrape-config_create.md create mode 100644 docs/stackit_observability_scrape-config_delete.md create mode 100644 docs/stackit_observability_scrape-config_describe.md create mode 100644 docs/stackit_observability_scrape-config_generate-payload.md create mode 100644 docs/stackit_observability_scrape-config_list.md create mode 100644 docs/stackit_observability_scrape-config_update.md diff --git a/docs/stackit_observability.md b/docs/stackit_observability.md new file mode 100644 index 000000000..2a4390ed8 --- /dev/null +++ b/docs/stackit_observability.md @@ -0,0 +1,37 @@ +## stackit observability + +Provides functionality for Observability + +### Synopsis + +Provides functionality for Observability. + +``` +stackit observability [flags] +``` + +### Options + +``` + -h, --help Help for "stackit observability" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit observability credentials](./stackit_observability_credentials.md) - Provides functionality for Observability credentials +* [stackit observability grafana](./stackit_observability_grafana.md) - Provides functionality for the Grafana configuration of Observability instances +* [stackit observability instance](./stackit_observability_instance.md) - Provides functionality for Observability instances +* [stackit observability plans](./stackit_observability_plans.md) - Lists all Observability service plans +* [stackit observability scrape-config](./stackit_observability_scrape-config.md) - Provides functionality for scrape configurations in Observability + diff --git a/docs/stackit_observability_credentials.md b/docs/stackit_observability_credentials.md new file mode 100644 index 000000000..0cadd8d0a --- /dev/null +++ b/docs/stackit_observability_credentials.md @@ -0,0 +1,35 @@ +## stackit observability credentials + +Provides functionality for Observability credentials + +### Synopsis + +Provides functionality for Observability credentials. + +``` +stackit observability credentials [flags] +``` + +### Options + +``` + -h, --help Help for "stackit observability credentials" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability](./stackit_observability.md) - Provides functionality for Observability +* [stackit observability credentials create](./stackit_observability_credentials_create.md) - Creates credentials for an Observability instance. +* [stackit observability credentials delete](./stackit_observability_credentials_delete.md) - Deletes credentials of an Observability instance +* [stackit observability credentials list](./stackit_observability_credentials_list.md) - Lists the usernames of all credentials for an Observability instance + diff --git a/docs/stackit_observability_credentials_create.md b/docs/stackit_observability_credentials_create.md new file mode 100644 index 000000000..0967926ff --- /dev/null +++ b/docs/stackit_observability_credentials_create.md @@ -0,0 +1,41 @@ +## stackit observability credentials create + +Creates credentials for an Observability instance. + +### Synopsis + +Creates credentials (username and password) for an Observability instance. +The credentials will be generated and included in the response. You won't be able to retrieve the password later. + +``` +stackit observability credentials create [flags] +``` + +### Examples + +``` + Create credentials for Observability instance with ID "xxx" + $ stackit observability credentials create --instance-id xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability credentials create" + --instance-id string Instance ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability credentials](./stackit_observability_credentials.md) - Provides functionality for Observability credentials + diff --git a/docs/stackit_observability_credentials_delete.md b/docs/stackit_observability_credentials_delete.md new file mode 100644 index 000000000..cc15e7982 --- /dev/null +++ b/docs/stackit_observability_credentials_delete.md @@ -0,0 +1,40 @@ +## stackit observability credentials delete + +Deletes credentials of an Observability instance + +### Synopsis + +Deletes credentials of an Observability instance. + +``` +stackit observability credentials delete USERNAME [flags] +``` + +### Examples + +``` + Delete credentials of username "xxx" for Observability instance with ID "yyy" + $ stackit observability credentials delete xxx --instance-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit observability credentials delete" + --instance-id string Instance ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability credentials](./stackit_observability_credentials.md) - Provides functionality for Observability credentials + diff --git a/docs/stackit_observability_credentials_list.md b/docs/stackit_observability_credentials_list.md new file mode 100644 index 000000000..de0dcb268 --- /dev/null +++ b/docs/stackit_observability_credentials_list.md @@ -0,0 +1,47 @@ +## stackit observability credentials list + +Lists the usernames of all credentials for an Observability instance + +### Synopsis + +Lists the usernames of all credentials for an Observability instance. + +``` +stackit observability credentials list [flags] +``` + +### Examples + +``` + List the usernames of all credentials for an Observability instance with ID "xxx" + $ stackit observability credentials list --instance-id xxx + + List the usernames of all credentials for an Observability instance in JSON format + $ stackit observability credentials list --instance-id xxx --output-format json + + List the usernames of up to 10 credentials for an Observability instance + $ stackit observability credentials list --instance-id xxx --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit observability credentials list" + --instance-id string Instance ID + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability credentials](./stackit_observability_credentials.md) - Provides functionality for Observability credentials + diff --git a/docs/stackit_observability_grafana.md b/docs/stackit_observability_grafana.md new file mode 100644 index 000000000..8b75aa44d --- /dev/null +++ b/docs/stackit_observability_grafana.md @@ -0,0 +1,35 @@ +## stackit observability grafana + +Provides functionality for the Grafana configuration of Observability instances + +### Synopsis + +Provides functionality for the Grafana configuration of Observability instances. + +``` +stackit observability grafana [flags] +``` + +### Options + +``` + -h, --help Help for "stackit observability grafana" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability](./stackit_observability.md) - Provides functionality for Observability +* [stackit observability grafana describe](./stackit_observability_grafana_describe.md) - Shows details of the Grafana configuration of an Observability instance +* [stackit observability grafana public-read-access](./stackit_observability_grafana_public-read-access.md) - Enable or disable public read access for Grafana in Observability instances +* [stackit observability grafana single-sign-on](./stackit_observability_grafana_single-sign-on.md) - Enable or disable single sign-on for Grafana in Observability instances + diff --git a/docs/stackit_observability_grafana_describe.md b/docs/stackit_observability_grafana_describe.md new file mode 100644 index 000000000..1fff9b64e --- /dev/null +++ b/docs/stackit_observability_grafana_describe.md @@ -0,0 +1,48 @@ +## stackit observability grafana describe + +Shows details of the Grafana configuration of an Observability instance + +### Synopsis + +Shows details of the Grafana configuration of an Observability instance. +The Grafana dashboard URL and initial credentials (admin user and password) will be shown in the "pretty" output format. These credentials are only valid for first login. Please change the password after first login. After changing, the initial password is no longer valid. +The initial password is hidden by default, if you want to show it use the "--show-password" flag. + +``` +stackit observability grafana describe INSTANCE_ID [flags] +``` + +### Examples + +``` + Get details of the Grafana configuration of an Observability instance with ID "xxx" + $ stackit observability credentials describe xxx + + Get details of the Grafana configuration of an Observability instance with ID "xxx" and show the initial admin password + $ stackit observability credentials describe xxx --show-password + + Get details of the Grafana configuration of an Observability instance with ID "xxx" in JSON format + $ stackit observability credentials describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit observability grafana describe" + -s, --show-password Show password in output +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability grafana](./stackit_observability_grafana.md) - Provides functionality for the Grafana configuration of Observability instances + diff --git a/docs/stackit_observability_grafana_public-read-access.md b/docs/stackit_observability_grafana_public-read-access.md new file mode 100644 index 000000000..e72c5666f --- /dev/null +++ b/docs/stackit_observability_grafana_public-read-access.md @@ -0,0 +1,35 @@ +## stackit observability grafana public-read-access + +Enable or disable public read access for Grafana in Observability instances + +### Synopsis + +Enable or disable public read access for Grafana in Observability instances. +When enabled, anyone can access the Grafana dashboards of the instance without logging in. Otherwise, a login is required. + +``` +stackit observability grafana public-read-access [flags] +``` + +### Options + +``` + -h, --help Help for "stackit observability grafana public-read-access" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability grafana](./stackit_observability_grafana.md) - Provides functionality for the Grafana configuration of Observability instances +* [stackit observability grafana public-read-access disable](./stackit_observability_grafana_public-read-access_disable.md) - Disables public read access for Grafana on Observability instances +* [stackit observability grafana public-read-access enable](./stackit_observability_grafana_public-read-access_enable.md) - Enables public read access for Grafana on Observability instances + diff --git a/docs/stackit_observability_grafana_public-read-access_disable.md b/docs/stackit_observability_grafana_public-read-access_disable.md new file mode 100644 index 000000000..b05fc0370 --- /dev/null +++ b/docs/stackit_observability_grafana_public-read-access_disable.md @@ -0,0 +1,40 @@ +## stackit observability grafana public-read-access disable + +Disables public read access for Grafana on Observability instances + +### Synopsis + +Disables public read access for Grafana on Observability instances. +When disabled, a login is required to access the Grafana dashboards of the instance. Otherwise, anyone can access the dashboards. + +``` +stackit observability grafana public-read-access disable INSTANCE_ID [flags] +``` + +### Examples + +``` + Disable public read access for Grafana on an Observability instance with ID "xxx" + $ stackit observability grafana public-read-access disable xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability grafana public-read-access disable" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability grafana public-read-access](./stackit_observability_grafana_public-read-access.md) - Enable or disable public read access for Grafana in Observability instances + diff --git a/docs/stackit_observability_grafana_public-read-access_enable.md b/docs/stackit_observability_grafana_public-read-access_enable.md new file mode 100644 index 000000000..0394314b1 --- /dev/null +++ b/docs/stackit_observability_grafana_public-read-access_enable.md @@ -0,0 +1,40 @@ +## stackit observability grafana public-read-access enable + +Enables public read access for Grafana on Observability instances + +### Synopsis + +Enables public read access for Grafana on Observability instances. +When enabled, anyone can access the Grafana dashboards of the instance without logging in. Otherwise, a login is required. + +``` +stackit observability grafana public-read-access enable INSTANCE_ID [flags] +``` + +### Examples + +``` + Enable public read access for Grafana on an Observability instance with ID "xxx" + $ stackit observability grafana public-read-access enable xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability grafana public-read-access enable" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability grafana public-read-access](./stackit_observability_grafana_public-read-access.md) - Enable or disable public read access for Grafana in Observability instances + diff --git a/docs/stackit_observability_grafana_single-sign-on.md b/docs/stackit_observability_grafana_single-sign-on.md new file mode 100644 index 000000000..2e0bb01c6 --- /dev/null +++ b/docs/stackit_observability_grafana_single-sign-on.md @@ -0,0 +1,35 @@ +## stackit observability grafana single-sign-on + +Enable or disable single sign-on for Grafana in Observability instances + +### Synopsis + +Enable or disable single sign-on for Grafana in Observability instances. +When enabled for an instance, overwrites the generic OAuth2 authentication and configures STACKIT single sign-on for that instance. + +``` +stackit observability grafana single-sign-on [flags] +``` + +### Options + +``` + -h, --help Help for "stackit observability grafana single-sign-on" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability grafana](./stackit_observability_grafana.md) - Provides functionality for the Grafana configuration of Observability instances +* [stackit observability grafana single-sign-on disable](./stackit_observability_grafana_single-sign-on_disable.md) - Disables single sign-on for Grafana on Observability instances +* [stackit observability grafana single-sign-on enable](./stackit_observability_grafana_single-sign-on_enable.md) - Enables single sign-on for Grafana on Observability instances + diff --git a/docs/stackit_observability_grafana_single-sign-on_disable.md b/docs/stackit_observability_grafana_single-sign-on_disable.md new file mode 100644 index 000000000..b6d772489 --- /dev/null +++ b/docs/stackit_observability_grafana_single-sign-on_disable.md @@ -0,0 +1,40 @@ +## stackit observability grafana single-sign-on disable + +Disables single sign-on for Grafana on Observability instances + +### Synopsis + +Disables single sign-on for Grafana on Observability instances. +When disabled for an instance, the generic OAuth2 authentication is used for that instance. + +``` +stackit observability grafana single-sign-on disable INSTANCE_ID [flags] +``` + +### Examples + +``` + Disable single sign-on for Grafana on an Observability instance with ID "xxx" + $ stackit observability grafana single-sign-on disable xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability grafana single-sign-on disable" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability grafana single-sign-on](./stackit_observability_grafana_single-sign-on.md) - Enable or disable single sign-on for Grafana in Observability instances + diff --git a/docs/stackit_observability_grafana_single-sign-on_enable.md b/docs/stackit_observability_grafana_single-sign-on_enable.md new file mode 100644 index 000000000..08c5cf52f --- /dev/null +++ b/docs/stackit_observability_grafana_single-sign-on_enable.md @@ -0,0 +1,40 @@ +## stackit observability grafana single-sign-on enable + +Enables single sign-on for Grafana on Observability instances + +### Synopsis + +Enables single sign-on for Grafana on Observability instances. +When enabled for an instance, overwrites the generic OAuth2 authentication and configures STACKIT single sign-on for that instance. + +``` +stackit observability grafana single-sign-on enable INSTANCE_ID [flags] +``` + +### Examples + +``` + Enable single sign-on for Grafana on an Observability instance with ID "xxx" + $ stackit observability grafana single-sign-on enable xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability grafana single-sign-on enable" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability grafana single-sign-on](./stackit_observability_grafana_single-sign-on.md) - Enable or disable single sign-on for Grafana in Observability instances + diff --git a/docs/stackit_observability_instance.md b/docs/stackit_observability_instance.md new file mode 100644 index 000000000..81786a254 --- /dev/null +++ b/docs/stackit_observability_instance.md @@ -0,0 +1,37 @@ +## stackit observability instance + +Provides functionality for Observability instances + +### Synopsis + +Provides functionality for Observability instances. + +``` +stackit observability instance [flags] +``` + +### Options + +``` + -h, --help Help for "stackit observability instance" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability](./stackit_observability.md) - Provides functionality for Observability +* [stackit observability instance create](./stackit_observability_instance_create.md) - Creates an Observability instance +* [stackit observability instance delete](./stackit_observability_instance_delete.md) - Deletes an Observability instance +* [stackit observability instance describe](./stackit_observability_instance_describe.md) - Shows details of an Observability instance +* [stackit observability instance list](./stackit_observability_instance_list.md) - Lists all Observability instances +* [stackit observability instance update](./stackit_observability_instance_update.md) - Updates an Observability instance + diff --git a/docs/stackit_observability_instance_create.md b/docs/stackit_observability_instance_create.md new file mode 100644 index 000000000..d47991c32 --- /dev/null +++ b/docs/stackit_observability_instance_create.md @@ -0,0 +1,45 @@ +## stackit observability instance create + +Creates an Observability instance + +### Synopsis + +Creates an Observability instance. + +``` +stackit observability instance create [flags] +``` + +### Examples + +``` + Create an Observability instance with name "my-instance" and specify plan by name + $ stackit observability instance create --name my-instance --plan-name Monitoring-Starter-EU01 + + Create an Observability instance with name "my-instance" and specify plan by ID + $ stackit observability instance create --name my-instance --plan-id xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability instance create" + -n, --name string Instance name + --plan-id string Plan ID + --plan-name string Plan name +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability instance](./stackit_observability_instance.md) - Provides functionality for Observability instances + diff --git a/docs/stackit_observability_instance_delete.md b/docs/stackit_observability_instance_delete.md new file mode 100644 index 000000000..1264e0f54 --- /dev/null +++ b/docs/stackit_observability_instance_delete.md @@ -0,0 +1,39 @@ +## stackit observability instance delete + +Deletes an Observability instance + +### Synopsis + +Deletes an Observability instance. + +``` +stackit observability instance delete INSTANCE_ID [flags] +``` + +### Examples + +``` + Delete an Observability instance with ID "xxx" + $ stackit Observability instance delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability instance delete" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability instance](./stackit_observability_instance.md) - Provides functionality for Observability instances + diff --git a/docs/stackit_observability_instance_describe.md b/docs/stackit_observability_instance_describe.md new file mode 100644 index 000000000..737612923 --- /dev/null +++ b/docs/stackit_observability_instance_describe.md @@ -0,0 +1,42 @@ +## stackit observability instance describe + +Shows details of an Observability instance + +### Synopsis + +Shows details of an Observability instance. + +``` +stackit observability instance describe INSTANCE_ID [flags] +``` + +### Examples + +``` + Get details of an Observability instance with ID "xxx" + $ stackit observability instance describe xxx + + Get details of an Observability instance with ID "xxx" in JSON format + $ stackit observability instance describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit observability instance 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability instance](./stackit_observability_instance.md) - Provides functionality for Observability instances + diff --git a/docs/stackit_observability_instance_list.md b/docs/stackit_observability_instance_list.md new file mode 100644 index 000000000..0fffefae1 --- /dev/null +++ b/docs/stackit_observability_instance_list.md @@ -0,0 +1,46 @@ +## stackit observability instance list + +Lists all Observability instances + +### Synopsis + +Lists all Observability instances. + +``` +stackit observability instance list [flags] +``` + +### Examples + +``` + List all Observability instances + $ stackit observability instance list + + List all Observability instances in JSON format + $ stackit observability instance list --output-format json + + List up to 10 Observability instances + $ stackit observability instance list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit observability instance list" + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability instance](./stackit_observability_instance.md) - Provides functionality for Observability instances + diff --git a/docs/stackit_observability_instance_update.md b/docs/stackit_observability_instance_update.md new file mode 100644 index 000000000..fd9619949 --- /dev/null +++ b/docs/stackit_observability_instance_update.md @@ -0,0 +1,48 @@ +## stackit observability instance update + +Updates an Observability instance + +### Synopsis + +Updates an Observability instance. + +``` +stackit observability instance update INSTANCE_ID [flags] +``` + +### Examples + +``` + Update the plan of an Observability instance with ID "xxx" by specifying the plan ID + $ stackit observability instance update xxx --plan-id yyy + + Update the plan of an Observability instance with ID "xxx" by specifying the plan name + $ stackit observability instance update xxx --plan-name Frontend-Starter-EU01 + + Update the name of an Observability instance with ID "xxx" + $ stackit observability instance update xxx --name new-instance-name +``` + +### Options + +``` + -h, --help Help for "stackit observability instance update" + -n, --name string Instance name + --plan-id string Plan ID + --plan-name string Plan name +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability instance](./stackit_observability_instance.md) - Provides functionality for Observability instances + diff --git a/docs/stackit_observability_plans.md b/docs/stackit_observability_plans.md new file mode 100644 index 000000000..1ad146a22 --- /dev/null +++ b/docs/stackit_observability_plans.md @@ -0,0 +1,46 @@ +## stackit observability plans + +Lists all Observability service plans + +### Synopsis + +Lists all Observability service plans. + +``` +stackit observability plans [flags] +``` + +### Examples + +``` + List all Observability service plans + $ stackit observability plans + + List all Observability service plans in JSON format + $ stackit observability plans --output-format json + + List up to 10 Observability service plans + $ stackit observability plans --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit observability plans" + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability](./stackit_observability.md) - Provides functionality for Observability + diff --git a/docs/stackit_observability_scrape-config.md b/docs/stackit_observability_scrape-config.md new file mode 100644 index 000000000..64d51d10e --- /dev/null +++ b/docs/stackit_observability_scrape-config.md @@ -0,0 +1,38 @@ +## stackit observability scrape-config + +Provides functionality for scrape configurations in Observability + +### Synopsis + +Provides functionality for scrape configurations in Observability. + +``` +stackit observability scrape-config [flags] +``` + +### Options + +``` + -h, --help Help for "stackit observability scrape-config" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability](./stackit_observability.md) - Provides functionality for Observability +* [stackit observability scrape-config create](./stackit_observability_scrape-config_create.md) - Creates a scrape configuration for an Observability instance +* [stackit observability scrape-config delete](./stackit_observability_scrape-config_delete.md) - Deletes a scrape configuration from an Observability instance +* [stackit observability scrape-config describe](./stackit_observability_scrape-config_describe.md) - Shows details of a scrape configuration from an Observability instance +* [stackit observability scrape-config generate-payload](./stackit_observability_scrape-config_generate-payload.md) - Generates a payload to create/update scrape configurations for an Observability instance +* [stackit observability scrape-config list](./stackit_observability_scrape-config_list.md) - Lists all scrape configurations of an Observability instance +* [stackit observability scrape-config update](./stackit_observability_scrape-config_update.md) - Updates a scrape configuration of an Observability instance + diff --git a/docs/stackit_observability_scrape-config_create.md b/docs/stackit_observability_scrape-config_create.md new file mode 100644 index 000000000..3a282c93a --- /dev/null +++ b/docs/stackit_observability_scrape-config_create.md @@ -0,0 +1,55 @@ +## stackit observability scrape-config create + +Creates a scrape configuration for an Observability instance + +### Synopsis + +Creates a scrape configuration job for an Observability instance. +The payload can be provided as a JSON string or a file path prefixed with "@". +If no payload is provided, a default payload will be used. +See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_create for information regarding the payload structure. + +``` +stackit observability scrape-config create [flags] +``` + +### Examples + +``` + Create a scrape configuration on Observability instance "xxx" using default configuration + $ stackit observability scrape-config create + + Create a scrape configuration on Observability instance "xxx" using an API payload sourced from the file "./payload.json" + $ stackit observability scrape-config create --payload @./payload.json --instance-id xxx + + Create a scrape configuration on Observability instance "xxx" using an API payload provided as a JSON string + $ stackit observability scrape-config create --payload "{...}" --instance-id xxx + + Generate a payload with default values, and adapt it with custom values for the different configuration options + $ stackit observability scrape-config generate-payload > ./payload.json + + $ stackit observability scrape-config create --payload @./payload.json --instance-id xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability scrape-config create" + --instance-id string Instance ID + --payload string Request payload (JSON). Can be a string or a file path, if prefixed with "@" (example: @./payload.json). If unset, will use a default payload (you can check it by running "stackit observability scrape-config generate-payload") +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability scrape-config](./stackit_observability_scrape-config.md) - Provides functionality for scrape configurations in Observability + diff --git a/docs/stackit_observability_scrape-config_delete.md b/docs/stackit_observability_scrape-config_delete.md new file mode 100644 index 000000000..3f7167e13 --- /dev/null +++ b/docs/stackit_observability_scrape-config_delete.md @@ -0,0 +1,40 @@ +## stackit observability scrape-config delete + +Deletes a scrape configuration from an Observability instance + +### Synopsis + +Deletes a scrape configuration from an Observability instance. + +``` +stackit observability scrape-config delete JOB_NAME [flags] +``` + +### Examples + +``` + Delete a scrape configuration job with name "my-config" from Observability instance "xxx" + $ stackit observability scrape-config delete my-config --instance-id xxx +``` + +### Options + +``` + -h, --help Help for "stackit observability scrape-config delete" + --instance-id string Instance ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability scrape-config](./stackit_observability_scrape-config.md) - Provides functionality for scrape configurations in Observability + diff --git a/docs/stackit_observability_scrape-config_describe.md b/docs/stackit_observability_scrape-config_describe.md new file mode 100644 index 000000000..000edbbb2 --- /dev/null +++ b/docs/stackit_observability_scrape-config_describe.md @@ -0,0 +1,43 @@ +## stackit observability scrape-config describe + +Shows details of a scrape configuration from an Observability instance + +### Synopsis + +Shows details of a scrape configuration from an Observability instance. + +``` +stackit observability scrape-config describe JOB_NAME [flags] +``` + +### Examples + +``` + Get details of a scrape configuration with name "my-config" from Observability instance "xxx" + $ stackit observability scrape-config describe my-config --instance-id xxx + + Get details of a scrape configuration with name "my-config" from Observability instance "xxx" in JSON format + $ stackit observability scrape-config describe my-config --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit observability scrape-config describe" + --instance-id string Instance ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability scrape-config](./stackit_observability_scrape-config.md) - Provides functionality for scrape configurations in Observability + diff --git a/docs/stackit_observability_scrape-config_generate-payload.md b/docs/stackit_observability_scrape-config_generate-payload.md new file mode 100644 index 000000000..99979b410 --- /dev/null +++ b/docs/stackit_observability_scrape-config_generate-payload.md @@ -0,0 +1,58 @@ +## stackit observability scrape-config generate-payload + +Generates a payload to create/update scrape configurations for an Observability instance + +### Synopsis + +Generates a JSON payload with values to be used as --payload input for scrape configurations creation or update. +This command can be used to generate a payload to update an existing scrape config or to create a new scrape config job. +To update an existing scrape config job, provide the job name and the instance ID of the Observability instance. +To obtain a default payload to create a new scrape config job, run the command with no flags. +Note that some of the default values provided, such as the job name, the metrics path and URL of the targets, should be adapted to your use case. +See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_create for information regarding the payload structure. + + +``` +stackit observability scrape-config generate-payload [flags] +``` + +### Examples + +``` + Generate a Create payload with default values, and adapt it with custom values for the different configuration options + $ stackit observability scrape-config generate-payload --file-path ./payload.json + + $ stackit observability scrape-config create my-config --payload @./payload.json + + Generate an Update payload with the values of an existing configuration named "my-config" for Observability instance xxx, and adapt it with custom values for the different configuration options + $ stackit observability scrape-config generate-payload --job-name my-config --instance-id xxx --file-path ./payload.json + + $ stackit observability scrape-config update my-config --payload @./payload.json + + Generate an Update payload with the values of an existing configuration named "my-config" for Observability instance xxx, and preview it in the terminal + $ stackit observability scrape-config generate-payload --job-name my-config --instance-id xxx +``` + +### Options + +``` + -f, --file-path string If set, writes the payload to the given file. If unset, writes the payload to the standard output + -h, --help Help for "stackit observability scrape-config generate-payload" + --instance-id string Instance ID + -n, --job-name string If set, generates an update payload with the current state of the given scrape config. If unset, generates a create payload with default values +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability scrape-config](./stackit_observability_scrape-config.md) - Provides functionality for scrape configurations in Observability + diff --git a/docs/stackit_observability_scrape-config_list.md b/docs/stackit_observability_scrape-config_list.md new file mode 100644 index 000000000..e798101ae --- /dev/null +++ b/docs/stackit_observability_scrape-config_list.md @@ -0,0 +1,47 @@ +## stackit observability scrape-config list + +Lists all scrape configurations of an Observability instance + +### Synopsis + +Lists all scrape configurations of an Observability instance. + +``` +stackit observability scrape-config list [flags] +``` + +### Examples + +``` + List all scrape configurations of Observability instance "xxx" + $ stackit observability scrape-config list --instance-id xxx + + List all scrape configurations of Observability instance "xxx" in JSON format + $ stackit observability scrape-config list --instance-id xxx --output-format json + + List up to 10 scrape configurations of Observability instance "xxx" + $ stackit observability scrape-config list --instance-id xxx --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit observability scrape-config list" + --instance-id string Instance ID + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability scrape-config](./stackit_observability_scrape-config.md) - Provides functionality for scrape configurations in Observability + diff --git a/docs/stackit_observability_scrape-config_update.md b/docs/stackit_observability_scrape-config_update.md new file mode 100644 index 000000000..c8370af7e --- /dev/null +++ b/docs/stackit_observability_scrape-config_update.md @@ -0,0 +1,51 @@ +## stackit observability scrape-config update + +Updates a scrape configuration of an Observability instance + +### Synopsis + +Updates a scrape configuration of an Observability instance. +The payload can be provided as a JSON string or a file path prefixed with "@". +See https://docs.api.stackit.cloud/documentation/argus/version/v1#tag/scrape-config/operation/v1_projects_instances_scrapeconfigs_update for information regarding the payload structure. + +``` +stackit observability scrape-config update JOB_NAME [flags] +``` + +### Examples + +``` + Update a scrape configuration with name "my-config" from Observability instance "xxx", using an API payload sourced from the file "./payload.json" + $ stackit observability scrape-config update my-config --payload @./payload.json --instance-id xxx + + Update an scrape configuration with name "my-config" from Observability instance "xxx", using an API payload provided as a JSON string + $ stackit observability scrape-config update my-config --payload "{...}" --instance-id xxx + + Generate a payload with the current values of a scrape configuration, and adapt it with custom values for the different configuration options + $ stackit observability scrape-config generate-payload --job-name my-config > ./payload.json + + $ stackit observability scrape-configs update my-config --payload @./payload.json +``` + +### Options + +``` + -h, --help Help for "stackit observability scrape-config update" + --instance-id string Instance ID + --payload string Request payload (JSON). Can be a string or a file path, if prefixed with "@". Example: @./payload.json +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit observability scrape-config](./stackit_observability_scrape-config.md) - Provides functionality for scrape configurations in Observability + From 34bade926c976cf07b4855479f447d90e1255abd Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:25:45 +0200 Subject: [PATCH 048/619] Fix grafana describe examples (#457) * fix grafana describe examples * update docs --- docs/stackit_observability_grafana_describe.md | 6 +++--- internal/cmd/observability/grafana/describe/describe.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/stackit_observability_grafana_describe.md b/docs/stackit_observability_grafana_describe.md index 1fff9b64e..99e09204e 100644 --- a/docs/stackit_observability_grafana_describe.md +++ b/docs/stackit_observability_grafana_describe.md @@ -16,13 +16,13 @@ stackit observability grafana describe INSTANCE_ID [flags] ``` Get details of the Grafana configuration of an Observability instance with ID "xxx" - $ stackit observability credentials describe xxx + $ stackit observability grafana describe xxx Get details of the Grafana configuration of an Observability instance with ID "xxx" and show the initial admin password - $ stackit observability credentials describe xxx --show-password + $ stackit observability grafana describe xxx --show-password Get details of the Grafana configuration of an Observability instance with ID "xxx" in JSON format - $ stackit observability credentials describe xxx --output-format json + $ stackit observability grafana describe xxx --output-format json ``` ### Options diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index 46e7f60ee..d21258329 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -44,13 +44,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details of the Grafana configuration of an Observability instance with ID "xxx"`, - "$ stackit observability credentials describe xxx"), + "$ stackit observability grafana describe xxx"), examples.NewExample( `Get details of the Grafana configuration of an Observability instance with ID "xxx" and show the initial admin password`, - "$ stackit observability credentials describe xxx --show-password"), + "$ stackit observability grafana describe xxx --show-password"), examples.NewExample( `Get details of the Grafana configuration of an Observability instance with ID "xxx" in JSON format`, - "$ stackit observability credentials describe xxx --output-format json"), + "$ stackit observability grafana describe xxx --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() From a10c4a513340f35553fe93a15962f29a68d1f606 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Mon, 26 Aug 2024 13:54:11 +0200 Subject: [PATCH 049/619] Validate IDP URL only for customized ones (#458) * validate idp url only if it is customized * fix linter issue --- internal/pkg/auth/utils.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/pkg/auth/utils.go b/internal/pkg/auth/utils.go index 34f5cbf1b..162306b15 100644 --- a/internal/pkg/auth/utils.go +++ b/internal/pkg/auth/utils.go @@ -14,10 +14,10 @@ func getIDPEndpoint() (string, error) { customIDPEndpoint := viper.GetString(config.IdentityProviderCustomEndpointKey) if customIDPEndpoint != "" { idpEndpoint = customIDPEndpoint - } - err := utils.ValidateURLDomain(idpEndpoint) - if err != nil { - return "", fmt.Errorf("validate custom identity provider endpoint: %w", err) + err := utils.ValidateURLDomain(idpEndpoint) + if err != nil { + return "", fmt.Errorf("validate custom identity provider endpoint: %w", err) + } } return idpEndpoint, nil From 628170108c02417dbf7522d4d5d377d22742cbe4 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Mon, 26 Aug 2024 13:55:04 +0200 Subject: [PATCH 050/619] remove deprecated jwks endpoint (#459) --- docs/stackit_config_set.md | 1 - docs/stackit_config_unset.md | 1 - .../activate_service_account.go | 14 ++++---------- .../activate_service_account_test.go | 19 +------------------ internal/cmd/config/set/set.go | 4 ---- internal/cmd/config/unset/unset.go | 7 ------- internal/cmd/config/unset/unset_test.go | 13 ------------- internal/pkg/config/config.go | 3 --- 8 files changed, 5 insertions(+), 57 deletions(-) diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 6c7378e4d..7fc9930ac 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -36,7 +36,6 @@ stackit config set [flags] --iaas-custom-endpoint string IaaS API base URL, used in calls to this API --identity-provider-custom-client-id string Identity Provider client ID, used for user authentication --identity-provider-custom-endpoint string Identity Provider base URL, used for user authentication - --jwks-custom-endpoint string Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API --logme-custom-endpoint string LogMe API base URL, used in calls to this API --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 3f6a4e508..1971e3605 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -34,7 +34,6 @@ stackit config unset [flags] --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL --identity-provider-custom-client-id Identity Provider client ID, used for user authentication --identity-provider-custom-endpoint Identity Provider base URL. If unset, uses the default base URL - --jwks-custom-endpoint Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL diff --git a/internal/cmd/auth/activate-service-account/activate_service_account.go b/internal/cmd/auth/activate-service-account/activate_service_account.go index e49ec48df..aca1dd4fe 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { model := parseInput(p, cmd) - tokenCustomEndpoint, jwksCustomEndpoint, err := storeFlags() + tokenCustomEndpoint, err := storeFlags() if err != nil { return err } @@ -64,7 +64,6 @@ func NewCmd(p *print.Printer) *cobra.Command { ServiceAccountKeyPath: model.ServiceAccountKeyPath, PrivateKeyPath: model.PrivateKeyPath, TokenCustomUrl: tokenCustomEndpoint, - JWKSCustomUrl: jwksCustomEndpoint, } // Setup authentication based on the provided credentials and the environment @@ -119,17 +118,12 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { return &model } -func storeFlags() (tokenCustomEndpoint, jwksCustomEndpoint string, err error) { +func storeFlags() (tokenCustomEndpoint string, err error) { tokenCustomEndpoint = viper.GetString(config.TokenCustomEndpointKey) - jwksCustomEndpoint = viper.GetString(config.JwksCustomEndpointKey) err = auth.SetAuthField(auth.TOKEN_CUSTOM_ENDPOINT, tokenCustomEndpoint) if err != nil { - return "", "", fmt.Errorf("set %s: %w", auth.TOKEN_CUSTOM_ENDPOINT, err) + return "", fmt.Errorf("set %s: %w", auth.TOKEN_CUSTOM_ENDPOINT, err) } - err = auth.SetAuthField(auth.JWKS_CUSTOM_ENDPOINT, jwksCustomEndpoint) - if err != nil { - return "", "", fmt.Errorf("set %s: %w", auth.JWKS_CUSTOM_ENDPOINT, err) - } - return tokenCustomEndpoint, jwksCustomEndpoint, nil + return tokenCustomEndpoint, nil } diff --git a/internal/cmd/auth/activate-service-account/activate_service_account_test.go b/internal/cmd/auth/activate-service-account/activate_service_account_test.go index 6beadb0d6..854022fd4 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account_test.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account_test.go @@ -14,7 +14,6 @@ import ( ) var testTokenCustomEndpoint = "token_url" -var testJwksCustomEndpoint = "jwks_url" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ @@ -45,7 +44,6 @@ func TestParseInput(t *testing.T) { description string flagValues map[string]string tokenCustomEndpoint string - jwksCustomEndpoint string isValid bool expectedModel *inputModel }{ @@ -53,7 +51,6 @@ func TestParseInput(t *testing.T) { description: "base", flagValues: fixtureFlagValues(), tokenCustomEndpoint: testTokenCustomEndpoint, - jwksCustomEndpoint: testJwksCustomEndpoint, isValid: true, expectedModel: fixtureInputModel(), }, @@ -61,7 +58,6 @@ func TestParseInput(t *testing.T) { description: "no values", flagValues: map[string]string{}, tokenCustomEndpoint: "", - jwksCustomEndpoint: "", isValid: true, expectedModel: &inputModel{ ServiceAccountToken: "", @@ -77,7 +73,6 @@ func TestParseInput(t *testing.T) { privateKeyPathFlag: "", }, tokenCustomEndpoint: "", - jwksCustomEndpoint: "", isValid: true, expectedModel: &inputModel{ ServiceAccountToken: "", @@ -131,14 +126,12 @@ func TestStoreFlags(t *testing.T) { description string model *inputModel tokenCustomEndpoint string - jwksCustomEndpoint string isValid bool }{ { description: "base", model: fixtureInputModel(), tokenCustomEndpoint: testTokenCustomEndpoint, - jwksCustomEndpoint: testJwksCustomEndpoint, isValid: true, }, { @@ -149,7 +142,6 @@ func TestStoreFlags(t *testing.T) { PrivateKeyPath: "", }, tokenCustomEndpoint: "", - jwksCustomEndpoint: "", isValid: true, }, } @@ -161,9 +153,8 @@ func TestStoreFlags(t *testing.T) { viper.Reset() viper.Set(config.TokenCustomEndpointKey, tt.tokenCustomEndpoint) - viper.Set(config.JwksCustomEndpointKey, tt.jwksCustomEndpoint) - tokenCustomEndpoint, jwksCustomEndpoint, err := storeFlags() + tokenCustomEndpoint, err := storeFlags() if !tt.isValid { if err == nil { t.Fatalf("did not fail on invalid input") @@ -181,14 +172,6 @@ func TestStoreFlags(t *testing.T) { if value != tokenCustomEndpoint { t.Errorf("Value of \"%s\" does not match: expected \"%s\", got \"%s\"", auth.TOKEN_CUSTOM_ENDPOINT, tokenCustomEndpoint, value) } - - value, err = auth.GetAuthField(auth.JWKS_CUSTOM_ENDPOINT) - if err != nil { - t.Errorf("Failed to get value of auth field: %v", err) - } - if value != jwksCustomEndpoint { - t.Errorf("Value of \"%s\" does not match: expected \"%s\", got \"%s\"", auth.JWKS_CUSTOM_ENDPOINT, jwksCustomEndpoint, value) - } }) } } diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 6231c9bb4..c5b46a3c3 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -44,7 +44,6 @@ const ( sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" iaasCustomEndpointFlag = "iaas-custom-endpoint" tokenCustomEndpointFlag = "token-custom-endpoint" - jwksCustomEndpointFlag = "jwks-custom-endpoint" ) type inputModel struct { @@ -157,7 +156,6 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") cmd.Flags().String(iaasCustomEndpointFlag, "", "IaaS API base URL, used in calls to this API") cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated") - cmd.Flags().String(jwksCustomEndpointFlag, "", "Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated") err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) cobra.CheckErr(err) @@ -212,8 +210,6 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.TokenCustomEndpointKey, cmd.Flags().Lookup(tokenCustomEndpointFlag)) cobra.CheckErr(err) - err = viper.BindPFlag(config.JwksCustomEndpointKey, cmd.Flags().Lookup(jwksCustomEndpointFlag)) - cobra.CheckErr(err) } func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index a73f452f6..ab94bf8cc 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -47,7 +47,6 @@ const ( sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" iaasCustomEndpointFlag = "iaas-custom-endpoint" tokenCustomEndpointFlag = "token-custom-endpoint" - jwksCustomEndpointFlag = "jwks-custom-endpoint" ) type inputModel struct { @@ -83,7 +82,6 @@ type inputModel struct { SQLServerFlexCustomEndpoint bool IaaSCustomEndpoint bool TokenCustomEndpoint bool - JwksCustomEndpoint bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -198,9 +196,6 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.TokenCustomEndpoint { viper.Set(config.TokenCustomEndpointKey, "") } - if model.JwksCustomEndpoint { - viper.Set(config.JwksCustomEndpointKey, "") - } err := config.Write() if err != nil { @@ -246,7 +241,6 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") cmd.Flags().Bool(iaasCustomEndpointFlag, false, "IaaS API base URL. If unset, uses the default base URL") cmd.Flags().Bool(tokenCustomEndpointFlag, false, "Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated") - cmd.Flags().Bool(jwksCustomEndpointFlag, false, "Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { @@ -283,7 +277,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), IaaSCustomEndpoint: flags.FlagToBoolValue(p, cmd, iaasCustomEndpointFlag), TokenCustomEndpoint: flags.FlagToBoolValue(p, cmd, tokenCustomEndpointFlag), - JwksCustomEndpoint: flags.FlagToBoolValue(p, cmd, jwksCustomEndpointFlag), } if p.IsVerbosityDebug() { diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index b97766ae2..46fb369a4 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -40,7 +40,6 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool sqlServerFlexCustomEndpointFlag: true, iaasCustomEndpointFlag: true, tokenCustomEndpointFlag: true, - jwksCustomEndpointFlag: true, } for _, mod := range mods { mod(flagValues) @@ -79,7 +78,6 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { SQLServerFlexCustomEndpoint: true, IaaSCustomEndpoint: true, TokenCustomEndpoint: true, - JwksCustomEndpoint: true, } for _, mod := range mods { mod(model) @@ -134,7 +132,6 @@ func TestParseInput(t *testing.T) { model.SQLServerFlexCustomEndpoint = false model.IaaSCustomEndpoint = false model.TokenCustomEndpoint = false - model.JwksCustomEndpoint = false }), }, { @@ -277,16 +274,6 @@ func TestParseInput(t *testing.T) { model.TokenCustomEndpoint = false }), }, - { - description: "jwks custom endpoint empty", - flagValues: fixtureFlagValues(func(flagValues map[string]bool) { - flagValues[jwksCustomEndpointFlag] = false - }), - isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.JwksCustomEndpoint = false - }), - }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 8132254a4..8f19a885c 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -43,7 +43,6 @@ const ( SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" IaaSCustomEndpointKey = "iaas_custom_endpoint" TokenCustomEndpointKey = "token_custom_endpoint" - JwksCustomEndpointKey = "jwks_custom_endpoint" ProjectNameKey = "project_name" DefaultProfileName = "default" @@ -99,7 +98,6 @@ var ConfigKeys = []string{ SQLServerFlexCustomEndpointKey, IaaSCustomEndpointKey, TokenCustomEndpointKey, - JwksCustomEndpointKey, } var defaultConfigFolderPath string @@ -177,7 +175,6 @@ func setConfigDefaults() { viper.SetDefault(SQLServerFlexCustomEndpointKey, "") viper.SetDefault(IaaSCustomEndpointKey, "") viper.SetDefault(TokenCustomEndpointKey, "") - viper.SetDefault(JwksCustomEndpointKey, "") } func getConfigFilePath(configFolder string) string { From dcad93e35fb38d137cad6c641921e2eed95079fc Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:21:38 +0200 Subject: [PATCH 051/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.8.0 (#453) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d2be18fc3..cb19b8c0e 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.7.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 diff --git a/go.sum b/go.sum index 84bd7f50a..2b5cbc4c9 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.7.0 h1:BnDF0RSW+gN2/AxC5TAkNMzVPGsbnCrURj755so6EBY= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.7.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0 h1:RPqCcepRpm4c2POVuq+W41UwhXEfSRQAM696evHIOlQ= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 h1:/GwkGMD7ID5hSjdZs1l/Mj8waceCt7oj3TxHgBfEMDQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 h1:S8UZYBu2lHmKCPTR17jZetIal8X7cHO1gVRv101UdPw= From 0c732f9a84bc6b00cbbc1037dc3c59bf8747833b Mon Sep 17 00:00:00 2001 From: Vicente Pinto Date: Mon, 26 Aug 2024 18:03:45 +0100 Subject: [PATCH 052/619] Remove jwks from auth storage (#461) * Remove jwks from auth storage * Remove jwks endpoint from storage --- internal/pkg/auth/auth_test.go | 11 ----------- internal/pkg/auth/service_account.go | 1 - internal/pkg/auth/storage.go | 2 -- 3 files changed, 14 deletions(-) diff --git a/internal/pkg/auth/auth_test.go b/internal/pkg/auth/auth_test.go index 9d4ee8778..6c64c359c 100644 --- a/internal/pkg/auth/auth_test.go +++ b/internal/pkg/auth/auth_test.go @@ -70,7 +70,6 @@ func TestAuthenticationConfig(t *testing.T) { saKey string privateKeySet bool tokenEndpoint string - jwksEndpoint string isValid bool expectedCustomAuthSet bool expectedTokenSet bool @@ -102,7 +101,6 @@ func TestAuthenticationConfig(t *testing.T) { saKey: testServiceAccountKey, privateKeySet: true, tokenEndpoint: "token_url", - jwksEndpoint: "jwks_url", isValid: true, expectedCustomAuthSet: true, }, @@ -115,7 +113,6 @@ func TestAuthenticationConfig(t *testing.T) { saKey: testServiceAccountKey, privateKeySet: true, tokenEndpoint: "token_url", - jwksEndpoint: "jwks_url", isValid: false, }, { @@ -180,7 +177,6 @@ func TestAuthenticationConfig(t *testing.T) { authFields[REFRESH_TOKEN] = tt.refreshToken authFields[SERVICE_ACCOUNT_KEY] = tt.saKey authFields[TOKEN_CUSTOM_ENDPOINT] = tt.tokenEndpoint - authFields[JWKS_CUSTOM_ENDPOINT] = tt.jwksEndpoint err = SetAuthFlow(tt.flow) if err != nil { @@ -245,7 +241,6 @@ func TestInitKeyFlow(t *testing.T) { saKey string privateKeySet bool tokenEndpoint string - jwksEndpoint string isValid bool }{ { @@ -255,7 +250,6 @@ func TestInitKeyFlow(t *testing.T) { saKey: testServiceAccountKey, privateKeySet: true, tokenEndpoint: "token_url", - jwksEndpoint: "jwks_url", isValid: true, }, { @@ -265,7 +259,6 @@ func TestInitKeyFlow(t *testing.T) { saKey: "", privateKeySet: true, tokenEndpoint: "token_url", - jwksEndpoint: "jwks_url", isValid: false, }, { @@ -275,7 +268,6 @@ func TestInitKeyFlow(t *testing.T) { saKey: testServiceAccountKey, privateKeySet: false, tokenEndpoint: "token_url", - jwksEndpoint: "jwks_url", isValid: false, }, { @@ -285,7 +277,6 @@ func TestInitKeyFlow(t *testing.T) { saKey: testServiceAccountKey, privateKeySet: true, tokenEndpoint: "token_url", - jwksEndpoint: "jwks_url", isValid: false, }, { @@ -295,7 +286,6 @@ func TestInitKeyFlow(t *testing.T) { saKey: testServiceAccountKey, privateKeySet: true, tokenEndpoint: "token_url", - jwksEndpoint: "jwks_url", isValid: false, }, } @@ -326,7 +316,6 @@ func TestInitKeyFlow(t *testing.T) { authFields[REFRESH_TOKEN] = tt.refreshToken authFields[SERVICE_ACCOUNT_KEY] = tt.saKey authFields[TOKEN_CUSTOM_ENDPOINT] = tt.tokenEndpoint - authFields[JWKS_CUSTOM_ENDPOINT] = tt.jwksEndpoint err = SetAuthFieldMap(authFields) if err != nil { t.Fatalf("Failed to set in auth storage: %v", err) diff --git a/internal/pkg/auth/service_account.go b/internal/pkg/auth/service_account.go index 747832f6e..62e154bad 100644 --- a/internal/pkg/auth/service_account.go +++ b/internal/pkg/auth/service_account.go @@ -102,7 +102,6 @@ func initKeyFlowWithStorage() (*keyFlowWithStorage, error) { SERVICE_ACCOUNT_KEY: "", PRIVATE_KEY: "", TOKEN_CUSTOM_ENDPOINT: "", - JWKS_CUSTOM_ENDPOINT: "", } err := GetAuthFieldMap(authFields) if err != nil { diff --git a/internal/pkg/auth/storage.go b/internal/pkg/auth/storage.go index a53b5a256..1d30d1997 100644 --- a/internal/pkg/auth/storage.go +++ b/internal/pkg/auth/storage.go @@ -37,7 +37,6 @@ const ( SERVICE_ACCOUNT_KEY authFieldKey = "service_account_key" PRIVATE_KEY authFieldKey = "private_key" TOKEN_CUSTOM_ENDPOINT authFieldKey = "token_custom_endpoint" - JWKS_CUSTOM_ENDPOINT authFieldKey = "jwks_custom_endpoint" ) const ( @@ -58,7 +57,6 @@ var authFieldKeys = []authFieldKey{ SERVICE_ACCOUNT_KEY, PRIVATE_KEY, TOKEN_CUSTOM_ENDPOINT, - JWKS_CUSTOM_ENDPOINT, authFlowType, } From fe140ac7daa7940039826799da18b2fff16469bb Mon Sep 17 00:00:00 2001 From: Vicente Pinto Date: Tue, 27 Aug 2024 11:01:22 +0100 Subject: [PATCH 053/619] Add SECURITY.md (#460) --- SECURITY.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..049f3f6fe --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,9 @@ +# Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +We at STACKIT take security seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. + +To report a security issue, please send an email to [stackit-security@stackit.de](mailto:stackit-security@stackit.de). + +Our team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. From dcfa4ff8aea8759c6e296ceb45dcdec0d40c70a7 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:12:55 +0200 Subject: [PATCH 054/619] add note to installation md (#463) --- INSTALLATION.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/INSTALLATION.md b/INSTALLATION.md index 1f0f78ae6..1a92479c4 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -66,6 +66,8 @@ sudo apt-get update sudo apt-get install stackit ``` +If you can't get latest updates due to an expired key, please go back to Step 1 and execute the commands again to fetch and use the latest key. + #### Any distribution Alternatively, you can install via [Homebrew](https://brew.sh/) or refer to one of the installation methods below. From 2a98589920f7898c8d2f12e667f6c1c15a94ebbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Thu, 29 Aug 2024 14:55:27 +0100 Subject: [PATCH 055/619] Adjust APT release script during GPG key rotation (#464) --- scripts/new-public-key.gpg | 14 ++++++++++++++ scripts/publish-apt-packages.sh | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 scripts/new-public-key.gpg diff --git a/scripts/new-public-key.gpg b/scripts/new-public-key.gpg new file mode 100644 index 000000000..da8ce8fb9 --- /dev/null +++ b/scripts/new-public-key.gpg @@ -0,0 +1,14 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZs7fYxYJKwYBBAHaRw8BAQdAyoFCfBmwdPB3c7pVsQw+lYSuJzXZO3VkQlZs +mFteW5q0NVNUQUNLSVQgR1BHIFNJR05FUiA8c3RhY2tpdC1ncGctc2lnbmVyQHN0 +YWNraXQuY2xvdWQ+iJkEExYKAEEWIQS4bpVrR+qLfEWw7biJ8pBDfqyyqwUCZs7f +YwIbAwUJAO1OAAULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRCJ8pBDfqyy +q9RbAPsF3c+JkyXkOpHlIRzy0dfFwNO0H75ev95TuAhZlk6+5wEAl/WOogYvlUbD +x8Uko7PbY1cN3S1N8ZAruOabxSvjPAG4OARmzt9jEgorBgEEAZdVAQUBAQdAI62z +jCQW8MI6f9SFsaMHDOkhLTcQ5dGfngybmHTWgy4DAQgHiH4EGBYKACYWIQS4bpVr +R+qLfEWw7biJ8pBDfqyyqwUCZs7fYwIbDAUJAO1OAAAKCRCJ8pBDfqyyqwBxAP96 +6oW1eQLAeTkZTshfQOHU1JTEe5kNPqKg4j2QrnCyYwD/SI0yqHeHYSV+LQ1XYngY +dGSb94FNr07033VwWlokFg4= +=f80Z +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/scripts/publish-apt-packages.sh b/scripts/publish-apt-packages.sh index 6f71243de..3447b84b7 100755 --- a/scripts/publish-apt-packages.sh +++ b/scripts/publish-apt-packages.sh @@ -50,6 +50,9 @@ aptly snapshot create new-snapshot from repo new-repo printf "\n>>> Merging snapshots \n" aptly snapshot pull -no-remove -architectures="amd64,i386,arm64" current-snapshot new-snapshot updated-snapshot ${DISTRIBUTION} +# Import new public key (temporary) +gpg --no-default-keyring --keyring=${CUSTOM_KEYRING_FILE} --import new-public-key.gpg + # Publish the new snapshot to the remote repo printf "\n>>> Publishing updated snapshot \n" aptly publish snapshot -keyring="${CUSTOM_KEYRING_FILE}" -gpg-key="${GPG_PRIVATE_KEY_FINGERPRINT}" -passphrase "${GPG_PASSPHRASE}" -config "${APTLY_CONFIG_FILE_PATH}" updated-snapshot "s3:${APT_BUCKET_NAME}:${APT_REPO_FOLDER}" From fdc2b77025c42e04759cb307239a3c639d9ab68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Thu, 29 Aug 2024 15:29:34 +0100 Subject: [PATCH 056/619] Publish pre-releases to APT during GPG key rotation (#465) --- .github/workflows/release.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0344e3995..cabd272c6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -69,7 +69,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.CLI_RELEASE }} GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} - name: Publish packages to APT repo - if: contains(github.ref_name, '-') == false env: GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} GPG_PRIVATE_KEY_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} From da287857574beb9114ce24ccdef0852c1a4e6c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Thu, 29 Aug 2024 16:41:11 +0100 Subject: [PATCH 057/619] Revert "Adjust APT release script during GPG key rotation (#464)" (#466) This reverts commit 2a98589920f7898c8d2f12e667f6c1c15a94ebbf. --- scripts/new-public-key.gpg | 14 -------------- scripts/publish-apt-packages.sh | 3 --- 2 files changed, 17 deletions(-) delete mode 100644 scripts/new-public-key.gpg diff --git a/scripts/new-public-key.gpg b/scripts/new-public-key.gpg deleted file mode 100644 index da8ce8fb9..000000000 --- a/scripts/new-public-key.gpg +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -mDMEZs7fYxYJKwYBBAHaRw8BAQdAyoFCfBmwdPB3c7pVsQw+lYSuJzXZO3VkQlZs -mFteW5q0NVNUQUNLSVQgR1BHIFNJR05FUiA8c3RhY2tpdC1ncGctc2lnbmVyQHN0 -YWNraXQuY2xvdWQ+iJkEExYKAEEWIQS4bpVrR+qLfEWw7biJ8pBDfqyyqwUCZs7f -YwIbAwUJAO1OAAULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRCJ8pBDfqyy -q9RbAPsF3c+JkyXkOpHlIRzy0dfFwNO0H75ev95TuAhZlk6+5wEAl/WOogYvlUbD -x8Uko7PbY1cN3S1N8ZAruOabxSvjPAG4OARmzt9jEgorBgEEAZdVAQUBAQdAI62z -jCQW8MI6f9SFsaMHDOkhLTcQ5dGfngybmHTWgy4DAQgHiH4EGBYKACYWIQS4bpVr -R+qLfEWw7biJ8pBDfqyyqwUCZs7fYwIbDAUJAO1OAAAKCRCJ8pBDfqyyqwBxAP96 -6oW1eQLAeTkZTshfQOHU1JTEe5kNPqKg4j2QrnCyYwD/SI0yqHeHYSV+LQ1XYngY -dGSb94FNr07033VwWlokFg4= -=f80Z ------END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/scripts/publish-apt-packages.sh b/scripts/publish-apt-packages.sh index 3447b84b7..6f71243de 100755 --- a/scripts/publish-apt-packages.sh +++ b/scripts/publish-apt-packages.sh @@ -50,9 +50,6 @@ aptly snapshot create new-snapshot from repo new-repo printf "\n>>> Merging snapshots \n" aptly snapshot pull -no-remove -architectures="amd64,i386,arm64" current-snapshot new-snapshot updated-snapshot ${DISTRIBUTION} -# Import new public key (temporary) -gpg --no-default-keyring --keyring=${CUSTOM_KEYRING_FILE} --import new-public-key.gpg - # Publish the new snapshot to the remote repo printf "\n>>> Publishing updated snapshot \n" aptly publish snapshot -keyring="${CUSTOM_KEYRING_FILE}" -gpg-key="${GPG_PRIVATE_KEY_FINGERPRINT}" -passphrase "${GPG_PASSPHRASE}" -config "${APTLY_CONFIG_FILE_PATH}" updated-snapshot "s3:${APT_BUCKET_NAME}:${APT_REPO_FOLDER}" From d3948186140f2439627780d4574e6da37e4b6ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Thu, 29 Aug 2024 17:23:37 +0100 Subject: [PATCH 058/619] Update URL of APT packages and key bucket (#467) --- scripts/publish-apt-packages.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/scripts/publish-apt-packages.sh b/scripts/publish-apt-packages.sh index 6f71243de..f6ec84174 100755 --- a/scripts/publish-apt-packages.sh +++ b/scripts/publish-apt-packages.sh @@ -6,11 +6,10 @@ set -eo pipefail ROOT_DIR=$(git rev-parse --show-toplevel) -OBJECT_STORAGE_ENDPOINT="https://object.storage.eu01.onstackit.cloud" +PACKAGES_BUCKET_URL="https://packages.stackit.cloud" +PUBLIC_KEY_FILE_PATH="keys/key.gpg" +APT_REPO_PATH="apt/cli" APT_BUCKET_NAME="distribution" -APT_REPO_FOLDER="apt/cli" -PUBLIC_KEY_BUCKET_NAME="stackit-public-key" -PUBLIC_KEY_FILE="key.gpg" CUSTOM_KEYRING_FILE="aptly-keyring.gpg" DISTRIBUTION="stackit" APTLY_CONFIG_FILE_PATH="./.aptly.conf" @@ -22,9 +21,9 @@ echo -n >~/.gnupg/common.conf # Create a local mirror of the current state of the remote APT repository printf ">>> Creating mirror \n" -curl ${OBJECT_STORAGE_ENDPOINT}/${PUBLIC_KEY_BUCKET_NAME}/${PUBLIC_KEY_FILE} >public.asc +curl ${PACKAGES_BUCKET_URL}/${PUBLIC_KEY_FILE_PATH} >public.asc gpg --no-default-keyring --keyring=${CUSTOM_KEYRING_FILE} --import public.asc -aptly mirror create -config "${APTLY_CONFIG_FILE_PATH}" -keyring="${CUSTOM_KEYRING_FILE}" current "${OBJECT_STORAGE_ENDPOINT}/${APT_BUCKET_NAME}/${APT_REPO_FOLDER}" ${DISTRIBUTION} +aptly mirror create -config "${APTLY_CONFIG_FILE_PATH}" -keyring="${CUSTOM_KEYRING_FILE}" current "${PACKAGES_BUCKET_URL}/${APT_REPO_PATH}" ${DISTRIBUTION} # Update the mirror to the latest state printf "\n>>> Updating mirror \n" @@ -52,4 +51,4 @@ aptly snapshot pull -no-remove -architectures="amd64,i386,arm64" current-snapsho # Publish the new snapshot to the remote repo printf "\n>>> Publishing updated snapshot \n" -aptly publish snapshot -keyring="${CUSTOM_KEYRING_FILE}" -gpg-key="${GPG_PRIVATE_KEY_FINGERPRINT}" -passphrase "${GPG_PASSPHRASE}" -config "${APTLY_CONFIG_FILE_PATH}" updated-snapshot "s3:${APT_BUCKET_NAME}:${APT_REPO_FOLDER}" +aptly publish snapshot -keyring="${CUSTOM_KEYRING_FILE}" -gpg-key="${GPG_PRIVATE_KEY_FINGERPRINT}" -passphrase "${GPG_PASSPHRASE}" -config "${APTLY_CONFIG_FILE_PATH}" updated-snapshot "s3:${APT_BUCKET_NAME}:${APT_REPO_PATH}" From fb9eb9019b9c9475cf50ccb98f81e286a705f4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Thu, 29 Aug 2024 17:39:36 +0100 Subject: [PATCH 059/619] Revert "Publish pre-releases to APT during GPG key rotation (#465)" (#468) This reverts commit fdc2b77025c42e04759cb307239a3c639d9ab68d. --- .github/workflows/release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index cabd272c6..0344e3995 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -69,6 +69,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.CLI_RELEASE }} GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} - name: Publish packages to APT repo + if: contains(github.ref_name, '-') == false env: GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} GPG_PRIVATE_KEY_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} From 93f88ce2a44bd2d4d8080e3db860946be1383747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Thu, 29 Aug 2024 18:12:56 +0100 Subject: [PATCH 060/619] Remove IDP migration warning from README (#469) --- INSTALLATION.md | 2 +- README.md | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/INSTALLATION.md b/INSTALLATION.md index 1a92479c4..565eab7dd 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -66,7 +66,7 @@ sudo apt-get update sudo apt-get install stackit ``` -If you can't get latest updates due to an expired key, please go back to Step 1 and execute the commands again to fetch and use the latest key. +> If you can't install the `stackit` package due to an expired key, please go back to step `1` to import the latest public key. #### Any distribution diff --git a/README.md b/README.md index 571c5b6ba..a46f741a4 100644 --- a/README.md +++ b/README.md @@ -17,19 +17,12 @@ Your feedback is appreciated! > [!WARNING] -> On August 26 2024, The STACKIT Argus service was renamed to STACKIT Observability. +> On August 26 2024, The STACKIT Argus service was renamed to STACKIT Observability. > > This means that there is a new command group `observability`, which offers the same functionality as the deprecated `argus` command. > > Please make sure to **update your STACKIT CLI to the latest version after August 26 2024** to ensure that you start using `observability` command. -> [!WARNING] -> On July 9 2024, the new [STACKIT Identity Provider (IDP)](https://docs.stackit.cloud/stackit/en/release-notes-23101442.html#ReleaseNotes-2024-06-21-identity-provider) was released. We are happy to announce that on [v0.9.0](https://github.com/stackitcloud/stackit-cli/releases/tag/v0.9.0), the new IDP was integrated in the STACKIT CLI, where it is used for user authentication. -> -> This also means that the **user authentication on STACKIT CLI versions released before July 9 2024 is no longer guaranteed to work for all services**. -> -> Please make sure to **update your STACKIT CLI to the latest version after July 9 2024** to ensure that you can continue to use all STACKIT services. - ## Installation Please refer to our [installation guide](./INSTALLATION.md) for instructions on how to install and get started using the STACKIT CLI. @@ -73,7 +66,7 @@ Help is available for any command by specifying the special flag `--help` (or si Below you can find a list of the STACKIT services already available in the CLI (along with their respective command names) and the ones that are currently planned to be integrated. | Service | CLI Commands | Status | -|------------------------------------|---------------------------|---------------------------| +| ---------------------------------- | ------------------------- | ------------------------- | | Observability | `observability` | :white_check_mark: | | Infrastructure as a Service (IaaS) | `beta network-area` | :white_check_mark: (beta) | | Authorization | `project`, `organization` | :white_check_mark: | From 8721b623f3d33ecce60fec02db4208fcc7268ae2 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Fri, 30 Aug 2024 10:28:16 +0200 Subject: [PATCH 061/619] Change payload handling for create and update network commands (#462) * fix network create payload * fix network update payload * extend create unit test --- internal/cmd/beta/network/create/create.go | 11 ++++++---- .../cmd/beta/network/create/create_test.go | 22 +++++++++++++++++++ internal/cmd/beta/network/update/update.go | 8 ++++--- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go index 166f71526..04170dadd 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/beta/network/create/create.go @@ -153,14 +153,14 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli req := apiClient.CreateNetwork(ctx, model.ProjectId) addressFamily := &iaas.CreateNetworkAddressFamily{} - if model.IPv6DnsNameServers != nil { + if model.IPv6DnsNameServers != nil || model.IPv6PrefixLength != nil { addressFamily.Ipv6 = &iaas.CreateNetworkIPv6Body{ Nameservers: model.IPv6DnsNameServers, PrefixLength: model.IPv6PrefixLength, } } - if model.IPv4DnsNameServers != nil { + if model.IPv4DnsNameServers != nil || model.IPv4PrefixLength != nil { addressFamily.Ipv4 = &iaas.CreateNetworkIPv4Body{ Nameservers: model.IPv4DnsNameServers, PrefixLength: model.IPv4PrefixLength, @@ -168,8 +168,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } payload := iaas.CreateNetworkPayload{ - Name: model.Name, - AddressFamily: addressFamily, + Name: model.Name, + } + + if addressFamily.Ipv4 != nil || addressFamily.Ipv6 != nil { + payload.AddressFamily = addressFamily } return req.CreateNetworkPayload(payload) diff --git a/internal/cmd/beta/network/create/create_test.go b/internal/cmd/beta/network/create/create_test.go index 0d8b23728..d1284558d 100644 --- a/internal/cmd/beta/network/create/create_test.go +++ b/internal/cmd/beta/network/create/create_test.go @@ -65,6 +65,17 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.Ap return request } +func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.ApiCreateNetworkRequest { + request := testClient.CreateNetwork(testCtx, testProjectId) + request = request.CreateNetworkPayload(iaas.CreateNetworkPayload{ + Name: utils.Ptr("example-network-name"), + }) + for _, mod := range mods { + mod(&request) + } + return request +} + func fixturePayload(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.CreateNetworkPayload { payload := iaas.CreateNetworkPayload{ Name: utils.Ptr("example-network-name"), @@ -226,6 +237,17 @@ func TestBuildRequest(t *testing.T) { model: fixtureInputModel(), expectedRequest: fixtureRequest(), }, + { + description: "only name in payload", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example-network-name"), + }, + expectedRequest: fixtureRequiredRequest(), + }, } for _, tt := range tests { diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/beta/network/update/update.go index 67f7e5acd..748828778 100644 --- a/internal/cmd/beta/network/update/update.go +++ b/internal/cmd/beta/network/update/update.go @@ -34,7 +34,6 @@ type inputModel struct { Name *string IPv4DnsNameServers *[]string IPv6DnsNameServers *[]string - IPv6PrefixLength *int64 } func NewCmd(p *print.Printer) *cobra.Command { @@ -166,8 +165,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } payload := iaas.PartialUpdateNetworkPayload{ - Name: model.Name, - AddressFamily: addressFamily, + Name: model.Name, + } + + if addressFamily.Ipv4 != nil || addressFamily.Ipv6 != nil { + payload.AddressFamily = addressFamily } return req.PartialUpdateNetworkPayload(payload) From 394f4dda08f731462d2fbdc9c0421344ad95884b Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 4 Sep 2024 10:54:34 +0200 Subject: [PATCH 062/619] fix(deps): update stackit sdk modules (#471) Co-authored-by: Renovate Bot --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index cb19b8c0e..147d74dfb 100644 --- a/go.mod +++ b/go.mod @@ -15,12 +15,12 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 - github.com/stackitcloud/stackit-sdk-go/core v0.12.0 + github.com/stackitcloud/stackit-sdk-go/core v0.13.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0 @@ -78,12 +78,12 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.17.0 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.19.0 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.19.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.19.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect diff --git a/go.sum b/go.sum index 2b5cbc4c9..9c9712ea5 100644 --- a/go.sum +++ b/go.sum @@ -123,8 +123,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= -github.com/stackitcloud/stackit-sdk-go/core v0.12.0 h1:auIzUUNRuydKOScvpICP4MifGgvOajiDQd+ncGmBL0U= -github.com/stackitcloud/stackit-sdk-go/core v0.12.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= +github.com/stackitcloud/stackit-sdk-go/core v0.13.0 h1:BtJT2WXqZdexPPQi/HPUIr8g4JUPOCheh6J9dxiCQ4Q= +github.com/stackitcloud/stackit-sdk-go/core v0.13.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd0rCm+2+xaWqtfibjWmkKlO+U+7qxqvtKpJ8= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= @@ -133,24 +133,24 @@ github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0 h1:RPqCcepRpm4c2POVu github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 h1:/GwkGMD7ID5hSjdZs1l/Mj8waceCt7oj3TxHgBfEMDQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0 h1:S8UZYBu2lHmKCPTR17jZetIal8X7cHO1gVRv101UdPw= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.17.0/go.mod h1:bj9cn1treNSxKTRCEmESwqfENN8vCYn60HUnEA0P83c= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.17.0 h1:+amOO/LW/PfUVU2ptxoB8PuNacawjjX2gGh7bHd45RE= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.17.0/go.mod h1:kPetkX9hNm9HkRyiKQL/tlgdi8frZdMP8afg0mEvQ9s= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0 h1:FaJYVfha+atvPfFIf3h3+BFjOjeux9OBHukG1J98kq0= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.14.0/go.mod h1:iFerEzGmkg6R13ldFUyHUWHm0ac9cS4ftTDLhP0k/dU= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.19.0 h1:KcsF549yXOrm8zlqFCNV+lf2L4zvQuh4L2i3kgdWbOE= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.19.0/go.mod h1:bj9cn1treNSxKTRCEmESwqfENN8vCYn60HUnEA0P83c= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.19.0 h1:tlU/Z1Z8IXqWdkdIQYSHkO/btqYX80rg3oddKBzn430= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.19.0/go.mod h1:kPetkX9hNm9HkRyiKQL/tlgdi8frZdMP8afg0mEvQ9s= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.15.0 h1:WjjG2GJ+7fBH7Akil2srDBZhCbqxNpAR8LhYwIoeylo= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.15.0/go.mod h1:iFerEzGmkg6R13ldFUyHUWHm0ac9cS4ftTDLhP0k/dU= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 h1:tn1MD1nu+gYEbT3lslRI6BrapKwuvHv5Wi2Zw9uVPPc= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0/go.mod h1:dkVMJI88eJ3Xs0ZV15r4tUpgitUGJXcvrX3RL4Zq2bQ= github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0 h1:VdxYMJqGKUvk7/l2b83Z/bB0FUYuFbELK/ipTicJ5QY= github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0/go.mod h1:cSnBZGdtx4jnn9HEefkQHDrm8+PuS0NCWvukVfuwP/8= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0 h1:EEjhfIFiC4TsaFKB4mkxz6NFz4InfVs5STmWc+oEjgQ= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.16.0/go.mod h1:ZecMIf9oYj2DGZqWh93l97WdVaRdLl+tW5Fq3YKGwBM= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.18.0 h1:pzHA3sxaAsZzKjsCffMcToAk3ooZsj1PxwZODGRTpoI= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.18.0/go.mod h1:ZecMIf9oYj2DGZqWh93l97WdVaRdLl+tW5Fq3YKGwBM= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 h1:05wQYhO37Z4y8xAD+4OTYz6rYu6eJEmwMfCG4tjETEc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0/go.mod h1:SdrqGLCkilL6wl1+jcxmLtks2IocgIg+bsyeyYUIzR4= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.17.0 h1:k8GIrOQj+COIgkkHNNXw5ciUzvWU/RjL5XD7t5DTrOM= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.17.0/go.mod h1:eSgnPBknTJh7t+jVKN+xzeAh+Cg1USOlH3QCyfvG20g= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0 h1:jnApmhchW5FYNWss1d2hJzH7O3slBOYa2wEseg5pl3o= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.17.0/go.mod h1:3LhiTR/DMbKR2HuleTzlFHltR1MT1KD0DeW46X6K2GE= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.19.0 h1:qZ62GSQKw73JrS7a9WeGILMki26KNyqrMOmD8r41u/A= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.19.0/go.mod h1:eSgnPBknTJh7t+jVKN+xzeAh+Cg1USOlH3QCyfvG20g= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.19.0 h1:/s9GUIpwZTN6I7J4nKmBBmxc6lPJYpCHHxYsC+gDsZs= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.19.0/go.mod h1:3LhiTR/DMbKR2HuleTzlFHltR1MT1KD0DeW46X6K2GE= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 h1:qCbvGqdG9saRB++UlhXt5ieCCDCITROqL5K2nm38efU= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0/go.mod h1:p16qz/pAW8b1gEhqMpIgJfutRPeDPqQLlbVGyCo3f8o= github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0 h1:4EApay9ceTTmIG7bI1XWN1zcevkAiCyAvHrS4sp7s5g= From 252640688008637edba69305ec84a7f7dff0d08f Mon Sep 17 00:00:00 2001 From: Vicente Pinto Date: Wed, 4 Sep 2024 10:42:51 +0100 Subject: [PATCH 063/619] Get IDP endpoints from well-known config (#470) * Get IDP endpoints from well-known config * Refactor parsing of the well known config * Fix lint * Add unit test * Fix resource-manager custom endpoint --- internal/cmd/config/set/set.go | 14 +-- internal/cmd/config/unset/unset.go | 14 +-- internal/cmd/config/unset/unset_test.go | 10 +- internal/pkg/auth/storage.go | 2 + internal/pkg/auth/user_login.go | 81 +++++++++++++--- internal/pkg/auth/user_login_test.go | 110 ++++++++++++++++++++++ internal/pkg/auth/user_token_flow.go | 14 ++- internal/pkg/auth/user_token_flow_test.go | 15 +-- internal/pkg/auth/utils.go | 22 +++-- internal/pkg/auth/utils_test.go | 8 +- internal/pkg/config/config.go | 10 +- 11 files changed, 236 insertions(+), 64 deletions(-) create mode 100644 internal/pkg/auth/user_login_test.go diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index c5b46a3c3..75fd59379 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -17,10 +17,10 @@ import ( ) const ( - sessionTimeLimitFlag = "session-time-limit" - identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" - identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" - allowedUrlDomainFlag = "allowed-url-domain" + sessionTimeLimitFlag = "session-time-limit" + identityProviderCustomWellKnownConfigurationFlag = "identity-provider-custom-well-known-configuration" + identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" + allowedUrlDomainFlag = "allowed-url-domain" authorizationCustomEndpointFlag = "authorization-custom-endpoint" dnsCustomEndpointFlag = "dns-custom-endpoint" @@ -131,7 +131,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e func configureFlags(cmd *cobra.Command) { cmd.Flags().String(sessionTimeLimitFlag, "", "Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect)") - cmd.Flags().String(identityProviderCustomEndpointFlag, "", "Identity Provider base URL, used for user authentication") + cmd.Flags().String(identityProviderCustomWellKnownConfigurationFlag, "", "Identity Provider well-known OpenID configuration URL, used for user authentication") cmd.Flags().String(identityProviderCustomClientIdFlag, "", "Identity Provider client ID, used for user authentication") cmd.Flags().String(allowedUrlDomainFlag, "", `Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command`) cmd.Flags().String(observabilityCustomEndpointFlag, "", "Observability API base URL, used in calls to this API") @@ -159,7 +159,7 @@ func configureFlags(cmd *cobra.Command) { err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) cobra.CheckErr(err) - err = viper.BindPFlag(config.IdentityProviderCustomEndpointKey, cmd.Flags().Lookup(identityProviderCustomEndpointFlag)) + err = viper.BindPFlag(config.IdentityProviderCustomWellKnownConfigurationKey, cmd.Flags().Lookup(identityProviderCustomWellKnownConfigurationFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.IdentityProviderCustomClientIdKey, cmd.Flags().Lookup(identityProviderCustomClientIdFlag)) cobra.CheckErr(err) @@ -190,7 +190,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.RedisCustomEndpointKey, cmd.Flags().Lookup(redisCustomEndpointFlag)) cobra.CheckErr(err) - err = viper.BindPFlag(config.ResourceManagerEndpointKey, cmd.Flags().Lookup(skeCustomEndpointFlag)) + err = viper.BindPFlag(config.ResourceManagerEndpointKey, cmd.Flags().Lookup(resourceManagerCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.SecretsManagerCustomEndpointKey, cmd.Flags().Lookup(secretsManagerCustomEndpointFlag)) cobra.CheckErr(err) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index ab94bf8cc..f437bc98e 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -20,10 +20,10 @@ const ( projectIdFlag = globalflags.ProjectIdFlag verbosityFlag = globalflags.VerbosityFlag - sessionTimeLimitFlag = "session-time-limit" - identityProviderCustomEndpointFlag = "identity-provider-custom-endpoint" - identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" - allowedUrlDomainFlag = "allowed-url-domain" + sessionTimeLimitFlag = "session-time-limit" + identityProviderCustomWellKnownConfigurationFlag = "identity-provider-custom-well-known-configuration" + identityProviderCustomClientIdFlag = "identity-provider-custom-client-id" + allowedUrlDomainFlag = "allowed-url-domain" authorizationCustomEndpointFlag = "authorization-custom-endpoint" dnsCustomEndpointFlag = "dns-custom-endpoint" @@ -121,7 +121,7 @@ func NewCmd(p *print.Printer) *cobra.Command { viper.Set(config.SessionTimeLimitKey, config.SessionTimeLimitDefault) } if model.IdentityProviderCustomEndpoint { - viper.Set(config.IdentityProviderCustomEndpointKey, "") + viper.Set(config.IdentityProviderCustomWellKnownConfigurationKey, "") } if model.IdentityProviderCustomClientID { viper.Set(config.IdentityProviderCustomClientIdKey, "") @@ -215,7 +215,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(verbosityFlag, false, "Verbosity of the CLI") cmd.Flags().Bool(sessionTimeLimitFlag, false, fmt.Sprintf("Maximum time before authentication is required again. If unset, defaults to %s", config.SessionTimeLimitDefault)) - cmd.Flags().Bool(identityProviderCustomEndpointFlag, false, "Identity Provider base URL. If unset, uses the default base URL") + cmd.Flags().Bool(identityProviderCustomWellKnownConfigurationFlag, false, "Identity Provider well-known OpenID configuration URL. If unset, uses the default identity provider") cmd.Flags().Bool(identityProviderCustomClientIdFlag, false, "Identity Provider client ID, used for user authentication") cmd.Flags().Bool(allowedUrlDomainFlag, false, fmt.Sprintf("Domain name, used for the verification of the URLs that are given in the IDP endpoint and curl commands. If unset, defaults to %s", config.AllowedUrlDomainDefault)) @@ -251,7 +251,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { Verbosity: flags.FlagToBoolValue(p, cmd, verbosityFlag), SessionTimeLimit: flags.FlagToBoolValue(p, cmd, sessionTimeLimitFlag), - IdentityProviderCustomEndpoint: flags.FlagToBoolValue(p, cmd, identityProviderCustomEndpointFlag), + IdentityProviderCustomEndpoint: flags.FlagToBoolValue(p, cmd, identityProviderCustomWellKnownConfigurationFlag), IdentityProviderCustomClientID: flags.FlagToBoolValue(p, cmd, identityProviderCustomClientIdFlag), AllowedUrlDomain: flags.FlagToBoolValue(p, cmd, allowedUrlDomainFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 46fb369a4..2bf703677 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -16,10 +16,10 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool projectIdFlag: true, verbosityFlag: true, - sessionTimeLimitFlag: true, - identityProviderCustomEndpointFlag: true, - identityProviderCustomClientIdFlag: true, - allowedUrlDomainFlag: true, + sessionTimeLimitFlag: true, + identityProviderCustomWellKnownConfigurationFlag: true, + identityProviderCustomClientIdFlag: true, + allowedUrlDomainFlag: true, authorizationCustomEndpointFlag: true, dnsCustomEndpointFlag: true, @@ -157,7 +157,7 @@ func TestParseInput(t *testing.T) { { description: "identity provider custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { - flagValues[identityProviderCustomEndpointFlag] = false + flagValues[identityProviderCustomWellKnownConfigurationFlag] = false }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { diff --git a/internal/pkg/auth/storage.go b/internal/pkg/auth/storage.go index 1d30d1997..d5488fe73 100644 --- a/internal/pkg/auth/storage.go +++ b/internal/pkg/auth/storage.go @@ -37,6 +37,7 @@ const ( SERVICE_ACCOUNT_KEY authFieldKey = "service_account_key" PRIVATE_KEY authFieldKey = "private_key" TOKEN_CUSTOM_ENDPOINT authFieldKey = "token_custom_endpoint" + IDP_TOKEN_ENDPOINT authFieldKey = "idp_token_endpoint" //nolint:gosec // linter false positive ) const ( @@ -57,6 +58,7 @@ var authFieldKeys = []authFieldKey{ SERVICE_ACCOUNT_KEY, PRIVATE_KEY, TOKEN_CUSTOM_ENDPOINT, + IDP_TOKEN_ENDPOINT, authFlowType, } diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index f35c8cc75..9e12fd15a 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -23,8 +23,8 @@ import ( ) const ( - defaultIDPEndpoint = "https://accounts.stackit.cloud/oauth/v2" - defaultCLIClientID = "stackit-cli-0000-0000-000000000001" + defaultWellKnownConfig = "https://accounts.stackit.cloud/.well-known/openid-configuration" + defaultCLIClientID = "stackit-cli-0000-0000-000000000001" loginSuccessPath = "/login-successful" stackitLandingPage = "https://www.stackit.de" @@ -44,20 +44,31 @@ type User struct { Email string } +type apiClient interface { + Do(req *http.Request) (*http.Response, error) +} + // AuthorizeUser implements the PKCE OAuth2 flow. func AuthorizeUser(p *print.Printer, isReauthentication bool) error { - idpEndpoint, err := getIDPEndpoint() + idpWellKnownConfigURL, err := getIDPWellKnownConfigURL() if err != nil { - return err + return fmt.Errorf("get IDP well-known configuration: %w", err) } - if idpEndpoint != defaultIDPEndpoint { - p.Warn("You are using a custom identity provider (%s) for authentication.\n", idpEndpoint) + if idpWellKnownConfigURL != defaultWellKnownConfig { + p.Warn("You are using a custom identity provider well-known configuration (%s) for authentication.\n", idpWellKnownConfigURL) err := p.PromptForEnter("Press Enter to proceed with the login...") if err != nil { return err } } + p.Debug(print.DebugLevel, "get IDP well-known configuration from %s", idpWellKnownConfigURL) + httpClient := &http.Client{} + idpWellKnownConfig, err := parseWellKnownConfiguration(httpClient, idpWellKnownConfigURL) + if err != nil { + return fmt.Errorf("parse IDP well-known configuration: %w", err) + } + idpClientID, err := getIDPClientID() if err != nil { return err @@ -100,7 +111,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { conf := &oauth2.Config{ ClientID: idpClientID, Endpoint: oauth2.Endpoint{ - AuthURL: fmt.Sprintf("%s/authorize", idpEndpoint), + AuthURL: idpWellKnownConfig.AuthorizationEndpoint, }, Scopes: []string{"openid offline_access email"}, RedirectURL: redirectURL, @@ -147,7 +158,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { p.Debug(print.DebugLevel, "trading authorization code for access and refresh tokens") // Trade the authorization code and the code verifier for access and refresh tokens - accessToken, refreshToken, err := getUserAccessAndRefreshTokens(idpEndpoint, idpClientID, codeVerifier, code, redirectURL) + accessToken, refreshToken, err := getUserAccessAndRefreshTokens(idpWellKnownConfig, idpClientID, codeVerifier, code, redirectURL) if err != nil { errServer = fmt.Errorf("retrieve tokens: %w", err) return @@ -222,7 +233,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { }) p.Debug(print.DebugLevel, "opening browser for authentication") - p.Debug(print.DebugLevel, "using authentication server on %s", idpEndpoint) + p.Debug(print.DebugLevel, "using authentication server on %s", idpWellKnownConfig.Issuer) p.Debug(print.DebugLevel, "using client ID %s for authentication ", idpClientID) // Open a browser window to the authorizationURL @@ -248,9 +259,8 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { } // getUserAccessAndRefreshTokens trades the authorization code retrieved from the first OAuth2 leg for an access token and a refresh token -func getUserAccessAndRefreshTokens(authDomain, clientID, codeVerifier, authorizationCode, callbackURL string) (accessToken, refreshToken string, err error) { - // Set the authUrl and form-encoded data for the POST to the access token endpoint - authUrl := fmt.Sprintf("%s/token", authDomain) +func getUserAccessAndRefreshTokens(idpWellKnownConfig *wellKnownConfig, clientID, codeVerifier, authorizationCode, callbackURL string) (accessToken, refreshToken string, err error) { + // Set form-encoded data for the POST to the access token endpoint data := fmt.Sprintf( "grant_type=authorization_code&client_id=%s"+ "&code_verifier=%s"+ @@ -260,7 +270,7 @@ func getUserAccessAndRefreshTokens(authDomain, clientID, codeVerifier, authoriza payload := strings.NewReader(data) // Create the request and execute it - req, _ := http.NewRequest("POST", authUrl, payload) + req, _ := http.NewRequest("POST", idpWellKnownConfig.TokenEndpoint, payload) req.Header.Add("content-type", "application/x-www-form-urlencoded") httpClient := &http.Client{} res, err := httpClient.Do(req) @@ -331,3 +341,48 @@ func openBrowser(pageUrl string) error { } return nil } + +// parseWellKnownConfiguration gets the well-known OpenID configuration from the provided URL and returns it as a JSON +// the method also stores the IDP token endpoint in the authentication storage +func parseWellKnownConfiguration(httpClient apiClient, wellKnownConfigURL string) (wellKnownConfig *wellKnownConfig, err error) { + req, _ := http.NewRequest("GET", wellKnownConfigURL, http.NoBody) + res, err := httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("make the request: %w", err) + } + + // Process the response + defer func() { + closeErr := res.Body.Close() + if closeErr != nil { + err = fmt.Errorf("close response body: %w", closeErr) + } + }() + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, fmt.Errorf("read response body: %w", err) + } + + err = json.Unmarshal(body, &wellKnownConfig) + if err != nil { + return nil, fmt.Errorf("unmarshal response: %w", err) + } + if wellKnownConfig == nil { + return nil, fmt.Errorf("nil well-known configuration response") + } + if wellKnownConfig.Issuer == "" { + return nil, fmt.Errorf("found no issuer") + } + if wellKnownConfig.AuthorizationEndpoint == "" { + return nil, fmt.Errorf("found no authorization endpoint") + } + if wellKnownConfig.TokenEndpoint == "" { + return nil, fmt.Errorf("found no token endpoint") + } + + err = SetAuthField(IDP_TOKEN_ENDPOINT, wellKnownConfig.TokenEndpoint) + if err != nil { + return nil, fmt.Errorf("set token endpoint in the authentication storage: %w", err) + } + return wellKnownConfig, err +} diff --git a/internal/pkg/auth/user_login_test.go b/internal/pkg/auth/user_login_test.go new file mode 100644 index 000000000..7b61a4af5 --- /dev/null +++ b/internal/pkg/auth/user_login_test.go @@ -0,0 +1,110 @@ +package auth + +import ( + "fmt" + "io" + "net/http" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/zalando/go-keyring" +) + +type apiClientMocked struct { + getFails bool + getResponse string +} + +func (a *apiClientMocked) Do(_ *http.Request) (*http.Response, error) { + if a.getFails { + return &http.Response{ + StatusCode: http.StatusNotFound, + }, fmt.Errorf("not found") + } + return &http.Response{ + Status: "200 OK", + StatusCode: http.StatusAccepted, + Body: io.NopCloser(strings.NewReader(a.getResponse)), + }, nil +} + +func TestParseWellKnownConfig(t *testing.T) { + tests := []struct { + name string + getFails bool + getResponse string + isValid bool + expected *wellKnownConfig + }{ + { + name: "success", + getFails: false, + getResponse: `{"issuer":"issuer","authorization_endpoint":"auth","token_endpoint":"token"}`, + isValid: true, + expected: &wellKnownConfig{ + Issuer: "issuer", + AuthorizationEndpoint: "auth", + TokenEndpoint: "token", + }, + }, + { + name: "get_fails", + getFails: true, + getResponse: "", + isValid: false, + expected: nil, + }, + { + name: "empty_response", + getFails: true, + getResponse: "", + isValid: false, + expected: nil, + }, + { + name: "missing_issuer", + getFails: true, + getResponse: `{"authorization_endpoint":"auth","token_endpoint":"token"}`, + isValid: false, + expected: nil, + }, + { + name: "missing_authorization", + getFails: true, + getResponse: `{"issuer":"issuer","token_endpoint":"token"}`, + isValid: false, + expected: nil, + }, + { + name: "missing_token", + getFails: true, + getResponse: `{"issuer":"issuer","authorization_endpoint":"auth"}`, + isValid: false, + expected: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + keyring.MockInit() + + testClient := apiClientMocked{ + tt.getFails, + tt.getResponse, + } + + got, err := parseWellKnownConfiguration(&testClient, "") + + if tt.isValid && err != nil { + t.Fatalf("expected no error, got %v", err) + } + if !tt.isValid && err == nil { + t.Fatalf("expected error, got none") + } + + if tt.isValid && !cmp.Equal(*got, *tt.expected) { + t.Fatalf("expected %v, got %v", tt.expected, got) + } + }) + } +} diff --git a/internal/pkg/auth/user_token_flow.go b/internal/pkg/auth/user_token_flow.go index 530672882..93d10b13a 100644 --- a/internal/pkg/auth/user_token_flow.go +++ b/internal/pkg/auth/user_token_flow.go @@ -19,6 +19,7 @@ type userTokenFlow struct { authFlow AuthFlow accessToken string refreshToken string + tokenEndpoint string } // Ensure the implementation satisfies the expected interface @@ -76,8 +77,9 @@ func loadVarsFromStorage(utf *userTokenFlow) error { return fmt.Errorf("get auth flow type: %w", err) } authFields := map[authFieldKey]string{ - ACCESS_TOKEN: "", - REFRESH_TOKEN: "", + ACCESS_TOKEN: "", + REFRESH_TOKEN: "", + IDP_TOKEN_ENDPOINT: "", } err = GetAuthFieldMap(authFields) if err != nil { @@ -87,6 +89,7 @@ func loadVarsFromStorage(utf *userTokenFlow) error { utf.authFlow = authFlow utf.accessToken = authFields[ACCESS_TOKEN] utf.refreshToken = authFields[REFRESH_TOKEN] + utf.tokenEndpoint = authFields[IDP_TOKEN_ENDPOINT] return nil } @@ -156,11 +159,6 @@ func refreshTokens(utf *userTokenFlow) (err error) { } func buildRequestToRefreshTokens(utf *userTokenFlow) (*http.Request, error) { - idpEndpoint, err := getIDPEndpoint() - if err != nil { - return nil, err - } - idpClientID, err := getIDPClientID() if err != nil { return nil, err @@ -168,7 +166,7 @@ func buildRequestToRefreshTokens(utf *userTokenFlow) (*http.Request, error) { req, err := http.NewRequest( http.MethodPost, - fmt.Sprintf("%s/token", idpEndpoint), + utf.tokenEndpoint, http.NoBody, ) if err != nil { diff --git a/internal/pkg/auth/user_token_flow_test.go b/internal/pkg/auth/user_token_flow_test.go index b014c5887..be57518ce 100644 --- a/internal/pkg/auth/user_token_flow_test.go +++ b/internal/pkg/auth/user_token_flow_test.go @@ -14,6 +14,10 @@ import ( "github.com/zalando/go-keyring" ) +const ( + testTokenEndpoint = "https://accounts.stackit.cloud/oauth/v2/token" //nolint:gosec // linter false positive +) + type clientTransport struct { t *testing.T // May write test errors requestURL string @@ -28,11 +32,7 @@ func (rt *clientTransport) RoundTrip(req *http.Request) (*http.Response, error) if reqURL == rt.requestURL { return rt.roundTripRequest() } - idpEndpoint, err := getIDPEndpoint() - if err != nil { - rt.t.Fatalf("get IDP endpoint for test: %v", err) - } - if fmt.Sprintf("https://%s", reqURL) == fmt.Sprintf("%s/token", idpEndpoint) { + if fmt.Sprintf("https://%s", reqURL) == testTokenEndpoint { return rt.roundTripRefreshTokens() } rt.t.Fatalf("unexpected request to %q", reqURL) @@ -354,8 +354,9 @@ func setAuthStorage(accessTokenExpiresAt, refreshTokenExpiresAt time.Time, acces return fmt.Errorf("set auth flow type: %w", err) } err = SetAuthFieldMap(map[authFieldKey]string{ - ACCESS_TOKEN: accessToken, - REFRESH_TOKEN: refreshToken, + ACCESS_TOKEN: accessToken, + REFRESH_TOKEN: refreshToken, + IDP_TOKEN_ENDPOINT: testTokenEndpoint, }) if err != nil { return fmt.Errorf("set refreshed tokens in auth storage: %w", err) diff --git a/internal/pkg/auth/utils.go b/internal/pkg/auth/utils.go index 162306b15..4fa431262 100644 --- a/internal/pkg/auth/utils.go +++ b/internal/pkg/auth/utils.go @@ -8,19 +8,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func getIDPEndpoint() (string, error) { - idpEndpoint := defaultIDPEndpoint +type wellKnownConfig struct { + Issuer string `json:"issuer"` + AuthorizationEndpoint string `json:"authorization_endpoint"` + TokenEndpoint string `json:"token_endpoint"` +} + +func getIDPWellKnownConfigURL() (wellKnownConfigURL string, err error) { + wellKnownConfigURL = defaultWellKnownConfig - customIDPEndpoint := viper.GetString(config.IdentityProviderCustomEndpointKey) - if customIDPEndpoint != "" { - idpEndpoint = customIDPEndpoint - err := utils.ValidateURLDomain(idpEndpoint) + customWellKnownConfig := viper.GetString(config.IdentityProviderCustomWellKnownConfigurationKey) + if customWellKnownConfig != "" { + wellKnownConfigURL = customWellKnownConfig + err := utils.ValidateURLDomain(wellKnownConfigURL) if err != nil { - return "", fmt.Errorf("validate custom identity provider endpoint: %w", err) + return "", fmt.Errorf("validate custom identity provider well-known configuration: %w", err) } } - return idpEndpoint, nil + return wellKnownConfigURL, nil } func getIDPClientID() (string, error) { diff --git a/internal/pkg/auth/utils_test.go b/internal/pkg/auth/utils_test.go index bb9e5a633..8112257d6 100644 --- a/internal/pkg/auth/utils_test.go +++ b/internal/pkg/auth/utils_test.go @@ -7,7 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" ) -func TestGetIDPEndpoint(t *testing.T) { +func TestGetWellKnownConfig(t *testing.T) { tests := []struct { name string idpCustomEndpoint string @@ -53,16 +53,16 @@ func TestGetIDPEndpoint(t *testing.T) { idpCustomEndpoint: "", allowedUrlDomain: "", isValid: true, - expected: defaultIDPEndpoint, + expected: defaultWellKnownConfig, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { viper.Reset() - viper.Set(config.IdentityProviderCustomEndpointKey, tt.idpCustomEndpoint) + viper.Set(config.IdentityProviderCustomWellKnownConfigurationKey, tt.idpCustomEndpoint) viper.Set(config.AllowedUrlDomainKey, tt.allowedUrlDomain) - got, err := getIDPEndpoint() + got, err := getIDPWellKnownConfigURL() if tt.isValid && err != nil { t.Fatalf("expected no error, got %v", err) diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 8f19a885c..6162e0521 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -17,9 +17,9 @@ const ( SessionTimeLimitKey = "session_time_limit" VerbosityKey = "verbosity" - IdentityProviderCustomEndpointKey = "identity_provider_custom_endpoint" - IdentityProviderCustomClientIdKey = "identity_provider_custom_client_id" - AllowedUrlDomainKey = "allowed_url_domain" + IdentityProviderCustomWellKnownConfigurationKey = "identity_provider_custom_well_known_configuration" + IdentityProviderCustomClientIdKey = "identity_provider_custom_client_id" + AllowedUrlDomainKey = "allowed_url_domain" AuthorizationCustomEndpointKey = "authorization_custom_endpoint" DNSCustomEndpointKey = "dns_custom_endpoint" @@ -71,7 +71,7 @@ var ConfigKeys = []string{ SessionTimeLimitKey, VerbosityKey, - IdentityProviderCustomEndpointKey, + IdentityProviderCustomWellKnownConfigurationKey, IdentityProviderCustomClientIdKey, AllowedUrlDomainKey, @@ -155,7 +155,7 @@ func setConfigDefaults() { viper.SetDefault(OutputFormatKey, "") viper.SetDefault(ProjectIdKey, "") viper.SetDefault(SessionTimeLimitKey, SessionTimeLimitDefault) - viper.SetDefault(IdentityProviderCustomEndpointKey, "") + viper.SetDefault(IdentityProviderCustomWellKnownConfigurationKey, "") viper.SetDefault(IdentityProviderCustomClientIdKey, "") viper.SetDefault(AllowedUrlDomainKey, AllowedUrlDomainDefault) viper.SetDefault(DNSCustomEndpointKey, "") From 2c4507add2b2b405ea0c803c18bd97c6a6426196 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:58:51 +0200 Subject: [PATCH 064/619] update docs (#472) --- docs/stackit_config_set.md | 54 +++++++++++++++---------------- docs/stackit_config_unset.md | 62 ++++++++++++++++++------------------ 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 7fc9930ac..087a45120 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -29,33 +29,33 @@ stackit config set [flags] ### Options ``` - --allowed-url-domain string Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command - --authorization-custom-endpoint string Authorization API base URL, used in calls to this API - --dns-custom-endpoint string DNS API base URL, used in calls to this API - -h, --help Help for "stackit config set" - --iaas-custom-endpoint string IaaS API base URL, used in calls to this API - --identity-provider-custom-client-id string Identity Provider client ID, used for user authentication - --identity-provider-custom-endpoint string Identity Provider base URL, used for user authentication - --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API - --logme-custom-endpoint string LogMe API base URL, used in calls to this API - --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API - --mongodbflex-custom-endpoint string MongoDB Flex API base URL, used in calls to this API - --object-storage-custom-endpoint string Object Storage API base URL, used in calls to this API - --observability-custom-endpoint string Observability API base URL, used in calls to this API - --opensearch-custom-endpoint string OpenSearch API base URL, used in calls to this API - --postgresflex-custom-endpoint string PostgreSQL Flex API base URL, used in calls to this API - --rabbitmq-custom-endpoint string RabbitMQ API base URL, used in calls to this API - --redis-custom-endpoint string Redis API base URL, used in calls to this API - --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API - --runcommand-custom-endpoint string Run Command API base URL, used in calls to this API - --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API - --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API - --service-account-custom-endpoint string Service Account API base URL, used in calls to this API - --service-enablement-custom-endpoint string Service Enablement API base URL, used in calls to this API - --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) - --ske-custom-endpoint string SKE API base URL, used in calls to this API - --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API - --token-custom-endpoint string Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated + --allowed-url-domain string Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command + --authorization-custom-endpoint string Authorization API base URL, used in calls to this API + --dns-custom-endpoint string DNS API base URL, used in calls to this API + -h, --help Help for "stackit config set" + --iaas-custom-endpoint string IaaS API base URL, used in calls to this API + --identity-provider-custom-client-id string Identity Provider client ID, used for user authentication + --identity-provider-custom-well-known-configuration string Identity Provider well-known OpenID configuration URL, used for user authentication + --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API + --logme-custom-endpoint string LogMe API base URL, used in calls to this API + --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API + --mongodbflex-custom-endpoint string MongoDB Flex API base URL, used in calls to this API + --object-storage-custom-endpoint string Object Storage API base URL, used in calls to this API + --observability-custom-endpoint string Observability API base URL, used in calls to this API + --opensearch-custom-endpoint string OpenSearch API base URL, used in calls to this API + --postgresflex-custom-endpoint string PostgreSQL Flex API base URL, used in calls to this API + --rabbitmq-custom-endpoint string RabbitMQ API base URL, used in calls to this API + --redis-custom-endpoint string Redis API base URL, used in calls to this API + --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API + --runcommand-custom-endpoint string Run Command API base URL, used in calls to this API + --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API + --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API + --service-account-custom-endpoint string Service Account API base URL, used in calls to this API + --service-enablement-custom-endpoint string Service Enablement API base URL, used in calls to this API + --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) + --ske-custom-endpoint string SKE API base URL, used in calls to this API + --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API + --token-custom-endpoint string Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated ``` ### Options inherited from parent commands diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 1971e3605..779cf2c57 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -26,37 +26,37 @@ stackit config unset [flags] ### Options ``` - --allowed-url-domain Domain name, used for the verification of the URLs that are given in the IDP endpoint and curl commands. If unset, defaults to stackit.cloud - --async Configuration option to run commands asynchronously - --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL - --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL - -h, --help Help for "stackit config unset" - --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL - --identity-provider-custom-client-id Identity Provider client ID, used for user authentication - --identity-provider-custom-endpoint Identity Provider base URL. If unset, uses the default base URL - --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL - --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL - --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL - --mongodbflex-custom-endpoint MongoDB Flex API base URL. If unset, uses the default base URL - --object-storage-custom-endpoint Object Storage API base URL. If unset, uses the default base URL - --observability-custom-endpoint Observability API base URL. If unset, uses the default base URL - --opensearch-custom-endpoint OpenSearch API base URL. If unset, uses the default base URL - --output-format Output format - --postgresflex-custom-endpoint PostgreSQL Flex API base URL. If unset, uses the default base URL - --project-id Project ID - --rabbitmq-custom-endpoint RabbitMQ API base URL. If unset, uses the default base URL - --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL - --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL - --runcommand-custom-endpoint Server Command base URL. If unset, uses the default base URL - --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL - --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL - --service-account-custom-endpoint Service Account API base URL. If unset, uses the default base URL - --service-enablement-custom-endpoint Service Enablement API base URL. If unset, uses the default base URL - --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h - --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL - --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL - --token-custom-endpoint Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated - --verbosity Verbosity of the CLI + --allowed-url-domain Domain name, used for the verification of the URLs that are given in the IDP endpoint and curl commands. If unset, defaults to stackit.cloud + --async Configuration option to run commands asynchronously + --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL + --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL + -h, --help Help for "stackit config unset" + --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL + --identity-provider-custom-client-id Identity Provider client ID, used for user authentication + --identity-provider-custom-well-known-configuration Identity Provider well-known OpenID configuration URL. If unset, uses the default identity provider + --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL + --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL + --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL + --mongodbflex-custom-endpoint MongoDB Flex API base URL. If unset, uses the default base URL + --object-storage-custom-endpoint Object Storage API base URL. If unset, uses the default base URL + --observability-custom-endpoint Observability API base URL. If unset, uses the default base URL + --opensearch-custom-endpoint OpenSearch API base URL. If unset, uses the default base URL + --output-format Output format + --postgresflex-custom-endpoint PostgreSQL Flex API base URL. If unset, uses the default base URL + --project-id Project ID + --rabbitmq-custom-endpoint RabbitMQ API base URL. If unset, uses the default base URL + --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL + --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL + --runcommand-custom-endpoint Server Command base URL. If unset, uses the default base URL + --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL + --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL + --service-account-custom-endpoint Service Account API base URL. If unset, uses the default base URL + --service-enablement-custom-endpoint Service Enablement API base URL. If unset, uses the default base URL + --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h + --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL + --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL + --token-custom-endpoint Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated + --verbosity Verbosity of the CLI ``` ### Options inherited from parent commands From fd8298139576432025e6eb715ee8e4132c82ea6a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 9 Sep 2024 09:54:00 +0200 Subject: [PATCH 065/619] fix(deps): update module golang.org/x/text to v0.18.0 (#476) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 147d74dfb..a25942f17 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.22.0 golang.org/x/term v0.23.0 - golang.org/x/text v0.17.0 + golang.org/x/text v0.18.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 ) diff --git a/go.sum b/go.sum index 9c9712ea5..310bdfe76 100644 --- a/go.sum +++ b/go.sum @@ -219,8 +219,8 @@ golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 425a9a2e4e560a6c7c76d3eaa059b3a1e2679dd6 Mon Sep 17 00:00:00 2001 From: Vicente Pinto Date: Thu, 12 Sep 2024 11:43:11 +0100 Subject: [PATCH 066/619] Update flag description (#477) * Update flag description * Update docs --- docs/stackit_config_set.md | 2 +- docs/stackit_config_unset.md | 2 +- internal/cmd/config/set/set.go | 2 +- internal/cmd/config/unset/unset.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 087a45120..85c02b0bf 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -55,7 +55,7 @@ stackit config set [flags] --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) --ske-custom-endpoint string SKE API base URL, used in calls to this API --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API - --token-custom-endpoint string Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated + --token-custom-endpoint string Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication. ``` ### Options inherited from parent commands diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 779cf2c57..254184b5d 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -55,7 +55,7 @@ stackit config unset [flags] --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL - --token-custom-endpoint Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated + --token-custom-endpoint Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication. --verbosity Verbosity of the CLI ``` diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 75fd59379..70ea7b7b6 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -155,7 +155,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") cmd.Flags().String(iaasCustomEndpointFlag, "", "IaaS API base URL, used in calls to this API") - cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated") + cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication.") err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) cobra.CheckErr(err) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index f437bc98e..2b9ff15ec 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -240,7 +240,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(skeCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") cmd.Flags().Bool(iaasCustomEndpointFlag, false, "IaaS API base URL. If unset, uses the default base URL") - cmd.Flags().Bool(tokenCustomEndpointFlag, false, "Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated") + cmd.Flags().Bool(tokenCustomEndpointFlag, false, "Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication.") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { From 72dc20a3541ddba9202ad6d5c1847818a12e13e7 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:10:57 +0200 Subject: [PATCH 067/619] add maxUnavailable to utils (#479) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gökçe Gök Klingel --- internal/pkg/services/ske/utils/utils.go | 10 ++++++---- internal/pkg/services/ske/utils/utils_test.go | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 8af234111..1ce6c8974 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -21,6 +21,7 @@ const ( defaultNodepoolMachineType = "b1.2" defaultNodepoolMachineImageName = "flatcar" defaultNodepoolMaxSurge = 1 + defaultNodepoolMaxUnavailable = 0 defaultNodepoolMaximum = 2 defaultNodepoolMinimum = 1 defaultNodepoolName = "pool-default" @@ -138,10 +139,11 @@ func getDefaultPayloadNodepool(resp *ske.ProviderOptions) (*ske.Nodepool, error) Name: utils.Ptr(defaultNodepoolMachineImageName), }, }, - MaxSurge: utils.Ptr(int64(defaultNodepoolMaxSurge)), - Maximum: utils.Ptr(int64(defaultNodepoolMaximum)), - Minimum: utils.Ptr(int64(defaultNodepoolMinimum)), - Name: utils.Ptr(defaultNodepoolName), + MaxSurge: utils.Ptr(int64(defaultNodepoolMaxSurge)), + MaxUnavailable: utils.Ptr(int64(defaultNodepoolMaxUnavailable)), + Maximum: utils.Ptr(int64(defaultNodepoolMaximum)), + Minimum: utils.Ptr(int64(defaultNodepoolMinimum)), + Name: utils.Ptr(defaultNodepoolName), Volume: &ske.Volume{ Type: utils.Ptr(defaultNodepoolVolumeType), Size: utils.Ptr(int64(defaultNodepoolVolumeSize)), diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index bcf8139b5..55331155a 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -312,10 +312,11 @@ func fixtureGetDefaultPayload(mods ...func(*ske.CreateOrUpdateClusterPayload)) * Name: utils.Ptr("flatcar"), }, }, - MaxSurge: utils.Ptr(int64(1)), - Maximum: utils.Ptr(int64(2)), - Minimum: utils.Ptr(int64(1)), - Name: utils.Ptr("pool-default"), + MaxSurge: utils.Ptr(int64(1)), + MaxUnavailable: utils.Ptr(int64(0)), + Maximum: utils.Ptr(int64(2)), + Minimum: utils.Ptr(int64(1)), + Name: utils.Ptr("pool-default"), Volume: &ske.Volume{ Type: utils.Ptr("storage_premium_perf2"), Size: utils.Ptr(int64(50)), From 0c414fe3a10f0eb4538a82bdbf9af493c4d64815 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:19:03 +0200 Subject: [PATCH 068/619] fix(deps): update module golang.org/x/term to v0.24.0 (#475) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index a25942f17..8c4ba8b07 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.22.0 - golang.org/x/term v0.23.0 + golang.org/x/term v0.24.0 golang.org/x/text v0.18.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 @@ -87,7 +87,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/sys v0.23.0 // indirect + golang.org/x/sys v0.25.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 310bdfe76..e896ea794 100644 --- a/go.sum +++ b/go.sum @@ -213,10 +213,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= From c9b7a731e89197a3d6077e253e5a97eb3019a528 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:19:45 +0200 Subject: [PATCH 069/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex to v0.6.0 (#480) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8c4ba8b07..a3e122163 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.6.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.22.0 diff --git a/go.sum b/go.sum index e896ea794..ba59336e8 100644 --- a/go.sum +++ b/go.sum @@ -165,8 +165,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 h1:HAEF github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0/go.mod h1:z6XdA+ndaWzcPW/P0QrUIcTXJzKlajxgGZ5+EwXNS+c= github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 h1:vmkfa26HO1VA40pKPNnYMHkcNMxBEWAdYbX+5LVIo48= github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.5.0 h1:Nil6gmhXik5FsnvvfagpHReFNg/uxeMS+8YHOkU5bRg= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.5.0/go.mod h1:Qnn+06i21XtagtMQ4cTwOCR3OLnXX+t1n+Vf/HH49Yw= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.6.0 h1:NmvKgrl3DIxRrQXJDCWG8Nq8CBsszXDDpNwKvtFg1OM= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.6.0/go.mod h1:v9H724TPZqulC9Mv7LkZJzHukzl/XPBhuoYf4yhFD3k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= From a74ba3754a2003d5fe583d0bd48a8b77d7cd74d8 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:28:59 +0200 Subject: [PATCH 070/619] fix(deps): update module golang.org/x/oauth2 to v0.23.0 (#474) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a3e122163..7c5e0dfce 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.6.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 - golang.org/x/oauth2 v0.22.0 + golang.org/x/oauth2 v0.23.0 golang.org/x/term v0.24.0 golang.org/x/text v0.18.0 k8s.io/apimachinery v0.29.2 diff --git a/go.sum b/go.sum index ba59336e8..72a0075a6 100644 --- a/go.sum +++ b/go.sum @@ -203,8 +203,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 4d745dc1ab534e1ef72a403048b2b250aee3a0a9 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:29:18 +0200 Subject: [PATCH 071/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.6.0 (#482) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7c5e0dfce..b1e42504f 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.5.9 + github.com/jedib0t/go-pretty/v6 v6.6.0 github.com/lmittmann/tint v1.0.5 github.com/mattn/go-colorable v0.1.13 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index 72a0075a6..1660257b9 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU= -github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.0 h1:wmZVuAcEkZRT+Aq1xXpE8IGat4vE5WXOMmBpbQqERXw= +github.com/jedib0t/go-pretty/v6 v6.6.0/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= From 66b708ad5e33e5183a474d9f2b639fb709399728 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:30:37 +0200 Subject: [PATCH 072/619] fix(deps): update module golang.org/x/text to v0.19.0 (#484) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b1e42504f..2feec819a 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.23.0 golang.org/x/term v0.24.0 - golang.org/x/text v0.18.0 + golang.org/x/text v0.19.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 ) diff --git a/go.sum b/go.sum index 1660257b9..cef5e8eec 100644 --- a/go.sum +++ b/go.sum @@ -219,8 +219,8 @@ golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From afc40babf32b52e6e1951e60d5dad7fedd46806d Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:38:38 +0200 Subject: [PATCH 073/619] fix(deps): update module golang.org/x/term to v0.25.0 (#483) Co-authored-by: Renovate Bot Co-authored-by: GokceGK <161626272+GokceGK@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 2feec819a..aa1a043cd 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.23.0 - golang.org/x/term v0.24.0 + golang.org/x/term v0.25.0 golang.org/x/text v0.19.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 @@ -87,7 +87,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/sys v0.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index cef5e8eec..a4921953c 100644 --- a/go.sum +++ b/go.sum @@ -213,10 +213,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= From ca3b2110d96d9c5b9818b63c2e019dda09f3aa38 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:53:12 +0200 Subject: [PATCH 074/619] fix(deps): update stackit sdk modules (#481) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update stackit sdk modules * change the function parameter type --------- Co-authored-by: Renovate Bot Co-authored-by: Gökçe Gök Klingel --- go.mod | 4 ++-- go.sum | 8 ++++---- .../sqlserverflex/user/reset-password/reset_password.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index aa1a043cd..346dd8165 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.13.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 @@ -29,7 +29,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.7.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.23.0 diff --git a/go.sum b/go.sum index a4921953c..7cb1b2f89 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0 h1:RPqCcepRpm4c2POVuq+W41UwhXEfSRQAM696evHIOlQ= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.8.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.10.0 h1:bqZ1CqiQLcu//4zc859XwYT/IZFjnlV9QeemmDbCPxc= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.10.0/go.mod h1:hEsLOmcqMFG0ftXSYOF8YtDrclkA0E89msGsH69B/BU= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 h1:/GwkGMD7ID5hSjdZs1l/Mj8waceCt7oj3TxHgBfEMDQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= github.com/stackitcloud/stackit-sdk-go/services/logme v0.19.0 h1:KcsF549yXOrm8zlqFCNV+lf2L4zvQuh4L2i3kgdWbOE= @@ -165,8 +165,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 h1:HAEF github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0/go.mod h1:z6XdA+ndaWzcPW/P0QrUIcTXJzKlajxgGZ5+EwXNS+c= github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 h1:vmkfa26HO1VA40pKPNnYMHkcNMxBEWAdYbX+5LVIo48= github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.6.0 h1:NmvKgrl3DIxRrQXJDCWG8Nq8CBsszXDDpNwKvtFg1OM= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.6.0/go.mod h1:v9H724TPZqulC9Mv7LkZJzHukzl/XPBhuoYf4yhFD3k= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.7.0 h1:BvLBsropXLpIXjyZ3GHZGa20ValT98Jpch4KW1lBliU= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.7.0/go.mod h1:v9H724TPZqulC9Mv7LkZJzHukzl/XPBhuoYf4yhFD3k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index 43802e763..d8cd47ad4 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -132,7 +132,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel string, user *sqlserverflex.User) error { +func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel string, user *sqlserverflex.SingleUser) error { switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") From 85688582cf51327283c9de004d5a3d7a8c92a637 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:53:54 +0200 Subject: [PATCH 075/619] update github-action to 40.3.1 (#485) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gökçe Gök Klingel --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index b44e7a13b..6e3af8c66 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v40.2.6 + uses: renovatebot/github-action@v40.3.1 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 9bc00050c8785041477c537dddc60a5a0d353b5b Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 16 Oct 2024 09:56:31 +0200 Subject: [PATCH 076/619] fix(deps): update stackit sdk modules (#486) Co-authored-by: Renovate Bot --- go.mod | 44 ++++++++++++++--------------- go.sum | 88 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/go.mod b/go.mod index 346dd8165..c52f8669e 100644 --- a/go.mod +++ b/go.mod @@ -15,21 +15,21 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 - github.com/stackitcloud/stackit-sdk-go/core v0.13.0 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.15.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.18.0 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.9.0 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.7.0 + github.com/stackitcloud/stackit-sdk-go/core v0.14.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.12.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.2.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.23.0 @@ -77,13 +77,13 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.19.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.0 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.0 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect diff --git a/go.sum b/go.sum index 7cb1b2f89..c8b30992d 100644 --- a/go.sum +++ b/go.sum @@ -123,50 +123,50 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= -github.com/stackitcloud/stackit-sdk-go/core v0.13.0 h1:BtJT2WXqZdexPPQi/HPUIr8g4JUPOCheh6J9dxiCQ4Q= -github.com/stackitcloud/stackit-sdk-go/core v0.13.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0 h1:AyzBgcbd0rCm+2+xaWqtfibjWmkKlO+U+7qxqvtKpJ8= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.3.0/go.mod h1:1sLuXa7Qvp9f+wKWdRjyNe8B2F8JX7nSTd8fBKadri4= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0 h1:QIZfs6nJ/l2pOweH1E+wazXnlAUtqisVbYUxWAokTbc= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.10.0/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.10.0 h1:bqZ1CqiQLcu//4zc859XwYT/IZFjnlV9QeemmDbCPxc= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.10.0/go.mod h1:hEsLOmcqMFG0ftXSYOF8YtDrclkA0E89msGsH69B/BU= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0 h1:/GwkGMD7ID5hSjdZs1l/Mj8waceCt7oj3TxHgBfEMDQ= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.14.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.19.0 h1:KcsF549yXOrm8zlqFCNV+lf2L4zvQuh4L2i3kgdWbOE= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.19.0/go.mod h1:bj9cn1treNSxKTRCEmESwqfENN8vCYn60HUnEA0P83c= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.19.0 h1:tlU/Z1Z8IXqWdkdIQYSHkO/btqYX80rg3oddKBzn430= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.19.0/go.mod h1:kPetkX9hNm9HkRyiKQL/tlgdi8frZdMP8afg0mEvQ9s= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.15.0 h1:WjjG2GJ+7fBH7Akil2srDBZhCbqxNpAR8LhYwIoeylo= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.15.0/go.mod h1:iFerEzGmkg6R13ldFUyHUWHm0ac9cS4ftTDLhP0k/dU= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0 h1:tn1MD1nu+gYEbT3lslRI6BrapKwuvHv5Wi2Zw9uVPPc= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.10.0/go.mod h1:dkVMJI88eJ3Xs0ZV15r4tUpgitUGJXcvrX3RL4Zq2bQ= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0 h1:VdxYMJqGKUvk7/l2b83Z/bB0FUYuFbELK/ipTicJ5QY= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.1.0/go.mod h1:cSnBZGdtx4jnn9HEefkQHDrm8+PuS0NCWvukVfuwP/8= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.18.0 h1:pzHA3sxaAsZzKjsCffMcToAk3ooZsj1PxwZODGRTpoI= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.18.0/go.mod h1:ZecMIf9oYj2DGZqWh93l97WdVaRdLl+tW5Fq3YKGwBM= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0 h1:05wQYhO37Z4y8xAD+4OTYz6rYu6eJEmwMfCG4tjETEc= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.15.0/go.mod h1:SdrqGLCkilL6wl1+jcxmLtks2IocgIg+bsyeyYUIzR4= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.19.0 h1:qZ62GSQKw73JrS7a9WeGILMki26KNyqrMOmD8r41u/A= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.19.0/go.mod h1:eSgnPBknTJh7t+jVKN+xzeAh+Cg1USOlH3QCyfvG20g= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.19.0 h1:/s9GUIpwZTN6I7J4nKmBBmxc6lPJYpCHHxYsC+gDsZs= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.19.0/go.mod h1:3LhiTR/DMbKR2HuleTzlFHltR1MT1KD0DeW46X6K2GE= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0 h1:qCbvGqdG9saRB++UlhXt5ieCCDCITROqL5K2nm38efU= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0/go.mod h1:p16qz/pAW8b1gEhqMpIgJfutRPeDPqQLlbVGyCo3f8o= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0 h1:4EApay9ceTTmIG7bI1XWN1zcevkAiCyAvHrS4sp7s5g= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.1.0/go.mod h1:pSDRPhmRYgRmKoQKL+tzgOmnin90sXUjfnc9jaTir8c= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.9.0 h1:Zzow6CUNFjM+gIPPR/onuR1yBeRqUOphDKf3zmefvFo= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.9.0/go.mod h1:LX0Mcyr7/QP77zf7e05fHCJO38RMuTxr7nEDUDZ3oPQ= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 h1:fYCBNvh4tqE+DXYDfbJEjC3n/I78zTZajdcPTPB/yig= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0/go.mod h1:ZYI3wj/NnhhWi25ugbdcniwnY/7mF6zN582c5HPe00o= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0 h1:JB1O0E9+L50ZaO36uz7azurvUuB5JdX5s2ZXuIdb9t8= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.4.0/go.mod h1:Ni9RBJvcaXRIrDIuQBpJcuQvCQSj27crQSyc+WM4p0c= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 h1:HAEFciLgeCY+kIcGcb+/zFUF3zt3z326v6JCen6fSjs= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0/go.mod h1:z6XdA+ndaWzcPW/P0QrUIcTXJzKlajxgGZ5+EwXNS+c= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0 h1:vmkfa26HO1VA40pKPNnYMHkcNMxBEWAdYbX+5LVIo48= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.19.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.7.0 h1:BvLBsropXLpIXjyZ3GHZGa20ValT98Jpch4KW1lBliU= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.7.0/go.mod h1:v9H724TPZqulC9Mv7LkZJzHukzl/XPBhuoYf4yhFD3k= +github.com/stackitcloud/stackit-sdk-go/core v0.14.0 h1:oBwwzrEHDTlZpRoQwmMQpNA8bWciTrtGkiN29nx14Z0= +github.com/stackitcloud/stackit-sdk-go/core v0.14.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 h1:WXSIE4KfdHzaiiD0MF8CsoIv8I+Two/Bf/r28tYhRCU= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 h1:+OZ82DwFy4JIJThadVjvll5kUWjHPSLbUIF65njsNBk= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.12.0 h1:tk/ztsZoFgcsyEFODaej8IGGuvprVbsrrJKGzm2PR14= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.12.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 h1:V0UGP7JEa4Q8SsZFUJsKgLGaoPruLn2KVKnqQtaoWCU= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0/go.mod h1:+NlUMcid2dEFSmqtbXJrcT57iP0oTdnIXHOQku0E04A= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.0 h1:Q59bOPYEI9HeFA4vFrpQN2z/KwbW9MFi7L4BJ2o40k8= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.0/go.mod h1:nuZK6OXyZ4zlGsC1gZDj9+ajJzzFi9vVgSSRQlEJAqA= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 h1:UYCEVpuv0Yq/sITf6yNCdJZw8PicWJJLT1TzBOego9g= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0/go.mod h1:CvGSm9Goma2O1xkA0LEJbHfZpGlhy0AXJnMPpMmRdMM= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.0 h1:pCuhlSsRUW/3YV/u7l8iWJCjGBXANboVFdW5WanASOg= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.0/go.mod h1:V2LEHKyTaaiEBi9L3v62mNQ7xyJSred4OK+himLJOZQ= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.0 h1:5UZrI0qs8CNAmv/Szhes6ebjQ4YrzShpanviJsX3gbg= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.0/go.mod h1:okcRTrNDTI3d7MQcYJMliK0qoXeLq0b1wvZuEqgJIWE= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 h1:KFP7xkVGU8b7tB6Rk3arKM8y9Q8OlSB9B5hVi0e1Xvo= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0/go.mod h1:U45gFwIAAdXWL/Wlp9rY3iPVWFHLGILz1C3Qc62o8KM= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 h1:aRVPIaTtM2zyep3k22lu6ARG0j0P1N/7fjH7TS6ucio= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0/go.mod h1:JnhCZzXprN/em1Uxpvl1ITMf6Hl/8N/4y5zNsRqEGlA= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.0 h1:823zATqn83jngf4XOzXxjoT338FhMUv9h+65dfk/SjY= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.0/go.mod h1:42oYZOqin+rIUrUqgtCIE4wzCWWY30H4UFhzvo1Wg2w= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.0 h1:GVBQbLvJlIViURciLiX8z9zpbTuHAg2dGwVdwWSEqac= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.0/go.mod h1:YJdkyuY7aK/clfE3lQDz7O369JLPcg0FO4yfCIPNUNE= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.10.0 h1:m6h1UYpB18mqunUBjWtps81hVe1FiUtgrNbGKu86gDY= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.10.0/go.mod h1:9Om4A5FI/wXZE/8zu5wF8eRBb70VddyPfnj/nlYXHX0= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0 h1:tb0w+0imdJhsaoWCBOuie8bu335ZbxruwR01Yx7FmRE= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0/go.mod h1:LgCIIj7jA2lWX4DI3bxUYD+m0TbWCr1VgAyBYNJeghc= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 h1:HrnEgRPt3eD/tEHyzDWyCRxNFzb9g/FLYfwIEEQZ+Rg= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.2.0 h1:6IUrNIBEIpmrlfEK3QENQZB35KHEmeyc7w1owFOfGpc= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.2.0/go.mod h1:+807U5ZLXns+CEbyIg483wNEwV10vaN6GjMnSZhw/64= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0 h1:6IZBX9fyza9Eln3FHGHquvLNXQslk+dtkQp41G9+7+Y= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0/go.mod h1:zyg0hpiNdZLRbelkJb2KDf9OHQKLqqcTpePQ1qHL5dE= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 h1:ssEywzCS8IdRtzyxweLUKBG5GFbgwjNWJh++wGqigJM= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0/go.mod h1:A4+9KslxCA31JvxnT+O/GC67eAOdw+iqhBzewZZaCD0= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 h1:1ByAgO10fxWF+UZ+RkJeAiv+h5AgqrzYz6r86Pn/BWE= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0/go.mod h1:ui+yRLddE9mknzjZa45boyaU1ZomQuZy3p7wuwOufCY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= From 51afc804541f264f26437aa65e57e57ba088fc20 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:59:13 +0200 Subject: [PATCH 077/619] update github-action to 40.3.4 (#487) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 6e3af8c66..da767512b 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v40.3.1 + uses: renovatebot/github-action@v40.3.4 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 27206c69ed7f4e971b3aaf5bb51c694977c187e0 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:08:38 +0200 Subject: [PATCH 078/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.14.0 (#489) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c52f8669e..e57c2c552 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.12.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 diff --git a/go.sum b/go.sum index c8b30992d..a63af31ca 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 h1:WXSIE4Kf github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 h1:+OZ82DwFy4JIJThadVjvll5kUWjHPSLbUIF65njsNBk= github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.12.0 h1:tk/ztsZoFgcsyEFODaej8IGGuvprVbsrrJKGzm2PR14= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.12.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.14.0 h1:2CLlZInB7ytcnIpPUhFSbCBrNp0mMhxIuGOxlz3rhoA= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.14.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 h1:V0UGP7JEa4Q8SsZFUJsKgLGaoPruLn2KVKnqQtaoWCU= From 7031c665bdddd52414179dcc69cfb0e5a8b98c89 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:00:03 +0200 Subject: [PATCH 079/619] fix(deps): update module github.com/fatih/color to v1.18.0 (#492) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e57c2c552..190e92c40 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/stackitcloud/stackit-cli go 1.22 require ( - github.com/fatih/color v1.17.0 + github.com/fatih/color v1.18.0 github.com/goccy/go-yaml v1.12.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 diff --git a/go.sum b/go.sum index a63af31ca..2ec58904d 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= From 9e76025a1cc33f0cf9a8242b3d956db2e87755ff Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:00:31 +0200 Subject: [PATCH 080/619] fix(deps): update stackit sdk modules (#491) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 190e92c40..e877c2d49 100644 --- a/go.mod +++ b/go.mod @@ -18,11 +18,11 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.14.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.2.0 diff --git a/go.sum b/go.sum index 2ec58904d..f9185cf0a 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 h1:WXSIE4Kf github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 h1:+OZ82DwFy4JIJThadVjvll5kUWjHPSLbUIF65njsNBk= github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.14.0 h1:2CLlZInB7ytcnIpPUhFSbCBrNp0mMhxIuGOxlz3rhoA= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.14.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.15.0 h1:bPNv+PuSykBcKCYVXHiYOcqNP+KLCA7XMFSY4V6J6ug= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.15.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 h1:V0UGP7JEa4Q8SsZFUJsKgLGaoPruLn2KVKnqQtaoWCU= @@ -151,8 +151,8 @@ github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.0 h1:823zATqn83jn github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.0/go.mod h1:42oYZOqin+rIUrUqgtCIE4wzCWWY30H4UFhzvo1Wg2w= github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.0 h1:GVBQbLvJlIViURciLiX8z9zpbTuHAg2dGwVdwWSEqac= github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.0/go.mod h1:YJdkyuY7aK/clfE3lQDz7O369JLPcg0FO4yfCIPNUNE= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.10.0 h1:m6h1UYpB18mqunUBjWtps81hVe1FiUtgrNbGKu86gDY= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.10.0/go.mod h1:9Om4A5FI/wXZE/8zu5wF8eRBb70VddyPfnj/nlYXHX0= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.0 h1:AScIIoDpq1rxpjW248Ahn/KZS5dCZ4xggjAES9M5XSI= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.0/go.mod h1:9Om4A5FI/wXZE/8zu5wF8eRBb70VddyPfnj/nlYXHX0= github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0 h1:tb0w+0imdJhsaoWCBOuie8bu335ZbxruwR01Yx7FmRE= github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0/go.mod h1:LgCIIj7jA2lWX4DI3bxUYD+m0TbWCr1VgAyBYNJeghc= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 h1:HrnEgRPt3eD/tEHyzDWyCRxNFzb9g/FLYfwIEEQZ+Rg= From 7bdeb5c701b0451e7e9e1f90cd6e48bc4470491f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:00:47 +0200 Subject: [PATCH 081/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.6.1 (#490) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e877c2d49..b67d886ec 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.0 + github.com/jedib0t/go-pretty/v6 v6.6.1 github.com/lmittmann/tint v1.0.5 github.com/mattn/go-colorable v0.1.13 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index f9185cf0a..daef4634d 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.0 h1:wmZVuAcEkZRT+Aq1xXpE8IGat4vE5WXOMmBpbQqERXw= -github.com/jedib0t/go-pretty/v6 v6.6.0/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtxYVWyc= +github.com/jedib0t/go-pretty/v6 v6.6.1/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= From 747c0fdf458d4d5c4c6f77e314c57d0ae9a00236 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 4 Nov 2024 19:43:06 +0100 Subject: [PATCH 082/619] fix(deps): update module github.com/goccy/go-yaml to v1.13.4 (#494) Co-authored-by: Renovate Bot --- go.mod | 9 +++------ go.sum | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index b67d886ec..4be13c730 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.12.0 + github.com/goccy/go-yaml v1.13.4 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 @@ -40,15 +40,12 @@ require ( ) require ( - golang.org/x/net v0.23.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/time v0.5.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) -require ( - github.com/mattn/go-isatty v0.0.20 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect -) +require github.com/mattn/go-isatty v0.0.20 // indirect require ( github.com/alessio/shellescape v1.4.2 // indirect diff --git a/go.sum b/go.sum index daef4634d..276982bac 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -25,14 +27,14 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= -github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-yaml v1.13.4 h1:XOnLX9GqT+kH/gB7YzCMUiDBFU9B7pm3HZz6kyeDPkk= +github.com/goccy/go-yaml v1.13.4/go.mod h1:IjYwxUiJDoqpx2RmbdjMUceGHZwYLon3sfOGl5Hi9lc= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -71,8 +73,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw= github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -189,8 +191,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -201,8 +203,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -231,8 +233,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From de8e0999249823b53ffa0911516ceb78b25421bf Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Mon, 11 Nov 2024 12:50:48 +0100 Subject: [PATCH 083/619] Add update command to network-area route Support to update labels for a network-area route. Signed-off-by: Alexander Dahmen --- docs/stackit_beta_network-area_route.md | 1 + .../stackit_beta_network-area_route_update.md | 44 +++ .../network-area/route/describe/describe.go | 13 +- .../cmd/beta/network-area/route/routes.go | 2 + .../beta/network-area/route/update/update.go | 166 +++++++++++ .../network-area/route/update/update_test.go | 269 ++++++++++++++++++ 6 files changed, 493 insertions(+), 2 deletions(-) create mode 100644 docs/stackit_beta_network-area_route_update.md create mode 100644 internal/cmd/beta/network-area/route/update/update.go create mode 100644 internal/cmd/beta/network-area/route/update/update_test.go diff --git a/docs/stackit_beta_network-area_route.md b/docs/stackit_beta_network-area_route.md index 39efe6da8..767afefe3 100644 --- a/docs/stackit_beta_network-area_route.md +++ b/docs/stackit_beta_network-area_route.md @@ -33,4 +33,5 @@ stackit beta network-area route [flags] * [stackit beta network-area route delete](./stackit_beta_network-area_route_delete.md) - Deletes a static route in a STACKIT Network Area (SNA) * [stackit beta network-area route describe](./stackit_beta_network-area_route_describe.md) - Shows details of a static route in a STACKIT Network Area (SNA) * [stackit beta network-area route list](./stackit_beta_network-area_route_list.md) - Lists all static routes in a STACKIT Network Area (SNA) +* [stackit beta network-area route update](./stackit_beta_network-area_route_update.md) - Updates a static route in a STACKIT Network Area (SNA) diff --git a/docs/stackit_beta_network-area_route_update.md b/docs/stackit_beta_network-area_route_update.md new file mode 100644 index 000000000..e52a914ad --- /dev/null +++ b/docs/stackit_beta_network-area_route_update.md @@ -0,0 +1,44 @@ +## stackit beta network-area route update + +Updates a static route in a STACKIT Network Area (SNA) + +### Synopsis + +Updates a static route in a STACKIT Network Area (SNA). +This command is currently asynchonous only due to limitations in the waiting functionality of the SDK. This will be updated in a future release. + + +``` +stackit beta network-area route update [flags] +``` + +### Examples + +``` + Updates the label(s) of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" + $ stackit beta network-area route update xxx --labels key=value,foo=bar --organization-id yyy --network-area-id zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta network-area route update" + --labels stringToString Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) + --network-area-id string STACKIT Network Area ID + --organization-id string Organization ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas + diff --git a/internal/cmd/beta/network-area/route/describe/describe.go b/internal/cmd/beta/network-area/route/describe/describe.go index 793d9b96f..f20fced9d 100644 --- a/internal/cmd/beta/network-area/route/describe/describe.go +++ b/internal/cmd/beta/network-area/route/describe/describe.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -134,9 +135,17 @@ func outputResult(p *print.Printer, outputFormat string, route *iaas.Route) erro table := tables.NewTable() table.AddRow("ID", *route.RouteId) table.AddSeparator() - table.AddRow("Prefix", *route.Prefix) + table.AddRow("PREFIX", *route.Prefix) table.AddSeparator() - table.AddRow("Nexthop", *route.Nexthop) + table.AddRow("NEXTHOP", *route.Nexthop) + if route.Labels != nil && len(*route.Labels) > 0 { + labels := []string{} + for key, value := range *route.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddSeparator() + table.AddRow("LABELS", strings.Join(labels, "\n")) + } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/network-area/route/routes.go b/internal/cmd/beta/network-area/route/routes.go index f4b5bfac9..1125d4d70 100644 --- a/internal/cmd/beta/network-area/route/routes.go +++ b/internal/cmd/beta/network-area/route/routes.go @@ -5,6 +5,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -29,4 +30,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(delete.NewCmd(p)) cmd.AddCommand(describe.NewCmd(p)) cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) } diff --git a/internal/cmd/beta/network-area/route/update/update.go b/internal/cmd/beta/network-area/route/update/update.go new file mode 100644 index 000000000..4a04ca654 --- /dev/null +++ b/internal/cmd/beta/network-area/route/update/update.go @@ -0,0 +1,166 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + routeIdArg = "ROUTE_ID" + + organizationIdFlag = "organization-id" + networkAreaIdFlag = "network-area-id" + + labelFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId *string + NetworkAreaId *string + RouteId string + Labels *map[string]string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a static route in a STACKIT Network Area (SNA)", + Long: fmt.Sprintf("%s\n%s\n", + "Updates a static route in a STACKIT Network Area (SNA).", + "This command is currently asynchonous only due to limitations in the waiting functionality of the SDK. This will be updated in a future release.", + ), + Args: args.SingleArg(routeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Updates the label(s) of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, + "$ stackit beta network-area route update xxx --labels key=value,foo=bar --organization-id yyy --network-area-id zzz", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Get network area label + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + if err != nil { + p.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = *model.NetworkAreaId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create static route: %w", err) + } + + return outputResult(p, model, networkAreaLabel, *resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area ID") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") + + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + routeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + + labels := flags.FlagToStringToStringPointer(p, cmd, labelFlag) + + if labels == nil { + return nil, &errors.EmptyUpdateError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + RouteId: routeId, + Labels: labels, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNetworkAreaRouteRequest { + req := apiClient.UpdateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.RouteId) + + // convert map[string]string to map[string]interface{} + labelsMap := make(map[string]interface{}) + for k, v := range *model.Labels { + labelsMap[k] = v + } + + payload := iaas.UpdateNetworkAreaRoutePayload{ + Labels: &labelsMap, + } + req = req.UpdateNetworkAreaRoutePayload(payload) + + return req +} + +func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, route iaas.Route) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(route, "", " ") + if err != nil { + return fmt.Errorf("marshal static route: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal static route: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Updated static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, *route.RouteId) + return nil + } +} diff --git a/internal/cmd/beta/network-area/route/update/update_test.go b/internal/cmd/beta/network-area/route/update/update_test.go new file mode 100644 index 000000000..f9b1ddd06 --- /dev/null +++ b/internal/cmd/beta/network-area/route/update/update_test.go @@ -0,0 +1,269 @@ +package update + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testOrgId = uuid.NewString() +var testNetworkAreaId = uuid.NewString() +var testRouteId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testRouteId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + organizationIdFlag: testOrgId, + networkAreaIdFlag: testNetworkAreaId, + labelFlag: "value=key", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixturePayload(mods ...func(payload *iaas.UpdateNetworkAreaRoutePayload)) iaas.UpdateNetworkAreaRoutePayload { + payload := iaas.UpdateNetworkAreaRoutePayload{ + Labels: &map[string]interface{}{ + "value": "key", + }, + } + + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixturePayloadAsStringMap() map[string]string { + payload := fixturePayload() + labelsMap := make(map[string]string) + for k, v := range *payload.Labels { + if value, ok := v.(string); ok { + labelsMap[k] = value + } + } + return labelsMap +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + payload := fixturePayloadAsStringMap() + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: utils.Ptr(testOrgId), + NetworkAreaId: utils.Ptr(testNetworkAreaId), + RouteId: testRouteId, + Labels: utils.Ptr(payload), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateNetworkAreaRouteRequest)) iaas.ApiUpdateNetworkAreaRouteRequest { + request := testClient.UpdateNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRouteId) + request = request.UpdateNetworkAreaRoutePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "network area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "network area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "route id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, routeIdArg) + }), + isValid: false, + }, + { + description: "route id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[routeIdArg] = "" + }), + isValid: false, + }, + { + description: "route id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[routeIdArg] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "labels missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateNetworkAreaRouteRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} From b88ebfb57d474b643a0a99030012ffdf64e18613 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Tue, 12 Nov 2024 14:30:38 +0100 Subject: [PATCH 084/619] Extend network-area route create command to support labels as well Labels are optional and can now be provided directly during creation of the route. Signed-off-by: Alexander Dahmen --- .../stackit_beta_network-area_route_create.md | 4 +++ .../beta/network-area/route/create/create.go | 26 ++++++++++++++++--- .../network-area/route/create/create_test.go | 21 +++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/docs/stackit_beta_network-area_route_create.md b/docs/stackit_beta_network-area_route_create.md index f9fca71f2..41a7d30c1 100644 --- a/docs/stackit_beta_network-area_route_create.md +++ b/docs/stackit_beta_network-area_route_create.md @@ -17,12 +17,16 @@ stackit beta network-area route create [flags] ``` Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" $ stackit beta network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 + + Create a static route with labels "key:value" and "foo:bar" with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit beta network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 ``` ### Options ``` -h, --help Help for "stackit beta network-area route create" + --labels stringToString Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) --network-area-id string STACKIT Network Area ID --next-hop string Next hop IP address. Must be a valid IPv4 --organization-id string Organization ID diff --git a/internal/cmd/beta/network-area/route/create/create.go b/internal/cmd/beta/network-area/route/create/create.go index b354d7d91..8c2673236 100644 --- a/internal/cmd/beta/network-area/route/create/create.go +++ b/internal/cmd/beta/network-area/route/create/create.go @@ -12,7 +12,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/cobra" @@ -23,6 +24,7 @@ const ( networkAreaIdFlag = "network-area-id" prefixFlag = "prefix" nexthopFlag = "next-hop" + labelFlag = "labels" ) type inputModel struct { @@ -31,6 +33,7 @@ type inputModel struct { NetworkAreaId *string Prefix *string Nexthop *string + Labels *map[string]string } func NewCmd(p *print.Printer) *cobra.Command { @@ -47,6 +50,10 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, "$ stackit beta network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", ), + examples.NewExample( + `Create a static route with labels "key:value" and "foo:bar" with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + "$ stackit beta network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", + ), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -62,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // Get network area label - networkAreaLabel, err := utils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { p.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId @@ -87,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("empty response from API") } - route, err := utils.GetRouteFromAPIResponse(*model.Prefix, *model.Nexthop, resp.Items) + route, err := iaasUtils.GetRouteFromAPIResponse(*model.Prefix, *model.Nexthop, resp.Items) if err != nil { return err } @@ -104,6 +111,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area ID") cmd.Flags().Var(flags.CIDRFlag(), prefixFlag, "Static route prefix") cmd.Flags().String(nexthopFlag, "", "Next hop IP address. Must be a valid IPv4") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag, prefixFlag, nexthopFlag) cobra.CheckErr(err) @@ -118,6 +126,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), Prefix: flags.FlagToStringPointer(p, cmd, prefixFlag), Nexthop: flags.FlagToStringPointer(p, cmd, nexthopFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } if p.IsVerbosityDebug() { @@ -134,11 +143,22 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRouteRequest { req := apiClient.CreateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + payload := iaas.CreateNetworkAreaRoutePayload{ Ipv4: &[]iaas.Route{ { Prefix: model.Prefix, Nexthop: model.Nexthop, + Labels: labelsMap, }, }, } diff --git a/internal/cmd/beta/network-area/route/create/create_test.go b/internal/cmd/beta/network-area/route/create/create_test.go index 03a3a7bb0..b106a937b 100644 --- a/internal/cmd/beta/network-area/route/create/create_test.go +++ b/internal/cmd/beta/network-area/route/create/create_test.go @@ -165,6 +165,16 @@ func TestParseInput(t *testing.T) { }), isValid: false, }, + { + description: "optional labels is provided", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelFlag] = "key=value" + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = utils.Ptr(map[string]string{"key": "value"}) + }), + isValid: true, + }, } for _, tt := range tests { @@ -224,6 +234,17 @@ func TestBuildRequest(t *testing.T) { model: fixtureInputModel(), expectedRequest: fixtureRequest(), }, + { + description: "optional labels provided", + model: fixtureInputModel(func(model *inputModel) { + model.Labels = utils.Ptr(map[string]string{"key": "value"}) + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateNetworkAreaRouteRequest) { + *request = request.CreateNetworkAreaRoutePayload(fixturePayload(func(payload *iaas.CreateNetworkAreaRoutePayload) { + (*payload.Ipv4)[0].Labels = utils.Ptr(map[string]interface{}{"key": "value"}) + })) + }), + }, } for _, tt := range tests { From 4a36ac05328ab1ee8cbd91ce0aaf4d9db7f249a3 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:46:47 +0100 Subject: [PATCH 085/619] Onboard IaaS volume commands (#503) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * onboard IaaS volume commands * generate docs * fix nil pointer exceptions * add volume command to readme * fix linter issues * fix linter issues * Update internal/cmd/beta/volume/create/create.go Co-authored-by: João Palet * Update internal/cmd/beta/volume/resize/resize.go Co-authored-by: João Palet * make changes from review * Update internal/cmd/beta/volume/create/create.go Co-authored-by: João Palet --------- Co-authored-by: João Palet --- README.md | 44 +-- docs/stackit_beta.md | 1 + docs/stackit_beta_volume.md | 39 +++ docs/stackit_beta_volume_create.md | 53 ++++ docs/stackit_beta_volume_delete.md | 41 +++ docs/stackit_beta_volume_describe.md | 42 +++ docs/stackit_beta_volume_list.md | 50 +++ docs/stackit_beta_volume_performance-class.md | 34 +++ ..._beta_volume_performance-class_describe.md | 42 +++ ...ckit_beta_volume_performance-class_list.md | 50 +++ docs/stackit_beta_volume_resize.md | 40 +++ docs/stackit_beta_volume_update.md | 45 +++ go.mod | 2 +- go.sum | 2 + internal/cmd/beta/beta.go | 2 + internal/cmd/beta/volume/create/create.go | 219 ++++++++++++++ .../cmd/beta/volume/create/create_test.go | 286 ++++++++++++++++++ internal/cmd/beta/volume/delete/delete.go | 129 ++++++++ .../cmd/beta/volume/delete/delete_test.go | 218 +++++++++++++ internal/cmd/beta/volume/describe/describe.go | 154 ++++++++++ .../cmd/beta/volume/describe/describe_test.go | 218 +++++++++++++ internal/cmd/beta/volume/list/list.go | 181 +++++++++++ internal/cmd/beta/volume/list/list_test.go | 204 +++++++++++++ .../performance-class/describe/describe.go | 137 +++++++++ .../describe/describe_test.go | 212 +++++++++++++ .../volume/performance-class/list/list.go | 177 +++++++++++ .../performance-class/list/list_test.go | 204 +++++++++++++ .../performance-class/performance_class.go | 28 ++ internal/cmd/beta/volume/resize/resize.go | 128 ++++++++ .../cmd/beta/volume/resize/resize_test.go | 232 ++++++++++++++ internal/cmd/beta/volume/update/update.go | 173 +++++++++++ .../cmd/beta/volume/update/update_test.go | 257 ++++++++++++++++ internal/cmd/beta/volume/volume.go | 38 +++ internal/pkg/services/iaas/utils/utils.go | 9 + .../pkg/services/iaas/utils/utils_test.go | 55 ++++ 35 files changed, 3723 insertions(+), 23 deletions(-) create mode 100644 docs/stackit_beta_volume.md create mode 100644 docs/stackit_beta_volume_create.md create mode 100644 docs/stackit_beta_volume_delete.md create mode 100644 docs/stackit_beta_volume_describe.md create mode 100644 docs/stackit_beta_volume_list.md create mode 100644 docs/stackit_beta_volume_performance-class.md create mode 100644 docs/stackit_beta_volume_performance-class_describe.md create mode 100644 docs/stackit_beta_volume_performance-class_list.md create mode 100644 docs/stackit_beta_volume_resize.md create mode 100644 docs/stackit_beta_volume_update.md create mode 100644 internal/cmd/beta/volume/create/create.go create mode 100644 internal/cmd/beta/volume/create/create_test.go create mode 100644 internal/cmd/beta/volume/delete/delete.go create mode 100644 internal/cmd/beta/volume/delete/delete_test.go create mode 100644 internal/cmd/beta/volume/describe/describe.go create mode 100644 internal/cmd/beta/volume/describe/describe_test.go create mode 100644 internal/cmd/beta/volume/list/list.go create mode 100644 internal/cmd/beta/volume/list/list_test.go create mode 100644 internal/cmd/beta/volume/performance-class/describe/describe.go create mode 100644 internal/cmd/beta/volume/performance-class/describe/describe_test.go create mode 100644 internal/cmd/beta/volume/performance-class/list/list.go create mode 100644 internal/cmd/beta/volume/performance-class/list/list_test.go create mode 100644 internal/cmd/beta/volume/performance-class/performance_class.go create mode 100644 internal/cmd/beta/volume/resize/resize.go create mode 100644 internal/cmd/beta/volume/resize/resize_test.go create mode 100644 internal/cmd/beta/volume/update/update.go create mode 100644 internal/cmd/beta/volume/update/update_test.go create mode 100644 internal/cmd/beta/volume/volume.go diff --git a/README.md b/README.md index a46f741a4..df0cbe601 100644 --- a/README.md +++ b/README.md @@ -65,28 +65,28 @@ Help is available for any command by specifying the special flag `--help` (or si Below you can find a list of the STACKIT services already available in the CLI (along with their respective command names) and the ones that are currently planned to be integrated. -| Service | CLI Commands | Status | -| ---------------------------------- | ------------------------- | ------------------------- | -| Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area` | :white_check_mark: (beta) | -| Authorization | `project`, `organization` | :white_check_mark: | -| DNS | `dns` | :white_check_mark: | -| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | -| Load Balancer | `load-balancer` | :white_check_mark: | -| LogMe | `logme` | :white_check_mark: | -| MariaDB | `mariadb` | :white_check_mark: | -| MongoDB Flex | `mongodbflex` | :white_check_mark: | -| Object Storage | `object-storage` | :white_check_mark: | -| OpenSearch | `opensearch` | :white_check_mark: | -| PostgreSQL Flex | `postgresflex` | :white_check_mark: | -| RabbitMQ | `rabbitmq` | :white_check_mark: | -| Redis | `redis` | :white_check_mark: | -| Resource Manager | `project` | :white_check_mark: | -| Secrets Manager | `secrets-manager` | :white_check_mark: | -| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | -| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | -| Service Account | `service-account` | :white_check_mark: | -| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | +| Service | CLI Commands | Status | +| ---------------------------------- |----------------------------------------------------------------| ------------------------- | +| Observability | `observability` | :white_check_mark: | +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume` | :white_check_mark: (beta) | +| Authorization | `project`, `organization` | :white_check_mark: | +| DNS | `dns` | :white_check_mark: | +| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | +| Load Balancer | `load-balancer` | :white_check_mark: | +| LogMe | `logme` | :white_check_mark: | +| MariaDB | `mariadb` | :white_check_mark: | +| MongoDB Flex | `mongodbflex` | :white_check_mark: | +| Object Storage | `object-storage` | :white_check_mark: | +| OpenSearch | `opensearch` | :white_check_mark: | +| PostgreSQL Flex | `postgresflex` | :white_check_mark: | +| RabbitMQ | `rabbitmq` | :white_check_mark: | +| Redis | `redis` | :white_check_mark: | +| Resource Manager | `project` | :white_check_mark: | +| Secrets Manager | `secrets-manager` | :white_check_mark: | +| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | +| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | +| Service Account | `service-account` | :white_check_mark: | +| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | ## Authentication diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index bf3beb0aa..8da8fef61 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -44,4 +44,5 @@ stackit beta [flags] * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) * [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume diff --git a/docs/stackit_beta_volume.md b/docs/stackit_beta_volume.md new file mode 100644 index 000000000..7255a1cec --- /dev/null +++ b/docs/stackit_beta_volume.md @@ -0,0 +1,39 @@ +## stackit beta volume + +Provides functionality for Volume + +### Synopsis + +Provides functionality for Volume. + +``` +stackit beta volume [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta volume" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta volume create](./stackit_beta_volume_create.md) - Creates a volume +* [stackit beta volume delete](./stackit_beta_volume_delete.md) - Deletes a volume +* [stackit beta volume describe](./stackit_beta_volume_describe.md) - Shows details of a volume +* [stackit beta volume list](./stackit_beta_volume_list.md) - Lists all volumes of a project +* [stackit beta volume performance-class](./stackit_beta_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project +* [stackit beta volume resize](./stackit_beta_volume_resize.md) - Resizes a volume +* [stackit beta volume update](./stackit_beta_volume_update.md) - Updates a volume + diff --git a/docs/stackit_beta_volume_create.md b/docs/stackit_beta_volume_create.md new file mode 100644 index 000000000..b24d2391c --- /dev/null +++ b/docs/stackit_beta_volume_create.md @@ -0,0 +1,53 @@ +## stackit beta volume create + +Creates a volume + +### Synopsis + +Creates a volume. + +``` +stackit beta volume create [flags] +``` + +### Examples + +``` + Create a volume with availability zone "eu01-1" and size 64 GB + $ stackit beta volume create --availability-zone eu01-1 --size 64 + + Create a volume with name "volume-1", source id "xxx" and type "image" + $ stackit beta volume create --availability-zone eu01-1 --name volume-1 --source-id xxx --source-type image + + Create a volume with availability zone "eu01-1", performance class "storage_premium_perf1" and size 64 GB + $ stackit beta volume create --availability-zone eu01-1 --performance-class storage_premium_perf1 --size 64 +``` + +### Options + +``` + --availability-zone string Availability zone + --description string Volume description + -h, --help Help for "stackit beta volume create" + --label stringToString Labels are key-value string pairs which can be attached to a volume. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) + -n, --name string Volume name + --performance-class string Performance class + --size int Volume size (GB). Either 'size' or the 'source-id' and 'source-type' flags must be given + --source-id string ID of the source object of volume. Either 'size' or the 'source-id' and 'source-type' flags must be given + --source-type string Type of the source object of volume. Either 'size' or the 'source-id' and 'source-type' flags must be given +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume + diff --git a/docs/stackit_beta_volume_delete.md b/docs/stackit_beta_volume_delete.md new file mode 100644 index 000000000..1ded8006d --- /dev/null +++ b/docs/stackit_beta_volume_delete.md @@ -0,0 +1,41 @@ +## stackit beta volume delete + +Deletes a volume + +### Synopsis + +Deletes a volume. +If the volume is still in use, the deletion will fail + + +``` +stackit beta volume delete [flags] +``` + +### Examples + +``` + Delete volume with ID "xxx" + $ stackit beta volume delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta volume delete" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume + diff --git a/docs/stackit_beta_volume_describe.md b/docs/stackit_beta_volume_describe.md new file mode 100644 index 000000000..387edf692 --- /dev/null +++ b/docs/stackit_beta_volume_describe.md @@ -0,0 +1,42 @@ +## stackit beta volume describe + +Shows details of a volume + +### Synopsis + +Shows details of a volume. + +``` +stackit beta volume describe [flags] +``` + +### Examples + +``` + Show details of a volume with ID "xxx" + $ stackit beta volume describe xxx + + Show details of a volume with ID "xxx" in JSON format + $ stackit beta volume describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta volume 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume + diff --git a/docs/stackit_beta_volume_list.md b/docs/stackit_beta_volume_list.md new file mode 100644 index 000000000..985db2475 --- /dev/null +++ b/docs/stackit_beta_volume_list.md @@ -0,0 +1,50 @@ +## stackit beta volume list + +Lists all volumes of a project + +### Synopsis + +Lists all volumes of a project. + +``` +stackit beta volume list [flags] +``` + +### Examples + +``` + Lists all volumes + $ stackit beta volume list + + Lists all volumes which contains the label xxx + $ stackit beta volume list --label-selector xxx + + Lists all volumes in JSON format + $ stackit beta volume list --output-format json + + Lists up to 10 volumes + $ stackit beta volume list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta volume list" + --label-selector string Filter by label + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume + diff --git a/docs/stackit_beta_volume_performance-class.md b/docs/stackit_beta_volume_performance-class.md new file mode 100644 index 000000000..f1b125cab --- /dev/null +++ b/docs/stackit_beta_volume_performance-class.md @@ -0,0 +1,34 @@ +## stackit beta volume performance-class + +Provides functionality for volume performance classes available inside a project + +### Synopsis + +Provides functionality for volume performance classes available inside a project. + +``` +stackit beta volume performance-class [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta volume performance-class" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume performance-class describe](./stackit_beta_volume_performance-class_describe.md) - Shows details of a volume performance class +* [stackit beta volume performance-class list](./stackit_beta_volume_performance-class_list.md) - Lists all volume performance classes for a project + diff --git a/docs/stackit_beta_volume_performance-class_describe.md b/docs/stackit_beta_volume_performance-class_describe.md new file mode 100644 index 000000000..902755ea4 --- /dev/null +++ b/docs/stackit_beta_volume_performance-class_describe.md @@ -0,0 +1,42 @@ +## stackit beta volume performance-class describe + +Shows details of a volume performance class + +### Synopsis + +Shows details of a volume performance class. + +``` +stackit beta volume performance-class describe [flags] +``` + +### Examples + +``` + Show details of a volume performance class with name "xxx" + $ stackit beta volume performance-class describe xxx + + Show details of a volume performance class with name "xxx" in JSON format + $ stackit beta volume performance-class describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta volume performance-class 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume performance-class](./stackit_beta_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project + diff --git a/docs/stackit_beta_volume_performance-class_list.md b/docs/stackit_beta_volume_performance-class_list.md new file mode 100644 index 000000000..a4a12222e --- /dev/null +++ b/docs/stackit_beta_volume_performance-class_list.md @@ -0,0 +1,50 @@ +## stackit beta volume performance-class list + +Lists all volume performance classes for a project + +### Synopsis + +Lists all volume performance classes for a project. + +``` +stackit beta volume performance-class list [flags] +``` + +### Examples + +``` + Lists all volume performance classes + $ stackit beta volume performance-class list + + Lists all volume performance classes which contains the label xxx + $ stackit beta volume performance-class list --label-selector xxx + + Lists all volume performance classes in JSON format + $ stackit beta volume performance-class list --output-format json + + Lists up to 10 volume performance classes + $ stackit beta volume performance-class list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta volume performance-class list" + --label-selector string Filter by label + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume performance-class](./stackit_beta_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project + diff --git a/docs/stackit_beta_volume_resize.md b/docs/stackit_beta_volume_resize.md new file mode 100644 index 000000000..c2e7aea0f --- /dev/null +++ b/docs/stackit_beta_volume_resize.md @@ -0,0 +1,40 @@ +## stackit beta volume resize + +Resizes a volume + +### Synopsis + +Resizes a volume. + +``` +stackit beta volume resize [flags] +``` + +### Examples + +``` + Resize volume with ID "xxx" with new size 10 GB + $ stackit beta volume resize xxx --size 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta volume resize" + --size int Volume size (GB) +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume + diff --git a/docs/stackit_beta_volume_update.md b/docs/stackit_beta_volume_update.md new file mode 100644 index 000000000..c8b0ccb44 --- /dev/null +++ b/docs/stackit_beta_volume_update.md @@ -0,0 +1,45 @@ +## stackit beta volume update + +Updates a volume + +### Synopsis + +Updates a volume. + +``` +stackit beta volume update [flags] +``` + +### Examples + +``` + Update volume with ID "xxx" with new name "volume-1-new" + $ stackit beta volume update xxx --name volume-1-new + + Update volume with ID "xxx" with new name "volume-1-new" and new description "volume-1-desc-new" + $ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new +``` + +### Options + +``` + --description string Volume description + -h, --help Help for "stackit beta volume update" + --label stringToString Labels are key-value string pairs which can be attached to a volume. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) + -n, --name string Volume name +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume + diff --git a/go.mod b/go.mod index 4be13c730..2cecb5db1 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 diff --git a/go.sum b/go.sum index 276982bac..aa2006847 100644 --- a/go.sum +++ b/go.sum @@ -133,6 +133,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 h1:+OZ82DwFy4JIJThad github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.15.0 h1:bPNv+PuSykBcKCYVXHiYOcqNP+KLCA7XMFSY4V6J6ug= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.15.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0 h1:geyW780gqNxzSsPvmlxy3kUUJaRA4eiF9V3b2Ibcdjs= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 h1:V0UGP7JEa4Q8SsZFUJsKgLGaoPruLn2KVKnqQtaoWCU= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 348118936..e1a16ccdb 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -7,6 +7,7 @@ import ( networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -42,4 +43,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(server.NewCmd(p)) cmd.AddCommand(networkArea.NewCmd(p)) cmd.AddCommand(network.NewCmd(p)) + cmd.AddCommand(volume.NewCmd(p)) } diff --git a/internal/cmd/beta/volume/create/create.go b/internal/cmd/beta/volume/create/create.go new file mode 100644 index 000000000..88467c54e --- /dev/null +++ b/internal/cmd/beta/volume/create/create.go @@ -0,0 +1,219 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + availabilityZoneFlag = "availability-zone" + nameFlag = "name" + descriptionFlag = "description" + labelFlag = "label" + performanceClassFlag = "performance-class" + sizeFlag = "size" + sourceIdFlag = "source-id" + sourceTypeFlag = "source-type" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + AvailabilityZone *string + Name *string + Description *string + Labels *map[string]string + PerformanceClass *string + Size *int64 + SourceId *string + SourceType *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a volume", + Long: "Creates a volume.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a volume with availability zone "eu01-1" and size 64 GB`, + `$ stackit beta volume create --availability-zone eu01-1 --size 64`, + ), + examples.NewExample( + `Create a volume with name "volume-1", from a source image with ID "xxx"`, + `$ stackit beta volume create --availability-zone eu01-1 --name volume-1 --source-id xxx --source-type image`, + ), + examples.NewExample( + `Create a volume with availability zone "eu01-1", performance class "storage_premium_perf1" and size 64 GB`, + `$ stackit beta volume create --availability-zone eu01-1 --performance-class storage_premium_perf1 --size 64`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a volume for project %q?", projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create volume : %w", err) + } + volumeId := *resp.Id + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Creating volume") + _, err = wait.CreateVolumeWaitHandler(ctx, apiClient, model.ProjectId, volumeId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for volume creation: %w", err) + } + s.Stop() + } + + return outputResult(p, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(availabilityZoneFlag, "", "Availability zone") + cmd.Flags().StringP(nameFlag, "n", "", "Volume name") + cmd.Flags().String(descriptionFlag, "", "Volume description") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a volume. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") + cmd.Flags().String(performanceClassFlag, "", "Performance class") + cmd.Flags().Int64(sizeFlag, 0, "Volume size (GB). Either 'size' or the 'source-id' and 'source-type' flags must be given") + cmd.Flags().String(sourceIdFlag, "", "ID of the source object of volume. Either 'size' or the 'source-id' and 'source-type' flags must be given") + cmd.Flags().String(sourceTypeFlag, "", "Type of the source object of volume. Either 'size' or the 'source-id' and 'source-type' flags must be given") + + err := flags.MarkFlagsRequired(cmd, availabilityZoneFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + AvailabilityZone: flags.FlagToStringPointer(p, cmd, availabilityZoneFlag), + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + PerformanceClass: flags.FlagToStringPointer(p, cmd, performanceClassFlag), + Size: flags.FlagToInt64Pointer(p, cmd, sizeFlag), + SourceId: flags.FlagToStringPointer(p, cmd, sourceIdFlag), + SourceType: flags.FlagToStringPointer(p, cmd, sourceTypeFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateVolumeRequest { + req := apiClient.CreateVolume(ctx, model.ProjectId) + source := &iaas.VolumeSource{ + Id: model.SourceId, + Type: model.SourceType, + } + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + + payload := iaas.CreateVolumePayload{ + AvailabilityZone: model.AvailabilityZone, + Name: model.Name, + Description: model.Description, + Labels: labelsMap, + PerformanceClass: model.PerformanceClass, + Size: model.Size, + } + + if model.SourceId != nil && model.SourceType != nil { + payload.Source = source + } + + return req.CreateVolumePayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, volume *iaas.Volume) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(volume, "", " ") + if err != nil { + return fmt.Errorf("marshal volume: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal volume: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created volume for project %q.\nVolume ID: %s\n", projectLabel, *volume.Id) + return nil + } +} diff --git a/internal/cmd/beta/volume/create/create_test.go b/internal/cmd/beta/volume/create/create_test.go new file mode 100644 index 000000000..c9fecec3a --- /dev/null +++ b/internal/cmd/beta/volume/create/create_test.go @@ -0,0 +1,286 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testSourceId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + availabilityZoneFlag: "eu01-1", + nameFlag: "example-volume-name", + descriptionFlag: "example-volume-description", + labelFlag: "key=value", + performanceClassFlag: "example-perf-class", + sizeFlag: "5", + sourceIdFlag: testSourceId, + sourceTypeFlag: "example-source-type", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + AvailabilityZone: utils.Ptr("eu01-1"), + Name: utils.Ptr("example-volume-name"), + Description: utils.Ptr("example-volume-description"), + PerformanceClass: utils.Ptr("example-perf-class"), + Size: utils.Ptr(int64(5)), + SourceId: utils.Ptr(testSourceId), + SourceType: utils.Ptr("example-source-type"), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateVolumeRequest)) iaas.ApiCreateVolumeRequest { + request := testClient.CreateVolume(testCtx, testProjectId) + request = request.CreateVolumePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateVolumeRequest)) iaas.ApiCreateVolumeRequest { + request := testClient.CreateVolume(testCtx, testProjectId) + request = request.CreateVolumePayload(iaas.CreateVolumePayload{ + AvailabilityZone: utils.Ptr("eu01-1"), + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateVolumePayload)) iaas.CreateVolumePayload { + payload := iaas.CreateVolumePayload{ + AvailabilityZone: utils.Ptr("eu01-1"), + Name: utils.Ptr("example-volume-name"), + Description: utils.Ptr("example-volume-description"), + PerformanceClass: utils.Ptr("example-perf-class"), + Size: utils.Ptr(int64(5)), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), + Source: &iaas.VolumeSource{ + Id: utils.Ptr(testSourceId), + Type: utils.Ptr("example-source-type"), + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + delete(flagValues, descriptionFlag) + delete(flagValues, labelFlag) + delete(flagValues, performanceClassFlag) + delete(flagValues, sizeFlag) + delete(flagValues, sourceIdFlag) + delete(flagValues, sourceTypeFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = nil + model.Description = nil + model.Labels = nil + model.PerformanceClass = nil + model.Size = nil + model.SourceType = nil + model.SourceId = nil + }), + }, + { + description: "availability zone missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, availabilityZoneFlag) + }), + isValid: false, + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "use performance class and size", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[performanceClassFlag] = "example-perf-class" + flagValues[sizeFlag] = "5" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.PerformanceClass = utils.Ptr("example-perf-class") + model.Size = utils.Ptr(int64(5)) + }), + }, + { + description: "use source id and type", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sourceIdFlag] = testSourceId + flagValues[sourceTypeFlag] = "example-source-type" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.SourceId = utils.Ptr(testSourceId) + model.SourceType = utils.Ptr("example-source-type") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateVolumeRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "only availability zone in payload", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + AvailabilityZone: utils.Ptr("eu01-1"), + }, + expectedRequest: fixtureRequiredRequest(), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/volume/delete/delete.go b/internal/cmd/beta/volume/delete/delete.go new file mode 100644 index 000000000..ce170565c --- /dev/null +++ b/internal/cmd/beta/volume/delete/delete.go @@ -0,0 +1,129 @@ +package delete + +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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + volumeIdArg = "VOLUME_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + VolumeId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a volume", + Long: fmt.Sprintf("%s\n%s\n", + "Deletes a volume.", + "If the volume is still in use, the deletion will fail", + ), + Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete volume with ID "xxx"`, + "$ stackit beta volume delete xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + if err != nil { + p.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = model.VolumeId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete volume %q?", volumeLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete volume: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Deleting volume") + _, err = wait.DeleteVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.VolumeId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for volume deletion: %w", err) + } + s.Stop() + } + + operationState := "Deleted" + if model.Async { + operationState = "Triggered deletion of" + } + p.Info("%s volume %q\n", operationState, volumeLabel) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + VolumeId: volumeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteVolumeRequest { + return apiClient.DeleteVolume(ctx, model.ProjectId, model.VolumeId) +} diff --git a/internal/cmd/beta/volume/delete/delete_test.go b/internal/cmd/beta/volume/delete/delete_test.go new file mode 100644 index 000000000..5648c374c --- /dev/null +++ b/internal/cmd/beta/volume/delete/delete_test.go @@ -0,0 +1,218 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testVolumeId = uuid.NewString() +var testProjectId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + VolumeId: testVolumeId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteVolumeRequest)) iaas.ApiDeleteVolumeRequest { + request := testClient.DeleteVolume(testCtx, testProjectId, testVolumeId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "volume id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteVolumeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/volume/describe/describe.go b/internal/cmd/beta/volume/describe/describe.go new file mode 100644 index 000000000..0fc48e135 --- /dev/null +++ b/internal/cmd/beta/volume/describe/describe.go @@ -0,0 +1,154 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + volumeIdArg = "VOLUME_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + VolumeId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a volume", + Long: "Shows details of a volume.", + Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Show details of a volume with ID "xxx"`, + "$ stackit beta volume describe xxx", + ), + examples.NewExample( + `Show details of a volume with ID "xxx" in JSON format`, + "$ stackit beta volume describe xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read volume: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + VolumeId: volumeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetVolumeRequest { + return apiClient.GetVolume(ctx, model.ProjectId, model.VolumeId) +} + +func outputResult(p *print.Printer, outputFormat string, volume *iaas.Volume) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(volume, "", " ") + if err != nil { + return fmt.Errorf("marshal volume: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal volume: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *volume.Id) + table.AddSeparator() + table.AddRow("NAME", *volume.Name) + table.AddSeparator() + table.AddRow("STATE", *volume.Status) + table.AddSeparator() + table.AddRow("VOLUME SIZE (GB)", *volume.Size) + table.AddSeparator() + table.AddRow("PERFORMANCE CLASS", *volume.PerformanceClass) + table.AddSeparator() + table.AddRow("AVAILABILITY ZONE", *volume.AvailabilityZone) + table.AddSeparator() + + if volume.Source != nil { + sourceId := *volume.Source.Id + table.AddRow("SOURCE", sourceId) + table.AddSeparator() + } + + if volume.ServerId != nil { + serverId := *volume.ServerId + table.AddRow("SERVER", serverId) + table.AddSeparator() + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/volume/describe/describe_test.go b/internal/cmd/beta/volume/describe/describe_test.go new file mode 100644 index 000000000..8f3fcdd57 --- /dev/null +++ b/internal/cmd/beta/volume/describe/describe_test.go @@ -0,0 +1,218 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + VolumeId: testVolumeId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetVolumeRequest)) iaas.ApiGetVolumeRequest { + request := testClient.GetVolume(testCtx, testProjectId, testVolumeId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "volume id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetVolumeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/volume/list/list.go b/internal/cmd/beta/volume/list/list.go new file mode 100644 index 000000000..1594b390a --- /dev/null +++ b/internal/cmd/beta/volume/list/list.go @@ -0,0 +1,181 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + labelSelectorFlag = "label-selector" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + LabelSelector *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all volumes of a project", + Long: "Lists all volumes of a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all volumes`, + "$ stackit beta volume list", + ), + examples.NewExample( + `Lists all volumes which contains the label xxx`, + "$ stackit beta volume list --label-selector xxx", + ), + examples.NewExample( + `Lists all volumes in JSON format`, + "$ stackit beta volume list --output-format json", + ), + examples.NewExample( + `Lists up to 10 volumes`, + "$ stackit beta volume list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list volumes: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + p.Info("No volumes found for project %q\n", projectLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListVolumesRequest { + req := apiClient.ListVolumes(ctx, model.ProjectId) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + + return req +} + +func outputResult(p *print.Printer, outputFormat string, volumes []iaas.Volume) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(volumes, "", " ") + if err != nil { + return fmt.Errorf("marshal volume: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(volumes, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal volume: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "Name", "Status", "Server", "Availability Zone", "Size (GB)") + + for _, volume := range volumes { + serverId := "" + if volume.ServerId != nil { + serverId = *volume.ServerId + } + table.AddRow(*volume.Id, *volume.Name, *volume.Status, serverId, *volume.AvailabilityZone, *volume.Size) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/volume/list/list_test.go b/internal/cmd/beta/volume/list/list_test.go new file mode 100644 index 000000000..ea1b60ad3 --- /dev/null +++ b/internal/cmd/beta/volume/list/list_test.go @@ -0,0 +1,204 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testLabelSelector = "label" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + labelSelectorFlag: testLabelSelector, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr(testLabelSelector), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListVolumesRequest)) iaas.ApiListVolumesRequest { + request := testClient.ListVolumes(testCtx, testProjectId) + request = request.LabelSelector(testLabelSelector) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListVolumesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/volume/performance-class/describe/describe.go b/internal/cmd/beta/volume/performance-class/describe/describe.go new file mode 100644 index 000000000..a316babba --- /dev/null +++ b/internal/cmd/beta/volume/performance-class/describe/describe.go @@ -0,0 +1,137 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + volumePerformanceClassArg = "VOLUME_PERFORMANCE_CLASS" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + VolumePerformanceClass string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a volume performance class", + Long: "Shows details of a volume performance class.", + Args: args.SingleArg(volumePerformanceClassArg, nil), + Example: examples.Build( + examples.NewExample( + `Show details of a volume performance class with name "xxx"`, + "$ stackit beta volume performance-class describe xxx", + ), + examples.NewExample( + `Show details of a volume performance class with name "xxx" in JSON format`, + "$ stackit beta volume performance-class describe xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read volume performance class: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumePerformanceClass := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + VolumePerformanceClass: volumePerformanceClass, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetVolumePerformanceClassRequest { + return apiClient.GetVolumePerformanceClass(ctx, model.ProjectId, model.VolumePerformanceClass) +} + +func outputResult(p *print.Printer, outputFormat string, performanceClass *iaas.VolumePerformanceClass) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(performanceClass, "", " ") + if err != nil { + return fmt.Errorf("marshal volume performance class: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(performanceClass, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal volume performance class: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("NAME", *performanceClass.Name) + table.AddSeparator() + table.AddRow("DESCRIPTION", *performanceClass.Description) + table.AddSeparator() + table.AddRow("IOPS", *performanceClass.Iops) + table.AddSeparator() + table.AddRow("THROUGHPUT", *performanceClass.Throughput) + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/volume/performance-class/describe/describe_test.go b/internal/cmd/beta/volume/performance-class/describe/describe_test.go new file mode 100644 index 000000000..2a43beaf1 --- /dev/null +++ b/internal/cmd/beta/volume/performance-class/describe/describe_test.go @@ -0,0 +1,212 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testVolumePerformanceClass = "storage_premium_perf6" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumePerformanceClass, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + VolumePerformanceClass: testVolumePerformanceClass, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetVolumePerformanceClassRequest)) iaas.ApiGetVolumePerformanceClassRequest { + request := testClient.GetVolumePerformanceClass(testCtx, testProjectId, testVolumePerformanceClass) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume performance class invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetVolumePerformanceClassRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/volume/performance-class/list/list.go b/internal/cmd/beta/volume/performance-class/list/list.go new file mode 100644 index 000000000..3bb62e9d7 --- /dev/null +++ b/internal/cmd/beta/volume/performance-class/list/list.go @@ -0,0 +1,177 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + labelSelectorFlag = "label-selector" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + LabelSelector *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all volume performance classes for a project", + Long: "Lists all volume performance classes for a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all volume performance classes`, + "$ stackit beta volume performance-class list", + ), + examples.NewExample( + `Lists all volume performance classes which contains the label xxx`, + "$ stackit beta volume performance-class list --label-selector xxx", + ), + examples.NewExample( + `Lists all volume performance classes in JSON format`, + "$ stackit beta volume performance-class list --output-format json", + ), + examples.NewExample( + `Lists up to 10 volume performance classes`, + "$ stackit beta volume performance-class list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list volume performance classes: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + p.Info("No volume performance class found for project %q\n", projectLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListVolumePerformanceClassesRequest { + req := apiClient.ListVolumePerformanceClasses(ctx, model.ProjectId) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + + return req +} + +func outputResult(p *print.Printer, outputFormat string, performanceClasses []iaas.VolumePerformanceClass) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(performanceClasses, "", " ") + if err != nil { + return fmt.Errorf("marshal volume performance class: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(performanceClasses, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal volume performance class: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("Name", "Description") + + for _, performanceClass := range performanceClasses { + table.AddRow(*performanceClass.Name, *performanceClass.Description) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/volume/performance-class/list/list_test.go b/internal/cmd/beta/volume/performance-class/list/list_test.go new file mode 100644 index 000000000..91c2041bb --- /dev/null +++ b/internal/cmd/beta/volume/performance-class/list/list_test.go @@ -0,0 +1,204 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testLabelSelector = "label" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + labelSelectorFlag: testLabelSelector, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr(testLabelSelector), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListVolumePerformanceClassesRequest)) iaas.ApiListVolumePerformanceClassesRequest { + request := testClient.ListVolumePerformanceClasses(testCtx, testProjectId) + request = request.LabelSelector(testLabelSelector) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListVolumePerformanceClassesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/volume/performance-class/performance_class.go b/internal/cmd/beta/volume/performance-class/performance_class.go new file mode 100644 index 000000000..8df1e19fe --- /dev/null +++ b/internal/cmd/beta/volume/performance-class/performance_class.go @@ -0,0 +1,28 @@ +package performanceclass + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/performance-class/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/performance-class/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "performance-class", + Short: "Provides functionality for volume performance classes available inside a project", + Long: "Provides functionality for volume performance classes available inside a project.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} diff --git a/internal/cmd/beta/volume/resize/resize.go b/internal/cmd/beta/volume/resize/resize.go new file mode 100644 index 000000000..043ca14fe --- /dev/null +++ b/internal/cmd/beta/volume/resize/resize.go @@ -0,0 +1,128 @@ +package resize + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + volumeIdArg = "VOLUME_ID" + + sizeFlag = "size" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + VolumeId string + Size *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "resize", + Short: "Resizes a volume", + Long: "Resizes a volume.", + Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Resize volume with ID "xxx" with new size 10 GB`, + `$ stackit beta volume resize xxx --size 10`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + if err != nil { + p.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = model.VolumeId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to resize volume %q?", volumeLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("resize volume: %w", err) + } + + p.Outputf("Resized volume %q.\n", volumeLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(sizeFlag, 0, "Volume size (GB)") + + err := flags.MarkFlagsRequired(cmd, sizeFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Size: flags.FlagToInt64Pointer(p, cmd, sizeFlag), + VolumeId: volumeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiResizeVolumeRequest { + req := apiClient.ResizeVolume(ctx, model.ProjectId, model.VolumeId) + + payload := iaas.ResizeVolumePayload{ + Size: model.Size, + } + + return req.ResizeVolumePayload(payload) +} diff --git a/internal/cmd/beta/volume/resize/resize_test.go b/internal/cmd/beta/volume/resize/resize_test.go new file mode 100644 index 000000000..15dd9c757 --- /dev/null +++ b/internal/cmd/beta/volume/resize/resize_test.go @@ -0,0 +1,232 @@ +package resize + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + sizeFlag: "10", + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Size: utils.Ptr(int64(10)), + VolumeId: testVolumeId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiResizeVolumeRequest)) iaas.ApiResizeVolumeRequest { + request := testClient.ResizeVolume(testCtx, testProjectId, testVolumeId) + request = request.ResizeVolumePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.ResizeVolumePayload)) iaas.ResizeVolumePayload { + payload := iaas.ResizeVolumePayload{ + Size: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id invalid 1", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "volume id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "resize", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sizeFlag] = "15" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Size = utils.Ptr(int64(15)) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiResizeVolumeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/volume/update/update.go b/internal/cmd/beta/volume/update/update.go new file mode 100644 index 000000000..cdd8fc8d8 --- /dev/null +++ b/internal/cmd/beta/volume/update/update.go @@ -0,0 +1,173 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + volumeIdArg = "VOLUME_ID" + + nameFlag = "name" + descriptionFlag = "description" + labelFlag = "label" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + VolumeId string + Name *string + Description *string + Labels *map[string]string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a volume", + Long: "Updates a volume.", + Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update volume with ID "xxx" with new name "volume-1-new"`, + `$ stackit beta volume update xxx --name volume-1-new`, + ), + examples.NewExample( + `Update volume with ID "xxx" with new name "volume-1-new" and new description "volume-1-desc-new"`, + `$ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + if err != nil { + p.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = model.VolumeId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update volume %q?", volumeLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update volume: %w", err) + } + + return outputResult(p, model, volumeLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(nameFlag, "n", "", "Volume name") + cmd.Flags().String(descriptionFlag, "", "Volume description") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a volume. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + VolumeId: volumeId, + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateVolumeRequest { + req := apiClient.UpdateVolume(ctx, model.ProjectId, model.VolumeId) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + + payload := iaas.UpdateVolumePayload{ + Name: model.Name, + Description: model.Description, + Labels: labelsMap, + } + + return req.UpdateVolumePayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, volumeLabel string, volume *iaas.Volume) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(volume, "", " ") + if err != nil { + return fmt.Errorf("marshal volume: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal volume: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Updated volume %q.\n", volumeLabel) + return nil + } +} diff --git a/internal/cmd/beta/volume/update/update_test.go b/internal/cmd/beta/volume/update/update_test.go new file mode 100644 index 000000000..283bfda43 --- /dev/null +++ b/internal/cmd/beta/volume/update/update_test.go @@ -0,0 +1,257 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + nameFlag: "example-volume-name", + projectIdFlag: testProjectId, + descriptionFlag: "example-volume-desc", + labelFlag: "key=value", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example-volume-name"), + Description: utils.Ptr("example-volume-desc"), + VolumeId: testVolumeId, + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateVolumeRequest)) iaas.ApiUpdateVolumeRequest { + request := testClient.UpdateVolume(testCtx, testProjectId, testVolumeId) + request = request.UpdateVolumePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.UpdateVolumePayload)) iaas.UpdateVolumePayload { + payload := iaas.UpdateVolumePayload{ + Name: utils.Ptr("example-volume-name"), + Description: utils.Ptr("example-volume-desc"), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id invalid 1", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "volume id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "use name and description", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nameFlag] = "example-volume-name" + flagValues[descriptionFlag] = "example-volume-desc" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = utils.Ptr("example-volume-name") + model.Description = utils.Ptr("example-volume-desc") + }), + }, + { + description: "use labels", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelFlag] = "key=value" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = &map[string]string{ + "key": "value", + } + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateVolumeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/volume/volume.go b/internal/cmd/beta/volume/volume.go new file mode 100644 index 000000000..0fa6f59f2 --- /dev/null +++ b/internal/cmd/beta/volume/volume.go @@ -0,0 +1,38 @@ +package volume + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/list" + performanceclass "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/performance-class" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/resize" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "volume", + Short: "Provides functionality for Volume", + Long: "Provides functionality for Volume.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) + cmd.AddCommand(resize.NewCmd(p)) + cmd.AddCommand(performanceclass.NewCmd(p)) +} diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index 44807a4fc..9e7d79510 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -8,12 +8,21 @@ import ( ) type IaaSClient interface { + GetVolumeExecute(ctx context.Context, projectId, volumeId string) (*iaas.Volume, error) GetNetworkExecute(ctx context.Context, projectId, networkId string) (*iaas.Network, error) GetNetworkAreaExecute(ctx context.Context, organizationId, areaId string) (*iaas.NetworkArea, error) ListNetworkAreaProjectsExecute(ctx context.Context, organizationId, areaId string) (*iaas.ProjectListResponse, error) GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) } +func GetVolumeName(ctx context.Context, apiClient IaaSClient, projectId, volumeId string) (string, error) { + resp, err := apiClient.GetVolumeExecute(ctx, projectId, volumeId) + if err != nil { + return "", fmt.Errorf("get volume: %w", err) + } + return *resp.Name, nil +} + func GetNetworkName(ctx context.Context, apiClient IaaSClient, projectId, networkId string) (string, error) { resp, err := apiClient.GetNetworkExecute(ctx, projectId, networkId) if err != nil { diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index 4caa3c7fc..9c0e41ac1 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -11,6 +11,8 @@ import ( ) type IaaSClientMocked struct { + GetVolumeFails bool + GetVolumeResp *iaas.Volume GetNetworkFails bool GetNetworkResp *iaas.Network GetNetworkAreaFails bool @@ -21,6 +23,13 @@ type IaaSClientMocked struct { GetNetworkAreaRangeResp *iaas.NetworkRange } +func (m *IaaSClientMocked) GetVolumeExecute(_ context.Context, _, _ string) (*iaas.Volume, error) { + if m.GetVolumeFails { + return nil, fmt.Errorf("could not get volume") + } + return m.GetVolumeResp, nil +} + func (m *IaaSClientMocked) GetNetworkExecute(_ context.Context, _, _ string) (*iaas.Network, error) { if m.GetNetworkFails { return nil, fmt.Errorf("could not get network") @@ -49,6 +58,52 @@ func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _ return m.GetNetworkAreaRangeResp, nil } +func TestGetVolumeName(t *testing.T) { + type args struct { + getInstanceFails bool + getInstanceResp *iaas.Volume + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "base", + args: args{ + getInstanceResp: &iaas.Volume{ + Name: utils.Ptr("test"), + }, + }, + want: "test", + }, + { + name: "get volume fails", + args: args{ + getInstanceFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetVolumeFails: tt.args.getInstanceFails, + GetVolumeResp: tt.args.getInstanceResp, + } + got, err := GetVolumeName(context.Background(), m, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetVolumeName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetVolumeName() = %v, want %v", got, tt.want) + } + }) + } +} + func TestGetNetworkName(t *testing.T) { type args struct { getInstanceFails bool From a7b826a93d4dc309ff926ab2046e52a5016363d5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:16:58 +0100 Subject: [PATCH 086/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.16.0 (#501) Co-authored-by: Renovate Bot Co-authored-by: GokceGK <161626272+GokceGK@users.noreply.github.com> --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index aa2006847..1eb35470d 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,6 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 h1:WXSIE4Kf github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 h1:+OZ82DwFy4JIJThadVjvll5kUWjHPSLbUIF65njsNBk= github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.15.0 h1:bPNv+PuSykBcKCYVXHiYOcqNP+KLCA7XMFSY4V6J6ug= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.15.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0 h1:geyW780gqNxzSsPvmlxy3kUUJaRA4eiF9V3b2Ibcdjs= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= From e12f3f697c704d89999a243536feeeb315c89406 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:17:34 +0100 Subject: [PATCH 087/619] fix(deps): update module golang.org/x/text to v0.20.0 (#498) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2cecb5db1..b312a9e68 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.23.0 golang.org/x/term v0.25.0 - golang.org/x/text v0.19.0 + golang.org/x/text v0.20.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 ) diff --git a/go.sum b/go.sum index 1eb35470d..9e9876121 100644 --- a/go.sum +++ b/go.sum @@ -221,8 +221,8 @@ golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 7668acd56ea557f31ca858a6456dce60ccfe26b9 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:03:07 +0100 Subject: [PATCH 088/619] fix(deps): update module golang.org/x/term to v0.26.0 (#497) Co-authored-by: Renovate Bot Co-authored-by: GokceGK <161626272+GokceGK@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index b312a9e68..3afdc7473 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 golang.org/x/oauth2 v0.23.0 - golang.org/x/term v0.25.0 + golang.org/x/term v0.26.0 golang.org/x/text v0.20.0 k8s.io/apimachinery v0.29.2 k8s.io/client-go v0.29.2 @@ -84,7 +84,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/sys v0.26.0 // indirect + golang.org/x/sys v0.27.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 9e9876121..86809b900 100644 --- a/go.sum +++ b/go.sum @@ -215,10 +215,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= From 0245259559d47e223a8d972f8ee7c1e6d58ed9d5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:08:46 +0100 Subject: [PATCH 089/619] fix(deps): update module golang.org/x/oauth2 to v0.24.0 (#496) Co-authored-by: Renovate Bot Co-authored-by: GokceGK <161626272+GokceGK@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3afdc7473..642953b39 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 github.com/zalando/go-keyring v0.2.5 golang.org/x/mod v0.20.0 - golang.org/x/oauth2 v0.23.0 + golang.org/x/oauth2 v0.24.0 golang.org/x/term v0.26.0 golang.org/x/text v0.20.0 k8s.io/apimachinery v0.29.2 diff --git a/go.sum b/go.sum index 86809b900..04aea4191 100644 --- a/go.sum +++ b/go.sum @@ -205,8 +205,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 4324f073e017bcc5036ec759c1fc27f04408ec6d Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:40:22 +0100 Subject: [PATCH 090/619] IaaS volume command changes (#504) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * change label to labels * add labels to describe table output * fix typo * Update internal/cmd/beta/volume/create/create.go Co-authored-by: João Palet * update label flag descriptions --------- Co-authored-by: João Palet --- docs/stackit_beta_volume_create.md | 7 +++++-- docs/stackit_beta_volume_update.md | 11 +++++++---- internal/cmd/beta/volume/create/create.go | 8 ++++++-- internal/cmd/beta/volume/describe/describe.go | 9 +++++++++ internal/cmd/beta/volume/update/update.go | 8 ++++++-- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/docs/stackit_beta_volume_create.md b/docs/stackit_beta_volume_create.md index b24d2391c..dc44b1327 100644 --- a/docs/stackit_beta_volume_create.md +++ b/docs/stackit_beta_volume_create.md @@ -16,7 +16,10 @@ stackit beta volume create [flags] Create a volume with availability zone "eu01-1" and size 64 GB $ stackit beta volume create --availability-zone eu01-1 --size 64 - Create a volume with name "volume-1", source id "xxx" and type "image" + Create a volume with availability zone "eu01-1", size 64 GB and labels + $ stackit beta volume create --availability-zone eu01-1 --size 64 --labels key=value,foo=bar + + Create a volume with name "volume-1", from a source image with ID "xxx" $ stackit beta volume create --availability-zone eu01-1 --name volume-1 --source-id xxx --source-type image Create a volume with availability zone "eu01-1", performance class "storage_premium_perf1" and size 64 GB @@ -29,7 +32,7 @@ stackit beta volume create [flags] --availability-zone string Availability zone --description string Volume description -h, --help Help for "stackit beta volume create" - --label stringToString Labels are key-value string pairs which can be attached to a volume. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) + --labels stringToString Labels are key-value string pairs which can be attached to a volume. E.g. '--labels key1=value1,key2=value2,...' (default []) -n, --name string Volume name --performance-class string Performance class --size int Volume size (GB). Either 'size' or the 'source-id' and 'source-type' flags must be given diff --git a/docs/stackit_beta_volume_update.md b/docs/stackit_beta_volume_update.md index c8b0ccb44..98ad0a94a 100644 --- a/docs/stackit_beta_volume_update.md +++ b/docs/stackit_beta_volume_update.md @@ -18,15 +18,18 @@ stackit beta volume update [flags] Update volume with ID "xxx" with new name "volume-1-new" and new description "volume-1-desc-new" $ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new + + Update volume with ID "xxx" with new name "volume-1-new", new description "volume-1-desc-new" and label(s) + $ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new --labels key=value,foo=bar ``` ### Options ``` - --description string Volume description - -h, --help Help for "stackit beta volume update" - --label stringToString Labels are key-value string pairs which can be attached to a volume. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) - -n, --name string Volume name + --description string Volume description + -h, --help Help for "stackit beta volume update" + --labels stringToString Labels are key-value string pairs which can be attached to a volume. E.g. '--labels key1=value1,key2=value2,...' (default []) + -n, --name string Volume name ``` ### Options inherited from parent commands diff --git a/internal/cmd/beta/volume/create/create.go b/internal/cmd/beta/volume/create/create.go index 88467c54e..e1324feb0 100644 --- a/internal/cmd/beta/volume/create/create.go +++ b/internal/cmd/beta/volume/create/create.go @@ -26,7 +26,7 @@ const ( availabilityZoneFlag = "availability-zone" nameFlag = "name" descriptionFlag = "description" - labelFlag = "label" + labelFlag = "labels" performanceClassFlag = "performance-class" sizeFlag = "size" sourceIdFlag = "source-id" @@ -56,6 +56,10 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a volume with availability zone "eu01-1" and size 64 GB`, `$ stackit beta volume create --availability-zone eu01-1 --size 64`, ), + examples.NewExample( + `Create a volume with availability zone "eu01-1", size 64 GB and labels`, + `$ stackit beta volume create --availability-zone eu01-1 --size 64 --labels key=value,foo=bar`, + ), examples.NewExample( `Create a volume with name "volume-1", from a source image with ID "xxx"`, `$ stackit beta volume create --availability-zone eu01-1 --name volume-1 --source-id xxx --source-type image`, @@ -122,7 +126,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(availabilityZoneFlag, "", "Availability zone") cmd.Flags().StringP(nameFlag, "n", "", "Volume name") cmd.Flags().String(descriptionFlag, "", "Volume description") - cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a volume. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a volume. E.g. '--labels key1=value1,key2=value2,...'") cmd.Flags().String(performanceClassFlag, "", "Performance class") cmd.Flags().Int64(sizeFlag, 0, "Volume size (GB). Either 'size' or the 'source-id' and 'source-type' flags must be given") cmd.Flags().String(sourceIdFlag, "", "ID of the source object of volume. Either 'size' or the 'source-id' and 'source-type' flags must be given") diff --git a/internal/cmd/beta/volume/describe/describe.go b/internal/cmd/beta/volume/describe/describe.go index 0fc48e135..a8780c11b 100644 --- a/internal/cmd/beta/volume/describe/describe.go +++ b/internal/cmd/beta/volume/describe/describe.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/goccy/go-yaml" @@ -145,6 +146,14 @@ func outputResult(p *print.Printer, outputFormat string, volume *iaas.Volume) er table.AddSeparator() } + if volume.Labels != nil && len(*volume.Labels) > 0 { + labels := []string{} + for key, value := range *volume.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + } + err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/beta/volume/update/update.go b/internal/cmd/beta/volume/update/update.go index cdd8fc8d8..34bbc61f5 100644 --- a/internal/cmd/beta/volume/update/update.go +++ b/internal/cmd/beta/volume/update/update.go @@ -25,7 +25,7 @@ const ( nameFlag = "name" descriptionFlag = "description" - labelFlag = "label" + labelFlag = "labels" ) type inputModel struct { @@ -51,6 +51,10 @@ func NewCmd(p *print.Printer) *cobra.Command { `Update volume with ID "xxx" with new name "volume-1-new" and new description "volume-1-desc-new"`, `$ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new`, ), + examples.NewExample( + `Update volume with ID "xxx" with new name "volume-1-new", new description "volume-1-desc-new" and label(s)`, + `$ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new --labels key=value,foo=bar`, + ), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -96,7 +100,7 @@ func NewCmd(p *print.Printer) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(nameFlag, "n", "", "Volume name") cmd.Flags().String(descriptionFlag, "", "Volume description") - cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a volume. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a volume. E.g. '--labels key1=value1,key2=value2,...'") } func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { From a95814516492c395f84db28dfdc3dcd86d6ac5d7 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Mon, 18 Nov 2024 13:21:10 +0100 Subject: [PATCH 091/619] feat: Update golangci-lint version to 1.62.0 and go version to 1.23 Signed-off-by: Alexander Dahmen --- .github/workflows/ci.yaml | 2 +- go.mod | 2 +- golang-ci.yaml | 17 ++++++---------- .../activate_service_account.go | 2 +- internal/cmd/auth/login/login.go | 2 +- internal/cmd/auth/logout/logout.go | 2 +- .../cmd/beta/network-area/create/create.go | 2 +- internal/cmd/beta/network-area/list/list.go | 2 +- .../network-range/create/create.go | 2 +- .../network-area/network-range/list/list.go | 2 +- .../beta/network-area/route/create/create.go | 2 +- .../cmd/beta/network-area/route/list/list.go | 2 +- internal/cmd/beta/network/create/create.go | 2 +- internal/cmd/beta/network/list/list.go | 2 +- .../cmd/beta/server/backup/create/create.go | 2 +- .../cmd/beta/server/backup/disable/disable.go | 2 +- .../cmd/beta/server/backup/enable/enable.go | 2 +- internal/cmd/beta/server/backup/list/list.go | 2 +- .../server/backup/schedule/create/create.go | 2 +- .../beta/server/backup/schedule/list/list.go | 2 +- .../cmd/beta/server/command/create/create.go | 2 +- internal/cmd/beta/server/command/list/list.go | 2 +- .../beta/server/command/template/list/list.go | 2 +- .../beta/sqlserverflex/database/list/list.go | 2 +- .../sqlserverflex/instance/create/create.go | 2 +- .../beta/sqlserverflex/instance/list/list.go | 2 +- .../cmd/beta/sqlserverflex/options/options.go | 2 +- .../beta/sqlserverflex/user/create/create.go | 2 +- .../cmd/beta/sqlserverflex/user/list/list.go | 2 +- internal/cmd/beta/volume/create/create.go | 2 +- internal/cmd/beta/volume/list/list.go | 2 +- .../volume/performance-class/list/list.go | 2 +- internal/cmd/config/list/list.go | 2 +- internal/cmd/config/profile/list/list.go | 2 +- internal/cmd/config/profile/unset/unset.go | 2 +- internal/cmd/config/set/set.go | 2 +- internal/cmd/config/unset/unset.go | 2 +- internal/cmd/dns/record-set/create/create.go | 2 +- internal/cmd/dns/record-set/list/list.go | 20 ++++++++++++++++--- internal/cmd/dns/record-set/list/list_test.go | 2 +- internal/cmd/dns/zone/create/create.go | 2 +- internal/cmd/dns/zone/list/list.go | 20 ++++++++++++++++--- internal/cmd/dns/zone/list/list_test.go | 2 +- internal/cmd/load-balancer/create/create.go | 2 +- .../generate-payload/generate_payload.go | 2 +- internal/cmd/load-balancer/list/list.go | 2 +- .../observability-credentials/add/add.go | 2 +- .../cleanup/cleanup.go | 2 +- .../observability-credentials/list/list.go | 2 +- internal/cmd/load-balancer/quota/quota.go | 2 +- .../cmd/logme/credentials/create/create.go | 2 +- internal/cmd/logme/credentials/list/list.go | 2 +- internal/cmd/logme/instance/create/create.go | 2 +- internal/cmd/logme/instance/list/list.go | 2 +- internal/cmd/logme/plans/plans.go | 2 +- .../cmd/mariadb/credentials/create/create.go | 2 +- internal/cmd/mariadb/credentials/list/list.go | 2 +- .../cmd/mariadb/instance/create/create.go | 2 +- internal/cmd/mariadb/instance/list/list.go | 2 +- internal/cmd/mariadb/plans/plans.go | 2 +- internal/cmd/mongodbflex/backup/list/list.go | 2 +- .../backup/restore-jobs/restore_jobs.go | 2 +- .../cmd/mongodbflex/backup/restore/restore.go | 2 +- .../mongodbflex/backup/schedule/schedule.go | 2 +- .../backup/update-schedule/update_schedule.go | 2 +- .../cmd/mongodbflex/instance/create/create.go | 2 +- .../cmd/mongodbflex/instance/list/list.go | 2 +- internal/cmd/mongodbflex/options/options.go | 2 +- .../cmd/mongodbflex/user/create/create.go | 2 +- internal/cmd/mongodbflex/user/list/list.go | 2 +- .../cmd/object-storage/bucket/list/list.go | 2 +- .../credentials-group/create/create.go | 2 +- .../credentials-group/list/list.go | 2 +- .../credentials/create/create.go | 2 +- .../object-storage/credentials/list/list.go | 2 +- .../cmd/object-storage/disable/disable.go | 2 +- internal/cmd/object-storage/enable/enable.go | 2 +- .../credentials/create/create.go | 2 +- .../observability/credentials/list/list.go | 2 +- .../observability/instance/create/create.go | 2 +- .../cmd/observability/instance/list/list.go | 2 +- internal/cmd/observability/plans/plans.go | 2 +- .../scrape-config/create/create.go | 2 +- .../generate-payload/generate_payload.go | 2 +- .../observability/scrape-config/list/list.go | 2 +- .../opensearch/credentials/create/create.go | 2 +- .../cmd/opensearch/credentials/list/list.go | 2 +- .../cmd/opensearch/instance/create/create.go | 2 +- internal/cmd/opensearch/instance/list/list.go | 2 +- internal/cmd/opensearch/plans/plans.go | 2 +- internal/cmd/organization/member/list/list.go | 2 +- internal/cmd/organization/role/list/list.go | 2 +- internal/cmd/postgresflex/backup/list/list.go | 2 +- .../backup/update-schedule/update_schedule.go | 2 +- .../postgresflex/instance/create/create.go | 2 +- .../cmd/postgresflex/instance/list/list.go | 2 +- internal/cmd/postgresflex/options/options.go | 2 +- .../cmd/postgresflex/user/create/create.go | 2 +- internal/cmd/postgresflex/user/list/list.go | 2 +- .../postgresflex/user/update/update_test.go | 2 +- internal/cmd/project/create/create.go | 2 +- internal/cmd/project/delete/delete.go | 4 ++-- internal/cmd/project/list/list.go | 2 +- internal/cmd/project/list/list_test.go | 2 +- internal/cmd/project/member/list/list.go | 2 +- internal/cmd/project/role/list/list.go | 2 +- internal/cmd/project/update/update.go | 2 +- .../cmd/rabbitmq/credentials/create/create.go | 2 +- .../cmd/rabbitmq/credentials/list/list.go | 2 +- .../cmd/rabbitmq/instance/create/create.go | 2 +- internal/cmd/rabbitmq/instance/list/list.go | 2 +- internal/cmd/rabbitmq/plans/plans.go | 2 +- .../cmd/redis/credentials/create/create.go | 2 +- internal/cmd/redis/credentials/list/list.go | 2 +- internal/cmd/redis/instance/create/create.go | 2 +- internal/cmd/redis/instance/list/list.go | 2 +- internal/cmd/redis/plans/plans.go | 2 +- internal/cmd/root.go | 6 +++--- .../secrets-manager/instance/create/create.go | 2 +- .../cmd/secrets-manager/instance/list/list.go | 2 +- .../cmd/secrets-manager/user/create/create.go | 2 +- .../cmd/secrets-manager/user/list/list.go | 2 +- internal/cmd/service-account/create/create.go | 2 +- .../cmd/service-account/key/create/create.go | 2 +- internal/cmd/service-account/key/list/list.go | 2 +- .../cmd/service-account/key/update/update.go | 2 +- internal/cmd/service-account/list/list.go | 2 +- .../service-account/token/create/create.go | 2 +- .../cmd/service-account/token/list/list.go | 2 +- .../generate-payload/generate_payload.go | 2 +- internal/cmd/ske/cluster/list/list.go | 2 +- internal/cmd/ske/describe/describe.go | 2 +- internal/cmd/ske/disable/disable.go | 2 +- internal/cmd/ske/enable/enable.go | 2 +- internal/cmd/ske/kubeconfig/login/login.go | 4 ++-- internal/cmd/ske/options/options.go | 2 +- internal/pkg/args/args_test.go | 8 ++++---- internal/pkg/auth/auth.go | 2 +- internal/pkg/auth/auth_test.go | 2 +- internal/pkg/auth/storage.go | 2 +- internal/pkg/auth/user_login.go | 2 +- internal/pkg/auth/user_token_flow_test.go | 2 +- internal/pkg/cache/cache.go | 2 +- internal/pkg/cache/cache_test.go | 2 +- internal/pkg/config/config.go | 2 +- internal/pkg/config/config_test.go | 2 +- internal/pkg/config/profiles.go | 4 ++-- internal/pkg/errors/errors.go | 2 +- internal/pkg/fileutils/file_utils_test.go | 2 +- internal/pkg/flags/flags_test.go | 14 ++++++------- internal/pkg/print/print_test.go | 8 ++++---- .../object-storage/utils/utils_test.go | 2 +- scripts/generate.go | 4 ++-- scripts/project.sh | 2 +- 154 files changed, 209 insertions(+), 186 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0889f8fa6..d59bcee93 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,7 +3,7 @@ name: CI on: [pull_request, workflow_dispatch] env: - GO_VERSION: "1.22" + GO_VERSION: "1.23" jobs: main: diff --git a/go.mod b/go.mod index 642953b39..dbce1534f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/stackitcloud/stackit-cli -go 1.22 +go 1.23 require ( github.com/fatih/color v1.18.0 diff --git a/golang-ci.yaml b/golang-ci.yaml index 7eceed189..3487f7456 100644 --- a/golang-ci.yaml +++ b/golang-ci.yaml @@ -14,13 +14,12 @@ linters-settings: # it's a comma-separated list of prefixes local-prefixes: github.com/freiheit-com/nmww depguard: - list-type: blacklist - include-go-root: false - packages: - - github.com/stretchr/testify - packages-with-error-message: - # specify an error message to output when a blacklisted package is used - - github.com/stretchr/testify: "do not use a testing framework" + rules: + main: + list-mode: lax # Everything is allowed unless it is denied + deny: + - pkg: "github.com/stretchr/testify" + desc: Do not use a testing framework misspell: # Correct spellings using locale preferences for US or UK. # Default is to use a neutral variety of English. @@ -75,7 +74,6 @@ linters: - unused # additional linters - errorlint - - exportloopref - gochecknoinits - gocritic - gofmt @@ -91,9 +89,6 @@ linters: - forcetypeassert - errcheck disable: - - structcheck # deprecated - - deadcode # deprecated - - varcheck # deprecated - noctx # false positive: finds errors with http.NewRequest that dont make sense - unparam # false positives issues: diff --git a/internal/cmd/auth/activate-service-account/activate_service_account.go b/internal/cmd/auth/activate-service-account/activate_service_account.go index aca1dd4fe..82c549a5d 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account.go @@ -51,7 +51,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Activate service account authentication in the STACKIT CLI using the service account token`, "$ stackit auth activate-service-account --service-account-token my-service-account-token"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { model := parseInput(p, cmd) tokenCustomEndpoint, err := storeFlags() diff --git a/internal/cmd/auth/login/login.go b/internal/cmd/auth/login/login.go index e19f962f0..9c17acef3 100644 --- a/internal/cmd/auth/login/login.go +++ b/internal/cmd/auth/login/login.go @@ -24,7 +24,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Login to the STACKIT CLI. This command will open a browser window where you can login to your STACKIT account`, "$ stackit auth login"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { err := auth.AuthorizeUser(p, false) if err != nil { return fmt.Errorf("authorization failed: %w", err) diff --git a/internal/cmd/auth/logout/logout.go b/internal/cmd/auth/logout/logout.go index 454b977af..adc6f7069 100644 --- a/internal/cmd/auth/logout/logout.go +++ b/internal/cmd/auth/logout/logout.go @@ -22,7 +22,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Log out of the STACKIT CLI.`, "$ stackit auth logout"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { err := auth.LogoutUser() if err != nil { return fmt.Errorf("log out failed: %w", err) diff --git a/internal/cmd/beta/network-area/create/create.go b/internal/cmd/beta/network-area/create/create.go index 814241f05..83322226b 100644 --- a/internal/cmd/beta/network-area/create/create.go +++ b/internal/cmd/beta/network-area/create/create.go @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit beta network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24`, ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/network-area/list/list.go b/internal/cmd/beta/network-area/list/list.go index 1f3f9c294..08b619851 100644 --- a/internal/cmd/beta/network-area/list/list.go +++ b/internal/cmd/beta/network-area/list/list.go @@ -52,7 +52,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta network-area list --organization-id xxx --limit 10", ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/network-area/network-range/create/create.go b/internal/cmd/beta/network-area/network-range/create/create.go index 3e5d9639f..e66870dd4 100644 --- a/internal/cmd/beta/network-area/network-range/create/create.go +++ b/internal/cmd/beta/network-area/network-range/create/create.go @@ -43,7 +43,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit beta network-area network-range create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24"`, ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/network-area/network-range/list/list.go b/internal/cmd/beta/network-area/network-range/list/list.go index 6c0c98451..b5b28f688 100644 --- a/internal/cmd/beta/network-area/network-range/list/list.go +++ b/internal/cmd/beta/network-area/network-range/list/list.go @@ -53,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --limit 10", ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/network-area/route/create/create.go b/internal/cmd/beta/network-area/route/create/create.go index 8c2673236..24608f14f 100644 --- a/internal/cmd/beta/network-area/route/create/create.go +++ b/internal/cmd/beta/network-area/route/create/create.go @@ -55,7 +55,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/network-area/route/list/list.go b/internal/cmd/beta/network-area/route/list/list.go index a3e71d19e..6a33d5e2f 100644 --- a/internal/cmd/beta/network-area/route/list/list.go +++ b/internal/cmd/beta/network-area/route/list/list.go @@ -53,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta network-area route list --network-area-id xxx --organization-id yyy --limit 10", ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go index 04170dadd..c057098ec 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/beta/network/create/create.go @@ -58,7 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix-length 56`, ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index 3ed188fd2..4773d707a 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta network list --limit 10", ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/server/backup/create/create.go b/internal/cmd/beta/server/backup/create/create.go index 92a78a7cb..90b3109c4 100644 --- a/internal/cmd/beta/server/backup/create/create.go +++ b/internal/cmd/beta/server/backup/create/create.go @@ -50,7 +50,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a Server Backup with name "mybackup" and retention period of 5 days`, `$ stackit beta server backup create --server-id xxx --name=mybackup --retention-period=5`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/beta/server/backup/disable/disable.go b/internal/cmd/beta/server/backup/disable/disable.go index a40b23fa0..3f3777ccb 100644 --- a/internal/cmd/beta/server/backup/disable/disable.go +++ b/internal/cmd/beta/server/backup/disable/disable.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Disable Server Backup functionality for your server.`, "$ stackit beta server backup disable --server-id=zzz"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/server/backup/enable/enable.go b/internal/cmd/beta/server/backup/enable/enable.go index 885f0e6c3..b4192a177 100644 --- a/internal/cmd/beta/server/backup/enable/enable.go +++ b/internal/cmd/beta/server/backup/enable/enable.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Enable Server Backup functionality for your server`, "$ stackit beta server backup enable --server-id=zzz"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/server/backup/list/list.go b/internal/cmd/beta/server/backup/list/list.go index fd3897d3c..6588cd96e 100644 --- a/internal/cmd/beta/server/backup/list/list.go +++ b/internal/cmd/beta/server/backup/list/list.go @@ -45,7 +45,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List all backups for a server with ID "xxx" in JSON format`, "$ stackit beta server backup list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/server/backup/schedule/create/create.go b/internal/cmd/beta/server/backup/schedule/create/create.go index 5227c4bb0..d59a50df3 100644 --- a/internal/cmd/beta/server/backup/schedule/create/create.go +++ b/internal/cmd/beta/server/backup/schedule/create/create.go @@ -58,7 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a Server Backup Schedule with name "myschedule", backup name "mybackup" and retention period of 5 days`, `$ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule --backup-retention-period=5`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/beta/server/backup/schedule/list/list.go b/internal/cmd/beta/server/backup/schedule/list/list.go index 9ddde5860..0a5cd7f95 100644 --- a/internal/cmd/beta/server/backup/schedule/list/list.go +++ b/internal/cmd/beta/server/backup/schedule/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List all backup schedules for a server with ID "xxx" in JSON format`, "$ stackit beta server backup schedule list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/server/command/create/create.go b/internal/cmd/beta/server/command/create/create.go index ff593276e..6aeb808ec 100644 --- a/internal/cmd/beta/server/command/create/create.go +++ b/internal/cmd/beta/server/command/create/create.go @@ -47,7 +47,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a server command for server with ID "xxx", template name "RunShellScript" and a script provided on the command line`, `$ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='echo hello'`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/beta/server/command/list/list.go b/internal/cmd/beta/server/command/list/list.go index 475cd6328..b13a53319 100644 --- a/internal/cmd/beta/server/command/list/list.go +++ b/internal/cmd/beta/server/command/list/list.go @@ -45,7 +45,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List all commands for a server with ID "xxx" in JSON format`, "$ stackit beta server command list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/server/command/template/list/list.go b/internal/cmd/beta/server/command/template/list/list.go index dc14573d9..a544b2fc6 100644 --- a/internal/cmd/beta/server/command/template/list/list.go +++ b/internal/cmd/beta/server/command/template/list/list.go @@ -44,7 +44,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List all commands templates in JSON format`, "$ stackit beta server command template list --output-format json"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index 7398206f6..990884253 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 SQLServer Flex databases of instance with ID "xxx"`, "$ stackit beta sqlserverflex database list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 62cee12dc..8e0b87819 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -71,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a SQLServer Flex instance with name "my-instance", specify flavor by CPU and RAM, set storage size to 20 GB, and restrict access to a specific range of IP addresses. Other parameters are set to default values`, `$ stackit beta sqlserverflex instance create --name my-instance --cpu 1 --ram 4 --storage-size 20 --acl 1.2.3.0/24`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 7d89dd1d6..92814d3e4 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 SQLServer Flex instances`, "$ stackit beta sqlserverflex instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index 3b3ef5dbf..2624bffaa 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -93,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List SQL Server Flex user roles and database compatibilities for a given instance. The IDs of existing instances can be obtained by running "$ stackit beta sqlserverflex instance list"`, "$ stackit beta sqlserverflex options --user-roles --db-compatibilities --instance-id "), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 29b416460..7fc9b05e0 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -55,7 +55,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_LoginManager##,##STACKIT_DatabaseManager##"`), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index 3ca173b24..005f437f9 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta sqlserverflex user list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/volume/create/create.go b/internal/cmd/beta/volume/create/create.go index e1324feb0..943ee7d85 100644 --- a/internal/cmd/beta/volume/create/create.go +++ b/internal/cmd/beta/volume/create/create.go @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit beta volume create --availability-zone eu01-1 --performance-class storage_premium_perf1 --size 64`, ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/volume/list/list.go b/internal/cmd/beta/volume/list/list.go index 1594b390a..47b73170b 100644 --- a/internal/cmd/beta/volume/list/list.go +++ b/internal/cmd/beta/volume/list/list.go @@ -55,7 +55,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta volume list --limit 10", ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/beta/volume/performance-class/list/list.go b/internal/cmd/beta/volume/performance-class/list/list.go index 3bb62e9d7..7c37b7284 100644 --- a/internal/cmd/beta/volume/performance-class/list/list.go +++ b/internal/cmd/beta/volume/performance-class/list/list.go @@ -55,7 +55,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta volume performance-class list --limit 10", ), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/config/list/list.go b/internal/cmd/config/list/list.go index 8ba6160f4..ab5599d7a 100644 --- a/internal/cmd/config/list/list.go +++ b/internal/cmd/config/list/list.go @@ -47,7 +47,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List your active configuration in a json format`, "$ stackit config list --output-format json"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { configData := viper.AllSettings() model := parseInput(p, cmd) diff --git a/internal/cmd/config/profile/list/list.go b/internal/cmd/config/profile/list/list.go index 7f594d1e1..98cd68cb7 100644 --- a/internal/cmd/config/profile/list/list.go +++ b/internal/cmd/config/profile/list/list.go @@ -34,7 +34,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List the configuration profiles in a json format`, "$ stackit config profile list --output-format json"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { model := parseInput(p, cmd) profiles, err := config.ListProfiles() diff --git a/internal/cmd/config/profile/unset/unset.go b/internal/cmd/config/profile/unset/unset.go index f767cbfe4..4c06edb60 100644 --- a/internal/cmd/config/profile/unset/unset.go +++ b/internal/cmd/config/profile/unset/unset.go @@ -26,7 +26,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Unset the currently active configuration profile. The default profile will be used.`, "$ stackit config profile unset"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { err := config.UnsetProfile(p) if err != nil { return fmt.Errorf("unset profile: %w", err) diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 70ea7b7b6..5f983cd88 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -74,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Set the DNS custom endpoint. This endpoint will be used on all calls to the DNS API (unless overridden by the "STACKIT_DNS_CUSTOM_ENDPOINT" environment variable)`, "$ stackit config set --dns-custom-endpoint https://dns.stackit.cloud"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { model, err := parseInput(p, cmd) if err != nil { return err diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 2b9ff15ec..3e8c37f5c 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -101,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Unset the DNS custom endpoint stored in your configuration`, "$ stackit config unset --dns-custom-endpoint"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { model := parseInput(p, cmd) if model.Async { diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index a6beefdc3..36c065d1c 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a DNS record set with name "my-rr" with records "1.2.3.4" and "5.6.7.8" in zone with ID "xxx"`, "$ stackit dns record-set create --zone-id xxx --name my-rr --record 1.2.3.4 --record 5.6.7.8"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index 40edbcbec..caca06264 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "math" "strings" "github.com/goccy/go-yaml" @@ -31,6 +32,7 @@ const ( limitFlag = "limit" pageSizeFlag = "page-size" + defaultPage = 1 pageSizeDefault = 100 deleteSucceededState = "DELETE_SUCCEEDED" ) @@ -71,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List the deleted DNS record-sets for zone with ID "xxx"`, "$ stackit dns record-set list --zone-id xxx --deleted"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { @@ -193,8 +195,20 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient dnsClient, p if model.OrderByName != nil { req = req.OrderByName(strings.ToUpper(*model.OrderByName)) } - req = req.PageSize(int32(model.PageSize)) - req = req.Page(int32(page)) + + // check integer overflows + if model.PageSize > math.MaxInt32 || model.PageSize < math.MinInt32 { + req = req.PageSize(pageSizeDefault) + } else { + req = req.PageSize(int32(model.PageSize)) + } + + if page > math.MaxInt32 || page < math.MinInt32 { + req = req.Page(defaultPage) + } else { + req = req.Page(int32(page)) + } + return req } diff --git a/internal/cmd/dns/record-set/list/list_test.go b/internal/cmd/dns/record-set/list/list_test.go index 9c571c3ec..1ee21f9fb 100644 --- a/internal/cmd/dns/record-set/list/list_test.go +++ b/internal/cmd/dns/record-set/list/list_test.go @@ -489,7 +489,7 @@ func TestFetchRecordSets(t *testing.T) { } return } - if err == nil && tt.apiCallFails { + if tt.apiCallFails { t.Fatalf("did not fail on invalid input") } if numAPICalls != tt.expectedNumAPICalls { diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 95507e40d..32e6ab636 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -68,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a DNS zone with name "my-zone", DNS name "www.my-zone.com" and default time to live of 1000ms`, "$ stackit dns zone create --name my-zone --dns-name www.my-zone.com --default-ttl 1000"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index 46d08b31c..a318ef381 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "math" "strings" "github.com/goccy/go-yaml" @@ -30,6 +31,7 @@ const ( limitFlag = "limit" pageSizeFlag = "page-size" + defaultPage = 1 pageSizeDefault = 100 deleteSucceededState = "DELETE_SUCCEEDED" ) @@ -66,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List DNS zones, including deleted`, "$ stackit dns zone list --include-deleted"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { @@ -181,8 +183,20 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient dnsClient, p if !model.IncludeDeleted { req = req.StateNeq(deleteSucceededState) } - req = req.PageSize(int32(model.PageSize)) - req = req.Page(int32(page)) + + // check integer overflows + if model.PageSize > math.MaxInt32 || model.PageSize < math.MinInt32 { + req = req.PageSize(pageSizeDefault) + } else { + req = req.PageSize(int32(model.PageSize)) + } + + if page > math.MaxInt32 || page < math.MinInt32 { + req = req.Page(defaultPage) + } else { + req = req.Page(int32(page)) + } + return req } diff --git a/internal/cmd/dns/zone/list/list_test.go b/internal/cmd/dns/zone/list/list_test.go index 6343d5c4b..70b173864 100644 --- a/internal/cmd/dns/zone/list/list_test.go +++ b/internal/cmd/dns/zone/list/list_test.go @@ -483,7 +483,7 @@ func TestFetchZones(t *testing.T) { } return } - if err == nil && tt.apiCallFails { + if tt.apiCallFails { t.Fatalf("did not fail on invalid input") } if numAPICalls != tt.expectedNumAPICalls { diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index 324948fff..c6364ef2e 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -59,7 +59,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ``, `$ stackit load-balancer create --payload @./payload.json`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index 4d560fc42..4b13af079 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -133,7 +133,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Generate a payload with values of an existing load balancer, and preview it in the terminal`, `$ stackit load-balancer generate-payload --lb-name xxx`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index a82a0384d..512f984db 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 load balancers `, "$ stackit load-balancer list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index 96faa7a87..b6421195a 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Add observability credentials to a load balancer with username "xxx" and display name "yyy", providing the path to a file with the password as flag`, "$ stackit load-balancer observability-credentials add --username xxx --password @./password.txt --display-name yyy"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go index 2192b4591..221b155e5 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go @@ -32,7 +32,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Delete observability credentials unused by any Load Balancer`, "$ stackit load-balancer observability-credentials cleanup"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 226d9f06a..11c1a0161 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -58,7 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 Load Balancer observability credentials`, "$ stackit load-balancer observability-credentials list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index 593e117b7..eb6b3ea21 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -33,7 +33,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Get the configured load balancer quota for the project`, "$ stackit load-balancer quota"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 76b3b14f1..5d67574a2 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -44,7 +44,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create credentials for a LogMe instance and show the password in the output`, "$ stackit logme credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index 653902d56..e53a61174 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 credentials' IDs for a LogMe instance`, "$ stackit logme credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index 7e2b15e2f..c6b34b62c 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a LogMe instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit logme instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index 24e3cf999..dba438103 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 LogMe instances`, "$ stackit logme instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index dfa14ed0e..b1500eccd 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 LogMe service plans`, "$ stackit logme plans --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 487c976b3..602286821 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -45,7 +45,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create credentials for a MariaDB instance and show the password in the output`, "$ stackit mariadb credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index 75a438804..dde2678a1 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 credentials' IDs for a MariaDB instance`, "$ stackit mariadb credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index 754b50fcd..097588efd 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a MariaDB instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit mariadb instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index 4a3b31672..e550b01f4 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 MariaDB instances`, "$ stackit mariadb instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index 4fb14c3c2..fff09aaba 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 MariaDB service plans`, "$ stackit mariadb plans --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index f1a26ce75..13002dc49 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -50,7 +50,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit mongodbflex backup list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index 5d5d0cad8..6b289d2f8 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit mongodbflex backup restore-jobs --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index d74611db3..c8de137fc 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -55,7 +55,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Restore a MongoDB Flex instance with ID "yyy", using backup from instance with ID "zzz" with backup ID "xxx"`, `$ stackit mongodbflex backup restore --instance-id zzz --backup-instance-id yyy --backup-id xxx`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index 1e899fe22..c8a5a316d 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -42,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Get details of the backup schedule of a MongoDB Flex instance with ID "xxx" in JSON format`, "$ stackit mongodbflex backup schedule --instance-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go index 5b2f71bba..8f75c6964 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go @@ -66,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit mongodbflex backup update-schedule --instance-id xxx --store-for-days 5"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 607774a0c..5962804a1 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -74,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a MongoDB Flex instance with name "my-instance", allow access to a specific range of IP addresses, specify flavor by CPU and RAM and set storage size to 20 GB. Other parameters are set to default values`, `$ stackit mongodbflex instance create --name my-instance --cpu 1 --ram 4 --acl 1.2.3.0/24 --storage-size 20`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index 443c7ef08..d76c3d667 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 MongoDB Flex instances`, "$ stackit mongodbflex instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 2480e5b10..53b62932b 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -62,7 +62,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List MongoDB Flex storage options for a given flavor. The flavor ID can be retrieved by running "$ stackit mongodbflex options --flavors"`, "$ stackit mongodbflex options --storages --flavor-id "), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index 8e8b743c5..350142390 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -57,7 +57,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit mongodbflex user create --instance-id xxx --role read --database default"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index ada4d0f6f..8ba1f3908 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit mongodbflex user list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index 13367f035..554e6b6c4 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 Object Storage buckets`, "$ stackit object-storage bucket list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index d7399e501..c75a145ef 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -39,7 +39,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create credentials group to hold Object Storage access credentials`, "$ stackit object-storage credentials-group create --name example"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index 073a88a9a..416eef811 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -45,7 +45,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 credentials groups`, "$ stackit object-storage credentials-group list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index 2d9387cc3..a4cdab240 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -47,7 +47,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create credentials for a credentials group with ID "xxx", including a specific expiration date`, "$ stackit object-storage credentials create --credentials-group-id xxx --expire-date 2024-03-06T00:00:00.000Z"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index 3814a0464..da2643610 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 credentials for a credentials group with ID "xxx"`, "$ stackit object-storage credentials list --credentials-group-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/object-storage/disable/disable.go b/internal/cmd/object-storage/disable/disable.go index d38546ac4..40303b8da 100644 --- a/internal/cmd/object-storage/disable/disable.go +++ b/internal/cmd/object-storage/disable/disable.go @@ -31,7 +31,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Disable Object Storage functionality for your project.`, "$ stackit object-storage disable"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/object-storage/enable/enable.go b/internal/cmd/object-storage/enable/enable.go index 42c678784..52bbec6f9 100644 --- a/internal/cmd/object-storage/enable/enable.go +++ b/internal/cmd/object-storage/enable/enable.go @@ -31,7 +31,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Enable Object Storage functionality for your project`, "$ stackit object-storage enable"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index 844f25dda..d74983441 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -41,7 +41,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create credentials for Observability instance with ID "xxx"`, "$ stackit observability credentials create --instance-id xxx"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/observability/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go index 2fb435bb1..29096de24 100644 --- a/internal/cmd/observability/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List the usernames of up to 10 credentials for an Observability instance`, "$ stackit observability credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 0f1bd2714..02057ddbe 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -51,7 +51,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create an Observability instance with name "my-instance" and specify plan by ID`, "$ stackit observability instance create --name my-instance --plan-id xxx"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index d87fcdf0c..1db4743c3 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 Observability instances`, "$ stackit observability instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index 14baeaec3..2a62612e2 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 Observability service plans`, "$ stackit observability plans --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/observability/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go index dd7eba557..545a706c2 100644 --- a/internal/cmd/observability/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -58,7 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ``, `$ stackit observability scrape-config create --payload @./payload.json --instance-id xxx`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go index cdd20cd9f..363070be8 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go @@ -59,7 +59,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Generate an Update payload with the values of an existing configuration named "my-config" for Observability instance xxx, and preview it in the terminal`, `$ stackit observability scrape-config generate-payload --job-name my-config --instance-id xxx`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/observability/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go index f535db051..b1a33f886 100644 --- a/internal/cmd/observability/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 scrape configurations of Observability instance "xxx"`, "$ stackit observability scrape-config list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index eebf71bb8..44cef8420 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -45,7 +45,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create credentials for an OpenSearch instance and show the password in the output`, "$ stackit opensearch credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index e4baea08d..a6e1a8e48 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 credentials' IDs for an OpenSearch instance`, "$ stackit opensearch credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index 0433ce412..b287e54e8 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -74,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create an OpenSearch instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit opensearch instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index a08b7ed1c..dc116b510 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 OpenSearch instances`, "$ stackit opensearch instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index 6f8a4ab74..89409a89a 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 OpenSearch service plans`, "$ stackit opensearch plans --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index 8b68411cd..8ff1a1826 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -55,7 +55,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 members of an organization`, "$ stackit organization member list --organization-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index 68352bff1..6d62f190e 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -50,7 +50,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 roles and permissions of an organization`, "$ stackit organization role list --organization-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index 0ed9a5155..519b2065f 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -55,7 +55,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit postgresflex backup list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go index 318425c0c..9db444846 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit postgresflex backup update-schedule --instance-id xxx --schedule '6 6 * * *'"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index ed7cec878..5fb8b931c 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -74,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a PostgreSQL Flex instance with name "my-instance", allow access to a specific range of IP addresses, specify flavor by CPU and RAM and set storage size to 20 GB. Other parameters are set to default values`, `$ stackit postgresflex instance create --name my-instance --cpu 2 --ram 4 --acl 1.2.3.0/24 --storage-size 20`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index 3759061ea..cb469bfbe 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 PostgreSQL Flex instances`, "$ stackit postgresflex instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index ba94aea08..3dc3ee205 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -62,7 +62,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List PostgreSQL Flex storage options for a given flavor. The flavor ID can be retrieved by running "$ stackit postgresflex options --flavors"`, "$ stackit postgresflex options --storages --flavor-id "), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 6a0d1f103..c3399ab98 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -56,7 +56,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit postgresflex user create --instance-id xxx --username johndoe --role createdb"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index 62e354334..bb1f601f1 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit postgresflex user list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/postgresflex/user/update/update_test.go b/internal/cmd/postgresflex/user/update/update_test.go index b6cc8e1c1..f50e61f37 100644 --- a/internal/cmd/postgresflex/user/update/update_test.go +++ b/internal/cmd/postgresflex/user/update/update_test.go @@ -227,7 +227,7 @@ func TestBuildRequest(t *testing.T) { }{ { description: "base", - model: fixtureInputModel(func(model *inputModel) {}), + model: fixtureInputModel(), expectedRequest: fixtureRequest(), }, } diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index 1564b47e1..23b0cd9fc 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -64,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a STACKIT project with a network area`, "$ stackit project create --parent-id xxxx --name my-project --network-area-id yyyy"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/project/delete/delete.go b/internal/cmd/project/delete/delete.go index 12951b4ec..9b3178bce 100644 --- a/internal/cmd/project/delete/delete.go +++ b/internal/cmd/project/delete/delete.go @@ -34,7 +34,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Delete a STACKIT project by explicitly providing the project ID`, "$ stackit project delete --project-id xxx"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } p.Info("Deleted project %q\n", projectLabel) - p.Warn(fmt.Sprintf("%s\n%s\n", + p.Warn("%s", fmt.Sprintf("%s\n%s\n", "If this was your default project, consider configuring a new project ID by running:", " $ stackit config set --project-id ", )) diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index cb2d0b141..8b346322c 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List all STACKIT projects that a certain user is a member of`, "$ stackit project list --member example@email.com"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/project/list/list_test.go b/internal/cmd/project/list/list_test.go index bf0e2d68c..2f5bc9e98 100644 --- a/internal/cmd/project/list/list_test.go +++ b/internal/cmd/project/list/list_test.go @@ -483,7 +483,7 @@ func TestFetchProjects(t *testing.T) { } return } - if err == nil && tt.apiCallFails { + if tt.apiCallFails { t.Fatalf("did not fail on invalid input") } if numAPICalls != tt.expectedNumAPICalls { diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index 6171a0b4e..538934344 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 members of a project`, "$ stackit project member list --project-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index b00c10b4a..13b3f79e1 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 roles and permissions of a project`, "$ stackit project role list --project-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/project/update/update.go b/internal/cmd/project/update/update.go index 34499de26..ea91ccdae 100644 --- a/internal/cmd/project/update/update.go +++ b/internal/cmd/project/update/update.go @@ -53,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Update the name of a STACKIT project by explicitly providing the project ID`, "$ stackit project update --name my-updated-project --project-id xxx"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index bed0dafd2..a2b7b09af 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -44,7 +44,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create credentials for a RabbitMQ instance and show the password in the output`, "$ stackit rabbitmq credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index 54140ec86..95854a129 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 credentials' IDs for a RabbitMQ instance`, "$ stackit rabbitmq credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index 464f587b8..d4c970321 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -74,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a RabbitMQ instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit rabbitmq instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index b09ebd083..b5802e849 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 RabbitMQ instances`, "$ stackit rabbitmq instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index ad19ecf18..385858e8f 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 RabbitMQ service plans`, "$ stackit rabbitmq plans --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index 7906c2885..f96a6d1a9 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -45,7 +45,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create credentials for a Redis instance and show the password in the output`, "$ stackit redis credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index b701a03d8..8ec94d500 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 credentials' IDs for a Redis instance`, "$ stackit redis credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index cd71a84a4..eec468709 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a Redis instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit redis instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index 969b20058..de9db7f81 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 Redis instances`, "$ stackit redis instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 292857121..564fb75e5 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 Redis service plans`, "$ stackit redis plans --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/root.go b/internal/cmd/root.go index e1385befb..4bdf6359a 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -46,7 +46,7 @@ func NewRootCmd(version, date string, p *print.Printer) *cobra.Command { SilenceErrors: true, // Error is beautified in a custom way before being printed SilenceUsage: true, DisableAutoGenTag: true, - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { p.Cmd = cmd p.Verbosity = print.Level(globalflags.Parse(p, cmd).Verbosity) @@ -82,7 +82,7 @@ func NewRootCmd(version, date string, p *print.Printer) *cobra.Command { return nil }, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { if flags.FlagToBoolValue(p, cmd, "version") { p.Outputf("STACKIT CLI (beta)\n") @@ -187,7 +187,7 @@ func Execute(version, date string) { if err != nil { err := beautifyUnknownAndMissingCommandsError(cmd, err) p.Debug(print.ErrorLevel, "execute command: %v", err) - p.Error(err.Error()) + p.Error("%s", err.Error()) os.Exit(1) } } diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index e574e35c8..016a4326e 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a Secrets Manager instance with name "my-instance" and specify IP range which is allowed to access it`, `$ stackit secrets-manager instance create --name my-instance --acl 1.2.3.0/24`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index 9aa3a6a33..952ca13d0 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -46,7 +46,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 Secrets Manager instances`, "$ stackit secrets-manager instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index ac919e456..5506ea3d7 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -52,7 +52,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit secrets-manager user create --instance-id xxx --write"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index cfc9b1a87..a4feee550 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -49,7 +49,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 Secrets Manager users with ID "xxx"`, "$ stackit secrets-manager user list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index 5314543b8..d4aa6b026 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -39,7 +39,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a service account with name "my-service-account"`, "$ stackit service-account create --name my-service-account"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/service-account/key/create/create.go b/internal/cmd/service-account/key/create/create.go index 1e27768f6..8cf058592 100644 --- a/internal/cmd/service-account/key/create/create.go +++ b/internal/cmd/service-account/key/create/create.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a key for the service account with email "my-service-account-1234567@sa.stackit.cloud" and provide the public key in a .pem file"`, `$ stackit service-account key create --email my-service-account-1234567@sa.stackit.cloud --public-key @./public.pem`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index 6c3c29da5..5d9b1186e 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 keys belonging to the service account with email "my-service-account-1234567@sa.stackit.cloud"`, "$ stackit service-account key list --email my-service-account-1234567@sa.stackit.cloud --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/service-account/key/update/update.go b/internal/cmd/service-account/key/update/update.go index 753756e94..5aba23b81 100644 --- a/internal/cmd/service-account/key/update/update.go +++ b/internal/cmd/service-account/key/update/update.go @@ -90,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("marshal key: %w", err) } - p.Info(string(key)) + p.Info("%s", string(key)) return nil }, } diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index 7fc9ffbff..8dc2e178d 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List all service accounts`, "$ stackit service-account list"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index fdaf09b01..97c08dbbf 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -50,7 +50,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create an access token for the service account with email "my-service-account-1234567@sa.stackit.cloud" with a time to live of 10 days`, "$ stackit service-account token create --email my-service-account-1234567@sa.stackit.cloud --ttl-days 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index fc345d8cc..3bb6aa2bb 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -52,7 +52,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 access tokens of the service account with email "my-service-account-1234567@sa.stackit.cloud"`, "$ stackit service-account token list --email my-service-account-1234567@sa.stackit.cloud --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload.go b/internal/cmd/ske/cluster/generate-payload/generate_payload.go index 054fea2b3..461842528 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Generate a payload with values of a cluster, and preview it in the terminal`, `$ stackit ske cluster generate-payload --cluster-name my-cluster`), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index d0ee6da45..a4fcd139c 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -47,7 +47,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List up to 10 SKE clusters`, "$ stackit ske cluster list --limit 10"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index d56850a6b..f1b4cec26 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -33,7 +33,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Get details regarding SKE functionality on your project`, "$ stackit ske describe"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index 1a05ef2ad..491b06cb7 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -34,7 +34,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Disable SKE functionality for your project, deleting all associated clusters`, "$ stackit ske disable"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index ab1afb319..cdb07134d 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -34,7 +34,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `Enable SKE functionality for your project`, "$ stackit ske enable"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/cmd/ske/kubeconfig/login/login.go b/internal/cmd/ske/kubeconfig/login/login.go index 568b34c98..817b33ca4 100644 --- a/internal/cmd/ske/kubeconfig/login/login.go +++ b/internal/cmd/ske/kubeconfig/login/login.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ kubectl cluster-info", "$ kubectl get pods"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { ctx := context.Background() if err := cache.Init(); err != nil { @@ -223,7 +223,7 @@ func output(p *print.Printer, cacheKey string, kubeconfig *rest.Config) error { return fmt.Errorf("marshal ExecCredential: %w", err) } - p.Outputf(string(output)) + p.Outputf("%s", string(output)) return nil } diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index e69c93ece..4982eaa49 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -56,7 +56,7 @@ func NewCmd(p *print.Printer) *cobra.Command { `List SKE options regarding Kubernetes versions and machine images`, "$ stackit ske options --kubernetes-versions --machine-images"), ), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() model, err := parseInput(p, cmd) if err != nil { diff --git a/internal/pkg/args/args_test.go b/internal/pkg/args/args_test.go index 2a1360b44..2afe2b8d3 100644 --- a/internal/pkg/args/args_test.go +++ b/internal/pkg/args/args_test.go @@ -53,7 +53,7 @@ func TestSingleArg(t *testing.T) { { description: "valid", args: []string{"arg"}, - validateFunc: func(value string) error { + validateFunc: func(_ string) error { return nil }, isValid: true, @@ -76,7 +76,7 @@ func TestSingleArg(t *testing.T) { { description: "invalid_arg", args: []string{"arg"}, - validateFunc: func(value string) error { + validateFunc: func(_ string) error { return fmt.Errorf("error") }, isValid: false, @@ -118,7 +118,7 @@ func TestSingleOptionalArg(t *testing.T) { { description: "valid", args: []string{"arg"}, - validateFunc: func(value string) error { + validateFunc: func(_ string) error { return nil }, isValid: true, @@ -141,7 +141,7 @@ func TestSingleOptionalArg(t *testing.T) { { description: "invalid_arg", args: []string{"arg"}, - validateFunc: func(value string) error { + validateFunc: func(_ string) error { return fmt.Errorf("error") }, isValid: false, diff --git a/internal/pkg/auth/auth.go b/internal/pkg/auth/auth.go index 7416cb6eb..a036227ed 100644 --- a/internal/pkg/auth/auth.go +++ b/internal/pkg/auth/auth.go @@ -22,7 +22,7 @@ type tokenClaims struct { // It returns the configuration option that can be used to create an authenticated SDK client. // // If the user was logged in and the user session expired, reauthorizeUserRoutine is called to reauthenticate the user again. -func AuthenticationConfig(p *print.Printer, reauthorizeUserRoutine func(p *print.Printer, isReauthentication bool) error) (authCfgOption sdkConfig.ConfigurationOption, err error) { +func AuthenticationConfig(p *print.Printer, reauthorizeUserRoutine func(p *print.Printer, _ bool) error) (authCfgOption sdkConfig.ConfigurationOption, err error) { flow, err := GetAuthFlow() if err != nil { return nil, fmt.Errorf("get authentication flow: %w", err) diff --git a/internal/pkg/auth/auth_test.go b/internal/pkg/auth/auth_test.go index 6c64c359c..f7355f365 100644 --- a/internal/pkg/auth/auth_test.go +++ b/internal/pkg/auth/auth_test.go @@ -188,7 +188,7 @@ func TestAuthenticationConfig(t *testing.T) { } reauthorizeUserCalled := false - reauthenticateUser := func(p *print.Printer, isReauthentication bool) error { + reauthenticateUser := func(_ *print.Printer, _ bool) error { if reauthorizeUserCalled { t.Errorf("user reauthorized more than once") } diff --git a/internal/pkg/auth/storage.go b/internal/pkg/auth/storage.go index d5488fe73..02f397386 100644 --- a/internal/pkg/auth/storage.go +++ b/internal/pkg/auth/storage.go @@ -299,7 +299,7 @@ func createEncodedTextFile(activeProfile string) error { textFileDir := config.GetProfileFolderPath(activeProfile) textFilePath := filepath.Join(textFileDir, textFileName) - err := os.MkdirAll(textFileDir, os.ModePerm) + err := os.MkdirAll(textFileDir, 0o750) if err != nil { return fmt.Errorf("create file dir: %w", err) } diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index 9e12fd15a..fd9829348 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -207,7 +207,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { http.Redirect(w, r, loginSuccessURL, http.StatusSeeOther) }) - mux.HandleFunc(loginSuccessPath, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc(loginSuccessPath, func(w http.ResponseWriter, _ *http.Request) { defer cleanup(server) email, err := GetAuthField(USER_EMAIL) diff --git a/internal/pkg/auth/user_token_flow_test.go b/internal/pkg/auth/user_token_flow_test.go index be57518ce..6aeac368f 100644 --- a/internal/pkg/auth/user_token_flow_test.go +++ b/internal/pkg/auth/user_token_flow_test.go @@ -278,7 +278,7 @@ func TestRoundTrip(t *testing.T) { authorizeUserCalled: &authorizeUserCalled, tokensRefreshed: &tokensRefreshed, } - authorizeUserRoutine := func(p *print.Printer, isReauthentication bool) error { + authorizeUserRoutine := func(_ *print.Printer, _ bool) error { return reauthorizeUser(authorizeUserContext) } diff --git a/internal/pkg/cache/cache.go b/internal/pkg/cache/cache.go index d52670fd4..cf019ecb2 100644 --- a/internal/pkg/cache/cache.go +++ b/internal/pkg/cache/cache.go @@ -43,7 +43,7 @@ func PutObject(identifier string, data []byte) error { return ErrorInvalidCacheIdentifier } - err := os.MkdirAll(cacheFolderPath, os.ModePerm) + err := os.MkdirAll(cacheFolderPath, 0o750) if err != nil { return err } diff --git a/internal/pkg/cache/cache_test.go b/internal/pkg/cache/cache_test.go index 4ea003116..cc68c6590 100644 --- a/internal/pkg/cache/cache_test.go +++ b/internal/pkg/cache/cache_test.go @@ -46,7 +46,7 @@ func TestGetObject(t *testing.T) { // setup if tt.expectFile { - err := os.MkdirAll(cacheFolderPath, os.ModePerm) + err := os.MkdirAll(cacheFolderPath, 0o750) if err != nil { t.Fatalf("create cache folder: %s", err.Error()) } diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 6162e0521..b64762d83 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -141,7 +141,7 @@ func InitConfig() { // Write saves the config file (wrapping `viper.WriteConfig`) and ensures that its directory exists func Write() error { - err := os.MkdirAll(configFolderPath, os.ModePerm) + err := os.MkdirAll(configFolderPath, 0o750) if err != nil { return fmt.Errorf("create config directory: %w", err) } diff --git a/internal/pkg/config/config_test.go b/internal/pkg/config/config_test.go index 7c9954117..a8f1e71af 100644 --- a/internal/pkg/config/config_test.go +++ b/internal/pkg/config/config_test.go @@ -37,7 +37,7 @@ func TestWrite(t *testing.T) { configFolderPath = filepath.Dir(configPath) if tt.folderExists { - err := os.MkdirAll(configFolderPath, os.ModePerm) + err := os.MkdirAll(configFolderPath, 0o750) if err != nil { t.Fatalf("expected error to be nil, got %v", err) } diff --git a/internal/pkg/config/profiles.go b/internal/pkg/config/profiles.go index f05ae9a7b..69a1144cf 100644 --- a/internal/pkg/config/profiles.go +++ b/internal/pkg/config/profiles.go @@ -100,7 +100,7 @@ func CreateProfile(p *print.Printer, profile string, setProfile, emptyProfile bo return fmt.Errorf("profile %q already exists", profile) } - err = os.MkdirAll(configFolderPath, os.ModePerm) + err = os.MkdirAll(configFolderPath, 0o750) if err != nil { return fmt.Errorf("create config folder: %w", err) } @@ -190,7 +190,7 @@ func SetProfile(p *print.Printer, profile string) error { profileFilePath = getInitialProfileFilePath() } - err = os.WriteFile(profileFilePath, []byte(profile), os.ModePerm) + err = os.WriteFile(profileFilePath, []byte(profile), 0o600) if err != nil { return fmt.Errorf("write profile to file: %w", err) } diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index 92af7ab83..ec0aa3bda 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -352,7 +352,7 @@ type SubcommandMissingError struct { } func (e *SubcommandMissingError) Error() string { - err := fmt.Errorf(SUBCOMMAND_MISSING) + err := fmt.Errorf("%s", SUBCOMMAND_MISSING) return AppendUsageTip(err, e.Cmd).Error() } diff --git a/internal/pkg/fileutils/file_utils_test.go b/internal/pkg/fileutils/file_utils_test.go index e979bef94..587b476de 100644 --- a/internal/pkg/fileutils/file_utils_test.go +++ b/internal/pkg/fileutils/file_utils_test.go @@ -125,7 +125,7 @@ func TestCopyFile(t *testing.T) { src := filepath.Join(basePath, "file-with-content.txt") dst := filepath.Join(basePath, "file-with-content-copy.txt") - err := os.MkdirAll(basePath, os.ModePerm) + err := os.MkdirAll(basePath, 0o750) if err != nil { t.Fatalf("unexpected error: %s", err.Error()) } diff --git a/internal/pkg/flags/flags_test.go b/internal/pkg/flags/flags_test.go index 982f300b6..1021941de 100644 --- a/internal/pkg/flags/flags_test.go +++ b/internal/pkg/flags/flags_test.go @@ -83,7 +83,7 @@ func TestEnumFlag(t *testing.T) { flag := EnumFlag(tt.ignoreCase, "", options...) cmd := &cobra.Command{ Use: "test", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -236,7 +236,7 @@ func TestEnumSliceFlag(t *testing.T) { flag := EnumSliceFlag(tt.ignoreCase, tt.defaultValue, options...) cmd := &cobra.Command{ Use: "test", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -302,7 +302,7 @@ func TestUUIDFlag(t *testing.T) { flag := UUIDFlag() cmd := &cobra.Command{ Use: "test", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -400,7 +400,7 @@ func TestUUIDSliceFlag(t *testing.T) { flag := UUIDSliceFlag() cmd := &cobra.Command{ Use: "test", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -513,7 +513,7 @@ func TestCIDRFlag(t *testing.T) { flag := CIDRFlag() cmd := &cobra.Command{ Use: "test", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -615,7 +615,7 @@ func TestCIDRSliceFlag(t *testing.T) { flag := CIDRSliceFlag() cmd := &cobra.Command{ Use: "test", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -717,7 +717,7 @@ func TestReadFromFileFlag(t *testing.T) { } cmd := &cobra.Command{ Use: "test", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return nil }, } diff --git a/internal/pkg/print/print_test.go b/internal/pkg/print/print_test.go index f5841de37..942689ce4 100644 --- a/internal/pkg/print/print_test.go +++ b/internal/pkg/print/print_test.go @@ -69,7 +69,7 @@ func TestOutputf(t *testing.T) { } if len(tt.args) == 0 { - p.Outputf(tt.message) + p.Outputf("%s", tt.message) } else { p.Outputf(tt.message, tt.args...) } @@ -360,7 +360,7 @@ func TestInfo(t *testing.T) { Verbosity: tt.verbosity, } - p.Info(tt.message) + p.Info("%s", tt.message) expectedOutput := tt.message output := buf.String() @@ -419,7 +419,7 @@ func TestWarn(t *testing.T) { Verbosity: tt.verbosity, } - p.Warn(tt.message) + p.Warn("%s", tt.message) expectedOutput := fmt.Sprintf("Warning: %s", tt.message) output := buf.String() @@ -478,7 +478,7 @@ func TestError(t *testing.T) { Verbosity: tt.verbosity, } - p.Error(tt.message) + p.Error("%s", tt.message) expectedOutput := fmt.Sprintf("Error: %s\n", tt.message) output := buf.String() diff --git a/internal/pkg/services/object-storage/utils/utils_test.go b/internal/pkg/services/object-storage/utils/utils_test.go index 7c2a2f427..c2dc0bb61 100644 --- a/internal/pkg/services/object-storage/utils/utils_test.go +++ b/internal/pkg/services/object-storage/utils/utils_test.go @@ -314,7 +314,7 @@ func TestGetCredentialsName(t *testing.T) { t.Fatalf("Failed to marshal mocked response: %v", err) } - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json") if tt.getCredentialsNameFails { w.WriteHeader(http.StatusBadGateway) diff --git a/scripts/generate.go b/scripts/generate.go index 878078862..99d930910 100644 --- a/scripts/generate.go +++ b/scripts/generate.go @@ -27,12 +27,12 @@ func main() { if err != nil { log.Fatalf("Error removing old documentation directory: %v", err) } - err = os.Mkdir(docsDir, os.ModePerm) + err = os.Mkdir(docsDir, 0o750) if err != nil { log.Fatalf("Error creating new documentation directory: %v", err) } - filePrepender := func(filename string) string { + filePrepender := func(_ string) string { return "" } linkHandler := func(filename string) string { diff --git a/scripts/project.sh b/scripts/project.sh index fd15c32e6..2786e509e 100755 --- a/scripts/project.sh +++ b/scripts/project.sh @@ -14,7 +14,7 @@ if [ "$action" = "help" ]; then elif [ "$action" = "tools" ]; then cd ${ROOT_DIR} go mod download - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2 + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 else echo "Invalid action: '$action', please use $0 help for help" fi From 9239694e7098b0dd3af2d64d6ddf0ede9a2e9084 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Wed, 13 Nov 2024 12:15:57 +0100 Subject: [PATCH 092/619] Onboard IaaS network interface command Supported subcommands: create, delete, update, list, describe Signed-off-by: Alexander Dahmen --- README.md | 2 +- docs/stackit_beta.md | 1 + docs/stackit_beta_network-interface.md | 37 +++ docs/stackit_beta_network-interface_create.md | 50 +++ docs/stackit_beta_network-interface_delete.md | 40 +++ ...stackit_beta_network-interface_describe.md | 46 +++ docs/stackit_beta_network-interface_list.md | 51 +++ docs/stackit_beta_network-interface_update.md | 51 +++ internal/cmd/beta/beta.go | 2 + .../beta/network-interface/create/create.go | 251 +++++++++++++++ .../network-interface/create/create_test.go | 262 ++++++++++++++++ .../beta/network-interface/delete/delete.go | 111 +++++++ .../network-interface/delete/delete_test.go | 202 ++++++++++++ .../network-interface/describe/describe.go | 189 +++++++++++ .../describe/describe_test.go | 202 ++++++++++++ .../cmd/beta/network-interface/list/list.go | 179 +++++++++++ .../beta/network-interface/list/list_test.go | 207 +++++++++++++ .../network-interface/network-interface.go | 33 ++ .../beta/network-interface/update/update.go | 243 +++++++++++++++ .../network-interface/update/update_test.go | 293 ++++++++++++++++++ 20 files changed, 2451 insertions(+), 1 deletion(-) create mode 100644 docs/stackit_beta_network-interface.md create mode 100644 docs/stackit_beta_network-interface_create.md create mode 100644 docs/stackit_beta_network-interface_delete.md create mode 100644 docs/stackit_beta_network-interface_describe.md create mode 100644 docs/stackit_beta_network-interface_list.md create mode 100644 docs/stackit_beta_network-interface_update.md create mode 100644 internal/cmd/beta/network-interface/create/create.go create mode 100644 internal/cmd/beta/network-interface/create/create_test.go create mode 100644 internal/cmd/beta/network-interface/delete/delete.go create mode 100644 internal/cmd/beta/network-interface/delete/delete_test.go create mode 100644 internal/cmd/beta/network-interface/describe/describe.go create mode 100644 internal/cmd/beta/network-interface/describe/describe_test.go create mode 100644 internal/cmd/beta/network-interface/list/list.go create mode 100644 internal/cmd/beta/network-interface/list/list_test.go create mode 100644 internal/cmd/beta/network-interface/network-interface.go create mode 100644 internal/cmd/beta/network-interface/update/update.go create mode 100644 internal/cmd/beta/network-interface/update/update_test.go diff --git a/README.md b/README.md index df0cbe601..e15f0687b 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Service | CLI Commands | Status | | ---------------------------------- |----------------------------------------------------------------| ------------------------- | | Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume` | :white_check_mark: (beta) | +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`| :white_check_mark: (beta) | | Authorization | `project`, `organization` | :white_check_mark: | | DNS | `dns` | :white_check_mark: | | Kubernetes Engine (SKE) | `ske` | :white_check_mark: | diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 8da8fef61..56453f281 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -42,6 +42,7 @@ stackit beta [flags] * [stackit](./stackit.md) - Manage STACKIT resources using the command line * [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface * [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex * [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume diff --git a/docs/stackit_beta_network-interface.md b/docs/stackit_beta_network-interface.md new file mode 100644 index 000000000..1832e4ef9 --- /dev/null +++ b/docs/stackit_beta_network-interface.md @@ -0,0 +1,37 @@ +## stackit beta network-interface + +Provides functionality for Network Interface + +### Synopsis + +Provides functionality for Network Interface. + +``` +stackit beta network-interface [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta network-interface" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta network-interface create](./stackit_beta_network-interface_create.md) - Creates a network interface +* [stackit beta network-interface delete](./stackit_beta_network-interface_delete.md) - Deletes a network interface +* [stackit beta network-interface describe](./stackit_beta_network-interface_describe.md) - Describes a network interface +* [stackit beta network-interface list](./stackit_beta_network-interface_list.md) - Lists all network interfaces of a network +* [stackit beta network-interface update](./stackit_beta_network-interface_update.md) - Updates a network interface + diff --git a/docs/stackit_beta_network-interface_create.md b/docs/stackit_beta_network-interface_create.md new file mode 100644 index 000000000..a36ed217f --- /dev/null +++ b/docs/stackit_beta_network-interface_create.md @@ -0,0 +1,50 @@ +## stackit beta network-interface create + +Creates a network interface + +### Synopsis + +Creates a network interface. + +``` +stackit beta network-interface create [flags] +``` + +### Examples + +``` + Create a network interface for network with ID "xxx" + $ stackit beta network-interface create --network-id xxx + + Create a network interface with allowed addresses, labels, a name, security groups and nic security enabled for network with ID "xxx" + $ stackit beta network-interface create --network-id xxx --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 --name NAME --security-groups "UUID1,UUID2" --nic-security +``` + +### Options + +``` + --allowed-addresses strings List of allowed IPs + -h, --help Help for "stackit beta network-interface create" + -i, --ipv4 string IPv4 address + -s, --ipv6 string IPv6 address + --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) + -n, --name string Network interface name + --network-id string Network ID + -b, --nic-security If this is set to false, then no security groups will apply to this network interface. (default true) + --security-groups strings List of security groups +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface + diff --git a/docs/stackit_beta_network-interface_delete.md b/docs/stackit_beta_network-interface_delete.md new file mode 100644 index 000000000..954a7b472 --- /dev/null +++ b/docs/stackit_beta_network-interface_delete.md @@ -0,0 +1,40 @@ +## stackit beta network-interface delete + +Deletes a network interface + +### Synopsis + +Deletes a network interface. + +``` +stackit beta network-interface delete [flags] +``` + +### Examples + +``` + Delete network interface with nic id "xxx" and network ID "yyy" + $ stackit beta network-interface delete xxx --network-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta network-interface delete" + --network-id string Network ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface + diff --git a/docs/stackit_beta_network-interface_describe.md b/docs/stackit_beta_network-interface_describe.md new file mode 100644 index 000000000..a879d87aa --- /dev/null +++ b/docs/stackit_beta_network-interface_describe.md @@ -0,0 +1,46 @@ +## stackit beta network-interface describe + +Describes a network interface + +### Synopsis + +Describes a network interface. + +``` +stackit beta network-interface describe [flags] +``` + +### Examples + +``` + Describes network interface with nic id "xxx" and network ID "yyy" + $ stackit beta network-interface describe xxx --network-id yyy + + Describes network interface with nic id "xxx" and network ID "yyy" in JSON format + $ stackit beta network-interface describe xxx --network-id yyy --output-format json + + Describes network interface with nic id "xxx" and network ID "yyy" in yaml format + $ stackit beta network-interface describe xxx --network-id yyy --output-format yaml +``` + +### Options + +``` + -h, --help Help for "stackit beta network-interface describe" + --network-id string Network ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface + diff --git a/docs/stackit_beta_network-interface_list.md b/docs/stackit_beta_network-interface_list.md new file mode 100644 index 000000000..04707adcb --- /dev/null +++ b/docs/stackit_beta_network-interface_list.md @@ -0,0 +1,51 @@ +## stackit beta network-interface list + +Lists all network interfaces of a network + +### Synopsis + +Lists all network interfaces of a network. + +``` +stackit beta network-interface list [flags] +``` + +### Examples + +``` + Lists all network interfaces with network ID "xxx" + $ stackit beta network-interface list --network-id xxx + + Lists all network interfaces with network ID "xxx" which contains the label xxx + $ stackit beta network-interface list --network-id xxx --label-selector xxx + + Lists all network interfaces with network ID "xxx" in JSON format + $ stackit beta network-interface list --network-id xxx --output-format json + + Lists up to 10 network interfaces with network ID "xxx" + $ stackit beta network-interface list --network-id xxx --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta network-interface list" + --label-selector string Filter by label + --limit int Maximum number of entries to list + --network-id string Network ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface + diff --git a/docs/stackit_beta_network-interface_update.md b/docs/stackit_beta_network-interface_update.md new file mode 100644 index 000000000..506fb1ba4 --- /dev/null +++ b/docs/stackit_beta_network-interface_update.md @@ -0,0 +1,51 @@ +## stackit beta network-interface update + +Updates a network interface + +### Synopsis + +Updates a network interface. + +``` +stackit beta network-interface update [flags] +``` + +### Examples + +``` + Updates a network interface with nic id "xxx" and network-id "yyy" to new allowed addresses "1.1.1.1,8.8.8.8,9.9.9.9" and new labels "key=value,key2=value2" + $ stackit beta network-interface update xxx --network-id yyy --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 + + Updates a network interface with nic id "xxx" and network-id "yyy" with new name "nic-name-new" + $ stackit beta network-interface update xxx --network-id yyy --name nic-name-new + + Updates a network interface with nic id "xxx" and network-id "yyy" to include the security group "zzz" + $ stackit beta network-interface update xxx --network-id yyy --security-groups zzz +``` + +### Options + +``` + --allowed-addresses strings List of allowed IPs + -h, --help Help for "stackit beta network-interface update" + --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) + -n, --name string Network interface name + --network-id string Network ID + -b, --nic-security If this is set to false, then no security groups will apply to this network interface. (default true) + --security-groups strings List of security groups +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface + diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index e1a16ccdb..ab429fe4f 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -5,6 +5,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network" networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" + networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume" @@ -44,4 +45,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(networkArea.NewCmd(p)) cmd.AddCommand(network.NewCmd(p)) cmd.AddCommand(volume.NewCmd(p)) + cmd.AddCommand(networkinterface.NewCmd(p)) } diff --git a/internal/cmd/beta/network-interface/create/create.go b/internal/cmd/beta/network-interface/create/create.go new file mode 100644 index 000000000..0a1345f47 --- /dev/null +++ b/internal/cmd/beta/network-interface/create/create.go @@ -0,0 +1,251 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + "regexp" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + networkIdFlag = "network-id" + allowedAddressesFlag = "allowed-addresses" + ipv4Flag = "ipv4" + ipv6Flag = "ipv6" + labelFlag = "labels" + nameFlag = "name" + securityGroupsFlag = "security-groups" + nicSecurityFlag = "nic-security" + + nameRegex = `^[A-Za-z0-9]+((-|_|\s|\.)[A-Za-z0-9]+)*$` + maxNameLength = 63 + securityGroupsRegex = `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$` + securityGroupLength = 36 + defaultNicSecurityFlag = true +) + +type inputModel struct { + *globalflags.GlobalFlagModel + NetworkId *string + AllowedAddresses *[]iaas.AllowedAddressesInner + Ipv4 *string + Ipv6 *string + Labels *map[string]string + Name *string // <= 63 characters + regex ^[A-Za-z0-9]+((-|_|\s|\.)[A-Za-z0-9]+)*$ + NicSecurity *bool + SecurityGroups *[]string // = 36 characters + regex ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a network interface", + Long: "Creates a network interface.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a network interface for network with ID "xxx"`, + `$ stackit beta network-interface create --network-id xxx`, + ), + examples.NewExample( + `Create a network interface with allowed addresses, labels, a name, security groups and nic security enabled for network with ID "xxx"`, + `$ stackit beta network-interface create --network-id xxx --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 --name NAME --security-groups "UUID1,UUID2" --nic-security`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a network interface for project %q?", projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create network interface: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID") + cmd.Flags().StringSlice(allowedAddressesFlag, nil, "List of allowed IPs") + cmd.Flags().StringP(ipv4Flag, "i", "", "IPv4 address") + cmd.Flags().StringP(ipv6Flag, "s", "", "IPv6 address") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...'") + cmd.Flags().StringP(nameFlag, "n", "", "Network interface name") + cmd.Flags().BoolP(nicSecurityFlag, "b", defaultNicSecurityFlag, "If this is set to false, then no security groups will apply to this network interface.") + cmd.Flags().StringSlice(securityGroupsFlag, nil, "List of security groups") + + err := flags.MarkFlagsRequired(cmd, networkIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + allowedAddresses := flags.FlagToStringSlicePointer(p, cmd, allowedAddressesFlag) + var allowedAddressesInner []iaas.AllowedAddressesInner + if allowedAddresses != nil && len(*allowedAddresses) > 0 { + allowedAddressesInner = make([]iaas.AllowedAddressesInner, len(*allowedAddresses)) + for i, address := range *allowedAddresses { + allowedAddressesInner[i].String = &address + } + } + + // check name length <= 63 and regex must apply + name := flags.FlagToStringPointer(p, cmd, nameFlag) + if name != nil { + if len(*name) > maxNameLength { + return nil, &errors.FlagValidationError{ + Flag: nameFlag, + Details: fmt.Sprintf("name %s is too long (maximum length is %d characters)", *name, maxNameLength), + } + } + nameRegex := regexp.MustCompile(nameRegex) + if !nameRegex.MatchString(*name) { + return nil, &errors.FlagValidationError{ + Flag: nameFlag, + Details: fmt.Sprintf("name %s didn't match the required regex expression %s", *name, nameRegex), + } + } + } + + // check security groups size and regex + securityGroups := flags.FlagToStringSlicePointer(p, cmd, securityGroupsFlag) + if securityGroups != nil && len(*securityGroups) > 0 { + securityGroupsRegex := regexp.MustCompile(securityGroupsRegex) + // iterate over them + for _, value := range *securityGroups { + if len(value) != securityGroupLength { + return nil, &errors.FlagValidationError{ + Flag: securityGroupsFlag, + Details: fmt.Sprintf("security groups uuid %s does not match (must be %d characters long)", value, securityGroupLength), + } + } + if !securityGroupsRegex.MatchString(value) { + return nil, &errors.FlagValidationError{ + Flag: securityGroupsFlag, + Details: fmt.Sprintf("security groups uuid %s didn't match the required regex expression %s", value, securityGroupsRegex), + } + } + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + Ipv4: flags.FlagToStringPointer(p, cmd, ipv4Flag), + Ipv6: flags.FlagToStringPointer(p, cmd, ipv6Flag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + Name: name, + NicSecurity: flags.FlagToBoolPointer(p, cmd, nicSecurityFlag), + SecurityGroups: securityGroups, + } + + if allowedAddresses != nil { + model.AllowedAddresses = utils.Ptr(allowedAddressesInner) + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNicRequest { + req := apiClient.CreateNic(ctx, model.ProjectId, *model.NetworkId) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + convertedMap := make(map[string]interface{}, len(*model.Labels)) + for k, v := range *model.Labels { + convertedMap[k] = v + } + labelsMap = &convertedMap + } + + payload := iaas.CreateNicPayload{ + AllowedAddresses: model.AllowedAddresses, + Ipv4: model.Ipv4, + Ipv6: model.Ipv6, + Labels: labelsMap, + Name: model.Name, + NicSecurity: model.NicSecurity, + SecurityGroups: model.SecurityGroups, + } + return req.CreateNicPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(nic, "", " ") + if err != nil { + return fmt.Errorf("marshal network interface: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network interface: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created network interface for project %q.\nNIC ID: %s\n", model.ProjectId, *nic.Id) + return nil + } +} diff --git a/internal/cmd/beta/network-interface/create/create_test.go b/internal/cmd/beta/network-interface/create/create_test.go new file mode 100644 index 000000000..2173cf1ea --- /dev/null +++ b/internal/cmd/beta/network-interface/create/create_test.go @@ -0,0 +1,262 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var projectIdFlag = globalflags.ProjectIdFlag +var testProjectId = uuid.NewString() +var testNetworkId = uuid.NewString() +var testSecurityGroup = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + networkIdFlag: testNetworkId, + allowedAddressesFlag: "1.1.1.1,8.8.8.8,9.9.9.9", + ipv4Flag: "1.2.3.4", + ipv6Flag: "2001:0db8:85a3:08d3::0370:7344", + labelFlag: "key=value", + nameFlag: "testNic", + nicSecurityFlag: "true", + securityGroupsFlag: testSecurityGroup, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + var allowedAddresses []iaas.AllowedAddressesInner = []iaas.AllowedAddressesInner{ + iaas.StringAsAllowedAddressesInner(utils.Ptr("1.1.1.1")), + iaas.StringAsAllowedAddressesInner(utils.Ptr("8.8.8.8")), + iaas.StringAsAllowedAddressesInner(utils.Ptr("9.9.9.9")), + } + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + NetworkId: utils.Ptr(testNetworkId), + AllowedAddresses: utils.Ptr(allowedAddresses), + Ipv4: utils.Ptr("1.2.3.4"), + Ipv6: utils.Ptr("2001:0db8:85a3:08d3::0370:7344"), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + Name: utils.Ptr("testNic"), + NicSecurity: utils.Ptr(true), + SecurityGroups: utils.Ptr([]string{testSecurityGroup}), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateNicRequest)) iaas.ApiCreateNicRequest { + request := testClient.CreateNic(testCtx, testProjectId, testNetworkId) + request = request.CreateNicPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateNicPayload)) iaas.CreateNicPayload { + var allowedAddresses []iaas.AllowedAddressesInner = []iaas.AllowedAddressesInner{ + iaas.StringAsAllowedAddressesInner(utils.Ptr("1.1.1.1")), + iaas.StringAsAllowedAddressesInner(utils.Ptr("8.8.8.8")), + iaas.StringAsAllowedAddressesInner(utils.Ptr("9.9.9.9")), + } + payload := iaas.CreateNicPayload{ + AllowedAddresses: utils.Ptr(allowedAddresses), + Ipv4: utils.Ptr("1.2.3.4"), + Ipv6: utils.Ptr("2001:0db8:85a3:08d3::0370:7344"), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), + Name: utils.Ptr("testNic"), + NicSecurity: utils.Ptr(true), + SecurityGroups: utils.Ptr([]string{testSecurityGroup}), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "network id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkIdFlag) + }), + isValid: false, + }, + { + description: "network id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = "" + }), + isValid: false, + }, + { + description: "network id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "allowed addresses missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, allowedAddressesFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.AllowedAddresses = nil + }), + isValid: true, + }, + { + description: "name to long", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nameFlag] = "verylongstringwith66characterstotestthenameregexwithinthisunittest" + }), + isValid: false, + }, + { + description: "name invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nameFlag] = "test?" + }), + isValid: false, + }, + { + description: "name empty string invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nameFlag] = "" + }), + isValid: false, + }, + { + description: "security group uuid to short", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupsFlag] = "d61a8564-c8dd-4ffb-bc15-143e7d0c85e" + }), + isValid: false, + }, + { + description: "security group uuid invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupsFlag] = "d61a8564-c8dd-4ffb-bc15-143e7d0c85e?" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateNicRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-interface/delete/delete.go b/internal/cmd/beta/network-interface/delete/delete.go new file mode 100644 index 000000000..72adc082a --- /dev/null +++ b/internal/cmd/beta/network-interface/delete/delete.go @@ -0,0 +1,111 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + nicIdArg = "NIC_ID" + + networkIdFlag = "network-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + NetworkId *string + NicId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a network interface", + Long: "Deletes a network interface.", + Args: args.SingleArg(nicIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete network interface with nic id "xxx" and network ID "yyy"`, + `$ stackit beta network-interface delete xxx --network-id yyy`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete the network interface %q? (This cannot be undone)", model.NicId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete network interface: %w", err) + } + + p.Info("Deleted network interface %q\n", model.NicId) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID") + + err := flags.MarkFlagsRequired(cmd, networkIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + nicId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NicId: nicId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNicRequest { + req := apiClient.DeleteNic(ctx, model.ProjectId, *model.NetworkId, model.NicId) + return req +} diff --git a/internal/cmd/beta/network-interface/delete/delete_test.go b/internal/cmd/beta/network-interface/delete/delete_test.go new file mode 100644 index 000000000..4b9fdd56b --- /dev/null +++ b/internal/cmd/beta/network-interface/delete/delete_test.go @@ -0,0 +1,202 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var projectIdFlag = globalflags.ProjectIdFlag +var testProjectId = uuid.NewString() +var testNetworkId = uuid.NewString() +var testNicId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNicId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + networkIdFlag: testNetworkId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + NetworkId: utils.Ptr(testNetworkId), + NicId: testNicId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteNicRequest)) iaas.ApiDeleteNicRequest { + request := testClient.DeleteNic(testCtx, testProjectId, testNetworkId, testNicId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "network id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkIdFlag) + }), + isValid: false, + }, + { + description: "network id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = "" + }), + isValid: false, + }, + { + description: "network id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "nic argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteNicRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-interface/describe/describe.go b/internal/cmd/beta/network-interface/describe/describe.go new file mode 100644 index 000000000..45702c3df --- /dev/null +++ b/internal/cmd/beta/network-interface/describe/describe.go @@ -0,0 +1,189 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + nicIdArg = "NIC_ID" + + networkIdFlag = "network-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + NetworkId *string + NicId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Describes a network interface", + Long: "Describes a network interface.", + Args: args.SingleArg(nicIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Describes network interface with nic id "xxx" and network ID "yyy"`, + `$ stackit beta network-interface describe xxx --network-id yyy`, + ), + examples.NewExample( + `Describes network interface with nic id "xxx" and network ID "yyy" in JSON format`, + `$ stackit beta network-interface describe xxx --network-id yyy --output-format json`, + ), + examples.NewExample( + `Describes network interface with nic id "xxx" and network ID "yyy" in yaml format`, + `$ stackit beta network-interface describe xxx --network-id yyy --output-format yaml`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("describe network interface: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID") + + err := flags.MarkFlagsRequired(cmd, networkIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + nicId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NicId: nicId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNicRequest { + req := apiClient.GetNic(ctx, model.ProjectId, *model.NetworkId, model.NicId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(nic, "", " ") + if err != nil { + return fmt.Errorf("marshal network interface: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network interface: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *nic.Id) + table.AddSeparator() + table.AddRow("NETWORK ID", *nic.NetworkId) + table.AddSeparator() + if nic.Name != nil { + table.AddRow("NAME", *nic.Name) + table.AddSeparator() + } + if nic.Ipv4 != nil { + table.AddRow("IPV4", *nic.Ipv4) + table.AddSeparator() + } + if nic.Ipv6 != nil { + table.AddRow("IPV6", *nic.Ipv6) + table.AddSeparator() + } + table.AddRow("MAC", *nic.Mac) + table.AddSeparator() + table.AddRow("NIC SECURITY", *nic.NicSecurity) + if nic.AllowedAddresses != nil && len(*nic.AllowedAddresses) > 0 { + allowedAddresses := []string{} + for _, value := range *nic.AllowedAddresses { + allowedAddresses = append(allowedAddresses, *value.String) + } + table.AddSeparator() + table.AddRow("ALLOWED ADDRESSES", strings.Join(allowedAddresses, "\n")) + } + if nic.Labels != nil && len(*nic.Labels) > 0 { + labels := []string{} + for key, value := range *nic.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddSeparator() + table.AddRow("LABELS", strings.Join(labels, "\n")) + } + table.AddSeparator() + table.AddRow("STATUS", *nic.Status) + table.AddSeparator() + table.AddRow("TYPE", *nic.Type) + if nic.SecurityGroups != nil && len(*nic.SecurityGroups) > 0 { + table.AddSeparator() + table.AddRow("SECURITY GROUPS", strings.Join(*nic.SecurityGroups, "\n")) + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/network-interface/describe/describe_test.go b/internal/cmd/beta/network-interface/describe/describe_test.go new file mode 100644 index 000000000..145a12cc8 --- /dev/null +++ b/internal/cmd/beta/network-interface/describe/describe_test.go @@ -0,0 +1,202 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var projectIdFlag = globalflags.ProjectIdFlag +var testProjectId = uuid.NewString() +var testNetworkId = uuid.NewString() +var testNicId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNicId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + networkIdFlag: testNetworkId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + NetworkId: utils.Ptr(testNetworkId), + NicId: testNicId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetNicRequest)) iaas.ApiGetNicRequest { + request := testClient.GetNic(testCtx, testProjectId, testNetworkId, testNicId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "network id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkIdFlag) + }), + isValid: false, + }, + { + description: "network id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = "" + }), + isValid: false, + }, + { + description: "network id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "nic argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetNicRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-interface/list/list.go b/internal/cmd/beta/network-interface/list/list.go new file mode 100644 index 000000000..2257e6038 --- /dev/null +++ b/internal/cmd/beta/network-interface/list/list.go @@ -0,0 +1,179 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + labelSelectorFlag = "label-selector" + networkIdFlag = "network-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + LabelSelector *string + NetworkId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all network interfaces of a network", + Long: "Lists all network interfaces of a network.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all network interfaces with network ID "xxx"`, + `$ stackit beta network-interface list --network-id xxx`, + ), + examples.NewExample( + `Lists all network interfaces with network ID "xxx" which contains the label xxx`, + `$ stackit beta network-interface list --network-id xxx --label-selector xxx`, + ), + examples.NewExample( + `Lists all network interfaces with network ID "xxx" in JSON format`, + `$ stackit beta network-interface list --network-id xxx --output-format json`, + ), + examples.NewExample( + `Lists up to 10 network interfaces with network ID "xxx"`, + `$ stackit beta network-interface list --network-id xxx --limit 10`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list network interfaces: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + p.Info("No network interfaces found for network %d\n", model.NetworkId) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID") + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") + + err := flags.MarkFlagsRequired(cmd, networkIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), + NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNicsRequest { + req := apiClient.ListNics(ctx, model.ProjectId, *model.NetworkId) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + + return req +} + +func outputResult(p *print.Printer, outputFormat string, nics []iaas.NIC) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(nics, "", " ") + if err != nil { + return fmt.Errorf("marshal nics: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(nics, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal nics: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "NIC SECURITY", "STATUS", "TYPE") + + for _, nic := range nics { + name := "" + table.AddRow(*nic.Id, name, *nic.NicSecurity, *nic.Status, *nic.Type) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/network-interface/list/list_test.go b/internal/cmd/beta/network-interface/list/list_test.go new file mode 100644 index 000000000..3058072b0 --- /dev/null +++ b/internal/cmd/beta/network-interface/list/list_test.go @@ -0,0 +1,207 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testNetworkId = uuid.NewString() +var testLabelSelector = "label" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + networkIdFlag: testNetworkId, + limitFlag: "10", + labelSelectorFlag: testLabelSelector, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr(testLabelSelector), + NetworkId: utils.Ptr(testNetworkId), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListNicsRequest)) iaas.ApiListNicsRequest { + request := testClient.ListNics(testCtx, testProjectId, testNetworkId) + request = request.LabelSelector(testLabelSelector) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListNicsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/network-interface/network-interface.go b/internal/cmd/beta/network-interface/network-interface.go new file mode 100644 index 000000000..b1d648226 --- /dev/null +++ b/internal/cmd/beta/network-interface/network-interface.go @@ -0,0 +1,33 @@ +package networkinterface + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "network-interface", + Short: "Provides functionality for Network Interface", + Long: "Provides functionality for Network Interface.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} diff --git a/internal/cmd/beta/network-interface/update/update.go b/internal/cmd/beta/network-interface/update/update.go new file mode 100644 index 000000000..130a68a91 --- /dev/null +++ b/internal/cmd/beta/network-interface/update/update.go @@ -0,0 +1,243 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + "regexp" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + nicIdArg = "NIC_ID" + + networkIdFlag = "network-id" + allowedAddressesFlag = "allowed-addresses" + labelFlag = "labels" + nameFlag = "name" + securityGroupsFlag = "security-groups" + nicSecurityFlag = "nic-security" + + nameRegex = `^[A-Za-z0-9]+((-|_|\s|\.)[A-Za-z0-9]+)*$` + maxNameLength = 63 + securityGroupsRegex = `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$` + securityGroupLength = 36 + defaultNicSecurityFlag = true +) + +type inputModel struct { + *globalflags.GlobalFlagModel + NicId string + NetworkId *string + AllowedAddresses *[]iaas.AllowedAddressesInner + Labels *map[string]string + Name *string // <= 63 characters + regex ^[A-Za-z0-9]+((-|_|\s|\.)[A-Za-z0-9]+)*$ + NicSecurity *bool + SecurityGroups *[]string // = 36 characters + regex ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a network interface", + Long: "Updates a network interface.", + Args: args.SingleArg(nicIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Updates a network interface with nic id "xxx" and network-id "yyy" to new allowed addresses "1.1.1.1,8.8.8.8,9.9.9.9" and new labels "key=value,key2=value2"`, + `$ stackit beta network-interface update xxx --network-id yyy --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2`, + ), + examples.NewExample( + `Updates a network interface with nic id "xxx" and network-id "yyy" with new name "nic-name-new"`, + `$ stackit beta network-interface update xxx --network-id yyy --name nic-name-new`, + ), + examples.NewExample( + `Updates a network interface with nic id "xxx" and network-id "yyy" to include the security group "zzz"`, + `$ stackit beta network-interface update xxx --network-id yyy --security-groups zzz`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update the network interface %q?", model.NicId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update network interface: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID") + cmd.Flags().StringSlice(allowedAddressesFlag, nil, "List of allowed IPs") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...'") + cmd.Flags().StringP(nameFlag, "n", "", "Network interface name") + cmd.Flags().BoolP(nicSecurityFlag, "b", defaultNicSecurityFlag, "If this is set to false, then no security groups will apply to this network interface.") + cmd.Flags().StringSlice(securityGroupsFlag, nil, "List of security groups") + + err := flags.MarkFlagsRequired(cmd, networkIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + nicId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + allowedAddresses := flags.FlagToStringSlicePointer(p, cmd, allowedAddressesFlag) + var allowedAddressesInner []iaas.AllowedAddressesInner + if allowedAddresses != nil && len(*allowedAddresses) > 0 { + allowedAddressesInner = make([]iaas.AllowedAddressesInner, len(*allowedAddresses)) + for i, address := range *allowedAddresses { + allowedAddressesInner[i].String = &address + } + } + + // check name length and regex must apply + name := flags.FlagToStringPointer(p, cmd, nameFlag) + if name != nil { + if len(*name) > maxNameLength { + return nil, &errors.FlagValidationError{ + Flag: nameFlag, + Details: fmt.Sprintf("name %s is too long (maximum length is %d characters)", *name, maxNameLength), + } + } + nameRegex := regexp.MustCompile(nameRegex) + if !nameRegex.MatchString(*name) { + return nil, &errors.FlagValidationError{ + Flag: nameFlag, + Details: fmt.Sprintf("name %s didn't match the required regex expression %s", *name, nameRegex), + } + } + } + + // check security groups size and regex + securityGroups := flags.FlagToStringSlicePointer(p, cmd, securityGroupsFlag) + if securityGroups != nil && len(*securityGroups) > 0 { + securityGroupsRegex := regexp.MustCompile(securityGroupsRegex) + // iterate over them + for _, value := range *securityGroups { + if len(value) != securityGroupLength { + return nil, &errors.FlagValidationError{ + Flag: securityGroupsFlag, + Details: fmt.Sprintf("security groups uuid %s does not match (must be %d characters long)", value, securityGroupLength), + } + } + if !securityGroupsRegex.MatchString(value) { + return nil, &errors.FlagValidationError{ + Flag: securityGroupsFlag, + Details: fmt.Sprintf("security groups uuid %s didn't match the required regex expression %s", value, securityGroupsRegex), + } + } + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NicId: nicId, + NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + Name: name, + NicSecurity: flags.FlagToBoolPointer(p, cmd, nicSecurityFlag), + SecurityGroups: securityGroups, + } + + if allowedAddresses != nil { + model.AllowedAddresses = utils.Ptr(allowedAddressesInner) + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNicRequest { + req := apiClient.UpdateNic(ctx, model.ProjectId, *model.NetworkId, model.NicId) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + convertedMap := make(map[string]interface{}, len(*model.Labels)) + for k, v := range *model.Labels { + convertedMap[k] = v + } + labelsMap = &convertedMap + } + + payload := iaas.UpdateNicPayload{ + AllowedAddresses: model.AllowedAddresses, + Labels: labelsMap, + Name: model.Name, + NicSecurity: model.NicSecurity, + SecurityGroups: model.SecurityGroups, + } + return req.UpdateNicPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(nic, "", " ") + if err != nil { + return fmt.Errorf("marshal network interface: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal network interface: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Updated network interface for project %q.\n", model.ProjectId) + return nil + } +} diff --git a/internal/cmd/beta/network-interface/update/update_test.go b/internal/cmd/beta/network-interface/update/update_test.go new file mode 100644 index 000000000..00eeda71f --- /dev/null +++ b/internal/cmd/beta/network-interface/update/update_test.go @@ -0,0 +1,293 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testNetworkId = uuid.NewString() +var testNicId = uuid.NewString() +var testSecurityGroup = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testNicId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + networkIdFlag: testNetworkId, + allowedAddressesFlag: "1.1.1.1,8.8.8.8,9.9.9.9", + labelFlag: "key=value", + nameFlag: "testNic", + nicSecurityFlag: "true", + securityGroupsFlag: testSecurityGroup, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + var allowedAddresses []iaas.AllowedAddressesInner = []iaas.AllowedAddressesInner{ + iaas.StringAsAllowedAddressesInner(utils.Ptr("1.1.1.1")), + iaas.StringAsAllowedAddressesInner(utils.Ptr("8.8.8.8")), + iaas.StringAsAllowedAddressesInner(utils.Ptr("9.9.9.9")), + } + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + NetworkId: utils.Ptr(testNetworkId), + AllowedAddresses: utils.Ptr(allowedAddresses), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + Name: utils.Ptr("testNic"), + NicSecurity: utils.Ptr(true), + SecurityGroups: utils.Ptr([]string{testSecurityGroup}), + NicId: testNicId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateNicRequest)) iaas.ApiUpdateNicRequest { + request := testClient.UpdateNic(testCtx, testProjectId, testNetworkId, testNicId) + request = request.UpdateNicPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.UpdateNicPayload)) iaas.UpdateNicPayload { + var allowedAddresses []iaas.AllowedAddressesInner = []iaas.AllowedAddressesInner{ + iaas.StringAsAllowedAddressesInner(utils.Ptr("1.1.1.1")), + iaas.StringAsAllowedAddressesInner(utils.Ptr("8.8.8.8")), + iaas.StringAsAllowedAddressesInner(utils.Ptr("9.9.9.9")), + } + payload := iaas.UpdateNicPayload{ + AllowedAddresses: utils.Ptr(allowedAddresses), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), + Name: utils.Ptr("testNic"), + NicSecurity: utils.Ptr(true), + SecurityGroups: utils.Ptr([]string{testSecurityGroup}), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "network id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkIdFlag) + }), + isValid: false, + }, + { + description: "network id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = "" + }), + isValid: false, + }, + { + description: "network id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "allowed addresses missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, allowedAddressesFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.AllowedAddresses = nil + }), + isValid: true, + }, + { + description: "name to long", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nameFlag] = "verylongstringwith66characterstotestthenameregexwithinthisunittest" + }), + isValid: false, + }, + { + description: "name invalid", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nameFlag] = "test?" + }), + isValid: false, + }, + { + description: "name empty string invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nameFlag] = "" + }), + isValid: false, + }, + { + description: "security group uuid to short", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupsFlag] = "d61a8564-c8dd-4ffb-bc15-143e7d0c85e" + }), + isValid: false, + }, + { + description: "security group uuid invalid", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupsFlag] = "d61a8564-c8dd-4ffb-bc15-143e7d0c85e?" + }), + isValid: false, + }, + { + description: "nic argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateNicRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} From 7333218041635281b7db05570a485c9c15c5d73e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Go=CC=88kc=CC=A7e=20Go=CC=88k=20Klingel?= Date: Wed, 20 Nov 2024 11:33:48 +0100 Subject: [PATCH 093/619] fix name column in list command --- internal/cmd/beta/network-interface/list/list.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/cmd/beta/network-interface/list/list.go b/internal/cmd/beta/network-interface/list/list.go index 2257e6038..fc8b4a8c5 100644 --- a/internal/cmd/beta/network-interface/list/list.go +++ b/internal/cmd/beta/network-interface/list/list.go @@ -169,6 +169,9 @@ func outputResult(p *print.Printer, outputFormat string, nics []iaas.NIC) error for _, nic := range nics { name := "" + if nic.Name != nil { + name = *nic.Name + } table.AddRow(*nic.Id, name, *nic.NicSecurity, *nic.Status, *nic.Type) table.AddSeparator() } From b517fc1003e442507d0390f74fc4bcf4f828bca7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:25:56 +0100 Subject: [PATCH 094/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.6.2 (#506) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dbce1534f..5a8089643 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.1 + github.com/jedib0t/go-pretty/v6 v6.6.2 github.com/lmittmann/tint v1.0.5 github.com/mattn/go-colorable v0.1.13 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index 04aea4191..5fcce1242 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtxYVWyc= -github.com/jedib0t/go-pretty/v6 v6.6.1/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.2 h1:27bLj3nRODzaiA7tPIxy9UVWHoPspFfME9XxgwiiNsM= +github.com/jedib0t/go-pretty/v6 v6.6.2/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= From 3b8d284e949cc8c77281f27e107fb70e22cafbbf Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:14:02 +0100 Subject: [PATCH 095/619] fix(deps): update stackit sdk modules (#509) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update stackit sdk modules * changes for the renamed method --------- Co-authored-by: Renovate Bot Co-authored-by: Gökçe Gök Klingel --- go.mod | 4 +-- go.sum | 8 ++--- .../pkg/services/serverbackup/utils/utils.go | 4 +-- .../services/serverbackup/utils/utils_test.go | 32 +++++++++---------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 5a8089643..9b33df26d 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/viper v1.19.0 github.com/stackitcloud/stackit-sdk-go/core v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 @@ -25,7 +25,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.2.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 diff --git a/go.sum b/go.sum index 5fcce1242..8fb3b82ff 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/stackitcloud/stackit-sdk-go/core v0.14.0 h1:oBwwzrEHDTlZpRoQwmMQpNA8b github.com/stackitcloud/stackit-sdk-go/core v0.14.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 h1:WXSIE4KfdHzaiiD0MF8CsoIv8I+Two/Bf/r28tYhRCU= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0 h1:+OZ82DwFy4JIJThadVjvll5kUWjHPSLbUIF65njsNBk= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.11.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0 h1:NypnmRbvjCX7ANJej1epwmopBEjkMzklJT3SY5iVwWg= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0 h1:geyW780gqNxzSsPvmlxy3kUUJaRA4eiF9V3b2Ibcdjs= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= @@ -159,8 +159,8 @@ github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0 h1:tb0w+0imdJh github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0/go.mod h1:LgCIIj7jA2lWX4DI3bxUYD+m0TbWCr1VgAyBYNJeghc= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 h1:HrnEgRPt3eD/tEHyzDWyCRxNFzb9g/FLYfwIEEQZ+Rg= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.2.0 h1:6IUrNIBEIpmrlfEK3QENQZB35KHEmeyc7w1owFOfGpc= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.2.0/go.mod h1:+807U5ZLXns+CEbyIg483wNEwV10vaN6GjMnSZhw/64= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0 h1:Tlps8vBQmQ1mx2YFbzOzMIyWtXGJy7X3N9Qk3qk88Cc= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0/go.mod h1:+807U5ZLXns+CEbyIg483wNEwV10vaN6GjMnSZhw/64= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0 h1:6IZBX9fyza9Eln3FHGHquvLNXQslk+dtkQp41G9+7+Y= diff --git a/internal/pkg/services/serverbackup/utils/utils.go b/internal/pkg/services/serverbackup/utils/utils.go index 1dc32dfec..ecc02493e 100644 --- a/internal/pkg/services/serverbackup/utils/utils.go +++ b/internal/pkg/services/serverbackup/utils/utils.go @@ -8,8 +8,8 @@ import ( ) type ServerBackupClient interface { - ListBackupSchedulesExecute(ctx context.Context, projectId, serverId string) (*serverbackup.ListBackupSchedules200Response, error) - ListBackupsExecute(ctx context.Context, projectId, serverId string) (*serverbackup.ListBackups200Response, error) + ListBackupSchedulesExecute(ctx context.Context, projectId, serverId string) (*serverbackup.GetBackupSchedulesResponse, error) + ListBackupsExecute(ctx context.Context, projectId, serverId string) (*serverbackup.GetBackupsListResponse, error) } func CanDisableBackupService(ctx context.Context, client ServerBackupClient, projectId, serverId string) (bool, error) { diff --git a/internal/pkg/services/serverbackup/utils/utils_test.go b/internal/pkg/services/serverbackup/utils/utils_test.go index a25ce9ba5..ab8425f54 100644 --- a/internal/pkg/services/serverbackup/utils/utils_test.go +++ b/internal/pkg/services/serverbackup/utils/utils_test.go @@ -18,19 +18,19 @@ var ( type serverbackupClientMocked struct { listBackupSchedulesFails bool - listBackupSchedulesResp *serverbackup.ListBackupSchedules200Response + listBackupSchedulesResp *serverbackup.GetBackupSchedulesResponse listBackupsFails bool - listBackupsResp *serverbackup.ListBackups200Response + listBackupsResp *serverbackup.GetBackupsListResponse } -func (m *serverbackupClientMocked) ListBackupSchedulesExecute(_ context.Context, _, _ string) (*serverbackup.ListBackupSchedules200Response, error) { +func (m *serverbackupClientMocked) ListBackupSchedulesExecute(_ context.Context, _, _ string) (*serverbackup.GetBackupSchedulesResponse, error) { if m.listBackupSchedulesFails { return nil, fmt.Errorf("could not list backup schedules") } return m.listBackupSchedulesResp, nil } -func (m *serverbackupClientMocked) ListBackupsExecute(_ context.Context, _, _ string) (*serverbackup.ListBackups200Response, error) { +func (m *serverbackupClientMocked) ListBackupsExecute(_ context.Context, _, _ string) (*serverbackup.GetBackupsListResponse, error) { if m.listBackupsFails { return nil, fmt.Errorf("could not list backups") } @@ -42,8 +42,8 @@ func TestCanDisableBackupService(t *testing.T) { description string listBackupsFails bool listBackupSchedulesFails bool - listBackups *serverbackup.ListBackups200Response - listBackupSchedules *serverbackup.ListBackupSchedules200Response + listBackups *serverbackup.GetBackupsListResponse + listBackupSchedules *serverbackup.GetBackupSchedulesResponse isValid bool // isValid ==> err == nil expectedOutput bool // expectedCanDisable }{ @@ -51,8 +51,8 @@ func TestCanDisableBackupService(t *testing.T) { description: "base-ok-can-disable-backups-service-no-backups-no-backup-schedules", listBackupsFails: false, listBackupSchedulesFails: false, - listBackups: &serverbackup.ListBackups200Response{Items: &[]serverbackup.Backup{}}, - listBackupSchedules: &serverbackup.ListBackupSchedules200Response{Items: &[]serverbackup.BackupSchedule{}}, + listBackups: &serverbackup.GetBackupsListResponse{Items: &[]serverbackup.Backup{}}, + listBackupSchedules: &serverbackup.GetBackupSchedulesResponse{Items: &[]serverbackup.BackupSchedule{}}, isValid: true, expectedOutput: true, }, @@ -60,8 +60,8 @@ func TestCanDisableBackupService(t *testing.T) { description: "not-ok-api-error-list-backups", listBackupsFails: true, listBackupSchedulesFails: false, - listBackups: &serverbackup.ListBackups200Response{Items: &[]serverbackup.Backup{}}, - listBackupSchedules: &serverbackup.ListBackupSchedules200Response{Items: &[]serverbackup.BackupSchedule{}}, + listBackups: &serverbackup.GetBackupsListResponse{Items: &[]serverbackup.Backup{}}, + listBackupSchedules: &serverbackup.GetBackupSchedulesResponse{Items: &[]serverbackup.BackupSchedule{}}, isValid: false, expectedOutput: false, }, @@ -69,8 +69,8 @@ func TestCanDisableBackupService(t *testing.T) { description: "not-ok-api-error-list-backup-schedules", listBackupsFails: true, listBackupSchedulesFails: false, - listBackups: &serverbackup.ListBackups200Response{Items: &[]serverbackup.Backup{}}, - listBackupSchedules: &serverbackup.ListBackupSchedules200Response{Items: &[]serverbackup.BackupSchedule{}}, + listBackups: &serverbackup.GetBackupsListResponse{Items: &[]serverbackup.Backup{}}, + listBackupSchedules: &serverbackup.GetBackupSchedulesResponse{Items: &[]serverbackup.BackupSchedule{}}, isValid: false, expectedOutput: false, }, @@ -78,7 +78,7 @@ func TestCanDisableBackupService(t *testing.T) { description: "not-ok-has-backups-cannot-disable", listBackupsFails: false, listBackupSchedulesFails: false, - listBackups: &serverbackup.ListBackups200Response{ + listBackups: &serverbackup.GetBackupsListResponse{ Items: &[]serverbackup.Backup{ { CreatedAt: utils.Ptr("test timestamp"), @@ -92,7 +92,7 @@ func TestCanDisableBackupService(t *testing.T) { }, }, }, - listBackupSchedules: &serverbackup.ListBackupSchedules200Response{Items: &[]serverbackup.BackupSchedule{}}, + listBackupSchedules: &serverbackup.GetBackupSchedulesResponse{Items: &[]serverbackup.BackupSchedule{}}, isValid: true, expectedOutput: false, }, @@ -100,8 +100,8 @@ func TestCanDisableBackupService(t *testing.T) { description: "not-ok-has-backups-schedules-cannot-disable", listBackupsFails: false, listBackupSchedulesFails: false, - listBackups: &serverbackup.ListBackups200Response{Items: &[]serverbackup.Backup{}}, - listBackupSchedules: &serverbackup.ListBackupSchedules200Response{ + listBackups: &serverbackup.GetBackupsListResponse{Items: &[]serverbackup.Backup{}}, + listBackupSchedules: &serverbackup.GetBackupSchedulesResponse{ Items: &[]serverbackup.BackupSchedule{ { BackupProperties: nil, From a1aed69d12b6577892f12f18246a21c7b12e84e7 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 27 Nov 2024 08:16:42 +0100 Subject: [PATCH 096/619] Onboard IaaS server commands (#508) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * onboard iaas server commands * fix linter issues * change --details flag handling * remove userData from table output in describe command * fix linter issues * update descriptions * make flags conditionally required * add more examples * fix linter issues * Update internal/cmd/beta/server/create/create.go Co-authored-by: João Palet * Update internal/cmd/beta/server/create/create.go Co-authored-by: João Palet * adapt link in the create flags * update docs * change type of userDataFlag * change the flag validation * fix linter issues * Update internal/pkg/errors/errors.go Co-authored-by: João Palet * change error message * improve flag handling * extend unit tests * fix linter issues --------- Co-authored-by: João Palet --- docs/stackit_beta_server.md | 5 + docs/stackit_beta_server_create.md | 81 ++++ docs/stackit_beta_server_delete.md | 41 ++ docs/stackit_beta_server_describe.md | 46 ++ docs/stackit_beta_server_list.md | 50 +++ docs/stackit_beta_server_update.md | 44 ++ internal/cmd/beta/server/create/create.go | 359 +++++++++++++++ .../cmd/beta/server/create/create_test.go | 410 ++++++++++++++++++ internal/cmd/beta/server/delete/delete.go | 129 ++++++ .../cmd/beta/server/delete/delete_test.go | 218 ++++++++++ internal/cmd/beta/server/describe/describe.go | 218 ++++++++++ .../cmd/beta/server/describe/describe_test.go | 232 ++++++++++ internal/cmd/beta/server/list/list.go | 177 ++++++++ internal/cmd/beta/server/list/list_test.go | 204 +++++++++ internal/cmd/beta/server/server.go | 10 + internal/cmd/beta/server/update/update.go | 168 +++++++ .../cmd/beta/server/update/update_test.go | 252 +++++++++++ internal/pkg/errors/errors.go | 40 ++ internal/pkg/services/iaas/utils/utils.go | 9 + .../pkg/services/iaas/utils/utils_test.go | 55 +++ 20 files changed, 2748 insertions(+) create mode 100644 docs/stackit_beta_server_create.md create mode 100644 docs/stackit_beta_server_delete.md create mode 100644 docs/stackit_beta_server_describe.md create mode 100644 docs/stackit_beta_server_list.md create mode 100644 docs/stackit_beta_server_update.md create mode 100644 internal/cmd/beta/server/create/create.go create mode 100644 internal/cmd/beta/server/create/create_test.go create mode 100644 internal/cmd/beta/server/delete/delete.go create mode 100644 internal/cmd/beta/server/delete/delete_test.go create mode 100644 internal/cmd/beta/server/describe/describe.go create mode 100644 internal/cmd/beta/server/describe/describe_test.go create mode 100644 internal/cmd/beta/server/list/list.go create mode 100644 internal/cmd/beta/server/list/list_test.go create mode 100644 internal/cmd/beta/server/update/update.go create mode 100644 internal/cmd/beta/server/update/update_test.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index 1a2b67b25..2c96d2c32 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -31,4 +31,9 @@ stackit beta server [flags] * [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands * [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup * [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command +* [stackit beta server create](./stackit_beta_server_create.md) - Creates a server +* [stackit beta server delete](./stackit_beta_server_delete.md) - Deletes a server +* [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server +* [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project +* [stackit beta server update](./stackit_beta_server_update.md) - Updates a server diff --git a/docs/stackit_beta_server_create.md b/docs/stackit_beta_server_create.md new file mode 100644 index 000000000..6d8194715 --- /dev/null +++ b/docs/stackit_beta_server_create.md @@ -0,0 +1,81 @@ +## stackit beta server create + +Creates a server + +### Synopsis + +Creates a server. + +``` +stackit beta server create [flags] +``` + +### Examples + +``` + Create a server from an image with id xxx + $ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx + + Create a server with labels from an image with id xxx + $ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --labels key=value,foo=bar + + Create a server with a boot volume + $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 + + Create a server with a boot volume from an existing volume + $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type volume + + Create a server with a keypair + $ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --keypair-name example + + Create a server with a network + $ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --network-id yyy + + Create a server with a network interface + $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --network-interface-ids yyy + + Create a server with an attached volume + $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --volumes yyy + + Create a server with user data (cloud-init) + $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml") +``` + +### Options + +``` + --affinity-group string The affinity group the server is assigned to + --availability-zone string The availability zone of the server + --boot-volume-delete-on-termination Delete the volume during the termination of the server. Defaults to false + --boot-volume-performance-class string Boot volume performance class + --boot-volume-size int The size of the boot volume in GB. Must be provided when 'boot-volume-source-type' is 'image' + --boot-volume-source-id string ID of the source object of boot volume. It can be either an image or volume ID + --boot-volume-source-type string Type of the source object of boot volume. It can be either 'image' or 'volume' + -h, --help Help for "stackit beta server create" + --image-id string The image ID to be used for an ephemeral disk on the server. Either 'image-id' or 'boot-volume-...' flags are required + --keypair-name string The name of the SSH keypair used during the server creation + --labels stringToString Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...' (default []) + --machine-type string Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html + -n, --name string Server name + --network-id string ID of the network for the initial networking setup for the server creation + --network-interface-ids strings List of network interface IDs for the initial networking setup for the server creation + --security-groups strings The initial security groups for the server creation + --service-account-emails strings List of the service account mails + --user-data string User data that is passed via cloud-init to the server + --volumes strings The list of volumes attached to the server +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server + diff --git a/docs/stackit_beta_server_delete.md b/docs/stackit_beta_server_delete.md new file mode 100644 index 000000000..ffe1f941c --- /dev/null +++ b/docs/stackit_beta_server_delete.md @@ -0,0 +1,41 @@ +## stackit beta server delete + +Deletes a server + +### Synopsis + +Deletes a server. +If the server is still in use, the deletion will fail + + +``` +stackit beta server delete [flags] +``` + +### Examples + +``` + Delete server with ID "xxx" + $ stackit beta server delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta server delete" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server + diff --git a/docs/stackit_beta_server_describe.md b/docs/stackit_beta_server_describe.md new file mode 100644 index 000000000..1dab42995 --- /dev/null +++ b/docs/stackit_beta_server_describe.md @@ -0,0 +1,46 @@ +## stackit beta server describe + +Shows details of a server + +### Synopsis + +Shows details of a server. + +``` +stackit beta server describe [flags] +``` + +### Examples + +``` + Show details of a server with ID "xxx" + $ stackit beta server describe xxx + + Show detailed information of a server with ID "xxx" + $ stackit beta server describe xxx --details + + Show details of a server with ID "xxx" in JSON format + $ stackit beta server describe xxx --output-format json +``` + +### Options + +``` + --details Show detailed information about server + -h, --help Help for "stackit beta server 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server + diff --git a/docs/stackit_beta_server_list.md b/docs/stackit_beta_server_list.md new file mode 100644 index 000000000..4641bea02 --- /dev/null +++ b/docs/stackit_beta_server_list.md @@ -0,0 +1,50 @@ +## stackit beta server list + +Lists all servers of a project + +### Synopsis + +Lists all servers of a project. + +``` +stackit beta server list [flags] +``` + +### Examples + +``` + Lists all servers + $ stackit beta server list + + Lists all servers which contains the label xxx + $ stackit beta server list --label-selector xxx + + Lists all servers in JSON format + $ stackit beta server list --output-format json + + Lists up to 10 servers + $ stackit beta server list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta server list" + --label-selector string Filter by label + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server + diff --git a/docs/stackit_beta_server_update.md b/docs/stackit_beta_server_update.md new file mode 100644 index 000000000..633b75fbd --- /dev/null +++ b/docs/stackit_beta_server_update.md @@ -0,0 +1,44 @@ +## stackit beta server update + +Updates a server + +### Synopsis + +Updates a server. + +``` +stackit beta server update [flags] +``` + +### Examples + +``` + Update server with ID "xxx" with new name "server-1-new" + $ stackit beta server update xxx --name server-1-new + + Update server with ID "xxx" with new name "server-1-new" and label(s) + $ stackit beta server update xxx --name server-1-new --labels key=value,foo=bar +``` + +### Options + +``` + -h, --help Help for "stackit beta server update" + --labels stringToString Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...' (default []) + -n, --name string Server name +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server + diff --git a/internal/cmd/beta/server/create/create.go b/internal/cmd/beta/server/create/create.go new file mode 100644 index 000000000..106956633 --- /dev/null +++ b/internal/cmd/beta/server/create/create.go @@ -0,0 +1,359 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + nameFlag = "name" + machineTypeFlag = "machine-type" + affinityGroupFlag = "affinity-group" + availabilityZoneFlag = "availability-zone" + bootVolumeSourceIdFlag = "boot-volume-source-id" + bootVolumeSourceTypeFlag = "boot-volume-source-type" + bootVolumeSizeFlag = "boot-volume-size" + bootVolumePerformanceClassFlag = "boot-volume-performance-class" + bootVolumeDeleteOnTerminationFlag = "boot-volume-delete-on-termination" + imageIdFlag = "image-id" + keypairNameFlag = "keypair-name" + labelFlag = "labels" + networkIdFlag = "network-id" + networkInterfaceIdsFlag = "network-interface-ids" + securityGroupsFlag = "security-groups" + serviceAccountEmailsFlag = "service-account-emails" + userDataFlag = "user-data" + volumesFlag = "volumes" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name *string + MachineType *string + AffinityGroup *string + AvailabilityZone *string + BootVolumeSourceId *string + BootVolumeSourceType *string + BootVolumeSize *int64 + BootVolumePerformanceClass *string + BootVolumeDeleteOnTermination *bool + ImageId *string + KeypairName *string + Labels *map[string]string + NetworkId *string + NetworkInterfaceIds *[]string + SecurityGroups *[]string + ServiceAccountMails *[]string + UserData *string + Volumes *[]string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a server", + Long: "Creates a server.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a server from an image with id xxx`, + `$ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx`, + ), + examples.NewExample( + `Create a server with labels from an image with id xxx`, + `$ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --labels key=value,foo=bar`, + ), + examples.NewExample( + `Create a server with a boot volume`, + `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64`, + ), + examples.NewExample( + `Create a server with a boot volume from an existing volume`, + `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type volume`, + ), + examples.NewExample( + `Create a server with a keypair`, + `$ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --keypair-name example`, + ), + examples.NewExample( + `Create a server with a network`, + `$ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --network-id yyy`, + ), + examples.NewExample( + `Create a server with a network interface`, + `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --network-interface-ids yyy`, + ), + examples.NewExample( + `Create a server with an attached volume`, + `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --volumes yyy`, + ), + examples.NewExample( + `Create a server with user data (cloud-init)`, + `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml")`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a server for project %q?", projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create server : %w", err) + } + serverId := *resp.Id + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Creating server") + _, err = wait.CreateServerWaitHandler(ctx, apiClient, model.ProjectId, serverId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for server creation: %w", err) + } + s.Stop() + } + + return outputResult(p, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(nameFlag, "n", "", "Server name") + cmd.Flags().String(machineTypeFlag, "", "Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html") + cmd.Flags().String(affinityGroupFlag, "", "The affinity group the server is assigned to") + cmd.Flags().String(availabilityZoneFlag, "", "The availability zone of the server") + cmd.Flags().String(bootVolumeSourceIdFlag, "", "ID of the source object of boot volume. It can be either an image or volume ID") + cmd.Flags().String(bootVolumeSourceTypeFlag, "", "Type of the source object of boot volume. It can be either 'image' or 'volume'") + cmd.Flags().Int64(bootVolumeSizeFlag, 0, "The size of the boot volume in GB. Must be provided when 'boot-volume-source-type' is 'image'") + cmd.Flags().String(bootVolumePerformanceClassFlag, "", "Boot volume performance class") + cmd.Flags().Bool(bootVolumeDeleteOnTerminationFlag, false, "Delete the volume during the termination of the server. Defaults to false") + cmd.Flags().String(imageIdFlag, "", "The image ID to be used for an ephemeral disk on the server. Either 'image-id' or 'boot-volume-...' flags are required") + cmd.Flags().String(keypairNameFlag, "", "The name of the SSH keypair used during the server creation") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...'") + cmd.Flags().String(networkIdFlag, "", "ID of the network for the initial networking setup for the server creation") + cmd.Flags().StringSlice(networkInterfaceIdsFlag, []string{}, "List of network interface IDs for the initial networking setup for the server creation") + cmd.Flags().StringSlice(securityGroupsFlag, []string{}, "The initial security groups for the server creation") + cmd.Flags().StringSlice(serviceAccountEmailsFlag, []string{}, "List of the service account mails") + cmd.Flags().Var(flags.ReadFromFileFlag(), userDataFlag, "User data that is passed via cloud-init to the server") + cmd.Flags().StringSlice(volumesFlag, []string{}, "The list of volumes attached to the server") + + err := flags.MarkFlagsRequired(cmd, nameFlag, machineTypeFlag) + cmd.MarkFlagsMutuallyExclusive(imageIdFlag, bootVolumeSourceIdFlag) + cmd.MarkFlagsMutuallyExclusive(imageIdFlag, bootVolumeSourceTypeFlag) + cmd.MarkFlagsMutuallyExclusive(networkIdFlag, networkInterfaceIdsFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + bootVolumeSourceId := flags.FlagToStringPointer(p, cmd, bootVolumeSourceIdFlag) + bootVolumeSourceType := flags.FlagToStringPointer(p, cmd, bootVolumeSourceTypeFlag) + bootVolumeSize := flags.FlagToInt64Pointer(p, cmd, bootVolumeSizeFlag) + imageId := flags.FlagToStringPointer(p, cmd, imageIdFlag) + + if imageId == nil && bootVolumeSourceId == nil && bootVolumeSourceType == nil { + return nil, &cliErr.ServerCreateMissingFlagsError{ + Cmd: cmd, + } + } + + if imageId == nil { + err := flags.MarkFlagsRequired(cmd, bootVolumeSourceIdFlag, bootVolumeSourceTypeFlag) + cobra.CheckErr(err) + } + + if bootVolumeSourceId != nil && bootVolumeSourceType == nil { + err := cmd.MarkFlagRequired(bootVolumeSourceTypeFlag) + cobra.CheckErr(err) + + return nil, &cliErr.ServerCreateMissingVolumeTypeError{ + Cmd: cmd, + } + } + + if bootVolumeSourceType != nil { + if bootVolumeSourceId == nil { + err := cmd.MarkFlagRequired(bootVolumeSourceIdFlag) + cobra.CheckErr(err) + + return nil, &cliErr.ServerCreateMissingVolumeIdError{ + Cmd: cmd, + } + } + + if *bootVolumeSourceType == "image" && bootVolumeSize == nil { + err := cmd.MarkFlagRequired(bootVolumeSizeFlag) + cobra.CheckErr(err) + return nil, &cliErr.ServerCreateError{ + Cmd: cmd, + } + } + } + + if bootVolumeSourceId == nil && bootVolumeSourceType == nil { + err := cmd.MarkFlagRequired(imageIdFlag) + cobra.CheckErr(err) + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + MachineType: flags.FlagToStringPointer(p, cmd, machineTypeFlag), + AffinityGroup: flags.FlagToStringPointer(p, cmd, affinityGroupFlag), + AvailabilityZone: flags.FlagToStringPointer(p, cmd, availabilityZoneFlag), + BootVolumeSourceId: flags.FlagToStringPointer(p, cmd, bootVolumeSourceIdFlag), + BootVolumeSourceType: flags.FlagToStringPointer(p, cmd, bootVolumeSourceTypeFlag), + BootVolumeSize: flags.FlagToInt64Pointer(p, cmd, bootVolumeSizeFlag), + BootVolumePerformanceClass: flags.FlagToStringPointer(p, cmd, bootVolumePerformanceClassFlag), + BootVolumeDeleteOnTermination: flags.FlagToBoolPointer(p, cmd, bootVolumeDeleteOnTerminationFlag), + ImageId: flags.FlagToStringPointer(p, cmd, imageIdFlag), + KeypairName: flags.FlagToStringPointer(p, cmd, keypairNameFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NetworkInterfaceIds: flags.FlagToStringSlicePointer(p, cmd, networkInterfaceIdsFlag), + SecurityGroups: flags.FlagToStringSlicePointer(p, cmd, securityGroupsFlag), + ServiceAccountMails: flags.FlagToStringSlicePointer(p, cmd, serviceAccountEmailsFlag), + UserData: flags.FlagToStringPointer(p, cmd, userDataFlag), + Volumes: flags.FlagToStringSlicePointer(p, cmd, volumesFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateServerRequest { + req := apiClient.CreateServer(ctx, model.ProjectId) + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + + payload := iaas.CreateServerPayload{ + Name: model.Name, + MachineType: model.MachineType, + AffinityGroup: model.AffinityGroup, + AvailabilityZone: model.AvailabilityZone, + + ImageId: model.ImageId, + KeypairName: model.KeypairName, + SecurityGroups: model.SecurityGroups, + ServiceAccountMails: model.ServiceAccountMails, + UserData: model.UserData, + Volumes: model.Volumes, + Labels: labelsMap, + } + + if model.BootVolumePerformanceClass != nil || model.BootVolumeSize != nil || model.BootVolumeDeleteOnTermination != nil || model.BootVolumeSourceId != nil || model.BootVolumeSourceType != nil { + payload.BootVolume = &iaas.CreateServerPayloadBootVolume{ + PerformanceClass: model.BootVolumePerformanceClass, + Size: model.BootVolumeSize, + DeleteOnTermination: model.BootVolumeDeleteOnTermination, + Source: &iaas.BootVolumeSource{ + Id: model.BootVolumeSourceId, + Type: model.BootVolumeSourceType, + }, + } + } + + if model.NetworkInterfaceIds != nil || model.NetworkId != nil { + payload.Networking = &iaas.CreateServerPayloadNetworking{} + + if model.NetworkInterfaceIds != nil { + payload.Networking.CreateServerNetworkingWithNics = &iaas.CreateServerNetworkingWithNics{ + NicIds: model.NetworkInterfaceIds, + } + } + if model.NetworkId != nil { + payload.Networking.CreateServerNetworking = &iaas.CreateServerNetworking{ + NetworkId: model.NetworkId, + } + } + } + + return req.CreateServerPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, server *iaas.Server) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(server, "", " ") + if err != nil { + return fmt.Errorf("marshal server: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created server for project %q.\nServer ID: %s\n", projectLabel, *server.Id) + return nil + } +} diff --git a/internal/cmd/beta/server/create/create_test.go b/internal/cmd/beta/server/create/create_test.go new file mode 100644 index 000000000..2ac1afcac --- /dev/null +++ b/internal/cmd/beta/server/create/create_test.go @@ -0,0 +1,410 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testSourceId = uuid.NewString() +var testImageId = uuid.NewString() +var testNetworkId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + availabilityZoneFlag: "eu01-1", + nameFlag: "test-server-name", + machineTypeFlag: "t1.1", + affinityGroupFlag: "test-affinity-group", + labelFlag: "key=value", + bootVolumePerformanceClassFlag: "test-perf-class", + bootVolumeSizeFlag: "5", + bootVolumeSourceIdFlag: testSourceId, + bootVolumeSourceTypeFlag: "test-source-type", + bootVolumeDeleteOnTerminationFlag: "false", + imageIdFlag: testImageId, + keypairNameFlag: "test-keypair-name", + networkIdFlag: testNetworkId, + securityGroupsFlag: "test-security-groups", + serviceAccountEmailsFlag: "test-service-account", + userDataFlag: "test-user-data", + volumesFlag: testVolumeId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + AvailabilityZone: utils.Ptr("eu01-1"), + Name: utils.Ptr("test-server-name"), + MachineType: utils.Ptr("t1.1"), + AffinityGroup: utils.Ptr("test-affinity-group"), + BootVolumePerformanceClass: utils.Ptr("test-perf-class"), + BootVolumeSize: utils.Ptr(int64(5)), + BootVolumeSourceId: utils.Ptr(testSourceId), + BootVolumeSourceType: utils.Ptr("test-source-type"), + BootVolumeDeleteOnTermination: utils.Ptr(false), + ImageId: utils.Ptr(testImageId), + KeypairName: utils.Ptr("test-keypair-name"), + NetworkId: utils.Ptr(testNetworkId), + SecurityGroups: utils.Ptr([]string{"test-security-groups"}), + ServiceAccountMails: utils.Ptr([]string{"test-service-account"}), + UserData: utils.Ptr("test-user-data"), + Volumes: utils.Ptr([]string{testVolumeId}), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateServerRequest)) iaas.ApiCreateServerRequest { + request := testClient.CreateServer(testCtx, testProjectId) + request = request.CreateServerPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateServerRequest)) iaas.ApiCreateServerRequest { + request := testClient.CreateServer(testCtx, testProjectId) + request = request.CreateServerPayload(iaas.CreateServerPayload{ + MachineType: utils.Ptr("t1.1"), + Name: utils.Ptr("test-server-name"), + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateServerPayload)) iaas.CreateServerPayload { + payload := iaas.CreateServerPayload{ + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), + MachineType: utils.Ptr("t1.1"), + Name: utils.Ptr("test-server-name"), + AvailabilityZone: utils.Ptr("eu01-1"), + AffinityGroup: utils.Ptr("test-affinity-group"), + ImageId: utils.Ptr(testImageId), + KeypairName: utils.Ptr("test-keypair-name"), + SecurityGroups: utils.Ptr([]string{"test-security-groups"}), + ServiceAccountMails: utils.Ptr([]string{"test-service-account"}), + UserData: utils.Ptr("test-user-data"), + Volumes: utils.Ptr([]string{testVolumeId}), + BootVolume: &iaas.CreateServerPayloadBootVolume{ + PerformanceClass: utils.Ptr("test-perf-class"), + Size: utils.Ptr(int64(5)), + DeleteOnTermination: utils.Ptr(false), + Source: &iaas.BootVolumeSource{ + Id: utils.Ptr(testSourceId), + Type: utils.Ptr("test-source-type"), + }, + }, + Networking: &iaas.CreateServerPayloadNetworking{ + CreateServerNetworking: &iaas.CreateServerNetworking{ + NetworkId: utils.Ptr(testNetworkId), + }, + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, affinityGroupFlag) + delete(flagValues, availabilityZoneFlag) + delete(flagValues, labelFlag) + delete(flagValues, bootVolumeSourceIdFlag) + delete(flagValues, bootVolumeSourceTypeFlag) + delete(flagValues, bootVolumeSizeFlag) + delete(flagValues, bootVolumePerformanceClassFlag) + delete(flagValues, bootVolumeDeleteOnTerminationFlag) + delete(flagValues, keypairNameFlag) + delete(flagValues, networkIdFlag) + delete(flagValues, networkInterfaceIdsFlag) + delete(flagValues, securityGroupsFlag) + delete(flagValues, serviceAccountEmailsFlag) + delete(flagValues, userDataFlag) + delete(flagValues, volumesFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.AffinityGroup = nil + model.AvailabilityZone = nil + model.Labels = nil + model.BootVolumeSourceId = nil + model.BootVolumeSourceType = nil + model.BootVolumeSize = nil + model.BootVolumePerformanceClass = nil + model.BootVolumeDeleteOnTermination = nil + model.KeypairName = nil + model.NetworkId = nil + model.NetworkInterfaceIds = nil + model.SecurityGroups = nil + model.ServiceAccountMails = nil + model.UserData = nil + model.Volumes = nil + }), + }, + { + description: "machine type missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, machineTypeFlag) + }), + isValid: false, + }, + { + description: "name missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "use network id", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = testNetworkId + flagValues[nameFlag] = "test-server-name" + flagValues[machineTypeFlag] = "t1.1" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NetworkId = utils.Ptr(testNetworkId) + model.Name = utils.Ptr("test-server-name") + model.MachineType = utils.Ptr("t1.1") + }), + }, + { + description: "use boot volume source id and type", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[bootVolumeSourceIdFlag] = testImageId + flagValues[bootVolumeSourceTypeFlag] = "image" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.BootVolumeSourceId = utils.Ptr(testImageId) + model.BootVolumeSourceType = utils.Ptr("image") + }), + }, + { + description: "invalid without image-id, boot-volume-source-id and type", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, bootVolumeSourceIdFlag) + delete(flagValues, bootVolumeSourceTypeFlag) + delete(flagValues, imageIdFlag) + }), + isValid: false, + }, + { + description: "invalid with boot-volume-source-id and without type", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, bootVolumeSourceTypeFlag) + }), + isValid: false, + }, + { + description: "invalid with boot-volume-source-type is image and without size", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, bootVolumeSizeFlag) + flagValues[bootVolumeSourceIdFlag] = testImageId + flagValues[bootVolumeSourceTypeFlag] = "image" + }), + isValid: false, + }, + { + description: "valid with image-id", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, bootVolumeSourceIdFlag) + delete(flagValues, bootVolumeSourceTypeFlag) + delete(flagValues, bootVolumeSizeFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.BootVolumeSourceId = nil + model.BootVolumeSourceType = nil + model.BootVolumeSize = nil + }), + }, + { + description: "valid with boot-volume-source-id and type volume", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, imageIdFlag) + delete(flagValues, bootVolumeSizeFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.ImageId = nil + model.BootVolumeSize = nil + }), + }, + { + description: "valid with boot-volume-source-id, type volume and size", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, imageIdFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.ImageId = nil + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateServerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "only name and machine type in payload", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + MachineType: utils.Ptr("t1.1"), + Name: utils.Ptr("test-server-name"), + }, + expectedRequest: fixtureRequiredRequest(), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/delete/delete.go b/internal/cmd/beta/server/delete/delete.go new file mode 100644 index 000000000..c82059193 --- /dev/null +++ b/internal/cmd/beta/server/delete/delete.go @@ -0,0 +1,129 @@ +package delete + +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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a server", + Long: fmt.Sprintf("%s\n%s\n", + "Deletes a server.", + "If the server is still in use, the deletion will fail", + ), + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete server with ID "xxx"`, + "$ stackit beta server delete xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete server %q?", serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete server: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Deleting server") + _, err = wait.DeleteServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for server deletion: %w", err) + } + s.Stop() + } + + operationState := "Deleted" + if model.Async { + operationState = "Triggered deletion of" + } + p.Info("%s server %q\n", operationState, serverLabel) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteServerRequest { + return apiClient.DeleteServer(ctx, model.ProjectId, model.ServerId) +} diff --git a/internal/cmd/beta/server/delete/delete_test.go b/internal/cmd/beta/server/delete/delete_test.go new file mode 100644 index 000000000..3b7c0ba31 --- /dev/null +++ b/internal/cmd/beta/server/delete/delete_test.go @@ -0,0 +1,218 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testServerId = uuid.NewString() +var testProjectId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteServerRequest)) iaas.ApiDeleteServerRequest { + request := testClient.DeleteServer(testCtx, testProjectId, testServerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/beta/server/describe/describe.go new file mode 100644 index 000000000..a9c105a93 --- /dev/null +++ b/internal/cmd/beta/server/describe/describe.go @@ -0,0 +1,218 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" + detailsFlag = "details" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + Details bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a server", + Long: "Shows details of a server.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Show details of a server with ID "xxx"`, + "$ stackit beta server describe xxx", + ), + examples.NewExample( + `Show detailed information of a server with ID "xxx"`, + "$ stackit beta server describe xxx --details", + ), + examples.NewExample( + `Show details of a server with ID "xxx" in JSON format`, + "$ stackit beta server describe xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read server: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Bool(detailsFlag, false, "Show detailed information about server") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + Details: flags.FlagToBoolValue(p, cmd, detailsFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetServerRequest { + req := apiClient.GetServer(ctx, model.ProjectId, model.ServerId) + + if model.Details { + req = req.Details(true) + } + + return req +} + +func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) error { + outputFormat := model.OutputFormat + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(server, "", " ") + if err != nil { + return fmt.Errorf("marshal server: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *server.Id) + table.AddSeparator() + table.AddRow("NAME", *server.Name) + table.AddSeparator() + table.AddRow("STATE", *server.Status) + table.AddSeparator() + table.AddRow("AVAILABILITY ZONE", *server.AvailabilityZone) + table.AddSeparator() + table.AddRow("BOOT VOLUME", *server.BootVolume.Id) + table.AddSeparator() + table.AddRow("POWER STATUS", *server.PowerStatus) + table.AddSeparator() + + if server.AffinityGroup != nil { + table.AddRow("AFFINITY GROUP", *server.AffinityGroup) + table.AddSeparator() + } + + if server.ImageId != nil { + table.AddRow("IMAGE", *server.ImageId) + table.AddSeparator() + } + + if server.KeypairName != nil { + table.AddRow("KEYPAIR", *server.KeypairName) + table.AddSeparator() + } + + if server.MachineType != nil { + table.AddRow("MACHINE TYPE", *server.MachineType) + table.AddSeparator() + } + + if server.Labels != nil && len(*server.Labels) > 0 { + labels := []string{} + for key, value := range *server.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } + + if server.Volumes != nil && len(*server.Volumes) > 0 { + volumes := []string{} + volumes = append(volumes, *server.Volumes...) + table.AddRow("VOLUMES", strings.Join(volumes, "\n")) + table.AddSeparator() + } + + if model.Details { + if server.ServiceAccountMails != nil && len(*server.ServiceAccountMails) > 0 { + emails := []string{} + emails = append(emails, *server.ServiceAccountMails...) + table.AddRow("SERVICE ACCOUNTS", strings.Join(emails, "\n")) + table.AddSeparator() + } + + if server.Nics != nil && len(*server.Nics) > 0 { + nics := []string{} + for _, nic := range *server.Nics { + nics = append(nics, *nic.NicId) + } + table.AddRow("NICS", strings.Join(nics, "\n")) + table.AddSeparator() + } + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/describe/describe_test.go b/internal/cmd/beta/server/describe/describe_test.go new file mode 100644 index 000000000..0c8c2ff13 --- /dev/null +++ b/internal/cmd/beta/server/describe/describe_test.go @@ -0,0 +1,232 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + detailsFlag: "true", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + Details: true, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetServerRequest)) iaas.ApiGetServerRequest { + request := testClient.GetServer(testCtx, testProjectId, testServerId) + request = request.Details(true) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "details flag false", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[detailsFlag] = "false" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Details = false + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/list/list.go b/internal/cmd/beta/server/list/list.go new file mode 100644 index 000000000..af2e59655 --- /dev/null +++ b/internal/cmd/beta/server/list/list.go @@ -0,0 +1,177 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + labelSelectorFlag = "label-selector" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + LabelSelector *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all servers of a project", + Long: "Lists all servers of a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all servers`, + "$ stackit beta server list", + ), + examples.NewExample( + `Lists all servers which contains the label xxx`, + "$ stackit beta server list --label-selector xxx", + ), + examples.NewExample( + `Lists all servers in JSON format`, + "$ stackit beta server list --output-format json", + ), + examples.NewExample( + `Lists up to 10 servers`, + "$ stackit beta server list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list servers: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + p.Info("No servers found for project %q\n", projectLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServersRequest { + req := apiClient.ListServers(ctx, model.ProjectId) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + + return req +} + +func outputResult(p *print.Printer, outputFormat string, servers []iaas.Server) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(servers, "", " ") + if err != nil { + return fmt.Errorf("marshal server: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(servers, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "Name", "Status", "Availability Zones") + + for i := range servers { + server := servers[i] + table.AddRow(*server.Id, *server.Name, *server.Status, *server.AvailabilityZone) + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/server/list/list_test.go b/internal/cmd/beta/server/list/list_test.go new file mode 100644 index 000000000..47ed2e4f1 --- /dev/null +++ b/internal/cmd/beta/server/list/list_test.go @@ -0,0 +1,204 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testLabelSelector = "label" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + labelSelectorFlag: testLabelSelector, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr(testLabelSelector), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListServersRequest)) iaas.ApiListServersRequest { + request := testClient.ListServers(testCtx, testProjectId) + request = request.LabelSelector(testLabelSelector) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListServersRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 4a0d70559..d3debf967 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -3,6 +3,11 @@ package server import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -25,4 +30,9 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(backup.NewCmd(p)) cmd.AddCommand(command.NewCmd(p)) + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) } diff --git a/internal/cmd/beta/server/update/update.go b/internal/cmd/beta/server/update/update.go new file mode 100644 index 000000000..127cb67ca --- /dev/null +++ b/internal/cmd/beta/server/update/update.go @@ -0,0 +1,168 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serverIdArg = "SERVER_ID" + + nameFlag = "name" + labelFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + Name *string + Labels *map[string]string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a server", + Long: "Updates a server.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update server with ID "xxx" with new name "server-1-new"`, + `$ stackit beta server update xxx --name server-1-new`, + ), + examples.NewExample( + `Update server with ID "xxx" with new name "server-1-new" and label(s)`, + `$ stackit beta server update xxx --name server-1-new --labels key=value,foo=bar`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update server %q?", serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update server: %w", err) + } + + return outputResult(p, model, serverLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(nameFlag, "n", "", "Server name") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...'") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + ServerId: serverId, + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateServerRequest { + req := apiClient.UpdateServer(ctx, model.ProjectId, model.ServerId) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + + payload := iaas.UpdateServerPayload{ + Name: model.Name, + Labels: labelsMap, + } + + return req.UpdateServerPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, serverLabel string, server *iaas.Server) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(server, "", " ") + if err != nil { + return fmt.Errorf("marshal server: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Updated server %q.\n", serverLabel) + return nil + } +} diff --git a/internal/cmd/beta/server/update/update_test.go b/internal/cmd/beta/server/update/update_test.go new file mode 100644 index 000000000..f06cbd6a5 --- /dev/null +++ b/internal/cmd/beta/server/update/update_test.go @@ -0,0 +1,252 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + nameFlag: "example-server-name", + projectIdFlag: testProjectId, + labelFlag: "key=value", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example-server-name"), + ServerId: testServerId, + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateServerRequest)) iaas.ApiUpdateServerRequest { + request := testClient.UpdateServer(testCtx, testProjectId, testServerId) + request = request.UpdateServerPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.UpdateServerPayload)) iaas.UpdateServerPayload { + payload := iaas.UpdateServerPayload{ + Name: utils.Ptr("example-server-name"), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "use name", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nameFlag] = "example-server-name" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = utils.Ptr("example-server-name") + }), + }, + { + description: "use labels", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelFlag] = "key=value" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = &map[string]string{ + "key": "value", + } + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index ec0aa3bda..38aaa0835 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -138,8 +138,48 @@ The profile name can only contain lowercase letters, numbers, and "-" and cannot To enable it, run: $ stackit %s enable` + + IAAS_SERVER_MISSING_VOLUME_SIZE = `The "boot-volume-size" flag must be provided when "boot-volume-source-type" is "image".` + + IAAS_SERVER_MISSING_VOLUME_ID = `The "boot-volume-source-id" flag must be provided together with "boot-volume-source-type" flag.` + + IAAS_SERVER_MISSING_VOLUME_TYPE = `The "boot-volume-source-type" flag must be provided together with "boot-volume-source-id" flag.` + + IAAS_SERVER_MISSING_IMAGE_OR_VOLUME_FLAGS = `Either "image-id" or "boot-volume-source-type" and "boot-volume-source-id" flags must be provided.` ) +type ServerCreateMissingVolumeIdError struct { + Cmd *cobra.Command +} + +func (e *ServerCreateMissingVolumeIdError) Error() string { + return IAAS_SERVER_MISSING_VOLUME_ID +} + +type ServerCreateMissingVolumeTypeError struct { + Cmd *cobra.Command +} + +func (e *ServerCreateMissingVolumeTypeError) Error() string { + return IAAS_SERVER_MISSING_VOLUME_TYPE +} + +type ServerCreateMissingFlagsError struct { + Cmd *cobra.Command +} + +func (e *ServerCreateMissingFlagsError) Error() string { + return IAAS_SERVER_MISSING_IMAGE_OR_VOLUME_FLAGS +} + +type ServerCreateError struct { + Cmd *cobra.Command +} + +func (e *ServerCreateError) Error() string { + return IAAS_SERVER_MISSING_VOLUME_SIZE +} + type ProjectIdError struct{} func (e *ProjectIdError) Error() string { diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index 9e7d79510..c522633d5 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -8,6 +8,7 @@ import ( ) type IaaSClient interface { + GetServerExecute(ctx context.Context, projectId, serverId string) (*iaas.Server, error) GetVolumeExecute(ctx context.Context, projectId, volumeId string) (*iaas.Volume, error) GetNetworkExecute(ctx context.Context, projectId, networkId string) (*iaas.Network, error) GetNetworkAreaExecute(ctx context.Context, organizationId, areaId string) (*iaas.NetworkArea, error) @@ -15,6 +16,14 @@ type IaaSClient interface { GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) } +func GetServerName(ctx context.Context, apiClient IaaSClient, projectId, serverId string) (string, error) { + resp, err := apiClient.GetServerExecute(ctx, projectId, serverId) + if err != nil { + return "", fmt.Errorf("get server: %w", err) + } + return *resp.Name, nil +} + func GetVolumeName(ctx context.Context, apiClient IaaSClient, projectId, volumeId string) (string, error) { resp, err := apiClient.GetVolumeExecute(ctx, projectId, volumeId) if err != nil { diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index 9c0e41ac1..aeda9d6d3 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -11,6 +11,8 @@ import ( ) type IaaSClientMocked struct { + GetServerFails bool + GetServerResp *iaas.Server GetVolumeFails bool GetVolumeResp *iaas.Volume GetNetworkFails bool @@ -23,6 +25,13 @@ type IaaSClientMocked struct { GetNetworkAreaRangeResp *iaas.NetworkRange } +func (m *IaaSClientMocked) GetServerExecute(_ context.Context, _, _ string) (*iaas.Server, error) { + if m.GetServerFails { + return nil, fmt.Errorf("could not get server") + } + return m.GetServerResp, nil +} + func (m *IaaSClientMocked) GetVolumeExecute(_ context.Context, _, _ string) (*iaas.Volume, error) { if m.GetVolumeFails { return nil, fmt.Errorf("could not get volume") @@ -58,6 +67,52 @@ func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _ return m.GetNetworkAreaRangeResp, nil } +func TestGetServerName(t *testing.T) { + type args struct { + getInstanceFails bool + getInstanceResp *iaas.Server + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "base", + args: args{ + getInstanceResp: &iaas.Server{ + Name: utils.Ptr("test"), + }, + }, + want: "test", + }, + { + name: "get server fails", + args: args{ + getInstanceFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetServerFails: tt.args.getInstanceFails, + GetServerResp: tt.args.getInstanceResp, + } + got, err := GetServerName(context.Background(), m, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetServerName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetServerName() = %v, want %v", got, tt.want) + } + }) + } +} + func TestGetVolumeName(t *testing.T) { type args struct { getInstanceFails bool From 340811228fbe322d20945729490906771333fe02 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Thu, 21 Nov 2024 10:59:45 +0100 Subject: [PATCH 097/619] Onboard IaaS server volume commands Supported commands: attach, detach, list, describe, update Signed-off-by: Alexander Dahmen --- docs/stackit_beta_server.md | 1 + docs/stackit_beta_server_volume.md | 37 +++ docs/stackit_beta_server_volume_attach.md | 44 +++ docs/stackit_beta_server_volume_describe.md | 46 ++++ docs/stackit_beta_server_volume_detach.md | 40 +++ docs/stackit_beta_server_volume_list.md | 43 +++ docs/stackit_beta_server_volume_update.md | 41 +++ internal/cmd/beta/server/server.go | 2 + .../cmd/beta/server/volume/attach/attach.go | 168 ++++++++++++ .../beta/server/volume/attach/attach_test.go | 251 ++++++++++++++++++ .../beta/server/volume/describe/describe.go | 170 ++++++++++++ .../server/volume/describe/describe_test.go | 227 ++++++++++++++++ .../cmd/beta/server/volume/detach/detach.go | 130 +++++++++ .../beta/server/volume/detach/detach_test.go | 226 ++++++++++++++++ internal/cmd/beta/server/volume/list/list.go | 161 +++++++++++ .../cmd/beta/server/volume/list/list_test.go | 193 ++++++++++++++ .../cmd/beta/server/volume/update/update.go | 164 ++++++++++++ .../beta/server/volume/update/update_test.go | 250 +++++++++++++++++ internal/cmd/beta/server/volume/volume.go | 34 +++ 19 files changed, 2228 insertions(+) create mode 100644 docs/stackit_beta_server_volume.md create mode 100644 docs/stackit_beta_server_volume_attach.md create mode 100644 docs/stackit_beta_server_volume_describe.md create mode 100644 docs/stackit_beta_server_volume_detach.md create mode 100644 docs/stackit_beta_server_volume_list.md create mode 100644 docs/stackit_beta_server_volume_update.md create mode 100644 internal/cmd/beta/server/volume/attach/attach.go create mode 100644 internal/cmd/beta/server/volume/attach/attach_test.go create mode 100644 internal/cmd/beta/server/volume/describe/describe.go create mode 100644 internal/cmd/beta/server/volume/describe/describe_test.go create mode 100644 internal/cmd/beta/server/volume/detach/detach.go create mode 100644 internal/cmd/beta/server/volume/detach/detach_test.go create mode 100644 internal/cmd/beta/server/volume/list/list.go create mode 100644 internal/cmd/beta/server/volume/list/list_test.go create mode 100644 internal/cmd/beta/server/volume/update/update.go create mode 100644 internal/cmd/beta/server/volume/update/update_test.go create mode 100644 internal/cmd/beta/server/volume/volume.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index 2c96d2c32..4734979b3 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -36,4 +36,5 @@ stackit beta server [flags] * [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project * [stackit beta server update](./stackit_beta_server_update.md) - Updates a server +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes diff --git a/docs/stackit_beta_server_volume.md b/docs/stackit_beta_server_volume.md new file mode 100644 index 000000000..f2692f63f --- /dev/null +++ b/docs/stackit_beta_server_volume.md @@ -0,0 +1,37 @@ +## stackit beta server volume + +Provides functionality for Server volumes + +### Synopsis + +Provides functionality for Server volumes. + +``` +stackit beta server volume [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server volume" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server volume attach](./stackit_beta_server_volume_attach.md) - Attaches a volume to a server +* [stackit beta server volume describe](./stackit_beta_server_volume_describe.md) - Describes a server volume attachment +* [stackit beta server volume detach](./stackit_beta_server_volume_detach.md) - Detaches a volume from a server +* [stackit beta server volume list](./stackit_beta_server_volume_list.md) - Lists all server volumes +* [stackit beta server volume update](./stackit_beta_server_volume_update.md) - Updates an attached volume of a server + diff --git a/docs/stackit_beta_server_volume_attach.md b/docs/stackit_beta_server_volume_attach.md new file mode 100644 index 000000000..43dcb6089 --- /dev/null +++ b/docs/stackit_beta_server_volume_attach.md @@ -0,0 +1,44 @@ +## stackit beta server volume attach + +Attaches a volume to a server + +### Synopsis + +Attaches a volume to a server. + +``` +stackit beta server volume attach [flags] +``` + +### Examples + +``` + Attach a volume with ID "xxx" to a server with ID "yyy" + $ stackit beta server volume attach xxx --server-id yyy + + Attach a volume with ID "xxx" to a server with ID "yyy" and enable deletion on termination + $ stackit beta server volume attach xxx --server-id yyy --delete-on-termination +``` + +### Options + +``` + -b, --delete-on-termination Delete the volume during the termination of the server. (default false) + -h, --help Help for "stackit beta server volume attach" + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes + diff --git a/docs/stackit_beta_server_volume_describe.md b/docs/stackit_beta_server_volume_describe.md new file mode 100644 index 000000000..175931b86 --- /dev/null +++ b/docs/stackit_beta_server_volume_describe.md @@ -0,0 +1,46 @@ +## stackit beta server volume describe + +Describes a server volume attachment + +### Synopsis + +Describes a server volume attachment. + +``` +stackit beta server volume describe [flags] +``` + +### Examples + +``` + Get details of the attachment of volume with ID "xxx" to server with ID "yyy" + $ stackit beta server volume describe xxx --server-id yyy + + Get details of the attachment of volume with ID "xxx" to server with ID "yyy" in JSON format + $ stackit beta server volume describe xxx --server-id yyy --output-format json + + Get details of the attachment of volume with ID "xxx" to server with ID "yyy" in yaml format + $ stackit beta server volume describe xxx --server-id yyy --output-format yaml +``` + +### Options + +``` + -h, --help Help for "stackit beta server volume describe" + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes + diff --git a/docs/stackit_beta_server_volume_detach.md b/docs/stackit_beta_server_volume_detach.md new file mode 100644 index 000000000..5422aab8a --- /dev/null +++ b/docs/stackit_beta_server_volume_detach.md @@ -0,0 +1,40 @@ +## stackit beta server volume detach + +Detaches a volume from a server + +### Synopsis + +Detaches a volume from a server. + +``` +stackit beta server volume detach [flags] +``` + +### Examples + +``` + Detaches a volume with ID "xxx" from a server with ID "yyy" + $ stackit beta server volume detach xxx --server-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server volume detach" + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes + diff --git a/docs/stackit_beta_server_volume_list.md b/docs/stackit_beta_server_volume_list.md new file mode 100644 index 000000000..68cf83bbc --- /dev/null +++ b/docs/stackit_beta_server_volume_list.md @@ -0,0 +1,43 @@ +## stackit beta server volume list + +Lists all server volumes + +### Synopsis + +Lists all server volumes. + +``` +stackit beta server volume list [flags] +``` + +### Examples + +``` + List all volumes for a server with ID "xxx" + $ stackit beta server volume list --server-id xxx + + List all volumes for a server with ID "xxx" in JSON format + $ stackit beta server volumes list --server-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server volume list" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes + diff --git a/docs/stackit_beta_server_volume_update.md b/docs/stackit_beta_server_volume_update.md new file mode 100644 index 000000000..134cb81a4 --- /dev/null +++ b/docs/stackit_beta_server_volume_update.md @@ -0,0 +1,41 @@ +## stackit beta server volume update + +Updates an attached volume of a server + +### Synopsis + +Updates an attached volume of a server. + +``` +stackit beta server volume update [flags] +``` + +### Examples + +``` + Update a volume with ID "xxx" of a server with ID "yyy" and enables delete on termination + $ stackit beta server volume update xxx --server-id yyy --delete-on-termination +``` + +### Options + +``` + -b, --delete-on-termination Delete the volume during the termination of the server. (default false) + -h, --help Help for "stackit beta server volume update" + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes + diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index d3debf967..7f205988f 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -35,4 +36,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(describe.NewCmd(p)) cmd.AddCommand(list.NewCmd(p)) cmd.AddCommand(update.NewCmd(p)) + cmd.AddCommand(volume.NewCmd(p)) } diff --git a/internal/cmd/beta/server/volume/attach/attach.go b/internal/cmd/beta/server/volume/attach/attach.go new file mode 100644 index 000000000..c417265d7 --- /dev/null +++ b/internal/cmd/beta/server/volume/attach/attach.go @@ -0,0 +1,168 @@ +package attach + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + volumeIdArg = "VOLUME_ID" + + serverIdFlag = "server-id" + deleteOnTerminationFlag = "delete-on-termination" + + defaultDeleteOnTermination = false +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + VolumeId string + DeleteOnTermination *bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "attach", + Short: "Attaches a volume to a server", + Long: "Attaches a volume to a server.", + Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Attach a volume with ID "xxx" to a server with ID "yyy"`, + `$ stackit beta server volume attach xxx --server-id yyy`, + ), + examples.NewExample( + `Attach a volume with ID "xxx" to a server with ID "yyy" and enable deletion on termination`, + `$ stackit beta server volume attach xxx --server-id yyy --delete-on-termination`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + if err != nil { + p.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = model.VolumeId + } + if volumeLabel == "" { + volumeLabel = model.VolumeId + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to attach volume %q to server %q?", volumeLabel, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("attach server volume: %w", err) + } + + return outputResult(p, model.OutputFormat, volumeLabel, serverLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + cmd.Flags().BoolP(deleteOnTerminationFlag, "b", defaultDeleteOnTermination, "Delete the volume during the termination of the server. (default false)") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + DeleteOnTermination: flags.FlagToBoolPointer(p, cmd, deleteOnTerminationFlag), + VolumeId: volumeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddVolumeToServerRequest { + req := apiClient.AddVolumeToServer(ctx, model.ProjectId, *model.ServerId, model.VolumeId) + payload := iaas.AddVolumeToServerPayload{ + DeleteOnTermination: model.DeleteOnTermination, + } + return req.AddVolumeToServerPayload(payload) +} + +func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel string, volume *iaas.VolumeAttachment) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(volume, "", " ") + if err != nil { + return fmt.Errorf("marshal server volume: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server volume: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Attached volume %q to server %q\n", volumeLabel, serverLabel) + return nil + } +} diff --git a/internal/cmd/beta/server/volume/attach/attach_test.go b/internal/cmd/beta/server/volume/attach/attach_test.go new file mode 100644 index 000000000..9dd33f77f --- /dev/null +++ b/internal/cmd/beta/server/volume/attach/attach_test.go @@ -0,0 +1,251 @@ +package attach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + deleteOnTerminationFlag: "true", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + VolumeId: testVolumeId, + DeleteOnTermination: utils.Ptr(true), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixturePayload(mods ...func(payload *iaas.AddVolumeToServerPayload)) iaas.AddVolumeToServerPayload { + payload := iaas.AddVolumeToServerPayload{ + DeleteOnTermination: utils.Ptr(true), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *iaas.ApiAddVolumeToServerRequest)) iaas.ApiAddVolumeToServerRequest { + request := testClient.AddVolumeToServer(testCtx, testProjectId, testServerId, testVolumeId) + request = request.AddVolumeToServerPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id argument missing", + argValues: []string{}, + isValid: false, + }, + { + description: "required only", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, deleteOnTerminationFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.DeleteOnTermination = nil + }), + isValid: true, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiAddVolumeToServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/describe/describe.go b/internal/cmd/beta/server/volume/describe/describe.go new file mode 100644 index 000000000..94fa6dd82 --- /dev/null +++ b/internal/cmd/beta/server/volume/describe/describe.go @@ -0,0 +1,170 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + volumeIdArg = "VOLUME_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + VolumeId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Describes a server volume attachment", + Long: "Describes a server volume attachment.", + Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get details of the attachment of volume with ID "xxx" to server with ID "yyy"`, + `$ stackit beta server volume describe xxx --server-id yyy`, + ), + examples.NewExample( + `Get details of the attachment of volume with ID "xxx" to server with ID "yyy" in JSON format`, + `$ stackit beta server volume describe xxx --server-id yyy --output-format json`, + ), + examples.NewExample( + `Get details of the attachment of volume with ID "xxx" to server with ID "yyy" in yaml format`, + `$ stackit beta server volume describe xxx --server-id yyy --output-format yaml`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + if err != nil { + p.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = model.VolumeId + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("describe server volume: %w", err) + } + + return outputResult(p, model.OutputFormat, serverLabel, volumeLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + VolumeId: volumeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetAttachedVolumeRequest { + req := apiClient.GetAttachedVolume(ctx, model.ProjectId, *model.ServerId, model.VolumeId) + return req +} + +func outputResult(p *print.Printer, outputFormat, serverLabel, volumeLabel string, volume *iaas.VolumeAttachment) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(volume, "", " ") + if err != nil { + return fmt.Errorf("marshal server volume: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server volume: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("SERVER ID", *volume.ServerId) + table.AddSeparator() + table.AddRow("SERVER NAME", serverLabel) + table.AddSeparator() + table.AddRow("VOLUME ID", *volume.VolumeId) + table.AddSeparator() + // check if name is set + if volumeLabel != "" { + table.AddRow("VOLUME NAME", volumeLabel) + table.AddSeparator() + } + table.AddRow("DELETE ON TERMINATION", *volume.DeleteOnTermination) + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/volume/describe/describe_test.go b/internal/cmd/beta/server/volume/describe/describe_test.go new file mode 100644 index 000000000..1d53423de --- /dev/null +++ b/internal/cmd/beta/server/volume/describe/describe_test.go @@ -0,0 +1,227 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + VolumeId: testVolumeId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetAttachedVolumeRequest)) iaas.ApiGetAttachedVolumeRequest { + request := testClient.GetAttachedVolume(testCtx, testProjectId, testServerId, testVolumeId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetAttachedVolumeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/detach/detach.go b/internal/cmd/beta/server/volume/detach/detach.go new file mode 100644 index 000000000..6e80517f6 --- /dev/null +++ b/internal/cmd/beta/server/volume/detach/detach.go @@ -0,0 +1,130 @@ +package detach + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + volumeIdArg = "VOLUME_ID" + + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + VolumeId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "detach", + Short: "Detaches a volume from a server", + Long: "Detaches a volume from a server.", + Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Detaches a volume with ID "xxx" from a server with ID "yyy"`, + `$ stackit beta server volume detach xxx --server-id yyy`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + if err != nil { + p.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = model.VolumeId + } + if volumeLabel == "" { + volumeLabel = model.VolumeId + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to detach volume %q from server %q?", volumeLabel, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + if err := req.Execute(); err != nil { + return fmt.Errorf("detach server volume: %w", err) + } + + p.Info("Detached volume %q from server %q\n", volumeLabel, serverLabel) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + VolumeId: volumeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveVolumeFromServerRequest { + req := apiClient.RemoveVolumeFromServer(ctx, model.ProjectId, *model.ServerId, model.VolumeId) + return req +} diff --git a/internal/cmd/beta/server/volume/detach/detach_test.go b/internal/cmd/beta/server/volume/detach/detach_test.go new file mode 100644 index 000000000..dd2032277 --- /dev/null +++ b/internal/cmd/beta/server/volume/detach/detach_test.go @@ -0,0 +1,226 @@ +package detach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + VolumeId: testVolumeId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiRemoveVolumeFromServerRequest)) iaas.ApiRemoveVolumeFromServerRequest { + request := testClient.RemoveVolumeFromServer(testCtx, testProjectId, testServerId, testVolumeId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRemoveVolumeFromServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/list/list.go b/internal/cmd/beta/server/volume/list/list.go new file mode 100644 index 000000000..f09ddf5dc --- /dev/null +++ b/internal/cmd/beta/server/volume/list/list.go @@ -0,0 +1,161 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all server volumes", + Long: "Lists all server volumes.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all volumes for a server with ID "xxx"`, + "$ stackit beta server volume list --server-id xxx"), + examples.NewExample( + `List all volumes for a server with ID "xxx" in JSON format`, + "$ stackit beta server volumes list --server-id xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list server volumes: %w", err) + } + volumes := *resp.Items + if len(volumes) == 0 { + p.Info("No volumes found for server %s\n", *model.ServerId) + return nil + } + + // get volume names + var volumeNames []string + for i := range volumes { + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, *volumes[i].VolumeId) + if err != nil { + p.Debug(print.ErrorLevel, "get volume name: %v", err) + } + volumeNames = append(volumeNames, volumeLabel) + } + + return outputResult(p, model.OutputFormat, serverLabel, volumeNames, volumes) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListAttachedVolumesRequest { + req := apiClient.ListAttachedVolumes(ctx, model.ProjectId, *model.ServerId) + return req +} + +func outputResult(p *print.Printer, outputFormat, serverLabel string, volumeNames []string, volumes []iaas.VolumeAttachment) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(volumes, "", " ") + if err != nil { + return fmt.Errorf("marshal server volume list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(volumes, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server volume list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("SERVER ID", "SERVER NAME", "VOLUME ID", "VOLUME NAME") + for i := range volumes { + s := volumes[i] + table.AddRow(*s.ServerId, serverLabel, *s.VolumeId, volumeNames[i]) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/volume/list/list_test.go b/internal/cmd/beta/server/volume/list/list_test.go new file mode 100644 index 000000000..288c65fd6 --- /dev/null +++ b/internal/cmd/beta/server/volume/list/list_test.go @@ -0,0 +1,193 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListAttachedVolumesRequest)) iaas.ApiListAttachedVolumesRequest { + request := testClient.ListAttachedVolumes(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListAttachedVolumesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/update/update.go b/internal/cmd/beta/server/volume/update/update.go new file mode 100644 index 000000000..5ab7d58de --- /dev/null +++ b/internal/cmd/beta/server/volume/update/update.go @@ -0,0 +1,164 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + volumeIdArg = "VOLUME_ID" + + serverIdFlag = "server-id" + deleteOnTerminationFlag = "delete-on-termination" + + defaultDeleteOnTermination = false +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + VolumeId string + DeleteOnTermination *bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates an attached volume of a server", + Long: "Updates an attached volume of a server.", + Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update a volume with ID "xxx" of a server with ID "yyy" and enables delete on termination`, + `$ stackit beta server volume update xxx --server-id yyy --delete-on-termination`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + if err != nil { + p.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = model.VolumeId + } + if volumeLabel == "" { + volumeLabel = model.VolumeId + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update attached volume %q of server %q?", volumeLabel, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update server volume: %w", err) + } + + return outputResult(p, model.OutputFormat, volumeLabel, serverLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + cmd.Flags().BoolP(deleteOnTerminationFlag, "b", defaultDeleteOnTermination, "Delete the volume during the termination of the server. (default false)") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + DeleteOnTermination: flags.FlagToBoolPointer(p, cmd, deleteOnTerminationFlag), + VolumeId: volumeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateAttachedVolumeRequest { + req := apiClient.UpdateAttachedVolume(ctx, model.ProjectId, *model.ServerId, model.VolumeId) + payload := iaas.UpdateAttachedVolumePayload{ + DeleteOnTermination: model.DeleteOnTermination, + } + return req.UpdateAttachedVolumePayload(payload) +} + +func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel string, volume *iaas.VolumeAttachment) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(volume, "", " ") + if err != nil { + return fmt.Errorf("marshal server volume: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server volume: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Updated attached volume %q of server %q\n", volumeLabel, serverLabel) + return nil + } +} diff --git a/internal/cmd/beta/server/volume/update/update_test.go b/internal/cmd/beta/server/volume/update/update_test.go new file mode 100644 index 000000000..5d8171fbf --- /dev/null +++ b/internal/cmd/beta/server/volume/update/update_test.go @@ -0,0 +1,250 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testVolumeId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVolumeId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + deleteOnTerminationFlag: "true", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + VolumeId: testVolumeId, + DeleteOnTermination: utils.Ptr(true), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixturePayload(mods ...func(payload *iaas.UpdateAttachedVolumePayload)) iaas.UpdateAttachedVolumePayload { + payload := iaas.UpdateAttachedVolumePayload{ + DeleteOnTermination: utils.Ptr(true), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateAttachedVolumeRequest)) iaas.ApiUpdateAttachedVolumeRequest { + request := testClient.UpdateAttachedVolume(testCtx, testProjectId, testServerId, testVolumeId) + request = request.UpdateAttachedVolumePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "required only", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, deleteOnTerminationFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.DeleteOnTermination = nil + }), + isValid: true, + }, + { + description: "volume id argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateAttachedVolumeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/volume.go b/internal/cmd/beta/server/volume/volume.go new file mode 100644 index 000000000..7f8656021 --- /dev/null +++ b/internal/cmd/beta/server/volume/volume.go @@ -0,0 +1,34 @@ +package volume + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/detach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "volume", + Short: "Provides functionality for Server volumes", + Long: "Provides functionality for Server volumes.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(attach.NewCmd(p)) + cmd.AddCommand(detach.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) +} From 2d19165d34f9b8e4006f37334e911eb8eed8be29 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 20 Nov 2024 01:05:31 +0000 Subject: [PATCH 098/619] fix(deps): update module golang.org/x/mod to v0.22.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9b33df26d..104d98739 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 github.com/zalando/go-keyring v0.2.5 - golang.org/x/mod v0.20.0 + golang.org/x/mod v0.22.0 golang.org/x/oauth2 v0.24.0 golang.org/x/term v0.26.0 golang.org/x/text v0.20.0 diff --git a/go.sum b/go.sum index 8fb3b82ff..cbdf45cbc 100644 --- a/go.sum +++ b/go.sum @@ -197,8 +197,8 @@ golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRj golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From 4a355b93d8dda2ad597d5d4e8e45e6eb5c74282d Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:11:24 +0100 Subject: [PATCH 099/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.0 (#495) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 16 ++-------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 104d98739..61557d2d2 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.13.4 + github.com/goccy/go-yaml v1.15.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index cbdf45cbc..7cda90a52 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,6 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -27,14 +25,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/goccy/go-yaml v1.13.4 h1:XOnLX9GqT+kH/gB7YzCMUiDBFU9B7pm3HZz6kyeDPkk= -github.com/goccy/go-yaml v1.13.4/go.mod h1:IjYwxUiJDoqpx2RmbdjMUceGHZwYLon3sfOGl5Hi9lc= +github.com/goccy/go-yaml v1.15.0 h1:y5h8En94U97WFmXO0xH3rk91bESojNVmuS0v/ws//Qs= +github.com/goccy/go-yaml v1.15.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -73,8 +65,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw= github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -191,8 +181,6 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= From 1aa57b1dfbd5005a775bd03a4feb9e9e4c62d93a Mon Sep 17 00:00:00 2001 From: Melvin <70433111+MelvinKl@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:11:42 +0100 Subject: [PATCH 100/619] chore(deps): update renovatebot/github-action action to v41 (#500) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index da767512b..12454b9fd 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v40.3.4 + uses: renovatebot/github-action@v41.0.0 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 9eff2192dcde835ed469313c603a8dcc400a9077 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:21:05 +0100 Subject: [PATCH 101/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.1 (#512) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 61557d2d2..34b0ba9d0 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.0 + github.com/goccy/go-yaml v1.15.1 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 7cda90a52..029953c3c 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.0 h1:y5h8En94U97WFmXO0xH3rk91bESojNVmuS0v/ws//Qs= -github.com/goccy/go-yaml v1.15.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.1 h1:1vwC1ZjDzXyiMUKf7kKPazc6WUm4xnHGxNlzj4BIVu0= +github.com/goccy/go-yaml v1.15.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 767ed65fb65dfca17fd89a63f5a3e015e67a6f9f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:23:56 +0100 Subject: [PATCH 102/619] fix(deps): update module github.com/zalando/go-keyring to v0.2.6 (#493) Co-authored-by: Renovate Bot --- go.mod | 10 ++++++---- go.sum | 14 ++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 34b0ba9d0..a567a8d87 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 - github.com/zalando/go-keyring v0.2.5 + github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.22.0 golang.org/x/oauth2 v0.24.0 golang.org/x/term v0.26.0 @@ -45,12 +45,14 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect ) -require github.com/mattn/go-isatty v0.0.20 // indirect +require ( + al.essio.dev/pkg/shellescape v1.5.1 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect +) require ( - github.com/alessio/shellescape v1.4.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect - github.com/danieljoos/wincred v1.2.1 // indirect + github.com/danieljoos/wincred v1.2.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/go.sum b/go.sum index 029953c3c..3fd20ab88 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ -github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4uEoM0= -github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= +al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho= +al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= -github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= +github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= +github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -43,6 +43,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -174,8 +176,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/zalando/go-keyring v0.2.5 h1:Bc2HHpjALryKD62ppdEzaFG6VxL6Bc+5v0LYpN8Lba8= -github.com/zalando/go-keyring v0.2.5/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= +github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s= +github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= From 4ee0f0e10484657c3d0d406a677a60990db691e0 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 28 Nov 2024 10:05:45 +0100 Subject: [PATCH 103/619] handle nil pointer exception (#514) --- internal/cmd/beta/network/describe/describe.go | 8 ++++++-- internal/cmd/beta/network/list/list.go | 7 ++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/beta/network/describe/describe.go index d9a991388..bbd2a3fa4 100644 --- a/internal/cmd/beta/network/describe/describe.go +++ b/internal/cmd/beta/network/describe/describe.go @@ -146,8 +146,12 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) table.AddSeparator() table.AddRow("STATE", *network.State) table.AddSeparator() - table.AddRow("PUBLIC IP", *network.PublicIp) - table.AddSeparator() + + if network.PublicIp != nil { + table.AddRow("PUBLIC IP", *network.PublicIp) + table.AddSeparator() + } + if len(ipv4nameservers) > 0 { table.AddRow("IPv4 NAME SERVERS", strings.Join(ipv4nameservers, ", ")) } diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index 4773d707a..af91a4a1c 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -154,7 +154,12 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network table.SetHeader("ID", "Name", "Status", "Public IP") for _, network := range networks { - table.AddRow(*network.NetworkId, *network.Name, *network.State, *network.PublicIp) + publicIp := "" + if network.PublicIp != nil { + publicIp = *network.PublicIp + } + + table.AddRow(*network.NetworkId, *network.Name, *network.State, publicIp) table.AddSeparator() } From d01bfef711f9459925bb187e44853b1cbf27da72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Tue, 3 Dec 2024 11:27:42 +0000 Subject: [PATCH 104/619] Add commands to attach/detach public IP from servers (#518) * feat: Add server public IP attach/detach commands * feat: Generate docs * fix: Linter * feat: Improve comment * feat: Improve unit test * feat: Improvement after review * feat: Remove --details flag from server describe --- Makefile | 8 +- README.md | 44 ++-- docs/stackit_beta.md | 8 +- docs/stackit_beta_network-interface.md | 4 +- docs/stackit_beta_network-interface_create.md | 2 +- docs/stackit_beta_network-interface_delete.md | 2 +- ...stackit_beta_network-interface_describe.md | 2 +- docs/stackit_beta_network-interface_list.md | 2 +- docs/stackit_beta_network-interface_update.md | 2 +- docs/stackit_beta_network.md | 4 +- docs/stackit_beta_network_create.md | 2 +- docs/stackit_beta_network_delete.md | 2 +- docs/stackit_beta_network_describe.md | 2 +- docs/stackit_beta_network_list.md | 2 +- docs/stackit_beta_network_update.md | 2 +- docs/stackit_beta_server.md | 9 +- docs/stackit_beta_server_backup.md | 6 +- docs/stackit_beta_server_backup_create.md | 2 +- docs/stackit_beta_server_backup_delete.md | 2 +- docs/stackit_beta_server_backup_describe.md | 2 +- docs/stackit_beta_server_backup_disable.md | 2 +- docs/stackit_beta_server_backup_enable.md | 2 +- docs/stackit_beta_server_backup_list.md | 2 +- docs/stackit_beta_server_backup_restore.md | 2 +- docs/stackit_beta_server_backup_schedule.md | 2 +- ...tackit_beta_server_backup_volume-backup.md | 2 +- docs/stackit_beta_server_command.md | 2 +- docs/stackit_beta_server_create.md | 2 +- docs/stackit_beta_server_delete.md | 2 +- docs/stackit_beta_server_describe.md | 8 +- docs/stackit_beta_server_list.md | 2 +- docs/stackit_beta_server_public-ip.md | 34 +++ docs/stackit_beta_server_public-ip_attach.md | 40 +++ docs/stackit_beta_server_public-ip_detach.md | 40 +++ docs/stackit_beta_server_update.md | 2 +- docs/stackit_beta_server_volume.md | 6 +- docs/stackit_beta_server_volume_attach.md | 2 +- docs/stackit_beta_server_volume_describe.md | 2 +- docs/stackit_beta_server_volume_detach.md | 2 +- docs/stackit_beta_server_volume_list.md | 2 +- docs/stackit_beta_server_volume_update.md | 2 +- docs/stackit_beta_volume.md | 4 +- docs/stackit_beta_volume_create.md | 2 +- docs/stackit_beta_volume_delete.md | 2 +- docs/stackit_beta_volume_describe.md | 2 +- docs/stackit_beta_volume_list.md | 2 +- docs/stackit_beta_volume_performance-class.md | 2 +- docs/stackit_beta_volume_resize.md | 2 +- docs/stackit_beta_volume_update.md | 2 +- .../network-interface/network-interface.go | 4 +- internal/cmd/beta/network/network.go | 4 +- internal/cmd/beta/server/backup/backup.go | 4 +- internal/cmd/beta/server/describe/describe.go | 62 +++-- .../cmd/beta/server/describe/describe_test.go | 13 - .../beta/server/public-ip/attach/attach.go | 127 ++++++++++ .../server/public-ip/attach/attach_test.go | 227 ++++++++++++++++++ .../beta/server/public-ip/detach/detach.go | 129 ++++++++++ .../server/public-ip/detach/detach_test.go | 226 +++++++++++++++++ .../cmd/beta/server/public-ip/public_ip.go | 28 +++ internal/cmd/beta/server/server.go | 6 +- internal/cmd/beta/server/volume/volume.go | 4 +- internal/cmd/beta/volume/volume.go | 4 +- internal/pkg/services/iaas/utils/utils.go | 13 + .../pkg/services/iaas/utils/utils_test.go | 61 +++++ scripts/project.sh | 2 +- 65 files changed, 1053 insertions(+), 148 deletions(-) create mode 100644 docs/stackit_beta_server_public-ip.md create mode 100644 docs/stackit_beta_server_public-ip_attach.md create mode 100644 docs/stackit_beta_server_public-ip_detach.md create mode 100644 internal/cmd/beta/server/public-ip/attach/attach.go create mode 100644 internal/cmd/beta/server/public-ip/attach/attach_test.go create mode 100644 internal/cmd/beta/server/public-ip/detach/detach.go create mode 100644 internal/cmd/beta/server/public-ip/detach/detach_test.go create mode 100644 internal/cmd/beta/server/public-ip/public_ip.go diff --git a/Makefile b/Makefile index 9a6d08844..7657fc059 100644 --- a/Makefile +++ b/Makefile @@ -19,21 +19,21 @@ project-tools: # Lint lint-golangci-lint: - @echo "Linting with golangci-lint" + @echo ">> Linting with golangci-lint" @golangci-lint run ${GOLANG_CI_ARGS} lint-yamllint: - @echo "Linting with yamllint" + @echo ">> Linting with yamllint" @yamllint -c .yamllint.yaml . lint: lint-golangci-lint lint-yamllint # Test test: - @echo "Running tests for the CLI application" + @echo ">> Running tests for the CLI application" @go test ./... -count=1 # Generate docs generate-docs: - @echo "Generating docs..." + @echo ">> Generating docs..." @go run $(SCRIPTS_BASE)/generate.go diff --git a/README.md b/README.md index e15f0687b..eaae8e299 100644 --- a/README.md +++ b/README.md @@ -65,28 +65,28 @@ Help is available for any command by specifying the special flag `--help` (or si Below you can find a list of the STACKIT services already available in the CLI (along with their respective command names) and the ones that are currently planned to be integrated. -| Service | CLI Commands | Status | -| ---------------------------------- |----------------------------------------------------------------| ------------------------- | -| Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`| :white_check_mark: (beta) | -| Authorization | `project`, `organization` | :white_check_mark: | -| DNS | `dns` | :white_check_mark: | -| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | -| Load Balancer | `load-balancer` | :white_check_mark: | -| LogMe | `logme` | :white_check_mark: | -| MariaDB | `mariadb` | :white_check_mark: | -| MongoDB Flex | `mongodbflex` | :white_check_mark: | -| Object Storage | `object-storage` | :white_check_mark: | -| OpenSearch | `opensearch` | :white_check_mark: | -| PostgreSQL Flex | `postgresflex` | :white_check_mark: | -| RabbitMQ | `rabbitmq` | :white_check_mark: | -| Redis | `redis` | :white_check_mark: | -| Resource Manager | `project` | :white_check_mark: | -| Secrets Manager | `secrets-manager` | :white_check_mark: | -| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | -| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | -| Service Account | `service-account` | :white_check_mark: | -| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | +| Service | CLI Commands | Status | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------- | +| Observability | `observability` | :white_check_mark: | +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta server` | :white_check_mark: (beta) | +| Authorization | `project`, `organization` | :white_check_mark: | +| DNS | `dns` | :white_check_mark: | +| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | +| Load Balancer | `load-balancer` | :white_check_mark: | +| LogMe | `logme` | :white_check_mark: | +| MariaDB | `mariadb` | :white_check_mark: | +| MongoDB Flex | `mongodbflex` | :white_check_mark: | +| Object Storage | `object-storage` | :white_check_mark: | +| OpenSearch | `opensearch` | :white_check_mark: | +| PostgreSQL Flex | `postgresflex` | :white_check_mark: | +| RabbitMQ | `rabbitmq` | :white_check_mark: | +| Redis | `redis` | :white_check_mark: | +| Resource Manager | `project` | :white_check_mark: | +| Secrets Manager | `secrets-manager` | :white_check_mark: | +| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | +| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | +| Service Account | `service-account` | :white_check_mark: | +| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | ## Authentication diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 56453f281..edc19472c 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -40,10 +40,10 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_network-interface.md b/docs/stackit_beta_network-interface.md index 1832e4ef9..1d46a14e6 100644 --- a/docs/stackit_beta_network-interface.md +++ b/docs/stackit_beta_network-interface.md @@ -1,10 +1,10 @@ ## stackit beta network-interface -Provides functionality for Network Interface +Provides functionality for network interfaces ### Synopsis -Provides functionality for Network Interface. +Provides functionality for network interfaces. ``` stackit beta network-interface [flags] diff --git a/docs/stackit_beta_network-interface_create.md b/docs/stackit_beta_network-interface_create.md index a36ed217f..a9bf2c2d3 100644 --- a/docs/stackit_beta_network-interface_create.md +++ b/docs/stackit_beta_network-interface_create.md @@ -46,5 +46,5 @@ stackit beta network-interface create [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network-interface_delete.md b/docs/stackit_beta_network-interface_delete.md index 954a7b472..a30564843 100644 --- a/docs/stackit_beta_network-interface_delete.md +++ b/docs/stackit_beta_network-interface_delete.md @@ -36,5 +36,5 @@ stackit beta network-interface delete [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network-interface_describe.md b/docs/stackit_beta_network-interface_describe.md index a879d87aa..3f99be8f9 100644 --- a/docs/stackit_beta_network-interface_describe.md +++ b/docs/stackit_beta_network-interface_describe.md @@ -42,5 +42,5 @@ stackit beta network-interface describe [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network-interface_list.md b/docs/stackit_beta_network-interface_list.md index 04707adcb..12e76737b 100644 --- a/docs/stackit_beta_network-interface_list.md +++ b/docs/stackit_beta_network-interface_list.md @@ -47,5 +47,5 @@ stackit beta network-interface list [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network-interface_update.md b/docs/stackit_beta_network-interface_update.md index 506fb1ba4..5be029a85 100644 --- a/docs/stackit_beta_network-interface_update.md +++ b/docs/stackit_beta_network-interface_update.md @@ -47,5 +47,5 @@ stackit beta network-interface update [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for Network Interface +* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network.md b/docs/stackit_beta_network.md index cfde2f0c7..0a5636c39 100644 --- a/docs/stackit_beta_network.md +++ b/docs/stackit_beta_network.md @@ -1,10 +1,10 @@ ## stackit beta network -Provides functionality for Network +Provides functionality for networks ### Synopsis -Provides functionality for Network. +Provides functionality for networks. ``` stackit beta network [flags] diff --git a/docs/stackit_beta_network_create.md b/docs/stackit_beta_network_create.md index e9ac60921..954e64688 100644 --- a/docs/stackit_beta_network_create.md +++ b/docs/stackit_beta_network_create.md @@ -46,5 +46,5 @@ stackit beta network create [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_network_delete.md b/docs/stackit_beta_network_delete.md index 1e42ed58c..a2ff9cc84 100644 --- a/docs/stackit_beta_network_delete.md +++ b/docs/stackit_beta_network_delete.md @@ -37,5 +37,5 @@ stackit beta network delete [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_network_describe.md b/docs/stackit_beta_network_describe.md index 5c8a15752..ed449330c 100644 --- a/docs/stackit_beta_network_describe.md +++ b/docs/stackit_beta_network_describe.md @@ -38,5 +38,5 @@ stackit beta network describe [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_network_list.md b/docs/stackit_beta_network_list.md index 14f19bd40..5d5aef8b3 100644 --- a/docs/stackit_beta_network_list.md +++ b/docs/stackit_beta_network_list.md @@ -42,5 +42,5 @@ stackit beta network list [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_network_update.md b/docs/stackit_beta_network_update.md index b14bc9a8d..4afaa9d6d 100644 --- a/docs/stackit_beta_network_update.md +++ b/docs/stackit_beta_network_update.md @@ -44,5 +44,5 @@ stackit beta network update [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for Network +* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index 4734979b3..5d2443980 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -1,10 +1,10 @@ ## stackit beta server -Provides functionality for Server +Provides functionality for servers ### Synopsis -Provides functionality for Server. +Provides functionality for servers. ``` stackit beta server [flags] @@ -29,12 +29,13 @@ stackit beta server [flags] ### SEE ALSO * [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups * [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command * [stackit beta server create](./stackit_beta_server_create.md) - Creates a server * [stackit beta server delete](./stackit_beta_server_delete.md) - Deletes a server * [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project +* [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers * [stackit beta server update](./stackit_beta_server_update.md) - Updates a server -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_backup.md b/docs/stackit_beta_server_backup.md index 74164a5a1..324a45e9c 100644 --- a/docs/stackit_beta_server_backup.md +++ b/docs/stackit_beta_server_backup.md @@ -1,10 +1,10 @@ ## stackit beta server backup -Provides functionality for Server Backup +Provides functionality for server backups ### Synopsis -Provides functionality for Server Backup. +Provides functionality for server backups. ``` stackit beta server backup [flags] @@ -28,7 +28,7 @@ stackit beta server backup [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta server backup create](./stackit_beta_server_backup_create.md) - Creates a Server Backup. * [stackit beta server backup delete](./stackit_beta_server_backup_delete.md) - Deletes a Server Backup. * [stackit beta server backup describe](./stackit_beta_server_backup_describe.md) - Shows details of a Server Backup diff --git a/docs/stackit_beta_server_backup_create.md b/docs/stackit_beta_server_backup_create.md index 713b10dd1..734fc5f96 100644 --- a/docs/stackit_beta_server_backup_create.md +++ b/docs/stackit_beta_server_backup_create.md @@ -42,5 +42,5 @@ stackit beta server backup create [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_delete.md b/docs/stackit_beta_server_backup_delete.md index 82c96299d..681311431 100644 --- a/docs/stackit_beta_server_backup_delete.md +++ b/docs/stackit_beta_server_backup_delete.md @@ -36,5 +36,5 @@ stackit beta server backup delete BACKUP_ID [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_describe.md b/docs/stackit_beta_server_backup_describe.md index 6ce6eb8be..232c6a656 100644 --- a/docs/stackit_beta_server_backup_describe.md +++ b/docs/stackit_beta_server_backup_describe.md @@ -39,5 +39,5 @@ stackit beta server backup describe BACKUP_ID [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_disable.md b/docs/stackit_beta_server_backup_disable.md index b2175dc86..813a3ca15 100644 --- a/docs/stackit_beta_server_backup_disable.md +++ b/docs/stackit_beta_server_backup_disable.md @@ -36,5 +36,5 @@ stackit beta server backup disable [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_enable.md b/docs/stackit_beta_server_backup_enable.md index 6a297f2ae..0f347dda1 100644 --- a/docs/stackit_beta_server_backup_enable.md +++ b/docs/stackit_beta_server_backup_enable.md @@ -36,5 +36,5 @@ stackit beta server backup enable [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_list.md b/docs/stackit_beta_server_backup_list.md index f7313d09f..35940e3b6 100644 --- a/docs/stackit_beta_server_backup_list.md +++ b/docs/stackit_beta_server_backup_list.md @@ -40,5 +40,5 @@ stackit beta server backup list [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_restore.md b/docs/stackit_beta_server_backup_restore.md index 8009a85ef..c2440165f 100644 --- a/docs/stackit_beta_server_backup_restore.md +++ b/docs/stackit_beta_server_backup_restore.md @@ -41,5 +41,5 @@ stackit beta server backup restore BACKUP_ID [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_schedule.md b/docs/stackit_beta_server_backup_schedule.md index 43655d725..0acb68691 100644 --- a/docs/stackit_beta_server_backup_schedule.md +++ b/docs/stackit_beta_server_backup_schedule.md @@ -28,7 +28,7 @@ stackit beta server backup schedule [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups * [stackit beta server backup schedule create](./stackit_beta_server_backup_schedule_create.md) - Creates a Server Backup Schedule * [stackit beta server backup schedule delete](./stackit_beta_server_backup_schedule_delete.md) - Deletes a Server Backup Schedule * [stackit beta server backup schedule describe](./stackit_beta_server_backup_schedule_describe.md) - Shows details of a Server Backup Schedule diff --git a/docs/stackit_beta_server_backup_volume-backup.md b/docs/stackit_beta_server_backup_volume-backup.md index 5964784c8..5e1cad643 100644 --- a/docs/stackit_beta_server_backup_volume-backup.md +++ b/docs/stackit_beta_server_backup_volume-backup.md @@ -28,7 +28,7 @@ stackit beta server backup volume-backup [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for Server Backup +* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups * [stackit beta server backup volume-backup delete](./stackit_beta_server_backup_volume-backup_delete.md) - Deletes a Server Volume Backup. * [stackit beta server backup volume-backup restore](./stackit_beta_server_backup_volume-backup_restore.md) - Restore a Server Volume Backup to a volume. diff --git a/docs/stackit_beta_server_command.md b/docs/stackit_beta_server_command.md index 228a29930..eaa91d013 100644 --- a/docs/stackit_beta_server_command.md +++ b/docs/stackit_beta_server_command.md @@ -28,7 +28,7 @@ stackit beta server command [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta server command create](./stackit_beta_server_command_create.md) - Creates a Server Command * [stackit beta server command describe](./stackit_beta_server_command_describe.md) - Shows details of a Server Command * [stackit beta server command list](./stackit_beta_server_command_list.md) - Lists all server commands diff --git a/docs/stackit_beta_server_create.md b/docs/stackit_beta_server_create.md index 6d8194715..7f8865139 100644 --- a/docs/stackit_beta_server_create.md +++ b/docs/stackit_beta_server_create.md @@ -77,5 +77,5 @@ stackit beta server create [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_delete.md b/docs/stackit_beta_server_delete.md index ffe1f941c..d12115e26 100644 --- a/docs/stackit_beta_server_delete.md +++ b/docs/stackit_beta_server_delete.md @@ -37,5 +37,5 @@ stackit beta server delete [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_describe.md b/docs/stackit_beta_server_describe.md index 1dab42995..fc35fbda0 100644 --- a/docs/stackit_beta_server_describe.md +++ b/docs/stackit_beta_server_describe.md @@ -16,9 +16,6 @@ stackit beta server describe [flags] Show details of a server with ID "xxx" $ stackit beta server describe xxx - Show detailed information of a server with ID "xxx" - $ stackit beta server describe xxx --details - Show details of a server with ID "xxx" in JSON format $ stackit beta server describe xxx --output-format json ``` @@ -26,8 +23,7 @@ stackit beta server describe [flags] ### Options ``` - --details Show detailed information about server - -h, --help Help for "stackit beta server describe" + -h, --help Help for "stackit beta server describe" ``` ### Options inherited from parent commands @@ -42,5 +38,5 @@ stackit beta server describe [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_list.md b/docs/stackit_beta_server_list.md index 4641bea02..f2ed97364 100644 --- a/docs/stackit_beta_server_list.md +++ b/docs/stackit_beta_server_list.md @@ -46,5 +46,5 @@ stackit beta server list [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_public-ip.md b/docs/stackit_beta_server_public-ip.md new file mode 100644 index 000000000..9cc341e4c --- /dev/null +++ b/docs/stackit_beta_server_public-ip.md @@ -0,0 +1,34 @@ +## stackit beta server public-ip + +Allows attaching/detaching public IPs to servers + +### Synopsis + +Allows attaching/detaching public IPs to servers. + +``` +stackit beta server public-ip [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server public-ip" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit beta server public-ip attach](./stackit_beta_server_public-ip_attach.md) - Attaches a public IP to a server +* [stackit beta server public-ip detach](./stackit_beta_server_public-ip_detach.md) - Detaches a public IP from a server + diff --git a/docs/stackit_beta_server_public-ip_attach.md b/docs/stackit_beta_server_public-ip_attach.md new file mode 100644 index 000000000..2bd1f1914 --- /dev/null +++ b/docs/stackit_beta_server_public-ip_attach.md @@ -0,0 +1,40 @@ +## stackit beta server public-ip attach + +Attaches a public IP to a server + +### Synopsis + +Attaches a public IP to a server. + +``` +stackit beta server public-ip attach [flags] +``` + +### Examples + +``` + Attach a public IP with ID "xxx" to a server with ID "yyy" + $ stackit beta server public-ip attach xxx --server-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server public-ip attach" + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers + diff --git a/docs/stackit_beta_server_public-ip_detach.md b/docs/stackit_beta_server_public-ip_detach.md new file mode 100644 index 000000000..375ed68b6 --- /dev/null +++ b/docs/stackit_beta_server_public-ip_detach.md @@ -0,0 +1,40 @@ +## stackit beta server public-ip detach + +Detaches a public IP from a server + +### Synopsis + +Detaches a public IP from a server. + +``` +stackit beta server public-ip detach [flags] +``` + +### Examples + +``` + Detaches a public IP with ID "xxx" from a server with ID "yyy" + $ stackit beta server public-ip detach xxx --server-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server public-ip detach" + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers + diff --git a/docs/stackit_beta_server_update.md b/docs/stackit_beta_server_update.md index 633b75fbd..499208bc3 100644 --- a/docs/stackit_beta_server_update.md +++ b/docs/stackit_beta_server_update.md @@ -40,5 +40,5 @@ stackit beta server update [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_volume.md b/docs/stackit_beta_server_volume.md index f2692f63f..42b0bc958 100644 --- a/docs/stackit_beta_server_volume.md +++ b/docs/stackit_beta_server_volume.md @@ -1,10 +1,10 @@ ## stackit beta server volume -Provides functionality for Server volumes +Provides functionality for server volumes ### Synopsis -Provides functionality for Server volumes. +Provides functionality for server volumes. ``` stackit beta server volume [flags] @@ -28,7 +28,7 @@ stackit beta server volume [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for Server +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta server volume attach](./stackit_beta_server_volume_attach.md) - Attaches a volume to a server * [stackit beta server volume describe](./stackit_beta_server_volume_describe.md) - Describes a server volume attachment * [stackit beta server volume detach](./stackit_beta_server_volume_detach.md) - Detaches a volume from a server diff --git a/docs/stackit_beta_server_volume_attach.md b/docs/stackit_beta_server_volume_attach.md index 43dcb6089..060fa0774 100644 --- a/docs/stackit_beta_server_volume_attach.md +++ b/docs/stackit_beta_server_volume_attach.md @@ -40,5 +40,5 @@ stackit beta server volume attach [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_volume_describe.md b/docs/stackit_beta_server_volume_describe.md index 175931b86..3c31daa2b 100644 --- a/docs/stackit_beta_server_volume_describe.md +++ b/docs/stackit_beta_server_volume_describe.md @@ -42,5 +42,5 @@ stackit beta server volume describe [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_volume_detach.md b/docs/stackit_beta_server_volume_detach.md index 5422aab8a..a45c8a636 100644 --- a/docs/stackit_beta_server_volume_detach.md +++ b/docs/stackit_beta_server_volume_detach.md @@ -36,5 +36,5 @@ stackit beta server volume detach [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_volume_list.md b/docs/stackit_beta_server_volume_list.md index 68cf83bbc..68970d53c 100644 --- a/docs/stackit_beta_server_volume_list.md +++ b/docs/stackit_beta_server_volume_list.md @@ -39,5 +39,5 @@ stackit beta server volume list [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_volume_update.md b/docs/stackit_beta_server_volume_update.md index 134cb81a4..18d45a4ac 100644 --- a/docs/stackit_beta_server_volume_update.md +++ b/docs/stackit_beta_server_volume_update.md @@ -37,5 +37,5 @@ stackit beta server volume update [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for Server volumes +* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_volume.md b/docs/stackit_beta_volume.md index 7255a1cec..4fe120bab 100644 --- a/docs/stackit_beta_volume.md +++ b/docs/stackit_beta_volume.md @@ -1,10 +1,10 @@ ## stackit beta volume -Provides functionality for Volume +Provides functionality for volumes ### Synopsis -Provides functionality for Volume. +Provides functionality for volumes. ``` stackit beta volume [flags] diff --git a/docs/stackit_beta_volume_create.md b/docs/stackit_beta_volume_create.md index dc44b1327..c7ce43275 100644 --- a/docs/stackit_beta_volume_create.md +++ b/docs/stackit_beta_volume_create.md @@ -52,5 +52,5 @@ stackit beta volume create [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_delete.md b/docs/stackit_beta_volume_delete.md index 1ded8006d..d3de5b62d 100644 --- a/docs/stackit_beta_volume_delete.md +++ b/docs/stackit_beta_volume_delete.md @@ -37,5 +37,5 @@ stackit beta volume delete [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_describe.md b/docs/stackit_beta_volume_describe.md index 387edf692..72e77fc96 100644 --- a/docs/stackit_beta_volume_describe.md +++ b/docs/stackit_beta_volume_describe.md @@ -38,5 +38,5 @@ stackit beta volume describe [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_list.md b/docs/stackit_beta_volume_list.md index 985db2475..1f0c84b29 100644 --- a/docs/stackit_beta_volume_list.md +++ b/docs/stackit_beta_volume_list.md @@ -46,5 +46,5 @@ stackit beta volume list [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_performance-class.md b/docs/stackit_beta_volume_performance-class.md index f1b125cab..3c92fdc51 100644 --- a/docs/stackit_beta_volume_performance-class.md +++ b/docs/stackit_beta_volume_performance-class.md @@ -28,7 +28,7 @@ stackit beta volume performance-class [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes * [stackit beta volume performance-class describe](./stackit_beta_volume_performance-class_describe.md) - Shows details of a volume performance class * [stackit beta volume performance-class list](./stackit_beta_volume_performance-class_list.md) - Lists all volume performance classes for a project diff --git a/docs/stackit_beta_volume_resize.md b/docs/stackit_beta_volume_resize.md index c2e7aea0f..a609c7c85 100644 --- a/docs/stackit_beta_volume_resize.md +++ b/docs/stackit_beta_volume_resize.md @@ -36,5 +36,5 @@ stackit beta volume resize [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_update.md b/docs/stackit_beta_volume_update.md index 98ad0a94a..f85b37388 100644 --- a/docs/stackit_beta_volume_update.md +++ b/docs/stackit_beta_volume_update.md @@ -44,5 +44,5 @@ stackit beta volume update [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for Volume +* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/internal/cmd/beta/network-interface/network-interface.go b/internal/cmd/beta/network-interface/network-interface.go index b1d648226..b67392d43 100644 --- a/internal/cmd/beta/network-interface/network-interface.go +++ b/internal/cmd/beta/network-interface/network-interface.go @@ -15,8 +15,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "network-interface", - Short: "Provides functionality for Network Interface", - Long: "Provides functionality for Network Interface.", + Short: "Provides functionality for network interfaces", + Long: "Provides functionality for network interfaces.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/cmd/beta/network/network.go b/internal/cmd/beta/network/network.go index cf4ccdd4d..30197e2ed 100644 --- a/internal/cmd/beta/network/network.go +++ b/internal/cmd/beta/network/network.go @@ -16,8 +16,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "network", - Short: "Provides functionality for Network", - Long: "Provides functionality for Network.", + Short: "Provides functionality for networks", + Long: "Provides functionality for networks.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/cmd/beta/server/backup/backup.go b/internal/cmd/beta/server/backup/backup.go index 37312d2a3..512f9bd66 100644 --- a/internal/cmd/beta/server/backup/backup.go +++ b/internal/cmd/beta/server/backup/backup.go @@ -20,8 +20,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "backup", - Short: "Provides functionality for Server Backup", - Long: "Provides functionality for Server Backup.", + Short: "Provides functionality for server backups", + Long: "Provides functionality for server backups.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/beta/server/describe/describe.go index a9c105a93..b425a227d 100644 --- a/internal/cmd/beta/server/describe/describe.go +++ b/internal/cmd/beta/server/describe/describe.go @@ -11,7 +11,6 @@ import ( "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/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" @@ -24,13 +23,11 @@ import ( const ( serverIdArg = "SERVER_ID" - detailsFlag = "details" ) type inputModel struct { *globalflags.GlobalFlagModel ServerId string - Details bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -44,10 +41,6 @@ func NewCmd(p *print.Printer) *cobra.Command { `Show details of a server with ID "xxx"`, "$ stackit beta server describe xxx", ), - examples.NewExample( - `Show detailed information of a server with ID "xxx"`, - "$ stackit beta server describe xxx --details", - ), examples.NewExample( `Show details of a server with ID "xxx" in JSON format`, "$ stackit beta server describe xxx --output-format json", @@ -76,14 +69,9 @@ func NewCmd(p *print.Printer) *cobra.Command { return outputResult(p, model, resp) }, } - configureFlags(cmd) return cmd } -func configureFlags(cmd *cobra.Command) { - cmd.Flags().Bool(detailsFlag, false, "Show detailed information about server") -} - func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { serverId := inputArgs[0] @@ -95,7 +83,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, ServerId: serverId, - Details: flags.FlagToBoolValue(p, cmd, detailsFlag), } if p.IsVerbosityDebug() { @@ -112,10 +99,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetServerRequest { req := apiClient.GetServer(ctx, model.ProjectId, model.ServerId) - - if model.Details { - req = req.Details(true) - } + req = req.Details(true) return req } @@ -142,6 +126,8 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro return nil default: table := tables.NewTable() + table.SetTitle("Server") + table.AddRow("ID", *server.Id) table.AddSeparator() table.AddRow("NAME", *server.Name) @@ -184,6 +170,11 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro table.AddSeparator() } + if server.ServiceAccountMails != nil && len(*server.ServiceAccountMails) > 0 { + table.AddRow("SERVICE ACCOUNTS", strings.Join(*server.ServiceAccountMails, "\n")) + table.AddSeparator() + } + if server.Volumes != nil && len(*server.Volumes) > 0 { volumes := []string{} volumes = append(volumes, *server.Volumes...) @@ -191,28 +182,31 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro table.AddSeparator() } - if model.Details { - if server.ServiceAccountMails != nil && len(*server.ServiceAccountMails) > 0 { - emails := []string{} - emails = append(emails, *server.ServiceAccountMails...) - table.AddRow("SERVICE ACCOUNTS", strings.Join(emails, "\n")) - table.AddSeparator() - } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } - if server.Nics != nil && len(*server.Nics) > 0 { - nics := []string{} - for _, nic := range *server.Nics { - nics = append(nics, *nic.NicId) + if server.Nics != nil && len(*server.Nics) > 0 { + nicsTable := tables.NewTable() + nicsTable.SetTitle("Attached Network Interfaces") + nicsTable.SetHeader("ID", "NETWORK ID", "NETWORK NAME", "PUBLIC IP") + + for _, nic := range *server.Nics { + publicIp := "" + if nic.PublicIp != nil { + publicIp = *nic.PublicIp } - table.AddRow("NICS", strings.Join(nics, "\n")) - table.AddSeparator() + nicsTable.AddRow(*nic.NicId, *nic.NetworkId, *nic.NetworkName, publicIp) + nicsTable.AddSeparator() } - } - err := table.Display(p) - if err != nil { - return fmt.Errorf("render table: %w", err) + err := nicsTable.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } } + return nil } } diff --git a/internal/cmd/beta/server/describe/describe_test.go b/internal/cmd/beta/server/describe/describe_test.go index 0c8c2ff13..defc5dec6 100644 --- a/internal/cmd/beta/server/describe/describe_test.go +++ b/internal/cmd/beta/server/describe/describe_test.go @@ -35,7 +35,6 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, - detailsFlag: "true", } for _, mod := range mods { mod(flagValues) @@ -50,7 +49,6 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, - Details: true, } for _, mod := range mods { mod(model) @@ -136,17 +134,6 @@ func TestParseInput(t *testing.T) { flagValues: fixtureFlagValues(), isValid: false, }, - { - description: "details flag false", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[detailsFlag] = "false" - }), - isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.Details = false - }), - }, } for _, tt := range tests { diff --git a/internal/cmd/beta/server/public-ip/attach/attach.go b/internal/cmd/beta/server/public-ip/attach/attach.go new file mode 100644 index 000000000..28c0b15b2 --- /dev/null +++ b/internal/cmd/beta/server/public-ip/attach/attach.go @@ -0,0 +1,127 @@ +package attach + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + publicIpIdArg = "PUBLIC_IP_ID" + + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + PublicIpId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "attach", + Short: "Attaches a public IP to a server", + Long: "Attaches a public IP to a server.", + Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Attach a public IP with ID "xxx" to a server with ID "yyy"`, + `$ stackit beta server public-ip attach xxx --server-id yyy`, + )), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + if err != nil { + p.Debug(print.ErrorLevel, "get public ip name: %v", err) + } + if publicIpLabel == "" { + publicIpLabel = model.PublicIpId + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to attach public IP %q to server %q?", publicIpLabel, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("attach server to public ip: %w", err) + } + + p.Info("Attached public IP %q to server %q\n", publicIpLabel, serverLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + volumeId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + PublicIpId: volumeId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddPublicIpToServerRequest { + return apiClient.AddPublicIpToServer(ctx, model.ProjectId, *model.ServerId, model.PublicIpId) +} diff --git a/internal/cmd/beta/server/public-ip/attach/attach_test.go b/internal/cmd/beta/server/public-ip/attach/attach_test.go new file mode 100644 index 000000000..b8a80d6b2 --- /dev/null +++ b/internal/cmd/beta/server/public-ip/attach/attach_test.go @@ -0,0 +1,227 @@ +package attach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testPublicIpId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testPublicIpId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + PublicIpId: testPublicIpId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiAddPublicIpToServerRequest)) iaas.ApiAddPublicIpToServerRequest { + request := testClient.AddPublicIpToServer(testCtx, testProjectId, testServerId, testPublicIpId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiAddPublicIpToServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/public-ip/detach/detach.go b/internal/cmd/beta/server/public-ip/detach/detach.go new file mode 100644 index 000000000..9a9533df2 --- /dev/null +++ b/internal/cmd/beta/server/public-ip/detach/detach.go @@ -0,0 +1,129 @@ +package detach + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + publicIpIdArg = "PUBLIC_IP_ID" + + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + PublicIpId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "detach", + Short: "Detaches a public IP from a server", + Long: "Detaches a public IP from a server.", + Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Detaches a public IP with ID "xxx" from a server with ID "yyy"`, + `$ stackit beta server public-ip detach xxx --server-id yyy`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + if err != nil { + p.Debug(print.ErrorLevel, "get public ip: %v", err) + publicIpLabel = model.PublicIpId + } + if publicIpLabel == "" { + publicIpLabel = model.PublicIpId + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to detach public IP %q from server %q?", publicIpLabel, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + if err := req.Execute(); err != nil { + return fmt.Errorf("detach public ip from server: %w", err) + } + + p.Info("Detached public IP %q from server %q\n", publicIpLabel, serverLabel) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + publicIpId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + PublicIpId: publicIpId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemovePublicIpFromServerRequest { + return apiClient.RemovePublicIpFromServer(ctx, model.ProjectId, *model.ServerId, model.PublicIpId) +} diff --git a/internal/cmd/beta/server/public-ip/detach/detach_test.go b/internal/cmd/beta/server/public-ip/detach/detach_test.go new file mode 100644 index 000000000..b7ed5c286 --- /dev/null +++ b/internal/cmd/beta/server/public-ip/detach/detach_test.go @@ -0,0 +1,226 @@ +package detach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testPublicIpId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testPublicIpId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + PublicIpId: testPublicIpId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiRemovePublicIpFromServerRequest)) iaas.ApiRemovePublicIpFromServerRequest { + request := testClient.RemovePublicIpFromServer(testCtx, testProjectId, testServerId, testPublicIpId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "public ip id argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRemovePublicIpFromServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/public-ip/public_ip.go b/internal/cmd/beta/server/public-ip/public_ip.go new file mode 100644 index 000000000..662d00aa5 --- /dev/null +++ b/internal/cmd/beta/server/public-ip/public_ip.go @@ -0,0 +1,28 @@ +package publicip + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip/detach" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "public-ip", + Short: "Allows attaching/detaching public IPs to servers", + Long: "Allows attaching/detaching public IPs to servers.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(attach.NewCmd(p)) + cmd.AddCommand(detach.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 7f205988f..4b8ba0fd4 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" + publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -19,8 +20,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "server", - Short: "Provides functionality for Server", - Long: "Provides functionality for Server.", + Short: "Provides functionality for servers", + Long: "Provides functionality for servers.", Args: args.NoArgs, Run: utils.CmdHelp, } @@ -35,6 +36,7 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(delete.NewCmd(p)) cmd.AddCommand(describe.NewCmd(p)) cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(publicip.NewCmd(p)) cmd.AddCommand(update.NewCmd(p)) cmd.AddCommand(volume.NewCmd(p)) } diff --git a/internal/cmd/beta/server/volume/volume.go b/internal/cmd/beta/server/volume/volume.go index 7f8656021..77714f625 100644 --- a/internal/cmd/beta/server/volume/volume.go +++ b/internal/cmd/beta/server/volume/volume.go @@ -16,8 +16,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "volume", - Short: "Provides functionality for Server volumes", - Long: "Provides functionality for Server volumes.", + Short: "Provides functionality for server volumes", + Long: "Provides functionality for server volumes.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/cmd/beta/volume/volume.go b/internal/cmd/beta/volume/volume.go index 0fa6f59f2..5b03326bf 100644 --- a/internal/cmd/beta/volume/volume.go +++ b/internal/cmd/beta/volume/volume.go @@ -18,8 +18,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "volume", - Short: "Provides functionality for Volume", - Long: "Provides functionality for Volume.", + Short: "Provides functionality for volumes", + Long: "Provides functionality for volumes.", Args: args.NoArgs, Run: utils.CmdHelp, } diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index c522633d5..fecc0872c 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -8,6 +8,7 @@ import ( ) type IaaSClient interface { + GetPublicIPExecute(ctx context.Context, projectId, publicIpId string) (*iaas.PublicIp, error) GetServerExecute(ctx context.Context, projectId, serverId string) (*iaas.Server, error) GetVolumeExecute(ctx context.Context, projectId, volumeId string) (*iaas.Volume, error) GetNetworkExecute(ctx context.Context, projectId, networkId string) (*iaas.Network, error) @@ -16,6 +17,18 @@ type IaaSClient interface { GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) } +func GetPublicIP(ctx context.Context, apiClient IaaSClient, projectId, publicIpId string) (ip, associatedResource string, err error) { + resp, err := apiClient.GetPublicIPExecute(ctx, projectId, publicIpId) + if err != nil { + return "", "", fmt.Errorf("get public ip: %w", err) + } + associatedResourceId := "" + if resp.NetworkInterface != nil { + associatedResourceId = *resp.NetworkInterface.Get() + } + return *resp.Ip, associatedResourceId, nil +} + func GetServerName(ctx context.Context, apiClient IaaSClient, projectId, serverId string) (string, error) { resp, err := apiClient.GetServerExecute(ctx, projectId, serverId) if err != nil { diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index aeda9d6d3..bc0d94299 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -11,6 +11,8 @@ import ( ) type IaaSClientMocked struct { + GetPublicIpFails bool + GetPublicIpResp *iaas.PublicIp GetServerFails bool GetServerResp *iaas.Server GetVolumeFails bool @@ -25,6 +27,13 @@ type IaaSClientMocked struct { GetNetworkAreaRangeResp *iaas.NetworkRange } +func (m *IaaSClientMocked) GetPublicIPExecute(_ context.Context, _, _ string) (*iaas.PublicIp, error) { + if m.GetPublicIpFails { + return nil, fmt.Errorf("could not get public ip") + } + return m.GetPublicIpResp, nil +} + func (m *IaaSClientMocked) GetServerExecute(_ context.Context, _, _ string) (*iaas.Server, error) { if m.GetServerFails { return nil, fmt.Errorf("could not get server") @@ -67,6 +76,58 @@ func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _ return m.GetNetworkAreaRangeResp, nil } +func TestGetPublicIp(t *testing.T) { + type args struct { + getPublicIpFails bool + getPublicIpResp *iaas.PublicIp + } + tests := []struct { + name string + args args + wantPublicIp string + wantAssociatedResource string + wantErr bool + }{ + { + name: "base", + args: args{ + getPublicIpResp: &iaas.PublicIp{ + Ip: utils.Ptr("1.2.3.4"), + NetworkInterface: iaas.NewNullableString(utils.Ptr("5.6.7.8")), + }, + }, + wantPublicIp: "1.2.3.4", + wantAssociatedResource: "5.6.7.8", + }, + { + name: "get public ip fails", + args: args{ + getPublicIpFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetPublicIpFails: tt.args.getPublicIpFails, + GetPublicIpResp: tt.args.getPublicIpResp, + } + gotPublicIP, gotAssociatedResource, err := GetPublicIP(context.Background(), m, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetPublicIP() error = %v, wantErr %v", err, tt.wantErr) + return + } + if gotPublicIP != tt.wantPublicIp { + t.Errorf("GetPublicIP() = %v, want public IP %v", gotPublicIP, tt.wantPublicIp) + } + if gotAssociatedResource != tt.wantAssociatedResource { + t.Errorf("GetPublicIP() = %v, want associated resource %v", gotAssociatedResource, tt.wantAssociatedResource) + } + }) + } +} + func TestGetServerName(t *testing.T) { type args struct { getInstanceFails bool diff --git a/scripts/project.sh b/scripts/project.sh index 2786e509e..f8acf4e38 100755 --- a/scripts/project.sh +++ b/scripts/project.sh @@ -16,5 +16,5 @@ elif [ "$action" = "tools" ]; then go mod download go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 else - echo "Invalid action: '$action', please use $0 help for help" + echo "! Invalid action: '$action', please use $0 help for help" fi From 9859f26f389e52056d7514e6471f74f2fba02c45 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:10:26 +0100 Subject: [PATCH 105/619] Onboard IaaS Public IP commands (#513) * onboard public ip commands * changes in commands to edit descriptions and avoid nil pointer exceptions * fix utils * add public ip to read me * Update internal/cmd/beta/public-ip/create/create.go Co-authored-by: Alexander Dahmen * update examples * remove associated resource id from update command * Update internal/cmd/beta/public-ip/associate/associate.go Co-authored-by: Alexander Dahmen * Update internal/cmd/beta/public-ip/delete/delete.go Co-authored-by: Alexander Dahmen * add associated resource id information in the disassociate command * fix linter issues * remove obsolete unit tests * add empty update check * change public ip util to avoid NPE * adapt documentation --------- Co-authored-by: Alexander Dahmen --- README.md | 44 ++-- docs/stackit_beta.md | 1 + docs/stackit_beta_public-ip.md | 39 +++ docs/stackit_beta_public-ip_associate.md | 40 +++ docs/stackit_beta_public-ip_create.md | 47 ++++ docs/stackit_beta_public-ip_delete.md | 41 +++ docs/stackit_beta_public-ip_describe.md | 42 +++ docs/stackit_beta_public-ip_disassociate.md | 39 +++ docs/stackit_beta_public-ip_list.md | 50 ++++ docs/stackit_beta_public-ip_update.md | 43 +++ internal/cmd/beta/beta.go | 2 + .../cmd/beta/public-ip/associate/associate.go | 128 +++++++++ .../public-ip/associate/associate_test.go | 246 ++++++++++++++++++ internal/cmd/beta/public-ip/create/create.go | 165 ++++++++++++ .../cmd/beta/public-ip/create/create_test.go | 215 +++++++++++++++ internal/cmd/beta/public-ip/delete/delete.go | 111 ++++++++ .../cmd/beta/public-ip/delete/delete_test.go | 218 ++++++++++++++++ .../cmd/beta/public-ip/describe/describe.go | 149 +++++++++++ .../beta/public-ip/describe/describe_test.go | 218 ++++++++++++++++ .../public-ip/disassociate/disassociate.go | 115 ++++++++ .../disassociate/disassociate_test.go | 219 ++++++++++++++++ internal/cmd/beta/public-ip/list/list.go | 181 +++++++++++++ internal/cmd/beta/public-ip/list/list_test.go | 204 +++++++++++++++ internal/cmd/beta/public-ip/public-ip.go | 38 +++ internal/cmd/beta/public-ip/update/update.go | 170 ++++++++++++ .../cmd/beta/public-ip/update/update_test.go | 226 ++++++++++++++++ 26 files changed, 2969 insertions(+), 22 deletions(-) create mode 100644 docs/stackit_beta_public-ip.md create mode 100644 docs/stackit_beta_public-ip_associate.md create mode 100644 docs/stackit_beta_public-ip_create.md create mode 100644 docs/stackit_beta_public-ip_delete.md create mode 100644 docs/stackit_beta_public-ip_describe.md create mode 100644 docs/stackit_beta_public-ip_disassociate.md create mode 100644 docs/stackit_beta_public-ip_list.md create mode 100644 docs/stackit_beta_public-ip_update.md create mode 100644 internal/cmd/beta/public-ip/associate/associate.go create mode 100644 internal/cmd/beta/public-ip/associate/associate_test.go create mode 100644 internal/cmd/beta/public-ip/create/create.go create mode 100644 internal/cmd/beta/public-ip/create/create_test.go create mode 100644 internal/cmd/beta/public-ip/delete/delete.go create mode 100644 internal/cmd/beta/public-ip/delete/delete_test.go create mode 100644 internal/cmd/beta/public-ip/describe/describe.go create mode 100644 internal/cmd/beta/public-ip/describe/describe_test.go create mode 100644 internal/cmd/beta/public-ip/disassociate/disassociate.go create mode 100644 internal/cmd/beta/public-ip/disassociate/disassociate_test.go create mode 100644 internal/cmd/beta/public-ip/list/list.go create mode 100644 internal/cmd/beta/public-ip/list/list_test.go create mode 100644 internal/cmd/beta/public-ip/public-ip.go create mode 100644 internal/cmd/beta/public-ip/update/update.go create mode 100644 internal/cmd/beta/public-ip/update/update_test.go diff --git a/README.md b/README.md index eaae8e299..888f2e03d 100644 --- a/README.md +++ b/README.md @@ -65,28 +65,28 @@ Help is available for any command by specifying the special flag `--help` (or si Below you can find a list of the STACKIT services already available in the CLI (along with their respective command names) and the ones that are currently planned to be integrated. -| Service | CLI Commands | Status | -| ---------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------- | -| Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta server` | :white_check_mark: (beta) | -| Authorization | `project`, `organization` | :white_check_mark: | -| DNS | `dns` | :white_check_mark: | -| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | -| Load Balancer | `load-balancer` | :white_check_mark: | -| LogMe | `logme` | :white_check_mark: | -| MariaDB | `mariadb` | :white_check_mark: | -| MongoDB Flex | `mongodbflex` | :white_check_mark: | -| Object Storage | `object-storage` | :white_check_mark: | -| OpenSearch | `opensearch` | :white_check_mark: | -| PostgreSQL Flex | `postgresflex` | :white_check_mark: | -| RabbitMQ | `rabbitmq` | :white_check_mark: | -| Redis | `redis` | :white_check_mark: | -| Resource Manager | `project` | :white_check_mark: | -| Secrets Manager | `secrets-manager` | :white_check_mark: | -| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | -| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | -| Service Account | `service-account` | :white_check_mark: | -| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | +| Service | CLI Commands | Status | +| ---------------------------------- |----------------------------------------------------------------------------------------------------------------------| ------------------------- | +| Observability | `observability` | :white_check_mark: | +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip` | :white_check_mark: (beta) | +| Authorization | `project`, `organization` | :white_check_mark: | +| DNS | `dns` | :white_check_mark: | +| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | +| Load Balancer | `load-balancer` | :white_check_mark: | +| LogMe | `logme` | :white_check_mark: | +| MariaDB | `mariadb` | :white_check_mark: | +| MongoDB Flex | `mongodbflex` | :white_check_mark: | +| Object Storage | `object-storage` | :white_check_mark: | +| OpenSearch | `opensearch` | :white_check_mark: | +| PostgreSQL Flex | `postgresflex` | :white_check_mark: | +| RabbitMQ | `rabbitmq` | :white_check_mark: | +| Redis | `redis` | :white_check_mark: | +| Resource Manager | `project` | :white_check_mark: | +| Secrets Manager | `secrets-manager` | :white_check_mark: | +| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | +| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | +| Service Account | `service-account` | :white_check_mark: | +| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | ## Authentication diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index edc19472c..abc498479 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -43,6 +43,7 @@ stackit beta [flags] * [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) * [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces +* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs * [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex * [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_public-ip.md b/docs/stackit_beta_public-ip.md new file mode 100644 index 000000000..8d4ff0737 --- /dev/null +++ b/docs/stackit_beta_public-ip.md @@ -0,0 +1,39 @@ +## stackit beta public-ip + +Provides functionality for public IPs + +### Synopsis + +Provides functionality for public IPs. + +``` +stackit beta public-ip [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta public-ip" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta public-ip associate](./stackit_beta_public-ip_associate.md) - Associates a Public IP with a network interface or a virtual IP +* [stackit beta public-ip create](./stackit_beta_public-ip_create.md) - Creates a Public IP +* [stackit beta public-ip delete](./stackit_beta_public-ip_delete.md) - Deletes a Public IP +* [stackit beta public-ip describe](./stackit_beta_public-ip_describe.md) - Shows details of a Public IP +* [stackit beta public-ip disassociate](./stackit_beta_public-ip_disassociate.md) - Disassociates a Public IP from a network interface or a virtual IP +* [stackit beta public-ip list](./stackit_beta_public-ip_list.md) - Lists all Public IPs of a project +* [stackit beta public-ip update](./stackit_beta_public-ip_update.md) - Updates a Public IP + diff --git a/docs/stackit_beta_public-ip_associate.md b/docs/stackit_beta_public-ip_associate.md new file mode 100644 index 000000000..7a7cf8788 --- /dev/null +++ b/docs/stackit_beta_public-ip_associate.md @@ -0,0 +1,40 @@ +## stackit beta public-ip associate + +Associates a Public IP with a network interface or a virtual IP + +### Synopsis + +Associates a Public IP with a network interface or a virtual IP. + +``` +stackit beta public-ip associate [flags] +``` + +### Examples + +``` + Associate public IP with ID "xxx" to a resource (network interface or virtual IP) with ID "yyy" + $ stackit beta public-ip associate xxx --associated-resource-id yyy +``` + +### Options + +``` + --associated-resource-id string Associates the public IP with a network interface or virtual IP (ID) + -h, --help Help for "stackit beta public-ip associate" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs + diff --git a/docs/stackit_beta_public-ip_create.md b/docs/stackit_beta_public-ip_create.md new file mode 100644 index 000000000..03399d78e --- /dev/null +++ b/docs/stackit_beta_public-ip_create.md @@ -0,0 +1,47 @@ +## stackit beta public-ip create + +Creates a Public IP + +### Synopsis + +Creates a Public IP. + +``` +stackit beta public-ip create [flags] +``` + +### Examples + +``` + Create a public IP + $ stackit beta public-ip create + + Create a public IP with associated resource ID "xxx" + $ stackit beta public-ip create --associated-resource-id xxx + + Create a public IP with associated resource ID "xxx" and labels + $ stackit beta public-ip create --associated-resource-id xxx --labels key=value,foo=bar +``` + +### Options + +``` + --associated-resource-id string Associates the public IP with a network interface or virtual IP (ID) + -h, --help Help for "stackit beta public-ip create" + --labels stringToString Labels are key-value string pairs which can be attached to a public IP. E.g. '--labels key1=value1,key2=value2,...' (default []) +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs + diff --git a/docs/stackit_beta_public-ip_delete.md b/docs/stackit_beta_public-ip_delete.md new file mode 100644 index 000000000..ef5fb53c0 --- /dev/null +++ b/docs/stackit_beta_public-ip_delete.md @@ -0,0 +1,41 @@ +## stackit beta public-ip delete + +Deletes a Public IP + +### Synopsis + +Deletes a Public IP. +If the public IP is still in use, the deletion will fail + + +``` +stackit beta public-ip delete [flags] +``` + +### Examples + +``` + Delete public IP with ID "xxx" + $ stackit beta public-ip delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta public-ip delete" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs + diff --git a/docs/stackit_beta_public-ip_describe.md b/docs/stackit_beta_public-ip_describe.md new file mode 100644 index 000000000..4a0e85986 --- /dev/null +++ b/docs/stackit_beta_public-ip_describe.md @@ -0,0 +1,42 @@ +## stackit beta public-ip describe + +Shows details of a Public IP + +### Synopsis + +Shows details of a Public IP. + +``` +stackit beta public-ip describe [flags] +``` + +### Examples + +``` + Show details of a public IP with ID "xxx" + $ stackit beta public-ip describe xxx + + Show details of a public IP with ID "xxx" in JSON format + $ stackit beta public-ip describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta public-ip 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs + diff --git a/docs/stackit_beta_public-ip_disassociate.md b/docs/stackit_beta_public-ip_disassociate.md new file mode 100644 index 000000000..65c7cf8ac --- /dev/null +++ b/docs/stackit_beta_public-ip_disassociate.md @@ -0,0 +1,39 @@ +## stackit beta public-ip disassociate + +Disassociates a Public IP from a network interface or a virtual IP + +### Synopsis + +Disassociates a Public IP from a network interface or a virtual IP. + +``` +stackit beta public-ip disassociate [flags] +``` + +### Examples + +``` + Disassociate public IP with ID "xxx" from a resource (network interface or virtual IP) + $ stackit beta public-ip disassociate xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta public-ip disassociate" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs + diff --git a/docs/stackit_beta_public-ip_list.md b/docs/stackit_beta_public-ip_list.md new file mode 100644 index 000000000..7e237c8c8 --- /dev/null +++ b/docs/stackit_beta_public-ip_list.md @@ -0,0 +1,50 @@ +## stackit beta public-ip list + +Lists all Public IPs of a project + +### Synopsis + +Lists all Public IPs of a project. + +``` +stackit beta public-ip list [flags] +``` + +### Examples + +``` + Lists all public IPs + $ stackit beta public-ip list + + Lists all public IPs which contains the label xxx + $ stackit beta public-ip list --label-selector xxx + + Lists all public IPs in JSON format + $ stackit beta public-ip list --output-format json + + Lists up to 10 public IPs + $ stackit beta public-ip list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta public-ip list" + --label-selector string Filter by label + --limit int Maximum number of entries to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs + diff --git a/docs/stackit_beta_public-ip_update.md b/docs/stackit_beta_public-ip_update.md new file mode 100644 index 000000000..37c8ef7ed --- /dev/null +++ b/docs/stackit_beta_public-ip_update.md @@ -0,0 +1,43 @@ +## stackit beta public-ip update + +Updates a Public IP + +### Synopsis + +Updates a Public IP. + +``` +stackit beta public-ip update [flags] +``` + +### Examples + +``` + Update public IP with ID "xxx" + $ stackit beta public-ip update xxx + + Update public IP with ID "xxx" with new labels + $ stackit beta public-ip update xxx --labels key=value,foo=bar +``` + +### Options + +``` + -h, --help Help for "stackit beta public-ip update" + --labels stringToString Labels are key-value string pairs which can be attached to a public IP. E.g. '--labels key1=value1,key2=value2,...' (default []) +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs + diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index ab429fe4f..389c0d614 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -6,6 +6,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network" networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface" + publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume" @@ -46,4 +47,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(network.NewCmd(p)) cmd.AddCommand(volume.NewCmd(p)) cmd.AddCommand(networkinterface.NewCmd(p)) + cmd.AddCommand(publicip.NewCmd(p)) } diff --git a/internal/cmd/beta/public-ip/associate/associate.go b/internal/cmd/beta/public-ip/associate/associate.go new file mode 100644 index 000000000..9e82108e9 --- /dev/null +++ b/internal/cmd/beta/public-ip/associate/associate.go @@ -0,0 +1,128 @@ +package associate + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + publicIpIdArg = "PUBLIC_IP_ID" + + associatedResourceIdFlag = "associated-resource-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + PublicIpId string + AssociatedResourceId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "associate", + Short: "Associates a Public IP with a network interface or a virtual IP", + Long: "Associates a Public IP with a network interface or a virtual IP.", + Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Associate public IP with ID "xxx" to a resource (network interface or virtual IP) with ID "yyy"`, + `$ stackit beta public-ip associate xxx --associated-resource-id yyy`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + if err != nil { + p.Debug(print.ErrorLevel, "get public IP: %v", err) + publicIpLabel = model.PublicIpId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to associate public IP %q with resource %v?", publicIpLabel, *model.AssociatedResourceId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("associate public IP: %w", err) + } + + p.Outputf("Associated public IP %q with resource %v.\n", publicIpLabel, *resp.GetNetworkInterface()) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), associatedResourceIdFlag, "Associates the public IP with a network interface or virtual IP (ID)") + + err := flags.MarkFlagsRequired(cmd, associatedResourceIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + publicIpId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + AssociatedResourceId: flags.FlagToStringPointer(p, cmd, associatedResourceIdFlag), + PublicIpId: publicIpId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdatePublicIPRequest { + req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.PublicIpId) + + payload := iaas.UpdatePublicIPPayload{ + NetworkInterface: iaas.NewNullableString(model.AssociatedResourceId), + } + + return req.UpdatePublicIPPayload(payload) +} diff --git a/internal/cmd/beta/public-ip/associate/associate_test.go b/internal/cmd/beta/public-ip/associate/associate_test.go new file mode 100644 index 000000000..99b51c3e6 --- /dev/null +++ b/internal/cmd/beta/public-ip/associate/associate_test.go @@ -0,0 +1,246 @@ +package associate + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testPublicIpId = uuid.NewString() +var testAssociatedResourceId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testPublicIpId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + associatedResourceIdFlag: testAssociatedResourceId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + PublicIpId: testPublicIpId, + AssociatedResourceId: utils.Ptr(testAssociatedResourceId), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdatePublicIPRequest)) iaas.ApiUpdatePublicIPRequest { + request := testClient.UpdatePublicIP(testCtx, testProjectId, testPublicIpId) + request = request.UpdatePublicIPPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.UpdatePublicIPPayload)) iaas.UpdatePublicIPPayload { + payload := iaas.UpdatePublicIPPayload{ + NetworkInterface: iaas.NewNullableString(utils.Ptr(testAssociatedResourceId)), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "public ip id invalid 1", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "public ip id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "associated resource id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, associatedResourceIdFlag) + }), + isValid: false, + }, + { + description: "associated resource id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[associatedResourceIdFlag] = "" + }), + isValid: false, + }, + { + description: "associated resource id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[associatedResourceIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdatePublicIPRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/public-ip/create/create.go b/internal/cmd/beta/public-ip/create/create.go new file mode 100644 index 000000000..1f2bbe18c --- /dev/null +++ b/internal/cmd/beta/public-ip/create/create.go @@ -0,0 +1,165 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + associatedResourceIdFlag = "associated-resource-id" + labelFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + AssociatedResourceId *string + Labels *map[string]string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a Public IP", + Long: "Creates a Public IP.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a public IP`, + `$ stackit beta public-ip create`, + ), + examples.NewExample( + `Create a public IP with associated resource ID "xxx"`, + `$ stackit beta public-ip create --associated-resource-id xxx`, + ), + examples.NewExample( + `Create a public IP with associated resource ID "xxx" and labels`, + `$ stackit beta public-ip create --associated-resource-id xxx --labels key=value,foo=bar`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a public IP for project %q?", projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create public IP: %w", err) + } + + return outputResult(p, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), associatedResourceIdFlag, "Associates the public IP with a network interface or virtual IP (ID)") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a public IP. E.g. '--labels key1=value1,key2=value2,...'") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + AssociatedResourceId: flags.FlagToStringPointer(p, cmd, associatedResourceIdFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreatePublicIPRequest { + req := apiClient.CreatePublicIP(ctx, model.ProjectId) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + + payload := iaas.CreatePublicIPPayload{ + NetworkInterface: iaas.NewNullableString(model.AssociatedResourceId), + Labels: labelsMap, + } + + return req.CreatePublicIPPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, publicIp *iaas.PublicIp) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(publicIp, "", " ") + if err != nil { + return fmt.Errorf("marshal public IP: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal public IP: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created public IP for project %q.\nPublic IP ID: %s\n", projectLabel, *publicIp.Id) + return nil + } +} diff --git a/internal/cmd/beta/public-ip/create/create_test.go b/internal/cmd/beta/public-ip/create/create_test.go new file mode 100644 index 000000000..7411c0a9f --- /dev/null +++ b/internal/cmd/beta/public-ip/create/create_test.go @@ -0,0 +1,215 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testAssociatedResourceId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + associatedResourceIdFlag: testAssociatedResourceId, + labelFlag: "key=value", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + AssociatedResourceId: utils.Ptr(testAssociatedResourceId), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreatePublicIPRequest)) iaas.ApiCreatePublicIPRequest { + request := testClient.CreatePublicIP(testCtx, testProjectId) + request = request.CreatePublicIPPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreatePublicIPPayload)) iaas.CreatePublicIPPayload { + payload := iaas.CreatePublicIPPayload{ + NetworkInterface: iaas.NewNullableString(utils.Ptr(testAssociatedResourceId)), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, associatedResourceIdFlag) + delete(flagValues, labelFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.AssociatedResourceId = nil + model.Labels = nil + }), + }, + { + description: "valid with associated resource id", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.AssociatedResourceId = utils.Ptr(testAssociatedResourceId) + model.Labels = nil + }), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreatePublicIPRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/public-ip/delete/delete.go b/internal/cmd/beta/public-ip/delete/delete.go new file mode 100644 index 000000000..28e625e23 --- /dev/null +++ b/internal/cmd/beta/public-ip/delete/delete.go @@ -0,0 +1,111 @@ +package delete + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + publicIpIdArg = "PUBLIC_IP_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + PublicIpId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a Public IP", + Long: fmt.Sprintf("%s\n%s\n", + "Deletes a Public IP.", + "If the public IP is still in use, the deletion will fail", + ), + Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete public IP with ID "xxx"`, + "$ stackit beta public-ip delete xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + if err != nil { + p.Debug(print.ErrorLevel, "get public IP: %v", err) + publicIpLabel = model.PublicIpId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete public IP %q? (This cannot be undone)", publicIpLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete public IP: %w", err) + } + + p.Info("Deleted public IP %q\n", model.PublicIpId) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + publicIpId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + PublicIpId: publicIpId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeletePublicIPRequest { + return apiClient.DeletePublicIP(ctx, model.ProjectId, model.PublicIpId) +} diff --git a/internal/cmd/beta/public-ip/delete/delete_test.go b/internal/cmd/beta/public-ip/delete/delete_test.go new file mode 100644 index 000000000..1acd8b016 --- /dev/null +++ b/internal/cmd/beta/public-ip/delete/delete_test.go @@ -0,0 +1,218 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testPublicIpId = uuid.NewString() +var testProjectId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testPublicIpId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + PublicIpId: testPublicIpId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeletePublicIPRequest)) iaas.ApiDeletePublicIPRequest { + request := testClient.DeletePublicIP(testCtx, testProjectId, testPublicIpId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "public ip id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "public ip id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeletePublicIPRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/public-ip/describe/describe.go b/internal/cmd/beta/public-ip/describe/describe.go new file mode 100644 index 000000000..9e47ab890 --- /dev/null +++ b/internal/cmd/beta/public-ip/describe/describe.go @@ -0,0 +1,149 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + publicIpIdArg = "PUBLIC_IP_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + PublicIpId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a Public IP", + Long: "Shows details of a Public IP.", + Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Show details of a public IP with ID "xxx"`, + "$ stackit beta public-ip describe xxx", + ), + examples.NewExample( + `Show details of a public IP with ID "xxx" in JSON format`, + "$ stackit beta public-ip describe xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read public IP: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + publicIpId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + PublicIpId: publicIpId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetPublicIPRequest { + return apiClient.GetPublicIP(ctx, model.ProjectId, model.PublicIpId) +} + +func outputResult(p *print.Printer, outputFormat string, publicIp *iaas.PublicIp) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(publicIp, "", " ") + if err != nil { + return fmt.Errorf("marshal public IP: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal public IP: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *publicIp.Id) + table.AddSeparator() + table.AddRow("IP ADDRESS", *publicIp.Ip) + table.AddSeparator() + + if publicIp.NetworkInterface != nil { + networkInterfaceId := *publicIp.GetNetworkInterface() + table.AddRow("ASSOCIATED TO", networkInterfaceId) + table.AddSeparator() + } + + if publicIp.Labels != nil && len(*publicIp.Labels) > 0 { + labels := []string{} + for key, value := range *publicIp.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/public-ip/describe/describe_test.go b/internal/cmd/beta/public-ip/describe/describe_test.go new file mode 100644 index 000000000..9754de721 --- /dev/null +++ b/internal/cmd/beta/public-ip/describe/describe_test.go @@ -0,0 +1,218 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testPublicIpId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testPublicIpId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + PublicIpId: testPublicIpId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetPublicIPRequest)) iaas.ApiGetPublicIPRequest { + request := testClient.GetPublicIP(testCtx, testProjectId, testPublicIpId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "public ip id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "public ip id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetPublicIPRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/public-ip/disassociate/disassociate.go b/internal/cmd/beta/public-ip/disassociate/disassociate.go new file mode 100644 index 000000000..fe47bcdb0 --- /dev/null +++ b/internal/cmd/beta/public-ip/disassociate/disassociate.go @@ -0,0 +1,115 @@ +package disassociate + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + publicIpIdArg = "PUBLIC_IP_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + PublicIpId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "disassociate", + Short: "Disassociates a Public IP from a network interface or a virtual IP", + Long: "Disassociates a Public IP from a network interface or a virtual IP.", + Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Disassociate public IP with ID "xxx" from a resource (network interface or virtual IP)`, + `$ stackit beta public-ip disassociate xxx`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + publicIpLabel, associatedResourceId, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + if err != nil { + p.Debug(print.ErrorLevel, "get public IP: %v", err) + publicIpLabel = model.PublicIpId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to disassociate public IP %q from the associated resource %q?", publicIpLabel, associatedResourceId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("disassociate public IP: %w", err) + } + + p.Outputf("Disassociated public IP %q from the associated resource %q.\n", publicIpLabel, associatedResourceId) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + publicIpId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + PublicIpId: publicIpId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdatePublicIPRequest { + req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.PublicIpId) + + payload := iaas.UpdatePublicIPPayload{ + NetworkInterface: iaas.NewNullableString(nil), + } + + return req.UpdatePublicIPPayload(payload) +} diff --git a/internal/cmd/beta/public-ip/disassociate/disassociate_test.go b/internal/cmd/beta/public-ip/disassociate/disassociate_test.go new file mode 100644 index 000000000..e4478b0c7 --- /dev/null +++ b/internal/cmd/beta/public-ip/disassociate/disassociate_test.go @@ -0,0 +1,219 @@ +package disassociate + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testPublicIpId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testPublicIpId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + PublicIpId: testPublicIpId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdatePublicIPRequest)) iaas.ApiUpdatePublicIPRequest { + request := testClient.UpdatePublicIP(testCtx, testProjectId, testPublicIpId) + request = request.UpdatePublicIPPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.UpdatePublicIPPayload)) iaas.UpdatePublicIPPayload { + payload := iaas.UpdatePublicIPPayload{ + NetworkInterface: iaas.NewNullableString(nil), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "public ip id invalid 1", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "public ip id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdatePublicIPRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/public-ip/list/list.go b/internal/cmd/beta/public-ip/list/list.go new file mode 100644 index 000000000..4ab82d197 --- /dev/null +++ b/internal/cmd/beta/public-ip/list/list.go @@ -0,0 +1,181 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + labelSelectorFlag = "label-selector" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + LabelSelector *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all Public IPs of a project", + Long: "Lists all Public IPs of a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all public IPs`, + "$ stackit beta public-ip list", + ), + examples.NewExample( + `Lists all public IPs which contains the label xxx`, + "$ stackit beta public-ip list --label-selector xxx", + ), + examples.NewExample( + `Lists all public IPs in JSON format`, + "$ stackit beta public-ip list --output-format json", + ), + examples.NewExample( + `Lists up to 10 public IPs`, + "$ stackit beta public-ip list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list public IPs: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + p.Info("No public IPs found for project %q\n", projectLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListPublicIPsRequest { + req := apiClient.ListPublicIPs(ctx, model.ProjectId) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + + return req +} + +func outputResult(p *print.Printer, outputFormat string, publicIps []iaas.PublicIp) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(publicIps, "", " ") + if err != nil { + return fmt.Errorf("marshal public IP: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(publicIps, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal public IP: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "IP ADDRESS", "USED BY") + + for _, publicIp := range publicIps { + networkInterfaceId := "" + if publicIp.NetworkInterface != nil { + networkInterfaceId = *publicIp.GetNetworkInterface() + } + table.AddRow(*publicIp.Id, *publicIp.Ip, networkInterfaceId) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/public-ip/list/list_test.go b/internal/cmd/beta/public-ip/list/list_test.go new file mode 100644 index 000000000..b7f39f61d --- /dev/null +++ b/internal/cmd/beta/public-ip/list/list_test.go @@ -0,0 +1,204 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testLabelSelector = "label" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + labelSelectorFlag: testLabelSelector, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr(testLabelSelector), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListPublicIPsRequest)) iaas.ApiListPublicIPsRequest { + request := testClient.ListPublicIPs(testCtx, testProjectId) + request = request.LabelSelector(testLabelSelector) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListPublicIPsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/public-ip/public-ip.go b/internal/cmd/beta/public-ip/public-ip.go new file mode 100644 index 000000000..5c5c8f410 --- /dev/null +++ b/internal/cmd/beta/public-ip/public-ip.go @@ -0,0 +1,38 @@ +package publicip + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/associate" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/disassociate" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "public-ip", + Short: "Provides functionality for public IPs", + Long: "Provides functionality for public IPs.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) + cmd.AddCommand(associate.NewCmd(p)) + cmd.AddCommand(disassociate.NewCmd(p)) +} diff --git a/internal/cmd/beta/public-ip/update/update.go b/internal/cmd/beta/public-ip/update/update.go new file mode 100644 index 000000000..ff7899e89 --- /dev/null +++ b/internal/cmd/beta/public-ip/update/update.go @@ -0,0 +1,170 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + publicIpIdArg = "PUBLIC_IP_ID" + + labelFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + PublicIpId string + Labels *map[string]string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a Public IP", + Long: "Updates a Public IP.", + Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update public IP with ID "xxx"`, + `$ stackit beta public-ip update xxx`, + ), + examples.NewExample( + `Update public IP with ID "xxx" with new labels`, + `$ stackit beta public-ip update xxx --labels key=value,foo=bar`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + if err != nil { + p.Debug(print.ErrorLevel, "get public IP: %v", err) + publicIpLabel = model.PublicIpId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update public IP %q?", publicIpLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update public IP: %w", err) + } + + return outputResult(p, model, publicIpLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a public IP. E.g. '--labels key1=value1,key2=value2,...'") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + publicIpId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + labels := flags.FlagToStringToStringPointer(p, cmd, labelFlag) + + if labels == nil { + return nil, &errors.EmptyUpdateError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + PublicIpId: publicIpId, + Labels: labels, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdatePublicIPRequest { + req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.PublicIpId) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + + payload := iaas.UpdatePublicIPPayload{ + Labels: labelsMap, + } + + return req.UpdatePublicIPPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, publicIpLabel string, publicIp *iaas.PublicIp) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(publicIp, "", " ") + if err != nil { + return fmt.Errorf("marshal public IP: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal public IP: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Updated public IP %q.\n", publicIpLabel) + return nil + } +} diff --git a/internal/cmd/beta/public-ip/update/update_test.go b/internal/cmd/beta/public-ip/update/update_test.go new file mode 100644 index 000000000..9590a858a --- /dev/null +++ b/internal/cmd/beta/public-ip/update/update_test.go @@ -0,0 +1,226 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testPublicIpId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testPublicIpId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + labelFlag: "key=value", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + PublicIpId: testPublicIpId, + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdatePublicIPRequest)) iaas.ApiUpdatePublicIPRequest { + request := testClient.UpdatePublicIP(testCtx, testProjectId, testPublicIpId) + request = request.UpdatePublicIPPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.UpdatePublicIPPayload)) iaas.UpdatePublicIPPayload { + payload := iaas.UpdatePublicIPPayload{ + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "public ip id invalid 1", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "public ip id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdatePublicIPRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} From ad62c1ebd87ba6bc48b8585106bee6a0d828a511 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:16:20 +0100 Subject: [PATCH 106/619] Extend network commands with new fields (#517) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * extend network commands with new fields * change payload handling for create and update * edit flag descriptions in create and update command * fix flag names * remove routed from the updated * change routed handling in describe output * update descriptions * replace routed flag with non-routed to align with api values * set default values of routed to true * Update internal/cmd/beta/network/create/create_test.go Co-authored-by: João Palet * extend unit tests * set routed values to false * fix: Fix output of async network creation --------- Co-authored-by: João Palet Co-authored-by: test.test@freiheit.com --- docs/stackit_beta_network_create.md | 25 ++- docs/stackit_beta_network_update.md | 19 +- internal/cmd/beta/network/create/create.go | 80 +++++++- .../cmd/beta/network/create/create_test.go | 171 +++++++++++++++++- .../cmd/beta/network/describe/describe.go | 19 ++ internal/cmd/beta/network/list/list.go | 9 +- internal/cmd/beta/network/update/update.go | 48 ++++- .../cmd/beta/network/update/update_test.go | 41 ++++- 8 files changed, 372 insertions(+), 40 deletions(-) diff --git a/docs/stackit_beta_network_create.md b/docs/stackit_beta_network_create.md index 954e64688..6b7df5370 100644 --- a/docs/stackit_beta_network_create.md +++ b/docs/stackit_beta_network_create.md @@ -16,22 +16,35 @@ stackit beta network create [flags] Create a network with name "network-1" $ stackit beta network create --name network-1 - Create an IPv4 network with name "network-1" with DNS name servers and a prefix length - $ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix-length 25 + Create a non-routed network with name "network-1" + $ stackit beta network create --name network-1 --non-routed - Create an IPv6 network with name "network-1" with DNS name servers and a prefix length - $ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix-length 56 + Create a network with name "network-1" and no gateway + $ stackit beta network create --name network-1 --no-ipv4-gateway + + Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway + $ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3" + + Create an IPv6 network with name "network-1" with DNS name servers, a prefix and a gateway + $ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888" ``` ### Options ``` -h, --help Help for "stackit beta network create" - --ipv4-dns-name-servers strings List of DNS name servers for IPv4 + --ipv4-dns-name-servers strings List of DNS name servers for IPv4. Nameservers cannot be defined for routed networks + --ipv4-gateway string The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway + --ipv4-prefix string The IPv4 prefix of the network (CIDR) --ipv4-prefix-length int The prefix length of the IPv4 network - --ipv6-dns-name-servers strings List of DNS name servers for IPv6 + --ipv6-dns-name-servers strings List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks + --ipv6-gateway string The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway + --ipv6-prefix string The IPv6 prefix of the network (CIDR) --ipv6-prefix-length int The prefix length of the IPv6 network -n, --name string Network name + --no-ipv4-gateway If set to true, the network doesn't have an IPv4 gateway + --no-ipv6-gateway If set to true, the network doesn't have an IPv6 gateway + --non-routed If set to true, the network is not routed and therefore not accessible from other networks ``` ### Options inherited from parent commands diff --git a/docs/stackit_beta_network_update.md b/docs/stackit_beta_network_update.md index 4afaa9d6d..9f14775bd 100644 --- a/docs/stackit_beta_network_update.md +++ b/docs/stackit_beta_network_update.md @@ -16,20 +16,27 @@ stackit beta network update [flags] Update network with ID "xxx" with new name "network-1-new" $ stackit beta network update xxx --name network-1-new - Update IPv4 network with ID "xxx" with new name "network-1-new" and new DNS name servers - $ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" + Update network with ID "xxx" with no gateway + $ stackit beta network update --no-ipv4-gateway - Update IPv6 network with ID "xxx" with new name "network-1-new" and new DNS name servers - $ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" + Update IPv4 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers + $ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" --ipv4-gateway "10.1.2.3" + + Update IPv6 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers + $ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888" ``` ### Options ``` -h, --help Help for "stackit beta network update" - --ipv4-dns-name-servers strings List of DNS name servers IPv4 - --ipv6-dns-name-servers strings List of DNS name servers for IPv6 + --ipv4-dns-name-servers strings List of DNS name servers IPv4. Nameservers cannot be defined for routed networks + --ipv4-gateway string The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway + --ipv6-dns-name-servers strings List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks + --ipv6-gateway string The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway -n, --name string Network name + --no-ipv4-gateway If set to true, the network doesn't have an IPv4 gateway + --no-ipv6-gateway If set to true, the network doesn't have an IPv6 gateway ``` ### Options inherited from parent commands diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go index c057098ec..74abb08a4 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/beta/network/create/create.go @@ -25,8 +25,15 @@ const ( nameFlag = "name" ipv4DnsNameServersFlag = "ipv4-dns-name-servers" ipv4PrefixLengthFlag = "ipv4-prefix-length" + ipv4PrefixFlag = "ipv4-prefix" + ipv4GatewayFlag = "ipv4-gateway" ipv6DnsNameServersFlag = "ipv6-dns-name-servers" ipv6PrefixLengthFlag = "ipv6-prefix-length" + ipv6PrefixFlag = "ipv6-prefix" + ipv6GatewayFlag = "ipv6-gateway" + nonRoutedFlag = "non-routed" + noIpv4GatewayFlag = "no-ipv4-gateway" + noIpv6GatewayFlag = "no-ipv6-gateway" ) type inputModel struct { @@ -34,8 +41,15 @@ type inputModel struct { Name *string IPv4DnsNameServers *[]string IPv4PrefixLength *int64 + IPv4Prefix *string + IPv4Gateway *string IPv6DnsNameServers *[]string IPv6PrefixLength *int64 + IPv6Prefix *string + IPv6Gateway *string + NonRouted bool + NoIPv4Gateway bool + NoIPv6Gateway bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -50,12 +64,20 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit beta network create --name network-1`, ), examples.NewExample( - `Create an IPv4 network with name "network-1" with DNS name servers and a prefix length`, - `$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix-length 25`, + `Create a non-routed network with name "network-1"`, + `$ stackit beta network create --name network-1 --non-routed`, ), examples.NewExample( - `Create an IPv6 network with name "network-1" with DNS name servers and a prefix length`, - `$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix-length 56`, + `Create a network with name "network-1" and no gateway`, + `$ stackit beta network create --name network-1 --no-ipv4-gateway`, + ), + examples.NewExample( + `Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway`, + `$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3"`, + ), + examples.NewExample( + `Create an IPv6 network with name "network-1" with DNS name servers, a prefix and a gateway`, + `$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { @@ -113,10 +135,17 @@ func NewCmd(p *print.Printer) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(nameFlag, "n", "", "Network name") - cmd.Flags().StringSlice(ipv4DnsNameServersFlag, []string{}, "List of DNS name servers for IPv4") + cmd.Flags().StringSlice(ipv4DnsNameServersFlag, []string{}, "List of DNS name servers for IPv4. Nameservers cannot be defined for routed networks") cmd.Flags().Int64(ipv4PrefixLengthFlag, 0, "The prefix length of the IPv4 network") - cmd.Flags().StringSlice(ipv6DnsNameServersFlag, []string{}, "List of DNS name servers for IPv6") + cmd.Flags().String(ipv4PrefixFlag, "", "The IPv4 prefix of the network (CIDR)") + cmd.Flags().String(ipv4GatewayFlag, "", "The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway") + cmd.Flags().StringSlice(ipv6DnsNameServersFlag, []string{}, "List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks") cmd.Flags().Int64(ipv6PrefixLengthFlag, 0, "The prefix length of the IPv6 network") + cmd.Flags().String(ipv6PrefixFlag, "", "The IPv6 prefix of the network (CIDR)") + cmd.Flags().String(ipv6GatewayFlag, "", "The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway") + cmd.Flags().Bool(nonRoutedFlag, false, "If set to true, the network is not routed and therefore not accessible from other networks") + cmd.Flags().Bool(noIpv4GatewayFlag, false, "If set to true, the network doesn't have an IPv4 gateway") + cmd.Flags().Bool(noIpv6GatewayFlag, false, "If set to true, the network doesn't have an IPv6 gateway") err := flags.MarkFlagsRequired(cmd, nameFlag) cobra.CheckErr(err) @@ -133,8 +162,15 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Name: flags.FlagToStringPointer(p, cmd, nameFlag), IPv4DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv4DnsNameServersFlag), IPv4PrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4PrefixLengthFlag), + IPv4Prefix: flags.FlagToStringPointer(p, cmd, ipv4PrefixFlag), + IPv4Gateway: flags.FlagToStringPointer(p, cmd, ipv4GatewayFlag), IPv6DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv6DnsNameServersFlag), IPv6PrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv6PrefixLengthFlag), + IPv6Prefix: flags.FlagToStringPointer(p, cmd, ipv6PrefixFlag), + IPv6Gateway: flags.FlagToStringPointer(p, cmd, ipv6GatewayFlag), + NonRouted: flags.FlagToBoolValue(p, cmd, nonRoutedFlag), + NoIPv4Gateway: flags.FlagToBoolValue(p, cmd, noIpv4GatewayFlag), + NoIPv6Gateway: flags.FlagToBoolValue(p, cmd, noIpv6GatewayFlag), } if p.IsVerbosityDebug() { @@ -153,22 +189,42 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli req := apiClient.CreateNetwork(ctx, model.ProjectId) addressFamily := &iaas.CreateNetworkAddressFamily{} - if model.IPv6DnsNameServers != nil || model.IPv6PrefixLength != nil { + if model.IPv6DnsNameServers != nil || model.IPv6PrefixLength != nil || model.IPv6Prefix != nil || model.NoIPv6Gateway || model.IPv6Gateway != nil { addressFamily.Ipv6 = &iaas.CreateNetworkIPv6Body{ Nameservers: model.IPv6DnsNameServers, PrefixLength: model.IPv6PrefixLength, + Prefix: model.IPv6Prefix, + } + + if model.NoIPv6Gateway { + addressFamily.Ipv6.Gateway = iaas.NewNullableString(nil) + } else if model.IPv6Gateway != nil { + addressFamily.Ipv6.Gateway = iaas.NewNullableString(model.IPv6Gateway) } } - if model.IPv4DnsNameServers != nil || model.IPv4PrefixLength != nil { + if model.IPv4DnsNameServers != nil || model.IPv4PrefixLength != nil || model.IPv4Prefix != nil || model.NoIPv4Gateway || model.IPv4Gateway != nil { addressFamily.Ipv4 = &iaas.CreateNetworkIPv4Body{ Nameservers: model.IPv4DnsNameServers, PrefixLength: model.IPv4PrefixLength, + Prefix: model.IPv4Prefix, + } + + if model.NoIPv4Gateway { + addressFamily.Ipv4.Gateway = iaas.NewNullableString(nil) + } else if model.IPv4Gateway != nil { + addressFamily.Ipv4.Gateway = iaas.NewNullableString(model.IPv4Gateway) } } + routed := true + if model.NonRouted { + routed = false + } + payload := iaas.CreateNetworkPayload{ - Name: model.Name, + Name: model.Name, + Routed: &routed, } if addressFamily.Ipv4 != nil || addressFamily.Ipv6 != nil { @@ -197,7 +253,11 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, netw return nil default: - p.Outputf("Created network for project %q.\nNetwork ID: %s\n", projectLabel, *network.NetworkId) + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s network for project %q.\nNetwork ID: %s\n", operationState, projectLabel, *network.NetworkId) return nil } } diff --git a/internal/cmd/beta/network/create/create_test.go b/internal/cmd/beta/network/create/create_test.go index d1284558d..2cd2d606e 100644 --- a/internal/cmd/beta/network/create/create_test.go +++ b/internal/cmd/beta/network/create/create_test.go @@ -29,8 +29,13 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st nameFlag: "example-network-name", ipv4DnsNameServersFlag: "1.1.1.0,1.1.2.0", ipv4PrefixLengthFlag: "24", + ipv4PrefixFlag: "10.1.2.0/24", + ipv4GatewayFlag: "10.1.2.3", ipv6DnsNameServersFlag: "2001:4860:4860::8888,2001:4860:4860::8844", ipv6PrefixLengthFlag: "24", + ipv6PrefixFlag: "2001:4860:4860::8888", + ipv6GatewayFlag: "2001:4860:4860::8888", + nonRoutedFlag: "false", } for _, mod := range mods { mod(flagValues) @@ -47,8 +52,13 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Name: utils.Ptr("example-network-name"), IPv4DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), IPv4PrefixLength: utils.Ptr(int64(24)), + IPv4Prefix: utils.Ptr("10.1.2.0/24"), + IPv4Gateway: utils.Ptr("10.1.2.3"), IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), IPv6PrefixLength: utils.Ptr(int64(24)), + IPv6Prefix: utils.Ptr("2001:4860:4860::8888"), + IPv6Gateway: utils.Ptr("2001:4860:4860::8888"), + NonRouted: false, } for _, mod := range mods { mod(model) @@ -68,7 +78,8 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.Ap func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.ApiCreateNetworkRequest { request := testClient.CreateNetwork(testCtx, testProjectId) request = request.CreateNetworkPayload(iaas.CreateNetworkPayload{ - Name: utils.Ptr("example-network-name"), + Name: utils.Ptr("example-network-name"), + Routed: utils.Ptr(true), }) for _, mod := range mods { mod(&request) @@ -78,15 +89,20 @@ func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) func fixturePayload(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.CreateNetworkPayload { payload := iaas.CreateNetworkPayload{ - Name: utils.Ptr("example-network-name"), + Name: utils.Ptr("example-network-name"), + Routed: utils.Ptr(true), AddressFamily: &iaas.CreateNetworkAddressFamily{ Ipv4: &iaas.CreateNetworkIPv4Body{ Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), PrefixLength: utils.Ptr(int64(24)), + Prefix: utils.Ptr("10.1.2.0/24"), + Gateway: iaas.NewNullableString(utils.Ptr("10.1.2.3")), }, Ipv6: &iaas.CreateNetworkIPv6Body{ Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), PrefixLength: utils.Ptr(int64(24)), + Prefix: utils.Ptr("2001:4860:4860::8888"), + Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")), }, }, } @@ -155,27 +171,69 @@ func TestParseInput(t *testing.T) { isValid: false, }, { - description: "use dns servers and prefix", + description: "use dns servers, prefix, gateway and prefix length", flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[ipv4DnsNameServersFlag] = "1.1.1.1" flagValues[ipv4PrefixLengthFlag] = "25" + flagValues[ipv4PrefixFlag] = "10.1.2.0/24" + flagValues[ipv4GatewayFlag] = "10.1.2.3" }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { model.IPv4DnsNameServers = utils.Ptr([]string{"1.1.1.1"}) model.IPv4PrefixLength = utils.Ptr(int64(25)) + model.IPv4Prefix = utils.Ptr("10.1.2.0/24") + model.IPv4Gateway = utils.Ptr("10.1.2.3") }), }, { - description: "use ipv6 dns servers and prefix", + description: "use ipv4 gateway nil", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[noIpv4GatewayFlag] = "true" + delete(flagValues, ipv4GatewayFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NoIPv4Gateway = true + model.IPv4Gateway = nil + }), + }, + { + description: "use ipv6 dns servers, prefix, gateway and prefix length", flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[ipv6DnsNameServersFlag] = "2001:4860:4860::8888" flagValues[ipv6PrefixLengthFlag] = "25" + flagValues[ipv6PrefixFlag] = "2001:4860:4860::8888" + flagValues[ipv6GatewayFlag] = "2001:4860:4860::8888" }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { model.IPv6DnsNameServers = utils.Ptr([]string{"2001:4860:4860::8888"}) model.IPv6PrefixLength = utils.Ptr(int64(25)) + model.IPv6Prefix = utils.Ptr("2001:4860:4860::8888") + model.IPv6Gateway = utils.Ptr("2001:4860:4860::8888") + }), + }, + { + description: "use ipv6 gateway nil", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[noIpv6GatewayFlag] = "true" + delete(flagValues, ipv6GatewayFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NoIPv6Gateway = true + model.IPv6Gateway = nil + }), + }, + { + description: "non-routed network", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nonRoutedFlag] = "true" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NonRouted = true }), }, } @@ -227,7 +285,7 @@ func TestParseInput(t *testing.T) { } func TestBuildRequest(t *testing.T) { - tests := []struct { + var tests = []struct { description string model *inputModel expectedRequest iaas.ApiCreateNetworkRequest @@ -248,8 +306,108 @@ func TestBuildRequest(t *testing.T) { }, expectedRequest: fixtureRequiredRequest(), }, + { + description: "non-routed network", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr("example-network-name"), + NonRouted: true, + }, + expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ + Name: utils.Ptr("example-network-name"), + Routed: utils.Ptr(false), + }), + }, + { + description: "use dns servers, prefix, gateway and prefix length", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + IPv4DnsNameServers: utils.Ptr([]string{"1.1.1.1"}), + IPv4PrefixLength: utils.Ptr(int64(25)), + IPv4Prefix: utils.Ptr("10.1.2.0/24"), + IPv4Gateway: utils.Ptr("10.1.2.3"), + }, + expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ + AddressFamily: &iaas.CreateNetworkAddressFamily{ + Ipv4: &iaas.CreateNetworkIPv4Body{ + Nameservers: utils.Ptr([]string{"1.1.1.1"}), + PrefixLength: utils.Ptr(int64(25)), + Prefix: utils.Ptr("10.1.2.0/24"), + Gateway: iaas.NewNullableString(utils.Ptr("10.1.2.3")), + }, + }, + Routed: utils.Ptr(true), + }), + }, + { + description: "use ipv4 gateway nil", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + NoIPv4Gateway: true, + IPv4Gateway: nil, + }, + expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ + AddressFamily: &iaas.CreateNetworkAddressFamily{ + Ipv4: &iaas.CreateNetworkIPv4Body{ + Gateway: iaas.NewNullableString(nil), + }, + }, + Routed: utils.Ptr(true), + }), + }, + { + description: "use ipv6 dns servers, prefix, gateway and prefix length", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888"}), + IPv6PrefixLength: utils.Ptr(int64(25)), + IPv6Prefix: utils.Ptr("2001:4860:4860::8888"), + IPv6Gateway: utils.Ptr("2001:4860:4860::8888"), + }, + expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ + AddressFamily: &iaas.CreateNetworkAddressFamily{ + Ipv6: &iaas.CreateNetworkIPv6Body{ + Nameservers: utils.Ptr([]string{"2001:4860:4860::8888"}), + PrefixLength: utils.Ptr(int64(25)), + Prefix: utils.Ptr("2001:4860:4860::8888"), + Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")), + }, + }, + Routed: utils.Ptr(true), + }), + }, + { + description: "use ipv6 gateway nil", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + NoIPv6Gateway: true, + IPv6Gateway: nil, + }, + expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ + AddressFamily: &iaas.CreateNetworkAddressFamily{ + Ipv6: &iaas.CreateNetworkIPv6Body{ + Gateway: iaas.NewNullableString(nil), + }, + }, + Routed: utils.Ptr(true), + }), + }, } - for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { request := buildRequest(testCtx, tt.model, testClient) @@ -257,6 +415,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/beta/network/describe/describe.go index bbd2a3fa4..854fd65b0 100644 --- a/internal/cmd/beta/network/describe/describe.go +++ b/internal/cmd/beta/network/describe/describe.go @@ -152,6 +152,19 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) table.AddSeparator() } + routed := false + if network.Routed != nil { + routed = *network.Routed + } + + table.AddRow("ROUTED", routed) + table.AddSeparator() + + if network.Gateway != nil { + table.AddRow("IPv4 GATEWAY", *network.Gateway.Get()) + table.AddSeparator() + } + if len(ipv4nameservers) > 0 { table.AddRow("IPv4 NAME SERVERS", strings.Join(ipv4nameservers, ", ")) } @@ -160,6 +173,12 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) table.AddRow("IPv4 PREFIXES", strings.Join(ipv4prefixes, ", ")) } table.AddSeparator() + + if network.Gatewayv6 != nil { + table.AddRow("IPv6 GATEWAY", *network.Gatewayv6.Get()) + table.AddSeparator() + } + if len(ipv6nameservers) > 0 { table.AddRow("IPv6 NAME SERVERS", strings.Join(ipv6nameservers, ", ")) } diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index af91a4a1c..889f9e307 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -151,7 +151,7 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network return nil default: table := tables.NewTable() - table.SetHeader("ID", "Name", "Status", "Public IP") + table.SetHeader("ID", "NAME", "STATUS", "PUBLIC IP", "ROUTED") for _, network := range networks { publicIp := "" @@ -159,7 +159,12 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network publicIp = *network.PublicIp } - table.AddRow(*network.NetworkId, *network.Name, *network.State, publicIp) + routed := false + if network.Routed != nil { + routed = *network.Routed + } + + table.AddRow(*network.NetworkId, *network.Name, *network.State, publicIp, routed) table.AddSeparator() } diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/beta/network/update/update.go index 748828778..710205cd7 100644 --- a/internal/cmd/beta/network/update/update.go +++ b/internal/cmd/beta/network/update/update.go @@ -25,7 +25,11 @@ const ( nameFlag = "name" ipv4DnsNameServersFlag = "ipv4-dns-name-servers" + ipv4GatewayFlag = "ipv4-gateway" ipv6DnsNameServersFlag = "ipv6-dns-name-servers" + ipv6GatewayFlag = "ipv6-gateway" + noIpv4GatewayFlag = "no-ipv4-gateway" + noIpv6GatewayFlag = "no-ipv6-gateway" ) type inputModel struct { @@ -33,7 +37,11 @@ type inputModel struct { NetworkId string Name *string IPv4DnsNameServers *[]string + IPv4Gateway *string IPv6DnsNameServers *[]string + IPv6Gateway *string + NoIPv4Gateway bool + NoIPv6Gateway bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -48,12 +56,16 @@ func NewCmd(p *print.Printer) *cobra.Command { `$ stackit beta network update xxx --name network-1-new`, ), examples.NewExample( - `Update IPv4 network with ID "xxx" with new name "network-1-new" and new DNS name servers`, - `$ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2"`, + `Update network with ID "xxx" with no gateway`, + `$ stackit beta network update --no-ipv4-gateway`, ), examples.NewExample( - `Update IPv6 network with ID "xxx" with new name "network-1-new" and new DNS name servers`, - `$ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888"`, + `Update IPv4 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers`, + `$ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" --ipv4-gateway "10.1.2.3"`, + ), + examples.NewExample( + `Update IPv6 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers`, + `$ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"`, ), ), RunE: func(cmd *cobra.Command, args []string) error { @@ -116,8 +128,12 @@ func NewCmd(p *print.Printer) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(nameFlag, "n", "", "Network name") - cmd.Flags().StringSlice(ipv4DnsNameServersFlag, nil, "List of DNS name servers IPv4") - cmd.Flags().StringSlice(ipv6DnsNameServersFlag, nil, "List of DNS name servers for IPv6") + cmd.Flags().StringSlice(ipv4DnsNameServersFlag, nil, "List of DNS name servers IPv4. Nameservers cannot be defined for routed networks") + cmd.Flags().String(ipv4GatewayFlag, "", "The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway") + cmd.Flags().StringSlice(ipv6DnsNameServersFlag, nil, "List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks") + cmd.Flags().String(ipv6GatewayFlag, "", "The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway") + cmd.Flags().Bool(noIpv4GatewayFlag, false, "If set to true, the network doesn't have an IPv4 gateway") + cmd.Flags().Bool(noIpv6GatewayFlag, false, "If set to true, the network doesn't have an IPv6 gateway") } func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { @@ -133,7 +149,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Name: flags.FlagToStringPointer(p, cmd, nameFlag), NetworkId: networkId, IPv4DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv4DnsNameServersFlag), + IPv4Gateway: flags.FlagToStringPointer(p, cmd, ipv4GatewayFlag), IPv6DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv6DnsNameServersFlag), + IPv6Gateway: flags.FlagToStringPointer(p, cmd, ipv6GatewayFlag), + NoIPv4Gateway: flags.FlagToBoolValue(p, cmd, noIpv4GatewayFlag), + NoIPv6Gateway: flags.FlagToBoolValue(p, cmd, noIpv6GatewayFlag), } if p.IsVerbosityDebug() { @@ -152,16 +172,28 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli req := apiClient.PartialUpdateNetwork(ctx, model.ProjectId, model.NetworkId) addressFamily := &iaas.UpdateNetworkAddressFamily{} - if model.IPv6DnsNameServers != nil { + if model.IPv6DnsNameServers != nil || model.NoIPv6Gateway || model.IPv6Gateway != nil { addressFamily.Ipv6 = &iaas.UpdateNetworkIPv6Body{ Nameservers: model.IPv6DnsNameServers, } + + if model.NoIPv6Gateway { + addressFamily.Ipv6.Gateway = iaas.NewNullableString(nil) + } else if model.IPv6Gateway != nil { + addressFamily.Ipv6.Gateway = iaas.NewNullableString(model.IPv6Gateway) + } } - if model.IPv4DnsNameServers != nil { + if model.IPv4DnsNameServers != nil || model.NoIPv4Gateway || model.IPv4Gateway != nil { addressFamily.Ipv4 = &iaas.UpdateNetworkIPv4Body{ Nameservers: model.IPv4DnsNameServers, } + + if model.NoIPv4Gateway { + addressFamily.Ipv4.Gateway = iaas.NewNullableString(nil) + } else if model.IPv4Gateway != nil { + addressFamily.Ipv4.Gateway = iaas.NewNullableString(model.IPv4Gateway) + } } payload := iaas.PartialUpdateNetworkPayload{ diff --git a/internal/cmd/beta/network/update/update_test.go b/internal/cmd/beta/network/update/update_test.go index bc2c28e4e..99b3e8ba6 100644 --- a/internal/cmd/beta/network/update/update_test.go +++ b/internal/cmd/beta/network/update/update_test.go @@ -39,7 +39,9 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st nameFlag: "example-network-name", projectIdFlag: testProjectId, ipv4DnsNameServersFlag: "1.1.1.0,1.1.2.0", + ipv4GatewayFlag: "10.1.2.3", ipv6DnsNameServersFlag: "2001:4860:4860::8888,2001:4860:4860::8844", + ipv6GatewayFlag: "2001:4860:4860::8888", } for _, mod := range mods { mod(flagValues) @@ -56,7 +58,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Name: utils.Ptr("example-network-name"), NetworkId: testNetworkId, IPv4DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + IPv4Gateway: utils.Ptr("10.1.2.3"), IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), + IPv6Gateway: utils.Ptr("2001:4860:4860::8888"), } for _, mod := range mods { mod(model) @@ -79,9 +83,11 @@ func fixturePayload(mods ...func(payload *iaas.PartialUpdateNetworkPayload)) iaa AddressFamily: &iaas.UpdateNetworkAddressFamily{ Ipv4: &iaas.UpdateNetworkIPv4Body{ Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + Gateway: iaas.NewNullableString(utils.Ptr("10.1.2.3")), }, Ipv6: &iaas.UpdateNetworkIPv6Body{ Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), + Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")), }, }, } @@ -161,25 +167,55 @@ func TestParseInput(t *testing.T) { isValid: false, }, { - description: "use dns servers and prefix", + description: "use dns servers and gateway", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[ipv4DnsNameServersFlag] = "1.1.1.1" + flagValues[ipv4GatewayFlag] = "10.1.2.3" }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { model.IPv4DnsNameServers = utils.Ptr([]string{"1.1.1.1"}) + model.IPv4Gateway = utils.Ptr("10.1.2.3") }), }, { - description: "use ipv6 dns servers and prefix", + description: "use ipv4 gateway nil", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[noIpv4GatewayFlag] = "true" + delete(flagValues, ipv4GatewayFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NoIPv4Gateway = true + model.IPv4Gateway = nil + }), + }, + { + description: "use ipv6 dns servers and gateway", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[ipv6DnsNameServersFlag] = "2001:4860:4860::8888" + flagValues[ipv6GatewayFlag] = "2001:4860:4860::8888" }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { model.IPv6DnsNameServers = utils.Ptr([]string{"2001:4860:4860::8888"}) + model.IPv6Gateway = utils.Ptr("2001:4860:4860::8888") + }), + }, + { + description: "use ipv6 gateway nil", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[noIpv6GatewayFlag] = "true" + delete(flagValues, ipv6GatewayFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NoIPv6Gateway = true + model.IPv6Gateway = nil }), }, } @@ -258,6 +294,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) From f6c73fa787afe856fe8a5c1a0d5bc49e524768e5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:57:36 +0100 Subject: [PATCH 107/619] fix(deps): update kubernetes packages to v0.31.3 (#478) Co-authored-by: Renovate Bot --- go.mod | 16 +++++++++------- go.sum | 53 ++++++++++++++++++++++++++++------------------------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/go.mod b/go.mod index a567a8d87..aaeab5810 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( golang.org/x/oauth2 v0.24.0 golang.org/x/term v0.26.0 golang.org/x/text v0.20.0 - k8s.io/apimachinery v0.29.2 - k8s.io/client-go v0.29.2 + k8s.io/apimachinery v0.31.3 + k8s.io/client-go v0.31.3 ) require ( @@ -47,7 +47,9 @@ require ( require ( al.essio.dev/pkg/shellescape v1.5.1 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/x448/float16 v0.8.4 // indirect ) require ( @@ -55,7 +57,7 @@ require ( github.com/danieljoos/wincred v1.2.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -90,10 +92,10 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.29.2 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + k8s.io/api v0.31.3 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 3fd20ab88..f3983c4f3 100644 --- a/go.sum +++ b/go.sum @@ -16,15 +16,16 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/goccy/go-yaml v1.15.1 h1:1vwC1ZjDzXyiMUKf7kKPazc6WUm4xnHGxNlzj4BIVu0= github.com/goccy/go-yaml v1.15.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -33,8 +34,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -97,8 +98,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -174,6 +175,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s= @@ -223,8 +226,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -238,21 +241,21 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= -k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= -k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= -k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= -k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= -k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= +k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= +k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= +k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= +k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From e5486948c44908cbc3b3591f9490d6b5e046e288 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:02:31 +0100 Subject: [PATCH 108/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.6.3 (#516) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index aaeab5810..ad49ae4f3 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.2 + github.com/jedib0t/go-pretty/v6 v6.6.3 github.com/lmittmann/tint v1.0.5 github.com/mattn/go-colorable v0.1.13 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index f3983c4f3..613849eb1 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.2 h1:27bLj3nRODzaiA7tPIxy9UVWHoPspFfME9XxgwiiNsM= -github.com/jedib0t/go-pretty/v6 v6.6.2/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.3 h1:nGqgS0tgIO1Hto47HSaaK4ac/I/Bu7usmdD3qvs0WvM= +github.com/jedib0t/go-pretty/v6 v6.6.3/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= From 4d04901277bd78a381b7d2b5098deb8e92ead4bb Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:21:00 +0100 Subject: [PATCH 109/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.6 (#515) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ad49ae4f3..70fcb9f53 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.1 + github.com/goccy/go-yaml v1.15.6 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 613849eb1..21a5713bf 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.1 h1:1vwC1ZjDzXyiMUKf7kKPazc6WUm4xnHGxNlzj4BIVu0= -github.com/goccy/go-yaml v1.15.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.6 h1:gy5kf1yjMia3/c3wWD+u1z3lU5XlhpT8FZGaLJU9cOA= +github.com/goccy/go-yaml v1.15.6/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 97acbaa15b0a99649758a1e848ab1d7519217315 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:31:19 +0100 Subject: [PATCH 110/619] fix(deps): update module golang.org/x/term to v0.27.0 (#520) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 70fcb9f53..8be6bff58 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.22.0 golang.org/x/oauth2 v0.24.0 - golang.org/x/term v0.26.0 + golang.org/x/term v0.27.0 golang.org/x/text v0.20.0 k8s.io/apimachinery v0.31.3 k8s.io/client-go v0.31.3 @@ -88,7 +88,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/sys v0.27.0 // indirect + golang.org/x/sys v0.28.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 21a5713bf..c581fc696 100644 --- a/go.sum +++ b/go.sum @@ -208,10 +208,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= From b9be7a693788ba621ccb8bf251ba162f4b41c241 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:41:14 +0100 Subject: [PATCH 111/619] fix(deps): update module golang.org/x/text to v0.21.0 (#521) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8be6bff58..df32b3fa9 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( golang.org/x/mod v0.22.0 golang.org/x/oauth2 v0.24.0 golang.org/x/term v0.27.0 - golang.org/x/text v0.20.0 + golang.org/x/text v0.21.0 k8s.io/apimachinery v0.31.3 k8s.io/client-go v0.31.3 ) diff --git a/go.sum b/go.sum index c581fc696..19ed58320 100644 --- a/go.sum +++ b/go.sum @@ -214,8 +214,8 @@ golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 0da6d09db4ec5e5b1ff06f32b7b916081bd8e0d5 Mon Sep 17 00:00:00 2001 From: Marcel <72880145+marceljk@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:46:00 +0100 Subject: [PATCH 112/619] Onboard IaaS Server Service Account Commands (#522) * Add server service-account commands * Generate docs for server service-account commands --- docs/stackit_beta_server.md | 1 + docs/stackit_beta_server_service-account.md | 35 +++ ...ckit_beta_server_service-account_attach.md | 40 ++++ ...ckit_beta_server_service-account_detach.md | 40 ++++ ...tackit_beta_server_service-account_list.md | 47 ++++ internal/cmd/beta/server/server.go | 3 + .../server/service-account/attach/attach.go | 145 +++++++++++ .../service-account/attach/attach_test.go | 226 ++++++++++++++++++ .../server/service-account/detach/detach.go | 145 +++++++++++ .../service-account/detach/detach_test.go | 226 ++++++++++++++++++ .../beta/server/service-account/list/list.go | 170 +++++++++++++ .../server/service-account/list/list_test.go | 221 +++++++++++++++++ .../server/service-account/service-account.go | 30 +++ 13 files changed, 1329 insertions(+) create mode 100644 docs/stackit_beta_server_service-account.md create mode 100644 docs/stackit_beta_server_service-account_attach.md create mode 100644 docs/stackit_beta_server_service-account_detach.md create mode 100644 docs/stackit_beta_server_service-account_list.md create mode 100644 internal/cmd/beta/server/service-account/attach/attach.go create mode 100644 internal/cmd/beta/server/service-account/attach/attach_test.go create mode 100644 internal/cmd/beta/server/service-account/detach/detach.go create mode 100644 internal/cmd/beta/server/service-account/detach/detach_test.go create mode 100644 internal/cmd/beta/server/service-account/list/list.go create mode 100644 internal/cmd/beta/server/service-account/list/list_test.go create mode 100644 internal/cmd/beta/server/service-account/service-account.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index 5d2443980..35a7fb435 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -36,6 +36,7 @@ stackit beta server [flags] * [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project * [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers +* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers * [stackit beta server update](./stackit_beta_server_update.md) - Updates a server * [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_service-account.md b/docs/stackit_beta_server_service-account.md new file mode 100644 index 000000000..294f369d9 --- /dev/null +++ b/docs/stackit_beta_server_service-account.md @@ -0,0 +1,35 @@ +## stackit beta server service-account + +Allows attaching/detaching service accounts to servers + +### Synopsis + +Allows attaching/detaching service accounts to servers + +``` +stackit beta server service-account [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server service-account" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit beta server service-account attach](./stackit_beta_server_service-account_attach.md) - Attach a service account to a server +* [stackit beta server service-account detach](./stackit_beta_server_service-account_detach.md) - Detach a service account from a server +* [stackit beta server service-account list](./stackit_beta_server_service-account_list.md) - List all attached service accounts for a server + diff --git a/docs/stackit_beta_server_service-account_attach.md b/docs/stackit_beta_server_service-account_attach.md new file mode 100644 index 000000000..5d00495df --- /dev/null +++ b/docs/stackit_beta_server_service-account_attach.md @@ -0,0 +1,40 @@ +## stackit beta server service-account attach + +Attach a service account to a server + +### Synopsis + +Attach a service account to a server + +``` +stackit beta server service-account attach [flags] +``` + +### Examples + +``` + Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy" + $ stackit beta server service-account attach xxx@sa.stackit.cloud --server-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server service-account attach" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers + diff --git a/docs/stackit_beta_server_service-account_detach.md b/docs/stackit_beta_server_service-account_detach.md new file mode 100644 index 000000000..88276a8ce --- /dev/null +++ b/docs/stackit_beta_server_service-account_detach.md @@ -0,0 +1,40 @@ +## stackit beta server service-account detach + +Detach a service account from a server + +### Synopsis + +Detach a service account from a server + +``` +stackit beta server service-account detach [flags] +``` + +### Examples + +``` + Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy" + $ stackit beta server service-account detach xxx@sa.stackit.cloud --server-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server service-account detach" + -s, --server-id string Server id +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers + diff --git a/docs/stackit_beta_server_service-account_list.md b/docs/stackit_beta_server_service-account_list.md new file mode 100644 index 000000000..64f993e2d --- /dev/null +++ b/docs/stackit_beta_server_service-account_list.md @@ -0,0 +1,47 @@ +## stackit beta server service-account list + +List all attached service accounts for a server + +### Synopsis + +List all attached service accounts for a server + +``` +stackit beta server service-account list [flags] +``` + +### Examples + +``` + List all attached service accounts for a server with ID "xxx" + $ stackit beta server service-account list --server-id xxx + + List up to 10 attached service accounts for a server with ID "xxx" + $ stackit beta server service-account list --server-id xxx --limit 10 + + List all attached service accounts for a server with ID "xxx" in JSON format + $ stackit beta server service-account list --server-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server service-account list" + --limit int Maximum number of entries to list + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers + diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 4b8ba0fd4..3ca7dca6f 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -8,8 +8,10 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" + serviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -37,6 +39,7 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(describe.NewCmd(p)) cmd.AddCommand(list.NewCmd(p)) cmd.AddCommand(publicip.NewCmd(p)) + cmd.AddCommand(serviceaccount.NewCmd(p)) cmd.AddCommand(update.NewCmd(p)) cmd.AddCommand(volume.NewCmd(p)) } diff --git a/internal/cmd/beta/server/service-account/attach/attach.go b/internal/cmd/beta/server/service-account/attach/attach.go new file mode 100644 index 000000000..c5cffdbad --- /dev/null +++ b/internal/cmd/beta/server/service-account/attach/attach.go @@ -0,0 +1,145 @@ +package attach + +import ( + "context" + "encoding/json" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" + + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + ServiceAccMail string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "attach", + Short: "Attach a service account to a server", + Long: "Attach a service account to a server", + Args: args.SingleArg(serviceAccMailArg, nil), + Example: examples.Build( + examples.NewExample( + `Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy"`, + "$ stackit beta server service-account attach xxx@sa.stackit.cloud --server-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to attach service account %q to server %q?", model.ServiceAccMail, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("attach service account to server: %w", err) + } + + return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serviceAccMail := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServiceAccMail: serviceAccMail, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddServiceAccountToServerRequest { + req := apiClient.AddServiceAccountToServer(ctx, model.ProjectId, *model.ServerId, model.ServiceAccMail) + return req +} + +func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, serviceAccounts *iaas.ServiceAccountMailListResponse) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(serviceAccounts, "", " ") + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Attached service account %q to server %q\n", serviceAccMail, serverLabel) + return nil + } +} diff --git a/internal/cmd/beta/server/service-account/attach/attach_test.go b/internal/cmd/beta/server/service-account/attach/attach_test.go new file mode 100644 index 000000000..f7854c24b --- /dev/null +++ b/internal/cmd/beta/server/service-account/attach/attach_test.go @@ -0,0 +1,226 @@ +package attach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testServiceAccount = "test@example.com" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServiceAccount, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + ServiceAccMail: testServiceAccount, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiAddServiceAccountToServerRequest)) iaas.ApiAddServiceAccountToServerRequest { + request := testClient.AddServiceAccountToServer(testCtx, testProjectId, testServerId, testServiceAccount) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "service account argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiAddServiceAccountToServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/service-account/detach/detach.go b/internal/cmd/beta/server/service-account/detach/detach.go new file mode 100644 index 000000000..99e95506c --- /dev/null +++ b/internal/cmd/beta/server/service-account/detach/detach.go @@ -0,0 +1,145 @@ +package detach + +import ( + "context" + "encoding/json" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" + + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + ServiceAccMail string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "detach", + Short: "Detach a service account from a server", + Long: "Detach a service account from a server", + Args: args.SingleArg(serviceAccMailArg, nil), + Example: examples.Build( + examples.NewExample( + `Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy"`, + "$ stackit beta server service-account detach xxx@sa.stackit.cloud --server-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are your sure you want to detach service account %q from a server %q?", model.ServiceAccMail, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("detach service account request: %w", err) + } + + return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server id") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serviceAccMail := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServiceAccMail: serviceAccMail, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveServiceAccountFromServerRequest { + req := apiClient.RemoveServiceAccountFromServer(ctx, model.ProjectId, *model.ServerId, model.ServiceAccMail) + return req +} + +func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, service *iaas.ServiceAccountMailListResponse) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(service, "", " ") + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(service, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Detached service account %q from server %q\n", serviceAccMail, serverLabel) + return nil + } +} diff --git a/internal/cmd/beta/server/service-account/detach/detach_test.go b/internal/cmd/beta/server/service-account/detach/detach_test.go new file mode 100644 index 000000000..5250e0a6f --- /dev/null +++ b/internal/cmd/beta/server/service-account/detach/detach_test.go @@ -0,0 +1,226 @@ +package detach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testServiceAccount = "test@example.com" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServiceAccount, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + ServiceAccMail: testServiceAccount, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiRemoveServiceAccountFromServerRequest)) iaas.ApiRemoveServiceAccountFromServerRequest { + request := testClient.RemoveServiceAccountFromServer(testCtx, testProjectId, testServerId, testServiceAccount) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "service account argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRemoveServiceAccountFromServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/service-account/list/list.go b/internal/cmd/beta/server/service-account/list/list.go new file mode 100644 index 000000000..c938f2b80 --- /dev/null +++ b/internal/cmd/beta/server/service-account/list/list.go @@ -0,0 +1,170 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serverIdFlag = "server-id" + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + ServerId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List all attached service accounts for a server", + Long: "List all attached service accounts for a server", + Args: cobra.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all attached service accounts for a server with ID "xxx"`, + "$ stackit beta server service-account list --server-id xxx", + ), + examples.NewExample( + `List up to 10 attached service accounts for a server with ID "xxx"`, + "$ stackit beta server service-account list --server-id xxx --limit 10", + ), + examples.NewExample( + `List all attached service accounts for a server with ID "xxx" in JSON format`, + "$ stackit beta server service-account list --server-id xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverName, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverName = *model.ServerId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list service accounts: %w", err) + } + serviceAccounts := *resp.Items + if len(serviceAccounts) == 0 { + p.Info("No service accounts found for server %s\n", *model.ServerId) + return nil + } + + if model.Limit != nil && len(serviceAccounts) > int(*model.Limit) { + serviceAccounts = serviceAccounts[:int(*model.Limit)] + } + + return outputResult(p, model.OutputFormat, *model.ServerId, serverName, serviceAccounts) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServerServiceAccountsRequest { + req := apiClient.ListServerServiceAccounts(ctx, model.ProjectId, *model.ServerId) + return req +} + +func outputResult(p *print.Printer, outputFormat, serverId, serverName string, serviceAccounts []string) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(serviceAccounts, "", " ") + if err != nil { + return fmt.Errorf("marshal service accounts list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal service accounts list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("SERVER ID", "SERVER NAME", "SERVICE ACCOUNT") + for i := range serviceAccounts { + table.AddRow(serverId, serverName, serviceAccounts[i]) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("rednder table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/service-account/list/list_test.go b/internal/cmd/beta/server/service-account/list/list_test.go new file mode 100644 index 000000000..04ba8c721 --- /dev/null +++ b/internal/cmd/beta/server/service-account/list/list_test.go @@ -0,0 +1,221 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testLimit = int64(10) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + limitFlag: strconv.FormatInt(testLimit, 10), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(inputModel *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + Limit: utils.Ptr(testLimit), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListServerServiceAccountsRequest)) iaas.ApiListServerServiceAccountsRequest { + request := testClient.ListServerServiceAccounts(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "without limit", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, limitFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Limit = nil + }), + }, + { + description: "limit invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListServerServiceAccountsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Request does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/service-account/service-account.go b/internal/cmd/beta/server/service-account/service-account.go new file mode 100644 index 000000000..e0907d4f1 --- /dev/null +++ b/internal/cmd/beta/server/service-account/service-account.go @@ -0,0 +1,30 @@ +package serviceaccount + +import ( + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/detach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/list" + + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "service-account", + Short: "Allows attaching/detaching service accounts to servers", + Long: "Allows attaching/detaching service accounts to servers", + Args: cobra.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(attach.NewCmd(p)) + cmd.AddCommand(detach.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} From 056dc2eacf1a2cf448451261b1233e35dbe92fb5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 6 Dec 2024 08:09:53 +0100 Subject: [PATCH 113/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.7 (#524) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index df32b3fa9..0b91100e7 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.6 + github.com/goccy/go-yaml v1.15.7 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 19ed58320..eaad7a9f8 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.6 h1:gy5kf1yjMia3/c3wWD+u1z3lU5XlhpT8FZGaLJU9cOA= -github.com/goccy/go-yaml v1.15.6/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.7 h1:L7XuKpd/A66X4w/dlk08lVfiIADdy79a1AzRoIefC98= +github.com/goccy/go-yaml v1.15.7/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From d00572db5c66ed76ed657c556e6674078c90668a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 6 Dec 2024 08:10:18 +0100 Subject: [PATCH 114/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/serviceenablement to v0.4.0 (#525) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0b91100e7..819d674f8 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 github.com/zalando/go-keyring v0.2.6 diff --git a/go.sum b/go.sum index eaad7a9f8..22eda04e1 100644 --- a/go.sum +++ b/go.sum @@ -156,8 +156,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0 h1:Tlps8vBQm github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0/go.mod h1:+807U5ZLXns+CEbyIg483wNEwV10vaN6GjMnSZhw/64= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0 h1:6IZBX9fyza9Eln3FHGHquvLNXQslk+dtkQp41G9+7+Y= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.3.0/go.mod h1:zyg0hpiNdZLRbelkJb2KDf9OHQKLqqcTpePQ1qHL5dE= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0/go.mod h1:zyg0hpiNdZLRbelkJb2KDf9OHQKLqqcTpePQ1qHL5dE= github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 h1:ssEywzCS8IdRtzyxweLUKBG5GFbgwjNWJh++wGqigJM= github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0/go.mod h1:A4+9KslxCA31JvxnT+O/GC67eAOdw+iqhBzewZZaCD0= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 h1:1ByAgO10fxWF+UZ+RkJeAiv+h5AgqrzYz6r86Pn/BWE= From a5de91d29143681b3a8f7eef627250c8d86df7e6 Mon Sep 17 00:00:00 2001 From: Marcel <72880145+marceljk@users.noreply.github.com> Date: Fri, 6 Dec 2024 11:48:05 +0100 Subject: [PATCH 115/619] Revert "Onboard IaaS Server Service Account Commands (#522)" (#526) This reverts commit 0da6d09db4ec5e5b1ff06f32b7b916081bd8e0d5. --- docs/stackit_beta_server.md | 1 - docs/stackit_beta_server_service-account.md | 35 --- ...ckit_beta_server_service-account_attach.md | 40 ---- ...ckit_beta_server_service-account_detach.md | 40 ---- ...tackit_beta_server_service-account_list.md | 47 ---- internal/cmd/beta/server/server.go | 3 - .../server/service-account/attach/attach.go | 145 ----------- .../service-account/attach/attach_test.go | 226 ------------------ .../server/service-account/detach/detach.go | 145 ----------- .../service-account/detach/detach_test.go | 226 ------------------ .../beta/server/service-account/list/list.go | 170 ------------- .../server/service-account/list/list_test.go | 221 ----------------- .../server/service-account/service-account.go | 30 --- 13 files changed, 1329 deletions(-) delete mode 100644 docs/stackit_beta_server_service-account.md delete mode 100644 docs/stackit_beta_server_service-account_attach.md delete mode 100644 docs/stackit_beta_server_service-account_detach.md delete mode 100644 docs/stackit_beta_server_service-account_list.md delete mode 100644 internal/cmd/beta/server/service-account/attach/attach.go delete mode 100644 internal/cmd/beta/server/service-account/attach/attach_test.go delete mode 100644 internal/cmd/beta/server/service-account/detach/detach.go delete mode 100644 internal/cmd/beta/server/service-account/detach/detach_test.go delete mode 100644 internal/cmd/beta/server/service-account/list/list.go delete mode 100644 internal/cmd/beta/server/service-account/list/list_test.go delete mode 100644 internal/cmd/beta/server/service-account/service-account.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index 35a7fb435..5d2443980 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -36,7 +36,6 @@ stackit beta server [flags] * [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project * [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers -* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers * [stackit beta server update](./stackit_beta_server_update.md) - Updates a server * [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_service-account.md b/docs/stackit_beta_server_service-account.md deleted file mode 100644 index 294f369d9..000000000 --- a/docs/stackit_beta_server_service-account.md +++ /dev/null @@ -1,35 +0,0 @@ -## stackit beta server service-account - -Allows attaching/detaching service accounts to servers - -### Synopsis - -Allows attaching/detaching service accounts to servers - -``` -stackit beta server service-account [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta server service-account" -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server service-account attach](./stackit_beta_server_service-account_attach.md) - Attach a service account to a server -* [stackit beta server service-account detach](./stackit_beta_server_service-account_detach.md) - Detach a service account from a server -* [stackit beta server service-account list](./stackit_beta_server_service-account_list.md) - List all attached service accounts for a server - diff --git a/docs/stackit_beta_server_service-account_attach.md b/docs/stackit_beta_server_service-account_attach.md deleted file mode 100644 index 5d00495df..000000000 --- a/docs/stackit_beta_server_service-account_attach.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit beta server service-account attach - -Attach a service account to a server - -### Synopsis - -Attach a service account to a server - -``` -stackit beta server service-account attach [flags] -``` - -### Examples - -``` - Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy" - $ stackit beta server service-account attach xxx@sa.stackit.cloud --server-id yyy -``` - -### Options - -``` - -h, --help Help for "stackit beta server service-account attach" - -s, --server-id string Server ID -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers - diff --git a/docs/stackit_beta_server_service-account_detach.md b/docs/stackit_beta_server_service-account_detach.md deleted file mode 100644 index 88276a8ce..000000000 --- a/docs/stackit_beta_server_service-account_detach.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit beta server service-account detach - -Detach a service account from a server - -### Synopsis - -Detach a service account from a server - -``` -stackit beta server service-account detach [flags] -``` - -### Examples - -``` - Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy" - $ stackit beta server service-account detach xxx@sa.stackit.cloud --server-id yyy -``` - -### Options - -``` - -h, --help Help for "stackit beta server service-account detach" - -s, --server-id string Server id -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers - diff --git a/docs/stackit_beta_server_service-account_list.md b/docs/stackit_beta_server_service-account_list.md deleted file mode 100644 index 64f993e2d..000000000 --- a/docs/stackit_beta_server_service-account_list.md +++ /dev/null @@ -1,47 +0,0 @@ -## stackit beta server service-account list - -List all attached service accounts for a server - -### Synopsis - -List all attached service accounts for a server - -``` -stackit beta server service-account list [flags] -``` - -### Examples - -``` - List all attached service accounts for a server with ID "xxx" - $ stackit beta server service-account list --server-id xxx - - List up to 10 attached service accounts for a server with ID "xxx" - $ stackit beta server service-account list --server-id xxx --limit 10 - - List all attached service accounts for a server with ID "xxx" in JSON format - $ stackit beta server service-account list --server-id xxx --output-format json -``` - -### Options - -``` - -h, --help Help for "stackit beta server service-account list" - --limit int Maximum number of entries to list - -s, --server-id string Server ID -``` - -### 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 - --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") -``` - -### SEE ALSO - -* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers - diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 3ca7dca6f..4b8ba0fd4 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -8,10 +8,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" - serviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume" - "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -39,7 +37,6 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(describe.NewCmd(p)) cmd.AddCommand(list.NewCmd(p)) cmd.AddCommand(publicip.NewCmd(p)) - cmd.AddCommand(serviceaccount.NewCmd(p)) cmd.AddCommand(update.NewCmd(p)) cmd.AddCommand(volume.NewCmd(p)) } diff --git a/internal/cmd/beta/server/service-account/attach/attach.go b/internal/cmd/beta/server/service-account/attach/attach.go deleted file mode 100644 index c5cffdbad..000000000 --- a/internal/cmd/beta/server/service-account/attach/attach.go +++ /dev/null @@ -1,145 +0,0 @@ -package attach - -import ( - "context" - "encoding/json" - "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/flags" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" - - "github.com/goccy/go-yaml" - "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" -) - -const ( - serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" - - serverIdFlag = "server-id" -) - -type inputModel struct { - *globalflags.GlobalFlagModel - ServerId *string - ServiceAccMail string -} - -func NewCmd(p *print.Printer) *cobra.Command { - cmd := &cobra.Command{ - Use: "attach", - Short: "Attach a service account to a server", - Long: "Attach a service account to a server", - Args: args.SingleArg(serviceAccMailArg, nil), - Example: examples.Build( - examples.NewExample( - `Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy"`, - "$ stackit beta server service-account attach xxx@sa.stackit.cloud --server-id yyy", - ), - ), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() - model, err := parseInput(p, cmd, args) - if err != nil { - return err - } - - // Configure API client - apiClient, err := client.ConfigureClient(p) - if err != nil { - return err - } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) - if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId - } - - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to attach service account %q to server %q?", model.ServiceAccMail, serverLabel) - err = p.PromptForConfirmation(prompt) - if err != nil { - return err - } - } - - // Call API - req := buildRequest(ctx, model, apiClient) - resp, err := req.Execute() - if err != nil { - return fmt.Errorf("attach service account to server: %w", err) - } - - return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, resp) - }, - } - configureFlags(cmd) - return cmd -} - -func configureFlags(cmd *cobra.Command) { - cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") - - err := flags.MarkFlagsRequired(cmd, serverIdFlag) - cobra.CheckErr(err) -} - -func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { - serviceAccMail := inputArgs[0] - globalFlags := globalflags.Parse(p, cmd) - if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} - } - - model := inputModel{ - GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), - ServiceAccMail: serviceAccMail, - } - - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - - return &model, nil -} - -func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddServiceAccountToServerRequest { - req := apiClient.AddServiceAccountToServer(ctx, model.ProjectId, *model.ServerId, model.ServiceAccMail) - return req -} - -func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, serviceAccounts *iaas.ServiceAccountMailListResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(serviceAccounts, "", " ") - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - default: - p.Outputf("Attached service account %q to server %q\n", serviceAccMail, serverLabel) - return nil - } -} diff --git a/internal/cmd/beta/server/service-account/attach/attach_test.go b/internal/cmd/beta/server/service-account/attach/attach_test.go deleted file mode 100644 index f7854c24b..000000000 --- a/internal/cmd/beta/server/service-account/attach/attach_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package attach - -import ( - "context" - "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" -) - -var projectIdFlag = globalflags.ProjectIdFlag - -type testCtxKey struct{} - -var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") -var testClient = &iaas.APIClient{} -var testProjectId = uuid.NewString() -var testServerId = uuid.NewString() -var testServiceAccount = "test@example.com" - -func fixtureArgValues(mods ...func(argValues []string)) []string { - argValues := []string{ - testServiceAccount, - } - for _, mod := range mods { - mod(argValues) - } - return argValues -} - -func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { - flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - } - for _, mod := range mods { - mod(flagValues) - } - return flagValues -} - -func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { - model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ - Verbosity: globalflags.VerbosityDefault, - ProjectId: testProjectId, - }, - ServerId: utils.Ptr(testServerId), - ServiceAccMail: testServiceAccount, - } - for _, mod := range mods { - mod(model) - } - return model -} - -func fixtureRequest(mods ...func(request *iaas.ApiAddServiceAccountToServerRequest)) iaas.ApiAddServiceAccountToServerRequest { - request := testClient.AddServiceAccountToServer(testCtx, testProjectId, testServerId, testServiceAccount) - for _, mod := range mods { - mod(&request) - } - return request -} - -func TestParseInput(t *testing.T) { - tests := []struct { - description string - argValues []string - flagValues map[string]string - isValid bool - expectedModel *inputModel - }{ - { - description: "base", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(), - }, - { - description: "no values", - argValues: fixtureArgValues(), - flagValues: map[string]string{}, - isValid: false, - }, - { - description: "project id missing", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) - }), - isValid: false, - }, - { - description: "project id invalid 1", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" - }), - isValid: false, - }, - { - description: "project id invalid 2", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" - }), - isValid: false, - }, - { - description: "server id missing", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, serverIdFlag) - }), - }, - { - description: "server id invalid 1", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[serverIdFlag] = "" - }), - isValid: false, - }, - { - description: "server id invalid 2", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[serverIdFlag] = "invalid-uuid" - }), - isValid: false, - }, - { - description: "service account argument missing", - argValues: []string{}, - isValid: false, - }, - } - - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing 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 input: %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) - } - }) - } -} - -func TestBuildRequest(t *testing.T) { - tests := []struct { - description string - model *inputModel - expectedRequest iaas.ApiAddServiceAccountToServerRequest - }{ - { - 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), - cmpopts.EquateComparable(testCtx), - ) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } - }) - } -} diff --git a/internal/cmd/beta/server/service-account/detach/detach.go b/internal/cmd/beta/server/service-account/detach/detach.go deleted file mode 100644 index 99e95506c..000000000 --- a/internal/cmd/beta/server/service-account/detach/detach.go +++ /dev/null @@ -1,145 +0,0 @@ -package detach - -import ( - "context" - "encoding/json" - "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/flags" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" - - "github.com/goccy/go-yaml" - "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" -) - -const ( - serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" - - serverIdFlag = "server-id" -) - -type inputModel struct { - *globalflags.GlobalFlagModel - ServerId *string - ServiceAccMail string -} - -func NewCmd(p *print.Printer) *cobra.Command { - cmd := &cobra.Command{ - Use: "detach", - Short: "Detach a service account from a server", - Long: "Detach a service account from a server", - Args: args.SingleArg(serviceAccMailArg, nil), - Example: examples.Build( - examples.NewExample( - `Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy"`, - "$ stackit beta server service-account detach xxx@sa.stackit.cloud --server-id yyy", - ), - ), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() - model, err := parseInput(p, cmd, args) - if err != nil { - return err - } - - // Configure API client - apiClient, err := client.ConfigureClient(p) - if err != nil { - return err - } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) - if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId - } - - if !model.AssumeYes { - prompt := fmt.Sprintf("Are your sure you want to detach service account %q from a server %q?", model.ServiceAccMail, serverLabel) - err = p.PromptForConfirmation(prompt) - if err != nil { - return err - } - } - - // Call API - req := buildRequest(ctx, model, apiClient) - resp, err := req.Execute() - if err != nil { - return fmt.Errorf("detach service account request: %w", err) - } - - return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, resp) - }, - } - configureFlags(cmd) - return cmd -} - -func configureFlags(cmd *cobra.Command) { - cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server id") - - err := flags.MarkFlagsRequired(cmd, serverIdFlag) - cobra.CheckErr(err) -} - -func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { - serviceAccMail := inputArgs[0] - globalFlags := globalflags.Parse(p, cmd) - if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} - } - - model := inputModel{ - GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), - ServiceAccMail: serviceAccMail, - } - - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - - return &model, nil -} - -func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveServiceAccountFromServerRequest { - req := apiClient.RemoveServiceAccountFromServer(ctx, model.ProjectId, *model.ServerId, model.ServiceAccMail) - return req -} - -func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, service *iaas.ServiceAccountMailListResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(service, "", " ") - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(service, yaml.IndentSequence(true)) - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - default: - p.Outputf("Detached service account %q from server %q\n", serviceAccMail, serverLabel) - return nil - } -} diff --git a/internal/cmd/beta/server/service-account/detach/detach_test.go b/internal/cmd/beta/server/service-account/detach/detach_test.go deleted file mode 100644 index 5250e0a6f..000000000 --- a/internal/cmd/beta/server/service-account/detach/detach_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package detach - -import ( - "context" - "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" -) - -var projectIdFlag = globalflags.ProjectIdFlag - -type testCtxKey struct{} - -var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") -var testClient = &iaas.APIClient{} -var testProjectId = uuid.NewString() -var testServerId = uuid.NewString() -var testServiceAccount = "test@example.com" - -func fixtureArgValues(mods ...func(argValues []string)) []string { - argValues := []string{ - testServiceAccount, - } - for _, mod := range mods { - mod(argValues) - } - return argValues -} - -func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { - flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - } - for _, mod := range mods { - mod(flagValues) - } - return flagValues -} - -func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { - model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ - Verbosity: globalflags.VerbosityDefault, - ProjectId: testProjectId, - }, - ServerId: utils.Ptr(testServerId), - ServiceAccMail: testServiceAccount, - } - for _, mod := range mods { - mod(model) - } - return model -} - -func fixtureRequest(mods ...func(request *iaas.ApiRemoveServiceAccountFromServerRequest)) iaas.ApiRemoveServiceAccountFromServerRequest { - request := testClient.RemoveServiceAccountFromServer(testCtx, testProjectId, testServerId, testServiceAccount) - for _, mod := range mods { - mod(&request) - } - return request -} - -func TestParseInput(t *testing.T) { - tests := []struct { - description string - argValues []string - flagValues map[string]string - isValid bool - expectedModel *inputModel - }{ - { - description: "base", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(), - }, - { - description: "no values", - argValues: fixtureArgValues(), - flagValues: map[string]string{}, - isValid: false, - }, - { - description: "project id missing", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) - }), - isValid: false, - }, - { - description: "project id invalid 1", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" - }), - isValid: false, - }, - { - description: "project id invalid 2", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" - }), - isValid: false, - }, - { - description: "server id missing", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, serverIdFlag) - }), - }, - { - description: "server id invalid 1", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[serverIdFlag] = "" - }), - isValid: false, - }, - { - description: "server id invalid 2", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[serverIdFlag] = "invalid-uuid" - }), - isValid: false, - }, - { - description: "service account argument missing", - argValues: []string{}, - isValid: false, - }, - } - - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing 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 input: %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) - } - }) - } -} - -func TestBuildRequest(t *testing.T) { - tests := []struct { - description string - model *inputModel - expectedRequest iaas.ApiRemoveServiceAccountFromServerRequest - }{ - { - 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), - cmpopts.EquateComparable(testCtx), - ) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } - }) - } -} diff --git a/internal/cmd/beta/server/service-account/list/list.go b/internal/cmd/beta/server/service-account/list/list.go deleted file mode 100644 index c938f2b80..000000000 --- a/internal/cmd/beta/server/service-account/list/list.go +++ /dev/null @@ -1,170 +0,0 @@ -package list - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" - "github.com/stackitcloud/stackit-cli/internal/pkg/examples" - "github.com/stackitcloud/stackit-cli/internal/pkg/flags" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" - "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/goccy/go-yaml" - "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" -) - -const ( - serverIdFlag = "server-id" - limitFlag = "limit" -) - -type inputModel struct { - *globalflags.GlobalFlagModel - Limit *int64 - ServerId *string -} - -func NewCmd(p *print.Printer) *cobra.Command { - cmd := &cobra.Command{ - Use: "list", - Short: "List all attached service accounts for a server", - Long: "List all attached service accounts for a server", - Args: cobra.NoArgs, - Example: examples.Build( - examples.NewExample( - `List all attached service accounts for a server with ID "xxx"`, - "$ stackit beta server service-account list --server-id xxx", - ), - examples.NewExample( - `List up to 10 attached service accounts for a server with ID "xxx"`, - "$ stackit beta server service-account list --server-id xxx --limit 10", - ), - examples.NewExample( - `List all attached service accounts for a server with ID "xxx" in JSON format`, - "$ stackit beta server service-account list --server-id xxx --output-format json", - ), - ), - RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() - model, err := parseInput(p, cmd) - if err != nil { - return err - } - - // Configure API client - apiClient, err := client.ConfigureClient(p) - if err != nil { - return err - } - - serverName, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) - if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) - serverName = *model.ServerId - } - - // Call API - req := buildRequest(ctx, model, apiClient) - resp, err := req.Execute() - if err != nil { - return fmt.Errorf("list service accounts: %w", err) - } - serviceAccounts := *resp.Items - if len(serviceAccounts) == 0 { - p.Info("No service accounts found for server %s\n", *model.ServerId) - return nil - } - - if model.Limit != nil && len(serviceAccounts) > int(*model.Limit) { - serviceAccounts = serviceAccounts[:int(*model.Limit)] - } - - return outputResult(p, model.OutputFormat, *model.ServerId, serverName, serviceAccounts) - }, - } - configureFlags(cmd) - return cmd -} - -func configureFlags(cmd *cobra.Command) { - cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") - cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") - - err := flags.MarkFlagsRequired(cmd, serverIdFlag) - cobra.CheckErr(err) -} - -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { - globalFlags := globalflags.Parse(p, cmd) - if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} - } - - limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) - if limit != nil && *limit < 1 { - return nil, &errors.FlagValidationError{ - Flag: limitFlag, - Details: "must be greater than 0", - } - } - - model := inputModel{ - GlobalFlagModel: globalFlags, - Limit: limit, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), - } - - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - - return &model, nil -} - -func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServerServiceAccountsRequest { - req := apiClient.ListServerServiceAccounts(ctx, model.ProjectId, *model.ServerId) - return req -} - -func outputResult(p *print.Printer, outputFormat, serverId, serverName string, serviceAccounts []string) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(serviceAccounts, "", " ") - if err != nil { - return fmt.Errorf("marshal service accounts list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) - if err != nil { - return fmt.Errorf("marshal service accounts list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: - table := tables.NewTable() - table.SetHeader("SERVER ID", "SERVER NAME", "SERVICE ACCOUNT") - for i := range serviceAccounts { - table.AddRow(serverId, serverName, serviceAccounts[i]) - } - err := table.Display(p) - if err != nil { - return fmt.Errorf("rednder table: %w", err) - } - return nil - } -} diff --git a/internal/cmd/beta/server/service-account/list/list_test.go b/internal/cmd/beta/server/service-account/list/list_test.go deleted file mode 100644 index 04ba8c721..000000000 --- a/internal/cmd/beta/server/service-account/list/list_test.go +++ /dev/null @@ -1,221 +0,0 @@ -package list - -import ( - "context" - "strconv" - "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" -) - -var projectIdFlag = globalflags.ProjectIdFlag - -type testCtxKey struct{} - -var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") -var testClient = &iaas.APIClient{} -var testProjectId = uuid.NewString() -var testServerId = uuid.NewString() -var testLimit = int64(10) - -func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { - flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - limitFlag: strconv.FormatInt(testLimit, 10), - } - for _, mod := range mods { - mod(flagValues) - } - return flagValues -} - -func fixtureInputModel(mods ...func(inputModel *inputModel)) *inputModel { - model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ - Verbosity: globalflags.VerbosityDefault, - ProjectId: testProjectId, - }, - ServerId: utils.Ptr(testServerId), - Limit: utils.Ptr(testLimit), - } - for _, mod := range mods { - mod(model) - } - return model -} - -func fixtureRequest(mods ...func(request *iaas.ApiListServerServiceAccountsRequest)) iaas.ApiListServerServiceAccountsRequest { - request := testClient.ListServerServiceAccounts(testCtx, testProjectId, testServerId) - 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: "no values", - flagValues: map[string]string{}, - isValid: false, - }, - { - description: "project id missing", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) - }), - isValid: false, - }, - { - description: "project id invalid 1", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" - }), - isValid: false, - }, - { - description: "project id invalid 2", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" - }), - isValid: false, - }, - { - description: "server id missing", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, serverIdFlag) - }), - isValid: false, - }, - { - description: "server id invalid 1", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[serverIdFlag] = "" - }), - isValid: false, - }, - { - description: "server id invalid 2", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[serverIdFlag] = "invalid-uuid" - }), - isValid: false, - }, - { - description: "without limit", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, limitFlag) - }), - isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.Limit = nil - }), - }, - { - description: "limit invalid 1", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[limitFlag] = "invalid" - }), - isValid: false, - }, - { - description: "limit invalid 2", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[limitFlag] = "0" - }), - isValid: false, - }, - } - - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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) - } - }) - } -} - -func TestBuildRequest(t *testing.T) { - tests := []struct { - description string - model *inputModel - expectedRequest iaas.ApiListServerServiceAccountsRequest - }{ - { - 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), - cmpopts.EquateComparable(testCtx), - ) - if diff != "" { - t.Fatalf("Request does not match: %s", diff) - } - }) - } -} diff --git a/internal/cmd/beta/server/service-account/service-account.go b/internal/cmd/beta/server/service-account/service-account.go deleted file mode 100644 index e0907d4f1..000000000 --- a/internal/cmd/beta/server/service-account/service-account.go +++ /dev/null @@ -1,30 +0,0 @@ -package serviceaccount - -import ( - "github.com/spf13/cobra" - - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/attach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/detach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/list" - - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" -) - -func NewCmd(p *print.Printer) *cobra.Command { - cmd := &cobra.Command{ - Use: "service-account", - Short: "Allows attaching/detaching service accounts to servers", - Long: "Allows attaching/detaching service accounts to servers", - Args: cobra.NoArgs, - Run: utils.CmdHelp, - } - addSubcommands(cmd, p) - return cmd -} - -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(attach.NewCmd(p)) - cmd.AddCommand(detach.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) -} From 610086073aed747350c0c007e7cc183b08721f42 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 6 Dec 2024 12:04:25 +0100 Subject: [PATCH 116/619] chore(deps): update renovatebot/github-action action to v41.0.5 (#527) Signed-off-by: Alexander Dahmen --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 12454b9fd..7a7d69056 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v41.0.0 + uses: renovatebot/github-action@v41.0.5 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From c3c4765443a0207d6a3877ec7a507ede11f167e6 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Mon, 9 Dec 2024 12:48:19 +0100 Subject: [PATCH 117/619] Onboard IaaS server network interface commands (#519) Supported commands: attach, detach, list Signed-off-by: Alexander Dahmen --- docs/stackit_beta_server.md | 1 + docs/stackit_beta_server_network-interface.md | 35 ++ ...it_beta_server_network-interface_attach.md | 46 +++ ...it_beta_server_network-interface_detach.md | 46 +++ ...ckit_beta_server_network-interface_list.md | 47 +++ .../server/network-interface/attach/attach.go | 171 ++++++++++ .../network-interface/attach/attach_test.go | 311 ++++++++++++++++++ .../server/network-interface/detach/detach.go | 171 ++++++++++ .../network-interface/detach/detach_test.go | 311 ++++++++++++++++++ .../server/network-interface/list/list.go | 172 ++++++++++ .../network-interface/list/list_test.go | 211 ++++++++++++ .../network-interface/network-interface.go | 30 ++ internal/cmd/beta/server/server.go | 2 + internal/pkg/errors/errors.go | 20 ++ 14 files changed, 1574 insertions(+) create mode 100644 docs/stackit_beta_server_network-interface.md create mode 100644 docs/stackit_beta_server_network-interface_attach.md create mode 100644 docs/stackit_beta_server_network-interface_detach.md create mode 100644 docs/stackit_beta_server_network-interface_list.md create mode 100644 internal/cmd/beta/server/network-interface/attach/attach.go create mode 100644 internal/cmd/beta/server/network-interface/attach/attach_test.go create mode 100644 internal/cmd/beta/server/network-interface/detach/detach.go create mode 100644 internal/cmd/beta/server/network-interface/detach/detach_test.go create mode 100644 internal/cmd/beta/server/network-interface/list/list.go create mode 100644 internal/cmd/beta/server/network-interface/list/list_test.go create mode 100644 internal/cmd/beta/server/network-interface/network-interface.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index 5d2443980..59943e5be 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -35,6 +35,7 @@ stackit beta server [flags] * [stackit beta server delete](./stackit_beta_server_delete.md) - Deletes a server * [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project +* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers * [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers * [stackit beta server update](./stackit_beta_server_update.md) - Updates a server * [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_network-interface.md b/docs/stackit_beta_server_network-interface.md new file mode 100644 index 000000000..53547f83c --- /dev/null +++ b/docs/stackit_beta_server_network-interface.md @@ -0,0 +1,35 @@ +## stackit beta server network-interface + +Allows attaching/detaching network interfaces to servers + +### Synopsis + +Allows attaching/detaching network interfaces to servers. + +``` +stackit beta server network-interface [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server network-interface" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit beta server network-interface attach](./stackit_beta_server_network-interface_attach.md) - Attaches a network interface to a server +* [stackit beta server network-interface detach](./stackit_beta_server_network-interface_detach.md) - Detaches a network interface from a server +* [stackit beta server network-interface list](./stackit_beta_server_network-interface_list.md) - Lists all attached network interfaces of a server + diff --git a/docs/stackit_beta_server_network-interface_attach.md b/docs/stackit_beta_server_network-interface_attach.md new file mode 100644 index 000000000..e376d5c90 --- /dev/null +++ b/docs/stackit_beta_server_network-interface_attach.md @@ -0,0 +1,46 @@ +## stackit beta server network-interface attach + +Attaches a network interface to a server + +### Synopsis + +Attaches a network interface to a server. + +``` +stackit beta server network-interface attach [flags] +``` + +### Examples + +``` + Attach a network interface with ID "xxx" to a server with ID "yyy" + $ stackit beta server network-interface attach --network-interface-id xxx --server-id yyy + + Create a network interface for network with ID "xxx" and attach it to a server with ID "yyy" + $ stackit beta server network-interface attach --network-id xxx --server-id yyy --create +``` + +### Options + +``` + -b, --create If this is set a network interface will be created. (default false) + -h, --help Help for "stackit beta server network-interface attach" + --network-id string Network ID + --network-interface-id string Network Interface ID + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers + diff --git a/docs/stackit_beta_server_network-interface_detach.md b/docs/stackit_beta_server_network-interface_detach.md new file mode 100644 index 000000000..e90a3165e --- /dev/null +++ b/docs/stackit_beta_server_network-interface_detach.md @@ -0,0 +1,46 @@ +## stackit beta server network-interface detach + +Detaches a network interface from a server + +### Synopsis + +Detaches a network interface from a server. + +``` +stackit beta server network-interface detach [flags] +``` + +### Examples + +``` + Detach a network interface with ID "xxx" from a server with ID "yyy" + $ stackit beta server network-interface detach --network-interface-id xxx --server-id yyy + + Detach and delete all network interfaces for network with ID "xxx" and detach them from a server with ID "yyy" + $ stackit beta server network-interface detach --network-id xxx --server-id yyy --delete +``` + +### Options + +``` + -b, --delete If this is set all network interfaces will be deleted. (default false) + -h, --help Help for "stackit beta server network-interface detach" + --network-id string Network ID + --network-interface-id string Network Interface ID + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers + diff --git a/docs/stackit_beta_server_network-interface_list.md b/docs/stackit_beta_server_network-interface_list.md new file mode 100644 index 000000000..433374769 --- /dev/null +++ b/docs/stackit_beta_server_network-interface_list.md @@ -0,0 +1,47 @@ +## stackit beta server network-interface list + +Lists all attached network interfaces of a server + +### Synopsis + +Lists all attached network interfaces of a server. + +``` +stackit beta server network-interface list [flags] +``` + +### Examples + +``` + Lists all attached network interfaces of server with ID "xxx" + $ stackit beta server network-interface list --server-id xxx + + Lists all attached network interfaces of server with ID "xxx" in JSON format + $ stackit beta server network-interface list --server-id xxx --output-format json + + Lists up to 10 attached network interfaces of server with ID "xxx" + $ stackit beta server network-interface list --server-id xxx --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta server network-interface list" + --limit int Maximum number of entries to list + --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers + diff --git a/internal/cmd/beta/server/network-interface/attach/attach.go b/internal/cmd/beta/server/network-interface/attach/attach.go new file mode 100644 index 000000000..1a2b45d45 --- /dev/null +++ b/internal/cmd/beta/server/network-interface/attach/attach.go @@ -0,0 +1,171 @@ +package attach + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serverIdFlag = "server-id" + networkInterfaceIdFlag = "network-interface-id" + createFlag = "create" + networkIdFlag = "network-id" + + defaultCreateFlag = false +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + NicId *string + NetworkId *string + Create *bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "attach", + Short: "Attaches a network interface to a server", + Long: "Attaches a network interface to a server.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Attach a network interface with ID "xxx" to a server with ID "yyy"`, + `$ stackit beta server network-interface attach --network-interface-id xxx --server-id yyy`, + ), + examples.NewExample( + `Create a network interface for network with ID "xxx" and attach it to a server with ID "yyy"`, + `$ stackit beta server network-interface attach --network-id xxx --server-id yyy --create`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + // if the create flag is provided a network interface will be created and attached + if model.Create != nil && *model.Create { + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) + if err != nil { + p.Debug(print.ErrorLevel, "get network name: %v", err) + networkLabel = *model.NetworkId + } + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a network interface for network %q and attach it to server %q?", networkLabel, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + // Call API + req := buildRequestCreateAndAttach(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("create and attach network interface: %w", err) + } + p.Info("Created a network interface for network %q and attached it to server %q\n", networkLabel, serverLabel) + return nil + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to attach network interface %q to server %q?", *model.NicId, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + // Call API + req := buildRequestAttach(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("attach network interface: %w", err) + } + p.Info("Attached network interface %q to server %q\n", *model.NicId, serverLabel) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + cmd.Flags().Var(flags.UUIDFlag(), networkInterfaceIdFlag, "Network Interface ID") + cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID") + cmd.Flags().BoolP(createFlag, "b", defaultCreateFlag, "If this is set a network interface will be created. (default false)") + + cmd.MarkFlagsRequiredTogether(createFlag, networkIdFlag) + cmd.MarkFlagsMutuallyExclusive(createFlag, networkInterfaceIdFlag) + cmd.MarkFlagsMutuallyExclusive(networkIdFlag, networkInterfaceIdFlag) + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + // if create is not provided then network-interface-id is needed + networkInterfaceId := flags.FlagToStringPointer(p, cmd, networkInterfaceIdFlag) + create := flags.FlagToBoolPointer(p, cmd, createFlag) + if create == nil && networkInterfaceId == nil { + return nil, &cliErr.ServerNicAttachMissingNicIdError{Cmd: cmd} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NicId: networkInterfaceId, + Create: create, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequestAttach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddNicToServerRequest { + return apiClient.AddNicToServer(ctx, model.ProjectId, *model.ServerId, *model.NicId) +} + +func buildRequestCreateAndAttach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddNetworkToServerRequest { + return apiClient.AddNetworkToServer(ctx, model.ProjectId, *model.ServerId, *model.NetworkId) +} diff --git a/internal/cmd/beta/server/network-interface/attach/attach_test.go b/internal/cmd/beta/server/network-interface/attach/attach_test.go new file mode 100644 index 000000000..2adeff447 --- /dev/null +++ b/internal/cmd/beta/server/network-interface/attach/attach_test.go @@ -0,0 +1,311 @@ +package attach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testNicId = uuid.NewString() +var testNetworkId = uuid.NewString() + +// contains nic id +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + networkInterfaceIdFlag: testNicId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + NicId: utils.Ptr(testNicId), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequestAttach(mods ...func(request *iaas.ApiAddNicToServerRequest)) iaas.ApiAddNicToServerRequest { + request := testClient.AddNicToServer(testCtx, testProjectId, testServerId, testNicId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixtureRequestCreateAndAttach(mods ...func(request *iaas.ApiAddNetworkToServerRequest)) iaas.ApiAddNetworkToServerRequest { + request := testClient.AddNetworkToServer(testCtx, testProjectId, testServerId, testNetworkId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + // only create + { + description: "provided flags invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[createFlag] = "true" + delete(flagValues, networkInterfaceIdFlag) + }), + isValid: false, + }, + // only network id + { + description: "provided flags invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkInterfaceIdFlag) + flagValues[networkIdFlag] = testNetworkId + }), + isValid: false, + }, + // create and nic id + { + description: "provided flags invalid 3", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[createFlag] = "true" + }), + isValid: false, + }, + // create and network id (valid) + { + description: "provided flags valid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[createFlag] = "true" + delete(flagValues, networkInterfaceIdFlag) + flagValues[networkIdFlag] = testNetworkId + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Create = utils.Ptr(true) + model.NicId = nil + model.NetworkId = utils.Ptr(testNetworkId) + }), + }, + // create, nic id and network id + { + description: "provided flags invalid 4", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[createFlag] = "true" + flagValues[networkIdFlag] = testNetworkId + }), + isValid: false, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Create = utils.Ptr(true) + model.NetworkId = utils.Ptr(testNetworkId) + }), + }, + // network id and nic id + { + description: "provided flags invalid 5", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = testNetworkId + }), + isValid: false, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NetworkId = utils.Ptr(testNetworkId) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateFlagGroups() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flag groups: %v", err) + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequestAttach(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiAddNicToServerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequestAttach(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequestAttach(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) + } + }) + } +} + +func TestBuildRequestCreateAndAttach(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiAddNetworkToServerRequest + }{ + { + description: "base", + model: fixtureInputModel(func(model *inputModel) { + model.NicId = nil + model.NetworkId = utils.Ptr(testNetworkId) + model.Create = utils.Ptr(true) + }), + expectedRequest: fixtureRequestCreateAndAttach(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequestCreateAndAttach(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) + } + }) + } +} diff --git a/internal/cmd/beta/server/network-interface/detach/detach.go b/internal/cmd/beta/server/network-interface/detach/detach.go new file mode 100644 index 000000000..fb11d12d9 --- /dev/null +++ b/internal/cmd/beta/server/network-interface/detach/detach.go @@ -0,0 +1,171 @@ +package detach + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serverIdFlag = "server-id" + networkInterfaceIdFlag = "network-interface-id" + networkIdFlag = "network-id" + deleteFlag = "delete" + + defaultDeleteFlag = false +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + NicId *string + NetworkId *string + Delete *bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "detach", + Short: "Detaches a network interface from a server", + Long: "Detaches a network interface from a server.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Detach a network interface with ID "xxx" from a server with ID "yyy"`, + `$ stackit beta server network-interface detach --network-interface-id xxx --server-id yyy`, + ), + examples.NewExample( + `Detach and delete all network interfaces for network with ID "xxx" and detach them from a server with ID "yyy"`, + `$ stackit beta server network-interface detach --network-id xxx --server-id yyy --delete`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + // if the delete flag is provided a network interface is detached and deleted + if model.Delete != nil && *model.Delete { + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) + if err != nil { + p.Debug(print.ErrorLevel, "get network name: %v", err) + networkLabel = *model.NetworkId + } + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to detach and delete all network interfaces of network %q from server %q? (This cannot be undone)", networkLabel, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + // Call API + req := buildRequestDetachAndDelete(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("detach and delete network interfaces: %w", err) + } + p.Info("Detached and deleted all network interfaces of network %q from server %q\n", networkLabel, serverLabel) + return nil + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to detach network interface %q from server %q?", *model.NicId, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + // Call API + req := buildRequestDetach(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("detach network interface: %w", err) + } + p.Info("Detached network interface %q from server %q\n", *model.NicId, serverLabel) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + cmd.Flags().Var(flags.UUIDFlag(), networkInterfaceIdFlag, "Network Interface ID") + cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID") + cmd.Flags().BoolP(deleteFlag, "b", defaultDeleteFlag, "If this is set all network interfaces will be deleted. (default false)") + + cmd.MarkFlagsRequiredTogether(deleteFlag, networkIdFlag) + cmd.MarkFlagsMutuallyExclusive(deleteFlag, networkInterfaceIdFlag) + cmd.MarkFlagsMutuallyExclusive(networkIdFlag, networkInterfaceIdFlag) + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + // if delete is not provided then network-interface-id is needed + networkInterfaceId := flags.FlagToStringPointer(p, cmd, networkInterfaceIdFlag) + deleteValue := flags.FlagToBoolPointer(p, cmd, deleteFlag) + if deleteValue == nil && networkInterfaceId == nil { + return nil, &cliErr.ServerNicDetachMissingNicIdError{Cmd: cmd} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NicId: networkInterfaceId, + Delete: deleteValue, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequestDetach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveNicFromServerRequest { + return apiClient.RemoveNicFromServer(ctx, model.ProjectId, *model.ServerId, *model.NicId) +} + +func buildRequestDetachAndDelete(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveNetworkFromServerRequest { + return apiClient.RemoveNetworkFromServer(ctx, model.ProjectId, *model.ServerId, *model.NetworkId) +} diff --git a/internal/cmd/beta/server/network-interface/detach/detach_test.go b/internal/cmd/beta/server/network-interface/detach/detach_test.go new file mode 100644 index 000000000..df408bbb8 --- /dev/null +++ b/internal/cmd/beta/server/network-interface/detach/detach_test.go @@ -0,0 +1,311 @@ +package detach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testNicId = uuid.NewString() +var testNetworkId = uuid.NewString() + +// contains nic id +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + networkInterfaceIdFlag: testNicId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + NicId: utils.Ptr(testNicId), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequestDetach(mods ...func(request *iaas.ApiRemoveNicFromServerRequest)) iaas.ApiRemoveNicFromServerRequest { + request := testClient.RemoveNicFromServer(testCtx, testProjectId, testServerId, testNicId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixtureRequestDetachAndDelete(mods ...func(request *iaas.ApiRemoveNetworkFromServerRequest)) iaas.ApiRemoveNetworkFromServerRequest { + request := testClient.RemoveNetworkFromServer(testCtx, testProjectId, testServerId, testNetworkId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + // only delete + { + description: "provided flags invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[deleteFlag] = "true" + delete(flagValues, networkInterfaceIdFlag) + }), + isValid: false, + }, + // only network id + { + description: "provided flags invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkInterfaceIdFlag) + flagValues[networkIdFlag] = testNetworkId + }), + isValid: false, + }, + // delete and nic id + { + description: "provided flags invalid 3", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[deleteFlag] = "true" + }), + isValid: false, + }, + // delete and network id (valid) + { + description: "provided flags valid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[deleteFlag] = "true" + delete(flagValues, networkInterfaceIdFlag) + flagValues[networkIdFlag] = testNetworkId + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Delete = utils.Ptr(true) + model.NicId = nil + model.NetworkId = utils.Ptr(testNetworkId) + }), + }, + // delete, nic id and network id + { + description: "provided flags invalid 4", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[deleteFlag] = "true" + flagValues[networkIdFlag] = testNetworkId + }), + isValid: false, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Delete = utils.Ptr(true) + model.NetworkId = utils.Ptr(testNetworkId) + }), + }, + // network id and nic id + { + description: "provided flags invalid 5", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkIdFlag] = testNetworkId + }), + isValid: false, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NetworkId = utils.Ptr(testNetworkId) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateFlagGroups() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flag groups: %v", err) + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequestDetach(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRemoveNicFromServerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequestDetach(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequestDetach(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) + } + }) + } +} + +func TestBuildRequestDetachAndDelete(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRemoveNetworkFromServerRequest + }{ + { + description: "base", + model: fixtureInputModel(func(model *inputModel) { + model.NicId = nil + model.NetworkId = utils.Ptr(testNetworkId) + model.Delete = utils.Ptr(true) + }), + expectedRequest: fixtureRequestDetachAndDelete(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequestDetachAndDelete(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) + } + }) + } +} diff --git a/internal/cmd/beta/server/network-interface/list/list.go b/internal/cmd/beta/server/network-interface/list/list.go new file mode 100644 index 000000000..307afdbcd --- /dev/null +++ b/internal/cmd/beta/server/network-interface/list/list.go @@ -0,0 +1,172 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + serverIdFlag = "server-id" + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all attached network interfaces of a server", + Long: "Lists all attached network interfaces of a server.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all attached network interfaces of server with ID "xxx"`, + "$ stackit beta server network-interface list --server-id xxx", + ), + examples.NewExample( + `Lists all attached network interfaces of server with ID "xxx" in JSON format`, + "$ stackit beta server network-interface list --server-id xxx --output-format json", + ), + examples.NewExample( + `Lists up to 10 attached network interfaces of server with ID "xxx"`, + "$ stackit beta server network-interface list --server-id xxx --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list attached network interfaces: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + p.Info("No attached network interfaces found for server %q\n", serverLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, *model.ServerId, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID") + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServerNicsRequest { + return apiClient.ListServerNics(ctx, model.ProjectId, *model.ServerId) +} + +func outputResult(p *print.Printer, outputFormat, serverId string, serverNics []iaas.NIC) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(serverNics, "", " ") + if err != nil { + return fmt.Errorf("marshal server network interfaces: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(serverNics, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server network interfaces: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("NIC ID", "SERVER ID") + + for i := range serverNics { + nic := serverNics[i] + table.AddRow(*nic.Id, serverId) + } + table.EnableAutoMergeOnColumns(2) + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/server/network-interface/list/list_test.go b/internal/cmd/beta/server/network-interface/list/list_test.go new file mode 100644 index 000000000..9f729b86a --- /dev/null +++ b/internal/cmd/beta/server/network-interface/list/list_test.go @@ -0,0 +1,211 @@ +package list + +// TODO: hier sind wir + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + ServerId: utils.Ptr(testServerId), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListServerNicsRequest)) iaas.ApiListServerNicsRequest { + request := testClient.ListServerNics(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListServerNicsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/network-interface/network-interface.go b/internal/cmd/beta/server/network-interface/network-interface.go new file mode 100644 index 000000000..88fc744dd --- /dev/null +++ b/internal/cmd/beta/server/network-interface/network-interface.go @@ -0,0 +1,30 @@ +package networkinterface + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface/detach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "network-interface", + Short: "Allows attaching/detaching network interfaces to servers", + Long: "Allows attaching/detaching network interfaces to servers.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(attach.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(detach.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 4b8ba0fd4..90aae1422 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" + networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume" @@ -39,4 +40,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(publicip.NewCmd(p)) cmd.AddCommand(update.NewCmd(p)) cmd.AddCommand(volume.NewCmd(p)) + cmd.AddCommand(networkinterface.NewCmd(p)) } diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index 38aaa0835..324abbadf 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -146,8 +146,28 @@ To enable it, run: IAAS_SERVER_MISSING_VOLUME_TYPE = `The "boot-volume-source-type" flag must be provided together with "boot-volume-source-id" flag.` IAAS_SERVER_MISSING_IMAGE_OR_VOLUME_FLAGS = `Either "image-id" or "boot-volume-source-type" and "boot-volume-source-id" flags must be provided.` + + IAAS_SERVER_NIC_ATTACH_MISSING_NIC_ID = `The "network-interface-id" flag must be provided if the "create" flag is not provided.` + + IAAS_SERVER_NIC_DETACH_MISSING_NIC_ID = `The "network-interface-id" flag must be provided if the "delete" flag is not provided.` ) +type ServerNicAttachMissingNicIdError struct { + Cmd *cobra.Command +} + +func (e *ServerNicAttachMissingNicIdError) Error() string { + return IAAS_SERVER_NIC_ATTACH_MISSING_NIC_ID +} + +type ServerNicDetachMissingNicIdError struct { + Cmd *cobra.Command +} + +func (e *ServerNicDetachMissingNicIdError) Error() string { + return IAAS_SERVER_NIC_DETACH_MISSING_NIC_ID +} + type ServerCreateMissingVolumeIdError struct { Cmd *cobra.Command } From c715b0ac904913e15db4550b8710f2910b6e39a3 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Mon, 9 Dec 2024 13:11:22 +0100 Subject: [PATCH 118/619] fix(debug printer): Handle HTML encodings correctly (#530) Signed-off-by: Alexander Dahmen --- internal/pkg/print/debug.go | 20 ++++++++++++++++---- internal/pkg/print/debug_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/internal/pkg/print/debug.go b/internal/pkg/print/debug.go index d0927d8df..60962ba7b 100644 --- a/internal/pkg/print/debug.go +++ b/internal/pkg/print/debug.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "net/url" "slices" "sort" "strings" @@ -141,13 +142,18 @@ func BuildDebugStrFromHTTPRequest(req *http.Request, includeHeaders []string) ([ return nil, fmt.Errorf("request is invalid") } - status := fmt.Sprintf("request to %s: %s %s", req.URL, req.Method, req.Proto) + // unescape url in order to get rid of e.g. %40 + unescapedURL, err := url.PathUnescape(req.URL.String()) + if err != nil { + return nil, fmt.Errorf("unescape request url: %w", err) + } + + status := fmt.Sprintf("request to %s: %s %s", unescapedURL, req.Method, req.Proto) headersMap := buildHeaderMap(req.Header, includeHeaders) headers := fmt.Sprintf("request headers: %v", BuildDebugStrFromMap(headersMap)) var save io.ReadCloser - var err error save, req.Body, err = drainBody(req.Body) if err != nil { @@ -184,13 +190,19 @@ func BuildDebugStrFromHTTPResponse(resp *http.Response, includeHeaders []string) return nil, fmt.Errorf("response is invalid") } - status := fmt.Sprintf("response from %s: %s %s", resp.Request.URL, resp.Proto, resp.Status) + var err error + // unescape url in order to get rid of e.g. %40 + unescapedURL, err := url.PathUnescape(resp.Request.URL.String()) + if err != nil { + return nil, fmt.Errorf("unescape response url: %w", err) + } + + status := fmt.Sprintf("response from %s: %s %s", unescapedURL, resp.Proto, resp.Status) headersMap := buildHeaderMap(resp.Header, includeHeaders) headers := fmt.Sprintf("response headers: %v", BuildDebugStrFromMap(headersMap)) var save io.ReadCloser - var err error save, resp.Body, err = drainBody(resp.Body) if err != nil { diff --git a/internal/pkg/print/debug_test.go b/internal/pkg/print/debug_test.go index 35c3dfb6a..45ef90482 100644 --- a/internal/pkg/print/debug_test.go +++ b/internal/pkg/print/debug_test.go @@ -78,6 +78,28 @@ func fixtureHTTPRequest(mods ...func(req *http.Request)) *http.Request { return request } +func fixtureHTTPRequestUnescaped(mods ...func(req *http.Request)) *http.Request { + testBody, err := json.Marshal(map[string]string{"key": "value"}) + if err != nil { + return nil + } + + request, err := http.NewRequest("GET", "http://example.com/v2/projects?limit=50&member=User.Name%40stackit.cloud", bytes.NewReader(testBody)) + if err != nil { + return nil + } + + request.Header.Set("Content-Type", "application/json") + request.Header.Set("Accept", "application/json") + request.Header.Set("Content-Length", "15") + + for _, mod := range mods { + mod(request) + } + + return request +} + func fixtureHTTPResponse(mods ...func(resp *http.Response)) *http.Response { testBody, err := json.Marshal(map[string]string{"key": "value"}) if err != nil { @@ -402,6 +424,16 @@ func TestBuildDebugStrFromHTTPRequest(t *testing.T) { }, isValid: true, }, + { + description: "unescaped test", + inputReq: fixtureHTTPRequestUnescaped(), + expected: []string{ + "request to http://example.com/v2/projects?limit=50&member=User.Name@stackit.cloud: GET HTTP/1.1", + "request headers: [Accept: application/json, Content-Length: 15, Content-Type: application/json]", + "request body: [key: value]", + }, + isValid: true, + }, } for _, tt := range tests { From 9e89466bc878ee35c2455f689d8fc17b36a7e4b0 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:19:29 +0100 Subject: [PATCH 119/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.8 (#533) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 819d674f8..e63eb868f 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.7 + github.com/goccy/go-yaml v1.15.8 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 22eda04e1..90e7fb510 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.7 h1:L7XuKpd/A66X4w/dlk08lVfiIADdy79a1AzRoIefC98= -github.com/goccy/go-yaml v1.15.7/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.8 h1:0UhHxTWCcHQh4lZPIOdKY0ENpuBTAnx4n0L07VnbFag= +github.com/goccy/go-yaml v1.15.8/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 36548b5ac1db746606f596b0f182aa90010701c2 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:20:04 +0100 Subject: [PATCH 120/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.6.4 (#534) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e63eb868f..8d1d08da4 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.3 + github.com/jedib0t/go-pretty/v6 v6.6.4 github.com/lmittmann/tint v1.0.5 github.com/mattn/go-colorable v0.1.13 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index 90e7fb510..64de80743 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.3 h1:nGqgS0tgIO1Hto47HSaaK4ac/I/Bu7usmdD3qvs0WvM= -github.com/jedib0t/go-pretty/v6 v6.6.3/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.4 h1:B51RjA+Sytv0C0Je7PHGDXZBF2JpS5dZEWWRueBLP6U= +github.com/jedib0t/go-pretty/v6 v6.6.4/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= From 0312d28639a0c3629184df81674c002b812b1fc1 Mon Sep 17 00:00:00 2001 From: Marcel <72880145+marceljk@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:16:13 +0100 Subject: [PATCH 121/619] Onboard keypair commands (#532) * onboard key-pair commands: - create - delete - describe - list - update --- README.md | 2 +- docs/stackit_beta.md | 1 + docs/stackit_beta_key-pair.md | 37 ++++ docs/stackit_beta_key-pair_create.md | 51 +++++ docs/stackit_beta_key-pair_delete.md | 39 ++++ docs/stackit_beta_key-pair_describe.md | 43 ++++ docs/stackit_beta_key-pair_list.md | 50 +++++ docs/stackit_beta_key-pair_update.md | 40 ++++ internal/cmd/beta/beta.go | 2 + internal/cmd/beta/key-pair/create/create.go | 162 +++++++++++++++ .../cmd/beta/key-pair/create/create_test.go | 196 ++++++++++++++++++ .../key-pair/create/template/id_ed25519.pub | 1 + internal/cmd/beta/key-pair/delete/delete.go | 98 +++++++++ .../cmd/beta/key-pair/delete/delete_test.go | 176 ++++++++++++++++ .../cmd/beta/key-pair/describe/describe.go | 177 ++++++++++++++++ .../beta/key-pair/describe/describe_test.go | 188 +++++++++++++++++ internal/cmd/beta/key-pair/key-pair.go | 33 +++ internal/cmd/beta/key-pair/list/list.go | 171 +++++++++++++++ internal/cmd/beta/key-pair/list/list_test.go | 188 +++++++++++++++++ internal/cmd/beta/key-pair/update/update.go | 143 +++++++++++++ .../cmd/beta/key-pair/update/update_test.go | 190 +++++++++++++++++ 21 files changed, 1987 insertions(+), 1 deletion(-) create mode 100644 docs/stackit_beta_key-pair.md create mode 100644 docs/stackit_beta_key-pair_create.md create mode 100644 docs/stackit_beta_key-pair_delete.md create mode 100644 docs/stackit_beta_key-pair_describe.md create mode 100644 docs/stackit_beta_key-pair_list.md create mode 100644 docs/stackit_beta_key-pair_update.md create mode 100644 internal/cmd/beta/key-pair/create/create.go create mode 100644 internal/cmd/beta/key-pair/create/create_test.go create mode 100644 internal/cmd/beta/key-pair/create/template/id_ed25519.pub create mode 100644 internal/cmd/beta/key-pair/delete/delete.go create mode 100644 internal/cmd/beta/key-pair/delete/delete_test.go create mode 100644 internal/cmd/beta/key-pair/describe/describe.go create mode 100644 internal/cmd/beta/key-pair/describe/describe_test.go create mode 100644 internal/cmd/beta/key-pair/key-pair.go create mode 100644 internal/cmd/beta/key-pair/list/list.go create mode 100644 internal/cmd/beta/key-pair/list/list_test.go create mode 100644 internal/cmd/beta/key-pair/update/update.go create mode 100644 internal/cmd/beta/key-pair/update/update_test.go diff --git a/README.md b/README.md index 888f2e03d..638180559 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Service | CLI Commands | Status | | ---------------------------------- |----------------------------------------------------------------------------------------------------------------------| ------------------------- | | Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip` | :white_check_mark: (beta) | +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta key-pair` | :white_check_mark: (beta) | | Authorization | `project`, `organization` | :white_check_mark: | | DNS | `dns` | :white_check_mark: | | Kubernetes Engine (SKE) | `ske` | :white_check_mark: | diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index abc498479..acc708dd4 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -40,6 +40,7 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs * [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) * [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_key-pair.md b/docs/stackit_beta_key-pair.md new file mode 100644 index 000000000..dfbdaa355 --- /dev/null +++ b/docs/stackit_beta_key-pair.md @@ -0,0 +1,37 @@ +## stackit beta key-pair + +Provides functionality for SSH key pairs + +### Synopsis + +Provides functionality for SSH key pairs + +``` +stackit beta key-pair [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta key-pair" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta key-pair create](./stackit_beta_key-pair_create.md) - Creates a key pair +* [stackit beta key-pair delete](./stackit_beta_key-pair_delete.md) - Deletes a key pair +* [stackit beta key-pair describe](./stackit_beta_key-pair_describe.md) - Describes a key pair +* [stackit beta key-pair list](./stackit_beta_key-pair_list.md) - Lists all key pairs +* [stackit beta key-pair update](./stackit_beta_key-pair_update.md) - Updates a key pair + diff --git a/docs/stackit_beta_key-pair_create.md b/docs/stackit_beta_key-pair_create.md new file mode 100644 index 000000000..72ce7dfdf --- /dev/null +++ b/docs/stackit_beta_key-pair_create.md @@ -0,0 +1,51 @@ +## stackit beta key-pair create + +Creates a key pair + +### Synopsis + +Creates a key pair. + +``` +stackit beta key-pair create [flags] +``` + +### Examples + +``` + Create a new key pair with public-key "ssh-rsa xxx" + $ stackit beta key-pair create --public-key `ssh-rsa xxx` + + Create a new key pair with public-key from file "/Users/username/.ssh/id_rsa.pub" + $ stackit beta key-pair create --public-key `@/Users/username/.ssh/id_rsa.pub` + + Create a new key pair with name "KEY_PAIR_NAME" and public-key "ssh-rsa yyy" + $ stackit beta key-pair create --name KEY_PAIR_NAME --public-key `ssh-rsa yyy` + + Create a new key pair with public-key "ssh-rsa xxx" and labels "key=value,key1=value1" + $ stackit beta key-pair create --public-key `ssh-rsa xxx` --labels key=value,key1=value1 +``` + +### Options + +``` + -h, --help Help for "stackit beta key-pair create" + --labels stringToString Labels are key-value string pairs which can be attached to a key pair. E.g. '--labels key1=value1,key2=value2,...' (default []) + --name string Key pair name + --public-key string Public key to be imported (format: ssh-rsa|ssh-ed25519) +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs + diff --git a/docs/stackit_beta_key-pair_delete.md b/docs/stackit_beta_key-pair_delete.md new file mode 100644 index 000000000..15de8a582 --- /dev/null +++ b/docs/stackit_beta_key-pair_delete.md @@ -0,0 +1,39 @@ +## stackit beta key-pair delete + +Deletes a key pair + +### Synopsis + +Deletes a key pair. + +``` +stackit beta key-pair delete [flags] +``` + +### Examples + +``` + Delete key pair with name "KEY_PAIR_NAME" + $ stackit beta key-pair delete KEY_PAIR_NAME +``` + +### Options + +``` + -h, --help Help for "stackit beta key-pair delete" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs + diff --git a/docs/stackit_beta_key-pair_describe.md b/docs/stackit_beta_key-pair_describe.md new file mode 100644 index 000000000..54b0189bc --- /dev/null +++ b/docs/stackit_beta_key-pair_describe.md @@ -0,0 +1,43 @@ +## stackit beta key-pair describe + +Describes a key pair + +### Synopsis + +Describes a key pair. + +``` +stackit beta key-pair describe [flags] +``` + +### Examples + +``` + Get details about a key pair with name "KEY_PAIR_NAME" + $ stackit beta key-pair describe KEY_PAIR_NAME + + Get only the SSH public key of a key pair with name "KEY_PAIR_NAME" + $ stackit beta key-pair describe KEY_PAIR_NAME --public-key +``` + +### Options + +``` + -h, --help Help for "stackit beta key-pair describe" + --public-key Show only the public key +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs + diff --git a/docs/stackit_beta_key-pair_list.md b/docs/stackit_beta_key-pair_list.md new file mode 100644 index 000000000..8b04bdbe2 --- /dev/null +++ b/docs/stackit_beta_key-pair_list.md @@ -0,0 +1,50 @@ +## stackit beta key-pair list + +Lists all key pairs + +### Synopsis + +Lists all key pairs. + +``` +stackit beta key-pair list [flags] +``` + +### Examples + +``` + Lists all key pairs + $ stackit beta key-pair list + + Lists all key pairs which contains the label xxx + $ stackit beta key-pair list --label-selector xxx + + Lists all key pairs in JSON format + $ stackit beta key-pair list --output-format json + + Lists up to 10 key pairs + $ stackit beta key-pair list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta key-pair list" + --label-selector string Filter by label + --limit int Number of key pairs to list +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs + diff --git a/docs/stackit_beta_key-pair_update.md b/docs/stackit_beta_key-pair_update.md new file mode 100644 index 000000000..1dc94a8e8 --- /dev/null +++ b/docs/stackit_beta_key-pair_update.md @@ -0,0 +1,40 @@ +## stackit beta key-pair update + +Updates a key pair + +### Synopsis + +Updates a key pair. + +``` +stackit beta key-pair update [flags] +``` + +### Examples + +``` + Update the labels of a key pair with name "KEY_PAIR_NAME" with "key=value,key1=value1" + $ stackit beta key-pair update KEY_PAIR_NAME --labels key=value,key1=value1 +``` + +### Options + +``` + -h, --help Help for "stackit beta key-pair update" + --labels stringToString Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...' (default []) +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs + diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 389c0d614..975704383 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,6 +3,7 @@ package beta import ( "fmt" + keypair "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network" networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface" @@ -48,4 +49,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(volume.NewCmd(p)) cmd.AddCommand(networkinterface.NewCmd(p)) cmd.AddCommand(publicip.NewCmd(p)) + cmd.AddCommand(keypair.NewCmd(p)) } diff --git a/internal/cmd/beta/key-pair/create/create.go b/internal/cmd/beta/key-pair/create/create.go new file mode 100644 index 000000000..4626946b2 --- /dev/null +++ b/internal/cmd/beta/key-pair/create/create.go @@ -0,0 +1,162 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + nameFlag = "name" + publicKeyFlag = "public-key" + labelFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name *string + PublicKey *string + Labels *map[string]string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a key pair", + Long: "Creates a key pair.", + Args: cobra.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a new key pair with public-key "ssh-rsa xxx"`, + "$ stackit beta key-pair create --public-key `ssh-rsa xxx`", + ), + examples.NewExample( + `Create a new key pair with public-key from file "/Users/username/.ssh/id_rsa.pub"`, + "$ stackit beta key-pair create --public-key `@/Users/username/.ssh/id_rsa.pub`", + ), + examples.NewExample( + `Create a new key pair with name "KEY_PAIR_NAME" and public-key "ssh-rsa yyy"`, + "$ stackit beta key-pair create --name KEY_PAIR_NAME --public-key `ssh-rsa yyy`", + ), + examples.NewExample( + `Create a new key pair with public-key "ssh-rsa xxx" and labels "key=value,key1=value1"`, + "$ stackit beta key-pair create --public-key `ssh-rsa xxx` --labels key=value,key1=value1", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := "Are your sure you want to create a key pair?" + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create key pair: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "Key pair name") + cmd.Flags().Var(flags.ReadFromFileFlag(), publicKeyFlag, "Public key to be imported (format: ssh-rsa|ssh-ed25519)") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a key pair. E.g. '--labels key1=value1,key2=value2,...'") + + err := cmd.MarkFlagRequired(publicKeyFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + PublicKey: flags.FlagToStringPointer(p, cmd, publicKeyFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string fo debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateKeyPairRequest { + req := apiClient.CreateKeyPair(ctx) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + + payload := iaas.CreateKeyPairPayload{ + Name: model.Name, + Labels: labelsMap, + PublicKey: model.PublicKey, + } + + return req.CreateKeyPairPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, item *iaas.Keypair) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(item, "", " ") + if err != nil { + return fmt.Errorf("marshal key pair: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(item, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal key pair: %w", err) + } + p.Outputln(string(details)) + default: + p.Outputf("Created key pair %q.\nkey pair Fingerprint: %q\n", *item.Name, *item.Fingerprint) + } + return nil +} diff --git a/internal/cmd/beta/key-pair/create/create_test.go b/internal/cmd/beta/key-pair/create/create_test.go new file mode 100644 index 000000000..adb0f90b7 --- /dev/null +++ b/internal/cmd/beta/key-pair/create/create_test.go @@ -0,0 +1,196 @@ +package create + +import ( + "context" + "os" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testPublicKey = "ssh-rsa " +var testKeyPairName = "foobar_key" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + publicKeyFlag: testPublicKey, + labelFlag: "foo=bar", + nameFlag: testKeyPairName, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Labels: utils.Ptr(map[string]string{ + "foo": "bar", + }), + PublicKey: utils.Ptr(testPublicKey), + Name: utils.Ptr(testKeyPairName), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateKeyPairRequest)) iaas.ApiCreateKeyPairRequest { + request := testClient.CreateKeyPair(testCtx) + request = request.CreateKeyPairPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateKeyPairPayload)) iaas.CreateKeyPairPayload { + payload := iaas.CreateKeyPairPayload{ + Labels: utils.Ptr(map[string]interface{}{ + "foo": "bar", + }), + PublicKey: utils.Ptr(testPublicKey), + Name: utils.Ptr(testKeyPairName), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + delete(flagValues, labelFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = nil + model.Labels = nil + }), + }, + { + description: "read public key from file", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[publicKeyFlag] = "@./template/id_ed25519.pub" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + file, err := os.ReadFile("./template/id_ed25519.pub") + if err != nil { + t.Fatal("could not create expected Model", err) + } + model.PublicKey = utils.Ptr(string(file)) + }), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateKeyPairRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/key-pair/create/template/id_ed25519.pub b/internal/cmd/beta/key-pair/create/template/id_ed25519.pub new file mode 100644 index 000000000..082c95349 --- /dev/null +++ b/internal/cmd/beta/key-pair/create/template/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFG1ogKtJ5SElBm3mxhFhdvXxXiz+FxYoOvcdWSW2/ZI diff --git a/internal/cmd/beta/key-pair/delete/delete.go b/internal/cmd/beta/key-pair/delete/delete.go new file mode 100644 index 000000000..0cc0c77bc --- /dev/null +++ b/internal/cmd/beta/key-pair/delete/delete.go @@ -0,0 +1,98 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "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/iaas/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + keyPairNameArg = "KEY_PAIR_NAME" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyPairName string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a key pair", + Long: "Deletes a key pair.", + Args: args.SingleArg(keyPairNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Delete key pair with name "KEY_PAIR_NAME"`, + "$ stackit beta key-pair delete KEY_PAIR_NAME", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete key pair %q?", model.KeyPairName) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete key pair: %w", err) + } + + p.Info("Deleted key pair %q\n", model.KeyPairName) + + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + keyPairName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyPairName: keyPairName, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteKeyPairRequest { + return apiClient.DeleteKeyPair(ctx, model.KeyPairName) +} diff --git a/internal/cmd/beta/key-pair/delete/delete_test.go b/internal/cmd/beta/key-pair/delete/delete_test.go new file mode 100644 index 000000000..cfbcd29e8 --- /dev/null +++ b/internal/cmd/beta/key-pair/delete/delete_test.go @@ -0,0 +1,176 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testKeyPairName = "key-pair-name" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testKeyPairName, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{} + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + KeyPairName: testKeyPairName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteKeyPairRequest)) iaas.ApiDeleteKeyPairRequest { + request := testClient.DeleteKeyPair(testCtx, testKeyPairName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no args", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flags", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: true, + expectedModel: fixtureInputModel(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteKeyPairRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/key-pair/describe/describe.go b/internal/cmd/beta/key-pair/describe/describe.go new file mode 100644 index 000000000..f45f11dff --- /dev/null +++ b/internal/cmd/beta/key-pair/describe/describe.go @@ -0,0 +1,177 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + keyPairNameArg = "KEY_PAIR_NAME" + + publicKeyFlag = "public-key" + + maxLengthPublicKey = 50 +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyPairName string + PublicKey bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Describes a key pair", + Long: "Describes a key pair.", + Args: args.SingleArg(keyPairNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details about a key pair with name "KEY_PAIR_NAME"`, + "$ stackit beta key-pair describe KEY_PAIR_NAME", + ), + examples.NewExample( + `Get only the SSH public key of a key pair with name "KEY_PAIR_NAME"`, + "$ stackit beta key-pair describe KEY_PAIR_NAME --public-key", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read key pair: %w", err) + } + + return outputResult(p, model.OutputFormat, model.PublicKey, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Bool(publicKeyFlag, false, "Show only the public key") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + keyPairName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyPairName: keyPairName, + PublicKey: flags.FlagToBoolValue(p, cmd, publicKeyFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetKeyPairRequest { + return apiClient.GetKeyPair(ctx, model.KeyPairName) +} + +func outputResult(p *print.Printer, outputFormat string, showOnlyPublicKey bool, keyPair *iaas.Keypair) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(keyPair, "", " ") + if showOnlyPublicKey { + onlyPublicKey := map[string]string{ + "publicKey": *keyPair.PublicKey, + } + details, err = json.MarshalIndent(onlyPublicKey, "", " ") + } + + if err != nil { + return fmt.Errorf("marshal key pair: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(keyPair, yaml.IndentSequence(true)) + if showOnlyPublicKey { + onlyPublicKey := map[string]string{ + "publicKey": *keyPair.PublicKey, + } + details, err = yaml.MarshalWithOptions(onlyPublicKey, yaml.IndentSequence(true)) + } + + if err != nil { + return fmt.Errorf("marshal key pair: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + if showOnlyPublicKey { + p.Outputln(*keyPair.PublicKey) + return nil + } + table := tables.NewTable() + table.AddRow("KEY PAIR NAME", *keyPair.Name) + table.AddSeparator() + + if *keyPair.Labels != nil && len(*keyPair.Labels) > 0 { + var labels []string + for key, value := range *keyPair.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } + + table.AddRow("FINGERPRINT", *keyPair.Fingerprint) + table.AddSeparator() + + truncatedPublicKey := (*keyPair.PublicKey)[:maxLengthPublicKey] + "..." + table.AddRow("PUBLIC KEY", truncatedPublicKey) + table.AddSeparator() + + table.AddRow("CREATED AT", *keyPair.CreatedAt) + table.AddSeparator() + + table.AddRow("UPDATED AT", *keyPair.UpdatedAt) + table.AddSeparator() + + p.Outputln(table.Render()) + } + + return nil +} diff --git a/internal/cmd/beta/key-pair/describe/describe_test.go b/internal/cmd/beta/key-pair/describe/describe_test.go new file mode 100644 index 000000000..69add5828 --- /dev/null +++ b/internal/cmd/beta/key-pair/describe/describe_test.go @@ -0,0 +1,188 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testKeyPairName = "foobar" +var testPublicKeyFlag = "true" + +func fixtureArgValues(mods ...func(argVales []string)) []string { + argVales := []string{ + testKeyPairName, + } + for _, m := range mods { + m(argVales) + } + return argVales +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{} + for _, m := range mods { + m(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + KeyPairName: testKeyPairName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetKeyPairRequest)) iaas.ApiGetKeyPairRequest { + request := testClient.GetKeyPair(testCtx, testKeyPairName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argsValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argsValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argsValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argsValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argsValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "set flag 'public-key' true", + argsValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[publicKeyFlag] = testPublicKeyFlag + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.PublicKey = true + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argsValues) + 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.argsValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedResult iaas.ApiGetKeyPairRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedResult: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, tt.model, testClient) + + diff := cmp.Diff(request, tt.expectedResult, + cmp.AllowUnexported(tt.expectedResult), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/key-pair/key-pair.go b/internal/cmd/beta/key-pair/key-pair.go new file mode 100644 index 000000000..d8e6f91aa --- /dev/null +++ b/internal/cmd/beta/key-pair/key-pair.go @@ -0,0 +1,33 @@ +package keypair + +import ( + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "key-pair", + Short: "Provides functionality for SSH key pairs", + Long: "Provides functionality for SSH key pairs", + Args: cobra.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) +} diff --git a/internal/cmd/beta/key-pair/list/list.go b/internal/cmd/beta/key-pair/list/list.go new file mode 100644 index 000000000..469a332fe --- /dev/null +++ b/internal/cmd/beta/key-pair/list/list.go @@ -0,0 +1,171 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + limitFlag = "limit" + labelSelectorFlag = "label-selector" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + LabelSelector *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all key pairs", + Long: "Lists all key pairs.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all key pairs`, + "$ stackit beta key-pair list", + ), + examples.NewExample( + `Lists all key pairs which contains the label xxx`, + "$ stackit beta key-pair list --label-selector xxx", + ), + examples.NewExample( + `Lists all key pairs in JSON format`, + "$ stackit beta key-pair list --output-format json", + ), + examples.NewExample( + `Lists up to 10 key pairs`, + "$ stackit beta key-pair list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list key pairs: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + p.Info("No key pairs found\n") + return nil + } + + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Number of key pairs to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.InfoLevel, modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListKeyPairsRequest { + req := apiClient.ListKeyPairs(ctx) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + return req +} + +func outputResult(p *print.Printer, outputFormat string, keyPairs []iaas.Keypair) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(keyPairs, "", " ") + if err != nil { + return fmt.Errorf("marshal key pairs: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(keyPairs, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal key pairs: %w", err) + } + p.Outputln(string(details)) + + default: + table := tables.NewTable() + table.SetHeader("KEY PAIR NAME", "LABELS", "FINGERPRINT", "CREATED AT", "UPDATED AT") + + for idx := range keyPairs { + keyPair := keyPairs[idx] + + var labels []string + for key, value := range *keyPair.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + + table.AddRow(*keyPair.Name, strings.Join(labels, ", "), *keyPair.Fingerprint, *keyPair.CreatedAt, *keyPair.UpdatedAt) + } + + p.Outputln(table.Render()) + } + return nil +} diff --git a/internal/cmd/beta/key-pair/list/list_test.go b/internal/cmd/beta/key-pair/list/list_test.go new file mode 100644 index 000000000..99bedd4ba --- /dev/null +++ b/internal/cmd/beta/key-pair/list/list_test.go @@ -0,0 +1,188 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testLabelSelector = "foo=bar" +var testLimit = int64(64) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + limitFlag: strconv.FormatInt(testLimit, 10), + labelSelectorFlag: testLabelSelector, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(inputModel *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(testLimit), + LabelSelector: utils.Ptr(testLabelSelector), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListKeyPairsRequest)) iaas.ApiListKeyPairsRequest { + request := testClient.ListKeyPairs(testCtx) + request = request.LabelSelector(testLabelSelector) + 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: "no values", + flagValues: map[string]string{}, + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.Limit = nil + inputModel.LabelSelector = nil + }), + }, + { + description: "withoutLimit", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, "limit") + }), + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.Limit = nil + }), + }, + { + description: "invalid limit 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "invalid limit 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "" + }), + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.LabelSelector = utils.Ptr("") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %v", err) + } + + if !tt.isValid { + t.Fatal("did not fail on invalid input") + } + diff := cmp.Diff(model, tt.expectedModel) + if diff != "" { + t.Fatalf("data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListKeyPairsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("request does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/key-pair/update/update.go b/internal/cmd/beta/key-pair/update/update.go new file mode 100644 index 000000000..483cd7798 --- /dev/null +++ b/internal/cmd/beta/key-pair/update/update.go @@ -0,0 +1,143 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + keyPairNameArg = "KEY_PAIR_NAME" + labelsFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Labels *map[string]string + KeyPairName *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a key pair", + Long: "Updates a key pair.", + Args: args.SingleArg(keyPairNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Update the labels of a key pair with name "KEY_PAIR_NAME" with "key=value,key1=value1"`, + "$ stackit beta key-pair update KEY_PAIR_NAME --labels key=value,key1=value1", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update key pair %q?", *model.KeyPairName) + err = p.PromptForConfirmation(prompt) + if err != nil { + return fmt.Errorf("update key pair: %w", err) + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update key pair: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringToString(labelsFlag, nil, "Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...'") + + err := cmd.MarkFlagRequired(labelsFlag) + cobra.CheckErr(err) +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateKeyPairRequest { + req := apiClient.UpdateKeyPair(ctx, *model.KeyPairName) + + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + payload := iaas.UpdateKeyPairPayload{ + Labels: labelsMap, + } + return req.UpdateKeyPairPayload(payload) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + keyPairName := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), + KeyPairName: utils.Ptr(keyPairName), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func outputResult(p *print.Printer, model *inputModel, keyPair *iaas.Keypair) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(keyPair, "", " ") + if err != nil { + return fmt.Errorf("marshal key pair: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(keyPair, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal key pair: %w", err) + } + p.Outputln(string(details)) + default: + p.Outputf("Updated labels of key pair %q\n", *model.KeyPairName) + } + return nil +} diff --git a/internal/cmd/beta/key-pair/update/update_test.go b/internal/cmd/beta/key-pair/update/update_test.go new file mode 100644 index 000000000..49d6aeabb --- /dev/null +++ b/internal/cmd/beta/key-pair/update/update_test.go @@ -0,0 +1,190 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testKeyPairName = "foobar_key" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testKeyPairName, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + labelsFlag: "foo=bar", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Labels: utils.Ptr(map[string]string{ + "foo": "bar", + }), + KeyPairName: utils.Ptr(testKeyPairName), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateKeyPairRequest)) iaas.ApiUpdateKeyPairRequest { + request := testClient.UpdateKeyPair(testCtx, testKeyPairName) + request = request.UpdateKeyPairPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.UpdateKeyPairPayload)) iaas.UpdateKeyPairPayload { + payload := iaas.UpdateKeyPairPayload{ + Labels: utils.Ptr(map[string]interface{}{ + "foo": "bar", + }), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flags", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateKeyPairRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} From 9324319c69c607028f0e2e3381348e0b861898f4 Mon Sep 17 00:00:00 2001 From: Marcel <72880145+marceljk@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:38:26 +0100 Subject: [PATCH 122/619] Onboard IaaS Server Service Account Commands (#528) * Onboard server service-account commands --- docs/stackit_beta_server.md | 1 + docs/stackit_beta_server_service-account.md | 35 +++ ...ckit_beta_server_service-account_attach.md | 40 ++++ ...ckit_beta_server_service-account_detach.md | 40 ++++ ...tackit_beta_server_service-account_list.md | 47 ++++ internal/cmd/beta/server/server.go | 3 + .../server/service-account/attach/attach.go | 145 +++++++++++ .../service-account/attach/attach_test.go | 226 ++++++++++++++++++ .../server/service-account/detach/detach.go | 145 +++++++++++ .../service-account/detach/detach_test.go | 226 ++++++++++++++++++ .../beta/server/service-account/list/list.go | 170 +++++++++++++ .../server/service-account/list/list_test.go | 221 +++++++++++++++++ .../server/service-account/service-account.go | 30 +++ 13 files changed, 1329 insertions(+) create mode 100644 docs/stackit_beta_server_service-account.md create mode 100644 docs/stackit_beta_server_service-account_attach.md create mode 100644 docs/stackit_beta_server_service-account_detach.md create mode 100644 docs/stackit_beta_server_service-account_list.md create mode 100644 internal/cmd/beta/server/service-account/attach/attach.go create mode 100644 internal/cmd/beta/server/service-account/attach/attach_test.go create mode 100644 internal/cmd/beta/server/service-account/detach/detach.go create mode 100644 internal/cmd/beta/server/service-account/detach/detach_test.go create mode 100644 internal/cmd/beta/server/service-account/list/list.go create mode 100644 internal/cmd/beta/server/service-account/list/list_test.go create mode 100644 internal/cmd/beta/server/service-account/service-account.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index 59943e5be..b8f078aad 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -37,6 +37,7 @@ stackit beta server [flags] * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project * [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers * [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers +* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers * [stackit beta server update](./stackit_beta_server_update.md) - Updates a server * [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_service-account.md b/docs/stackit_beta_server_service-account.md new file mode 100644 index 000000000..294f369d9 --- /dev/null +++ b/docs/stackit_beta_server_service-account.md @@ -0,0 +1,35 @@ +## stackit beta server service-account + +Allows attaching/detaching service accounts to servers + +### Synopsis + +Allows attaching/detaching service accounts to servers + +``` +stackit beta server service-account [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server service-account" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit beta server service-account attach](./stackit_beta_server_service-account_attach.md) - Attach a service account to a server +* [stackit beta server service-account detach](./stackit_beta_server_service-account_detach.md) - Detach a service account from a server +* [stackit beta server service-account list](./stackit_beta_server_service-account_list.md) - List all attached service accounts for a server + diff --git a/docs/stackit_beta_server_service-account_attach.md b/docs/stackit_beta_server_service-account_attach.md new file mode 100644 index 000000000..5d00495df --- /dev/null +++ b/docs/stackit_beta_server_service-account_attach.md @@ -0,0 +1,40 @@ +## stackit beta server service-account attach + +Attach a service account to a server + +### Synopsis + +Attach a service account to a server + +``` +stackit beta server service-account attach [flags] +``` + +### Examples + +``` + Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy" + $ stackit beta server service-account attach xxx@sa.stackit.cloud --server-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server service-account attach" + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers + diff --git a/docs/stackit_beta_server_service-account_detach.md b/docs/stackit_beta_server_service-account_detach.md new file mode 100644 index 000000000..88276a8ce --- /dev/null +++ b/docs/stackit_beta_server_service-account_detach.md @@ -0,0 +1,40 @@ +## stackit beta server service-account detach + +Detach a service account from a server + +### Synopsis + +Detach a service account from a server + +``` +stackit beta server service-account detach [flags] +``` + +### Examples + +``` + Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy" + $ stackit beta server service-account detach xxx@sa.stackit.cloud --server-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server service-account detach" + -s, --server-id string Server id +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers + diff --git a/docs/stackit_beta_server_service-account_list.md b/docs/stackit_beta_server_service-account_list.md new file mode 100644 index 000000000..64f993e2d --- /dev/null +++ b/docs/stackit_beta_server_service-account_list.md @@ -0,0 +1,47 @@ +## stackit beta server service-account list + +List all attached service accounts for a server + +### Synopsis + +List all attached service accounts for a server + +``` +stackit beta server service-account list [flags] +``` + +### Examples + +``` + List all attached service accounts for a server with ID "xxx" + $ stackit beta server service-account list --server-id xxx + + List up to 10 attached service accounts for a server with ID "xxx" + $ stackit beta server service-account list --server-id xxx --limit 10 + + List all attached service accounts for a server with ID "xxx" in JSON format + $ stackit beta server service-account list --server-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server service-account list" + --limit int Maximum number of entries to list + -s, --server-id string Server ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers + diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 90aae1422..9b96c1322 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -9,8 +9,10 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" + serviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -38,6 +40,7 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(describe.NewCmd(p)) cmd.AddCommand(list.NewCmd(p)) cmd.AddCommand(publicip.NewCmd(p)) + cmd.AddCommand(serviceaccount.NewCmd(p)) cmd.AddCommand(update.NewCmd(p)) cmd.AddCommand(volume.NewCmd(p)) cmd.AddCommand(networkinterface.NewCmd(p)) diff --git a/internal/cmd/beta/server/service-account/attach/attach.go b/internal/cmd/beta/server/service-account/attach/attach.go new file mode 100644 index 000000000..c5cffdbad --- /dev/null +++ b/internal/cmd/beta/server/service-account/attach/attach.go @@ -0,0 +1,145 @@ +package attach + +import ( + "context" + "encoding/json" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" + + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + ServiceAccMail string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "attach", + Short: "Attach a service account to a server", + Long: "Attach a service account to a server", + Args: args.SingleArg(serviceAccMailArg, nil), + Example: examples.Build( + examples.NewExample( + `Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy"`, + "$ stackit beta server service-account attach xxx@sa.stackit.cloud --server-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to attach service account %q to server %q?", model.ServiceAccMail, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("attach service account to server: %w", err) + } + + return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serviceAccMail := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServiceAccMail: serviceAccMail, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddServiceAccountToServerRequest { + req := apiClient.AddServiceAccountToServer(ctx, model.ProjectId, *model.ServerId, model.ServiceAccMail) + return req +} + +func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, serviceAccounts *iaas.ServiceAccountMailListResponse) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(serviceAccounts, "", " ") + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Attached service account %q to server %q\n", serviceAccMail, serverLabel) + return nil + } +} diff --git a/internal/cmd/beta/server/service-account/attach/attach_test.go b/internal/cmd/beta/server/service-account/attach/attach_test.go new file mode 100644 index 000000000..f7854c24b --- /dev/null +++ b/internal/cmd/beta/server/service-account/attach/attach_test.go @@ -0,0 +1,226 @@ +package attach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testServiceAccount = "test@example.com" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServiceAccount, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + ServiceAccMail: testServiceAccount, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiAddServiceAccountToServerRequest)) iaas.ApiAddServiceAccountToServerRequest { + request := testClient.AddServiceAccountToServer(testCtx, testProjectId, testServerId, testServiceAccount) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "service account argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiAddServiceAccountToServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/service-account/detach/detach.go b/internal/cmd/beta/server/service-account/detach/detach.go new file mode 100644 index 000000000..99e95506c --- /dev/null +++ b/internal/cmd/beta/server/service-account/detach/detach.go @@ -0,0 +1,145 @@ +package detach + +import ( + "context" + "encoding/json" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" + + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId *string + ServiceAccMail string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "detach", + Short: "Detach a service account from a server", + Long: "Detach a service account from a server", + Args: args.SingleArg(serviceAccMailArg, nil), + Example: examples.Build( + examples.NewExample( + `Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy"`, + "$ stackit beta server service-account detach xxx@sa.stackit.cloud --server-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = *model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are your sure you want to detach service account %q from a server %q?", model.ServiceAccMail, serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("detach service account request: %w", err) + } + + return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server id") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serviceAccMail := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServiceAccMail: serviceAccMail, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveServiceAccountFromServerRequest { + req := apiClient.RemoveServiceAccountFromServer(ctx, model.ProjectId, *model.ServerId, model.ServiceAccMail) + return req +} + +func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, service *iaas.ServiceAccountMailListResponse) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(service, "", " ") + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(service, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal service account: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Detached service account %q from server %q\n", serviceAccMail, serverLabel) + return nil + } +} diff --git a/internal/cmd/beta/server/service-account/detach/detach_test.go b/internal/cmd/beta/server/service-account/detach/detach_test.go new file mode 100644 index 000000000..5250e0a6f --- /dev/null +++ b/internal/cmd/beta/server/service-account/detach/detach_test.go @@ -0,0 +1,226 @@ +package detach + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testServiceAccount = "test@example.com" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServiceAccount, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + ServiceAccMail: testServiceAccount, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiRemoveServiceAccountFromServerRequest)) iaas.ApiRemoveServiceAccountFromServerRequest { + request := testClient.RemoveServiceAccountFromServer(testCtx, testProjectId, testServerId, testServiceAccount) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "service account argument missing", + argValues: []string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRemoveServiceAccountFromServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/service-account/list/list.go b/internal/cmd/beta/server/service-account/list/list.go new file mode 100644 index 000000000..c938f2b80 --- /dev/null +++ b/internal/cmd/beta/server/service-account/list/list.go @@ -0,0 +1,170 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + serverIdFlag = "server-id" + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + ServerId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List all attached service accounts for a server", + Long: "List all attached service accounts for a server", + Args: cobra.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all attached service accounts for a server with ID "xxx"`, + "$ stackit beta server service-account list --server-id xxx", + ), + examples.NewExample( + `List up to 10 attached service accounts for a server with ID "xxx"`, + "$ stackit beta server service-account list --server-id xxx --limit 10", + ), + examples.NewExample( + `List all attached service accounts for a server with ID "xxx" in JSON format`, + "$ stackit beta server service-account list --server-id xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverName, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverName = *model.ServerId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list service accounts: %w", err) + } + serviceAccounts := *resp.Items + if len(serviceAccounts) == 0 { + p.Info("No service accounts found for server %s\n", *model.ServerId) + return nil + } + + if model.Limit != nil && len(serviceAccounts) > int(*model.Limit) { + serviceAccounts = serviceAccounts[:int(*model.Limit)] + } + + return outputResult(p, model.OutputFormat, *model.ServerId, serverName, serviceAccounts) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServerServiceAccountsRequest { + req := apiClient.ListServerServiceAccounts(ctx, model.ProjectId, *model.ServerId) + return req +} + +func outputResult(p *print.Printer, outputFormat, serverId, serverName string, serviceAccounts []string) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(serviceAccounts, "", " ") + if err != nil { + return fmt.Errorf("marshal service accounts list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal service accounts list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("SERVER ID", "SERVER NAME", "SERVICE ACCOUNT") + for i := range serviceAccounts { + table.AddRow(serverId, serverName, serviceAccounts[i]) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("rednder table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/service-account/list/list_test.go b/internal/cmd/beta/server/service-account/list/list_test.go new file mode 100644 index 000000000..04ba8c721 --- /dev/null +++ b/internal/cmd/beta/server/service-account/list/list_test.go @@ -0,0 +1,221 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testLimit = int64(10) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + limitFlag: strconv.FormatInt(testLimit, 10), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(inputModel *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: utils.Ptr(testServerId), + Limit: utils.Ptr(testLimit), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListServerServiceAccountsRequest)) iaas.ApiListServerServiceAccountsRequest { + request := testClient.ListServerServiceAccounts(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, serverIdFlag) + }), + isValid: false, + }, + { + description: "server id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" + }), + isValid: false, + }, + { + description: "server id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "without limit", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, limitFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Limit = nil + }), + }, + { + description: "limit invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListServerServiceAccountsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Request does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/service-account/service-account.go b/internal/cmd/beta/server/service-account/service-account.go new file mode 100644 index 000000000..e0907d4f1 --- /dev/null +++ b/internal/cmd/beta/server/service-account/service-account.go @@ -0,0 +1,30 @@ +package serviceaccount + +import ( + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/detach" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/list" + + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "service-account", + Short: "Allows attaching/detaching service accounts to servers", + Long: "Allows attaching/detaching service accounts to servers", + Args: cobra.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(attach.NewCmd(p)) + cmd.AddCommand(detach.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} From 49589d54444c4ae52926d202c33322260d930aca Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:54:32 +0100 Subject: [PATCH 123/619] Onboard IaaS security group rule commands (#523) * onboard security group rule commands * fix NPE * Update internal/cmd/beta/security-group-rule/create/create.go Co-authored-by: Alexander Dahmen * Update internal/cmd/beta/security-group-rule/create/create.go Co-authored-by: Alexander Dahmen * Update internal/cmd/beta/security-group-rule/list/list.go Co-authored-by: Alexander Dahmen * Update internal/cmd/beta/security-group-rule/create/create_test.go Co-authored-by: Alexander Dahmen * fix unit tests * Update internal/cmd/beta/security-group-rule/delete/delete_test.go Co-authored-by: Alexander Dahmen * Update internal/cmd/beta/security-group-rule/delete/delete_test.go Co-authored-by: Alexander Dahmen * Update internal/cmd/beta/security-group-rule/delete/delete_test.go Co-authored-by: Alexander Dahmen * fix unit tests * update docs * fix linter issues * fix unit tests * apply acceptance feedbacks * add check for protocol if port range info is provided * changed the flag description * remove the flag control (api errors are sufficient) * edit flag descriptions --------- Co-authored-by: Alexander Dahmen --- README.md | 44 +-- docs/stackit_beta.md | 1 + docs/stackit_beta_security-group.md | 33 ++ docs/stackit_beta_security-group_rule.md | 36 ++ ...stackit_beta_security-group_rule_create.md | 60 ++++ ...stackit_beta_security-group_rule_delete.md | 42 +++ ...ackit_beta_security-group_rule_describe.md | 43 +++ docs/stackit_beta_security-group_rule_list.md | 47 +++ internal/cmd/beta/beta.go | 2 + .../beta/security-group/rule/create/create.go | 246 +++++++++++++ .../security-group/rule/create/create_test.go | 335 ++++++++++++++++++ .../beta/security-group/rule/delete/delete.go | 130 +++++++ .../security-group/rule/delete/delete_test.go | 235 ++++++++++++ .../security-group/rule/describe/describe.go | 186 ++++++++++ .../rule/describe/describe_test.go | 246 +++++++++++++ .../cmd/beta/security-group/rule/list/list.go | 191 ++++++++++ .../security-group/rule/list/list_test.go | 214 +++++++++++ .../rule/security_group_rule.go | 32 ++ .../cmd/beta/security-group/security_group.go | 26 ++ internal/pkg/services/iaas/utils/utils.go | 19 + .../pkg/services/iaas/utils/utils_test.go | 139 +++++++- 21 files changed, 2271 insertions(+), 36 deletions(-) create mode 100644 docs/stackit_beta_security-group.md create mode 100644 docs/stackit_beta_security-group_rule.md create mode 100644 docs/stackit_beta_security-group_rule_create.md create mode 100644 docs/stackit_beta_security-group_rule_delete.md create mode 100644 docs/stackit_beta_security-group_rule_describe.md create mode 100644 docs/stackit_beta_security-group_rule_list.md create mode 100644 internal/cmd/beta/security-group/rule/create/create.go create mode 100644 internal/cmd/beta/security-group/rule/create/create_test.go create mode 100644 internal/cmd/beta/security-group/rule/delete/delete.go create mode 100644 internal/cmd/beta/security-group/rule/delete/delete_test.go create mode 100644 internal/cmd/beta/security-group/rule/describe/describe.go create mode 100644 internal/cmd/beta/security-group/rule/describe/describe_test.go create mode 100644 internal/cmd/beta/security-group/rule/list/list.go create mode 100644 internal/cmd/beta/security-group/rule/list/list_test.go create mode 100644 internal/cmd/beta/security-group/rule/security_group_rule.go create mode 100644 internal/cmd/beta/security-group/security_group.go diff --git a/README.md b/README.md index 638180559..2bac5e5b5 100644 --- a/README.md +++ b/README.md @@ -65,28 +65,28 @@ Help is available for any command by specifying the special flag `--help` (or si Below you can find a list of the STACKIT services already available in the CLI (along with their respective command names) and the ones that are currently planned to be integrated. -| Service | CLI Commands | Status | -| ---------------------------------- |----------------------------------------------------------------------------------------------------------------------| ------------------------- | -| Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta key-pair` | :white_check_mark: (beta) | -| Authorization | `project`, `organization` | :white_check_mark: | -| DNS | `dns` | :white_check_mark: | -| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | -| Load Balancer | `load-balancer` | :white_check_mark: | -| LogMe | `logme` | :white_check_mark: | -| MariaDB | `mariadb` | :white_check_mark: | -| MongoDB Flex | `mongodbflex` | :white_check_mark: | -| Object Storage | `object-storage` | :white_check_mark: | -| OpenSearch | `opensearch` | :white_check_mark: | -| PostgreSQL Flex | `postgresflex` | :white_check_mark: | -| RabbitMQ | `rabbitmq` | :white_check_mark: | -| Redis | `redis` | :white_check_mark: | -| Resource Manager | `project` | :white_check_mark: | -| Secrets Manager | `secrets-manager` | :white_check_mark: | -| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | -| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | -| Service Account | `service-account` | :white_check_mark: | -| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | +| Service | CLI Commands | Status | +| ---------------------------------- |--------------------------------------------------------------------------------------------------------------------------------------------------| ------------------------- | +| Observability | `observability` | :white_check_mark: | +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta security-group`
`beta key-pair` | :white_check_mark: (beta) | +| Authorization | `project`, `organization` | :white_check_mark: | +| DNS | `dns` | :white_check_mark: | +| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | +| Load Balancer | `load-balancer` | :white_check_mark: | +| LogMe | `logme` | :white_check_mark: | +| MariaDB | `mariadb` | :white_check_mark: | +| MongoDB Flex | `mongodbflex` | :white_check_mark: | +| Object Storage | `object-storage` | :white_check_mark: | +| OpenSearch | `opensearch` | :white_check_mark: | +| PostgreSQL Flex | `postgresflex` | :white_check_mark: | +| RabbitMQ | `rabbitmq` | :white_check_mark: | +| Redis | `redis` | :white_check_mark: | +| Resource Manager | `project` | :white_check_mark: | +| Secrets Manager | `secrets-manager` | :white_check_mark: | +| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | +| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | +| Service Account | `service-account` | :white_check_mark: | +| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | ## Authentication diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index acc708dd4..4ab26fe12 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -45,6 +45,7 @@ stackit beta [flags] * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) * [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces * [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit beta security-group](./stackit_beta_security-group.md) - Provides functionality for security groups * [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex * [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_security-group.md b/docs/stackit_beta_security-group.md new file mode 100644 index 000000000..fcc28bdd7 --- /dev/null +++ b/docs/stackit_beta_security-group.md @@ -0,0 +1,33 @@ +## stackit beta security-group + +Provides functionality for security groups + +### Synopsis + +Provides functionality for security groups. + +``` +stackit beta security-group [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta security-group" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules + diff --git a/docs/stackit_beta_security-group_rule.md b/docs/stackit_beta_security-group_rule.md new file mode 100644 index 000000000..a680f5bfc --- /dev/null +++ b/docs/stackit_beta_security-group_rule.md @@ -0,0 +1,36 @@ +## stackit beta security-group rule + +Provides functionality for security group rules + +### Synopsis + +Provides functionality for security group rules. + +``` +stackit beta security-group rule [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta security-group rule" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group](./stackit_beta_security-group.md) - Provides functionality for security groups +* [stackit beta security-group rule create](./stackit_beta_security-group_rule_create.md) - Creates a security group rule +* [stackit beta security-group rule delete](./stackit_beta_security-group_rule_delete.md) - Deletes a security group rule +* [stackit beta security-group rule describe](./stackit_beta_security-group_rule_describe.md) - Shows details of a security group rule +* [stackit beta security-group rule list](./stackit_beta_security-group_rule_list.md) - Lists all security group rules in a security group of a project + diff --git a/docs/stackit_beta_security-group_rule_create.md b/docs/stackit_beta_security-group_rule_create.md new file mode 100644 index 000000000..7fba6fe31 --- /dev/null +++ b/docs/stackit_beta_security-group_rule_create.md @@ -0,0 +1,60 @@ +## stackit beta security-group rule create + +Creates a security group rule + +### Synopsis + +Creates a security group rule. + +``` +stackit beta security-group rule create [flags] +``` + +### Examples + +``` + Create a security group rule for security group with ID "xxx" with direction "ingress" + $ stackit beta security-group rule create --security-group-id xxx --direction ingress + + Create a security group rule for security group with ID "xxx" with direction "egress", protocol "icmp" and icmp parameters + $ stackit beta security-group rule create --security-group-id xxx --direction egress --protocol-name icmp --icmp-parameter-code 0 --icmp-parameter-type 8 + + Create a security group rule for security group with ID "xxx" with direction "ingress", protocol "tcp" and port range values + $ stackit beta security-group rule create --security-group-id xxx --direction ingress --protocol-name tcp --port-range-max 24 --port-range-min 22 + + Create a security group rule for security group with ID "xxx" with direction "ingress" and protocol number 1 + $ stackit beta security-group rule create --security-group-id xxx --direction ingress --protocol-number 1 +``` + +### Options + +``` + --description string The rule description + --direction string The direction of the traffic which the rule should match. The possible values are: "ingress", "egress" + --ether-type string The ethertype which the rule should match + -h, --help Help for "stackit beta security-group rule create" + --icmp-parameter-code int ICMP code. Can be set if the protocol is ICMP + --icmp-parameter-type int ICMP type. Can be set if the protocol is ICMP + --ip-range string The remote IP range which the rule should match + --port-range-max int The maximum port number. Should be greater or equal to the minimum. This should only be provided if the protocol is not ICMP + --port-range-min int The minimum port number. Should be less or equal to the maximum. This should only be provided if the protocol is not ICMP + --protocol-name string The protocol name which the rule should match. If a protocol is to be defined, either "protocol-name" or "protocol-number" must be provided + --protocol-number int The protocol number which the rule should match. If a protocol is to be defined, either "protocol-name" or "protocol-number" must be provided + --remote-security-group-id string The remote security group which the rule should match + --security-group-id string The security group ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules + diff --git a/docs/stackit_beta_security-group_rule_delete.md b/docs/stackit_beta_security-group_rule_delete.md new file mode 100644 index 000000000..fd56a81d6 --- /dev/null +++ b/docs/stackit_beta_security-group_rule_delete.md @@ -0,0 +1,42 @@ +## stackit beta security-group rule delete + +Deletes a security group rule + +### Synopsis + +Deletes a security group rule. +If the security group rule is still in use, the deletion will fail + + +``` +stackit beta security-group rule delete [flags] +``` + +### Examples + +``` + Delete security group rule with ID "xxx" in security group with ID "yyy" + $ stackit beta security-group rule delete xxx --security-group-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta security-group rule delete" + --security-group-id string The security group ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules + diff --git a/docs/stackit_beta_security-group_rule_describe.md b/docs/stackit_beta_security-group_rule_describe.md new file mode 100644 index 000000000..eaa29cc08 --- /dev/null +++ b/docs/stackit_beta_security-group_rule_describe.md @@ -0,0 +1,43 @@ +## stackit beta security-group rule describe + +Shows details of a security group rule + +### Synopsis + +Shows details of a security group rule. + +``` +stackit beta security-group rule describe [flags] +``` + +### Examples + +``` + Show details of a security group rule with ID "xxx" in security group with ID "yyy" + $ stackit beta security-group rule describe xxx --security-group-id yyy + + Show details of a security group rule with ID "xxx" in security group with ID "yyy" in JSON format + $ stackit beta security-group rule describe xxx --security-group-id yyy --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta security-group rule describe" + --security-group-id string The security group ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules + diff --git a/docs/stackit_beta_security-group_rule_list.md b/docs/stackit_beta_security-group_rule_list.md new file mode 100644 index 000000000..02fef7466 --- /dev/null +++ b/docs/stackit_beta_security-group_rule_list.md @@ -0,0 +1,47 @@ +## stackit beta security-group rule list + +Lists all security group rules in a security group of a project + +### Synopsis + +Lists all security group rules in a security group of a project. + +``` +stackit beta security-group rule list [flags] +``` + +### Examples + +``` + Lists all security group rules in security group with ID "xxx" + $ stackit beta security-group rule list --security-group-id xxx + + Lists all security group rules in security group with ID "xxx" in JSON format + $ stackit beta security-group rule list --security-group-id xxx --output-format json + + Lists up to 10 security group rules in security group with ID "xxx" + $ stackit beta security-group rule list --security-group-id xxx --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta security-group rule list" + --limit int Maximum number of entries to list + --security-group-id string The security group ID +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules + diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 975704383..0ec43d0f2 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -8,6 +8,7 @@ import ( networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip" + securitygroup "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume" @@ -49,5 +50,6 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(volume.NewCmd(p)) cmd.AddCommand(networkinterface.NewCmd(p)) cmd.AddCommand(publicip.NewCmd(p)) + cmd.AddCommand(securitygroup.NewCmd(p)) cmd.AddCommand(keypair.NewCmd(p)) } diff --git a/internal/cmd/beta/security-group/rule/create/create.go b/internal/cmd/beta/security-group/rule/create/create.go new file mode 100644 index 000000000..04b49745e --- /dev/null +++ b/internal/cmd/beta/security-group/rule/create/create.go @@ -0,0 +1,246 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + securityGroupIdFlag = "security-group-id" + directionFlag = "direction" + descriptionFlag = "description" + etherTypeFlag = "ether-type" + icmpParameterCodeFlag = "icmp-parameter-code" + icmpParameterTypeFlag = "icmp-parameter-type" + ipRangeFlag = "ip-range" + portRangeMaxFlag = "port-range-max" + portRangeMinFlag = "port-range-min" + remoteSecurityGroupIdFlag = "remote-security-group-id" + protocolNumberFlag = "protocol-number" + protocolNameFlag = "protocol-name" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SecurityGroupId string + Direction *string + Description *string + EtherType *string + IcmpParameterCode *int64 + IcmpParameterType *int64 + IpRange *string + PortRangeMax *int64 + PortRangeMin *int64 + RemoteSecurityGroupId *string + ProtocolNumber *int64 + ProtocolName *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a security group rule", + Long: "Creates a security group rule.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a security group rule for security group with ID "xxx" with direction "ingress"`, + `$ stackit beta security-group rule create --security-group-id xxx --direction ingress`, + ), + examples.NewExample( + `Create a security group rule for security group with ID "xxx" with direction "egress", protocol "icmp" and icmp parameters`, + `$ stackit beta security-group rule create --security-group-id xxx --direction egress --protocol-name icmp --icmp-parameter-code 0 --icmp-parameter-type 8`, + ), + examples.NewExample( + `Create a security group rule for security group with ID "xxx" with direction "ingress", protocol "tcp" and port range values`, + `$ stackit beta security-group rule create --security-group-id xxx --direction ingress --protocol-name tcp --port-range-max 24 --port-range-min 22`, + ), + examples.NewExample( + `Create a security group rule for security group with ID "xxx" with direction "ingress" and protocol number 1 `, + `$ stackit beta security-group rule create --security-group-id xxx --direction ingress --protocol-number 1`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) + if err != nil { + p.Debug(print.ErrorLevel, "get security group name: %v", err) + securityGroupLabel = model.SecurityGroupId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a security group rule for security group %q for project %q?", securityGroupLabel, projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create security group rule : %w", err) + } + + return outputResult(p, model, projectLabel, securityGroupLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), securityGroupIdFlag, `The security group ID`) + cmd.Flags().String(directionFlag, "", `The direction of the traffic which the rule should match. The possible values are: "ingress", "egress"`) + cmd.Flags().String(descriptionFlag, "", `The rule description`) + cmd.Flags().String(etherTypeFlag, "", `The ethertype which the rule should match`) + cmd.Flags().Int64(icmpParameterCodeFlag, 0, `ICMP code. Can be set if the protocol is ICMP`) + cmd.Flags().Int64(icmpParameterTypeFlag, 0, `ICMP type. Can be set if the protocol is ICMP`) + cmd.Flags().String(ipRangeFlag, "", `The remote IP range which the rule should match`) + cmd.Flags().Int64(portRangeMaxFlag, 0, `The maximum port number. Should be greater or equal to the minimum. This should only be provided if the protocol is not ICMP`) + cmd.Flags().Int64(portRangeMinFlag, 0, `The minimum port number. Should be less or equal to the maximum. This should only be provided if the protocol is not ICMP`) + cmd.Flags().Var(flags.UUIDFlag(), remoteSecurityGroupIdFlag, `The remote security group which the rule should match`) + cmd.Flags().Int64(protocolNumberFlag, 0, `The protocol number which the rule should match. If a protocol is to be defined, either "protocol-name" or "protocol-number" must be provided`) + cmd.Flags().String(protocolNameFlag, "", `The protocol name which the rule should match. If a protocol is to be defined, either "protocol-name" or "protocol-number" must be provided`) + + err := flags.MarkFlagsRequired(cmd, securityGroupIdFlag, directionFlag) + cmd.MarkFlagsMutuallyExclusive(protocolNumberFlag, protocolNameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SecurityGroupId: flags.FlagToStringValue(p, cmd, securityGroupIdFlag), + Direction: flags.FlagToStringPointer(p, cmd, directionFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + EtherType: flags.FlagToStringPointer(p, cmd, etherTypeFlag), + IcmpParameterCode: flags.FlagToInt64Pointer(p, cmd, icmpParameterCodeFlag), + IcmpParameterType: flags.FlagToInt64Pointer(p, cmd, icmpParameterTypeFlag), + IpRange: flags.FlagToStringPointer(p, cmd, ipRangeFlag), + PortRangeMax: flags.FlagToInt64Pointer(p, cmd, portRangeMaxFlag), + PortRangeMin: flags.FlagToInt64Pointer(p, cmd, portRangeMinFlag), + RemoteSecurityGroupId: flags.FlagToStringPointer(p, cmd, remoteSecurityGroupIdFlag), + ProtocolNumber: flags.FlagToInt64Pointer(p, cmd, protocolNumberFlag), + ProtocolName: flags.FlagToStringPointer(p, cmd, protocolNameFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateSecurityGroupRuleRequest { + req := apiClient.CreateSecurityGroupRule(ctx, model.ProjectId, model.SecurityGroupId) + icmpParameters := &iaas.ICMPParameters{} + portRange := &iaas.PortRange{} + protocol := &iaas.CreateProtocol{} + + payload := iaas.CreateSecurityGroupRulePayload{ + Direction: model.Direction, + Description: model.Description, + Ethertype: model.EtherType, + IpRange: model.IpRange, + RemoteSecurityGroupId: model.RemoteSecurityGroupId, + } + + if model.IcmpParameterCode != nil || model.IcmpParameterType != nil { + icmpParameters.Code = model.IcmpParameterCode + icmpParameters.Type = model.IcmpParameterType + + payload.IcmpParameters = icmpParameters + } + + if model.PortRangeMax != nil || model.PortRangeMin != nil { + portRange.Max = model.PortRangeMax + portRange.Min = model.PortRangeMin + + payload.PortRange = portRange + } + + if model.ProtocolNumber != nil || model.ProtocolName != nil { + protocol.Int64 = model.ProtocolNumber + protocol.String = model.ProtocolName + + payload.Protocol = protocol + } + + if model.RemoteSecurityGroupId == nil { + payload.RemoteSecurityGroupId = nil + } + + return req.CreateSecurityGroupRulePayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel, securityGroupName string, securityGroupRule *iaas.SecurityGroupRule) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(securityGroupRule, "", " ") + if err != nil { + return fmt.Errorf("marshal security group rule: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(securityGroupRule, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal security group rule: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s security group rule for security group %q in project %q.\nSecurity group rule ID: %s\n", operationState, securityGroupName, projectLabel, *securityGroupRule.Id) + return nil + } +} diff --git a/internal/cmd/beta/security-group/rule/create/create_test.go b/internal/cmd/beta/security-group/rule/create/create_test.go new file mode 100644 index 000000000..5d0fd2098 --- /dev/null +++ b/internal/cmd/beta/security-group/rule/create/create_test.go @@ -0,0 +1,335 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testSecurityGroupId = uuid.NewString() +var testRemoteSecurityGroupId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + securityGroupIdFlag: testSecurityGroupId, + directionFlag: "ingress", + descriptionFlag: "example-description", + etherTypeFlag: "ether", + icmpParameterCodeFlag: "0", + icmpParameterTypeFlag: "8", + ipRangeFlag: "10.1.2.3", + portRangeMaxFlag: "24", + portRangeMinFlag: "22", + remoteSecurityGroupIdFlag: testRemoteSecurityGroupId, + protocolNumberFlag: "1", + protocolNameFlag: "icmp", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + SecurityGroupId: testSecurityGroupId, + Direction: utils.Ptr("ingress"), + Description: utils.Ptr("example-description"), + EtherType: utils.Ptr("ether"), + IcmpParameterCode: utils.Ptr(int64(0)), + IcmpParameterType: utils.Ptr(int64(8)), + IpRange: utils.Ptr("10.1.2.3"), + PortRangeMax: utils.Ptr(int64(24)), + PortRangeMin: utils.Ptr(int64(22)), + RemoteSecurityGroupId: utils.Ptr(testRemoteSecurityGroupId), + ProtocolNumber: utils.Ptr(int64(1)), + ProtocolName: utils.Ptr("icmp"), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateSecurityGroupRuleRequest)) iaas.ApiCreateSecurityGroupRuleRequest { + request := testClient.CreateSecurityGroupRule(testCtx, testProjectId, testSecurityGroupId) + request = request.CreateSecurityGroupRulePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateSecurityGroupRuleRequest)) iaas.ApiCreateSecurityGroupRuleRequest { + request := testClient.CreateSecurityGroupRule(testCtx, testProjectId, testSecurityGroupId) + request = request.CreateSecurityGroupRulePayload(iaas.CreateSecurityGroupRulePayload{ + Direction: utils.Ptr("ingress"), + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateSecurityGroupRulePayload)) iaas.CreateSecurityGroupRulePayload { + payload := iaas.CreateSecurityGroupRulePayload{ + Direction: utils.Ptr("ingress"), + Description: utils.Ptr("example-description"), + Ethertype: utils.Ptr("ether"), + IcmpParameters: &iaas.ICMPParameters{ + Code: utils.Ptr(int64(0)), + Type: utils.Ptr(int64(8)), + }, + IpRange: utils.Ptr("10.1.2.3"), + PortRange: &iaas.PortRange{ + Max: utils.Ptr(int64(24)), + Min: utils.Ptr(int64(22)), + }, + Protocol: &iaas.CreateProtocol{ + Int64: utils.Ptr(int64(1)), + String: utils.Ptr("icmp"), + }, + RemoteSecurityGroupId: utils.Ptr(testRemoteSecurityGroupId), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, portRangeMaxFlag) + delete(flagValues, portRangeMinFlag) + delete(flagValues, protocolNumberFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.PortRangeMax = nil + model.PortRangeMin = nil + model.ProtocolNumber = nil + }), + }, + { + description: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, descriptionFlag) + delete(flagValues, etherTypeFlag) + delete(flagValues, icmpParameterCodeFlag) + delete(flagValues, icmpParameterTypeFlag) + delete(flagValues, ipRangeFlag) + delete(flagValues, portRangeMaxFlag) + delete(flagValues, portRangeMinFlag) + delete(flagValues, remoteSecurityGroupIdFlag) + delete(flagValues, protocolNumberFlag) + delete(flagValues, protocolNameFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Description = nil + model.EtherType = nil + model.IcmpParameterCode = nil + model.IcmpParameterType = nil + model.IpRange = nil + model.PortRangeMax = nil + model.PortRangeMin = nil + model.RemoteSecurityGroupId = nil + model.ProtocolNumber = nil + model.ProtocolName = nil + }), + }, + { + description: "direction missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, directionFlag) + delete(flagValues, protocolNumberFlag) + delete(flagValues, protocolNameFlag) + }), + isValid: false, + }, + { + description: "protocol is not icmp and port range values are provided", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[protocolNameFlag] = "not-icmp" + delete(flagValues, icmpParameterCodeFlag) + delete(flagValues, icmpParameterTypeFlag) + delete(flagValues, protocolNumberFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IcmpParameterCode = nil + model.IcmpParameterType = nil + model.ProtocolName = utils.Ptr("not-icmp") + model.ProtocolNumber = nil + }), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "security group id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, securityGroupIdFlag) + }), + isValid: false, + }, + { + description: "security group id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupIdFlag] = "" + }), + isValid: false, + }, + { + description: "security group id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateFlagGroups() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flag groups: %v", err) + } + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + var tests = []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateSecurityGroupRuleRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "only direction and security group id in payload", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Direction: utils.Ptr("ingress"), + SecurityGroupId: testSecurityGroupId, + }, + expectedRequest: fixtureRequiredRequest(), + }, + } + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/rule/delete/delete.go b/internal/cmd/beta/security-group/rule/delete/delete.go new file mode 100644 index 000000000..b28ade08e --- /dev/null +++ b/internal/cmd/beta/security-group/rule/delete/delete.go @@ -0,0 +1,130 @@ +package delete + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + securityGroupRuleIdArg = "SECURITY_GROUP_RULE_ID" + + securityGroupIdFlag = "security-group-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SecurityGroupRuleId string + SecurityGroupId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a security group rule", + Long: fmt.Sprintf("%s\n%s\n", + "Deletes a security group rule.", + "If the security group rule is still in use, the deletion will fail", + ), + Args: args.SingleArg(securityGroupRuleIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete security group rule with ID "xxx" in security group with ID "yyy"`, + "$ stackit beta security-group rule delete xxx --security-group-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, *model.SecurityGroupId) + if err != nil { + p.Debug(print.ErrorLevel, "get security group name: %v", err) + securityGroupLabel = *model.SecurityGroupId + } + + securityGroupRuleLabel, err := iaasUtils.GetSecurityGroupRuleName(ctx, apiClient, model.ProjectId, model.SecurityGroupRuleId, *model.SecurityGroupId) + if err != nil { + p.Debug(print.ErrorLevel, "get security group rule name: %v", err) + securityGroupRuleLabel = model.SecurityGroupRuleId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete security group rule %q from security group %q?", securityGroupRuleLabel, securityGroupLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete security group rule: %w", err) + } + + p.Info("Deleted security group rule %q from security group %q\n", securityGroupRuleLabel, securityGroupLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), securityGroupIdFlag, `The security group ID`) + + err := flags.MarkFlagsRequired(cmd, securityGroupIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + securityGroupRuleId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SecurityGroupRuleId: securityGroupRuleId, + SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteSecurityGroupRuleRequest { + return apiClient.DeleteSecurityGroupRule(ctx, model.ProjectId, *model.SecurityGroupId, model.SecurityGroupRuleId) +} diff --git a/internal/cmd/beta/security-group/rule/delete/delete_test.go b/internal/cmd/beta/security-group/rule/delete/delete_test.go new file mode 100644 index 000000000..e8d36d7f6 --- /dev/null +++ b/internal/cmd/beta/security-group/rule/delete/delete_test.go @@ -0,0 +1,235 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var testProjectId = uuid.NewString() +var testSecurityGroupId = uuid.NewString() +var testSecurityGroupRuleId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testSecurityGroupRuleId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + securityGroupIdFlag: testSecurityGroupId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + SecurityGroupId: utils.Ptr(testSecurityGroupId), + SecurityGroupRuleId: testSecurityGroupRuleId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteSecurityGroupRuleRequest)) iaas.ApiDeleteSecurityGroupRuleRequest { + request := testClient.DeleteSecurityGroupRule(testCtx, testProjectId, testSecurityGroupId, testSecurityGroupRuleId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "security group id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, securityGroupIdFlag) + }), + isValid: false, + }, + { + description: "security group id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupIdFlag] = "" + }), + isValid: false, + }, + { + description: "security group id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "security group rule id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "security group rule id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteSecurityGroupRuleRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/rule/describe/describe.go b/internal/cmd/beta/security-group/rule/describe/describe.go new file mode 100644 index 000000000..93f7df60c --- /dev/null +++ b/internal/cmd/beta/security-group/rule/describe/describe.go @@ -0,0 +1,186 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + securityGroupRuleIdArg = "SECURITY_GROUP_RULE_ID" + + securityGroupIdFlag = "security-group-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SecurityGroupRuleId string + SecurityGroupId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a security group rule", + Long: "Shows details of a security group rule.", + Args: args.SingleArg(securityGroupRuleIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Show details of a security group rule with ID "xxx" in security group with ID "yyy"`, + "$ stackit beta security-group rule describe xxx --security-group-id yyy", + ), + examples.NewExample( + `Show details of a security group rule with ID "xxx" in security group with ID "yyy" in JSON format`, + "$ stackit beta security-group rule describe xxx --security-group-id yyy --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read security group rule: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), securityGroupIdFlag, `The security group ID`) + + err := flags.MarkFlagsRequired(cmd, securityGroupIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + securityGroupRuleId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SecurityGroupRuleId: securityGroupRuleId, + SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetSecurityGroupRuleRequest { + return apiClient.GetSecurityGroupRule(ctx, model.ProjectId, *model.SecurityGroupId, model.SecurityGroupRuleId) +} + +func outputResult(p *print.Printer, outputFormat string, securityGroupRule *iaas.SecurityGroupRule) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(securityGroupRule, "", " ") + if err != nil { + return fmt.Errorf("marshal security group rule: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(securityGroupRule, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal security group rule: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *securityGroupRule.Id) + table.AddSeparator() + + if securityGroupRule.Protocol != nil { + if securityGroupRule.Protocol.Name != nil { + table.AddRow("PROTOCOL NAME", *securityGroupRule.Protocol.Name) + table.AddSeparator() + } + + if securityGroupRule.Protocol.Number != nil { + table.AddRow("PROTOCOL NUMBER", *securityGroupRule.Protocol.Number) + table.AddSeparator() + } + } + + table.AddRow("DIRECTION", *securityGroupRule.Direction) + table.AddSeparator() + + if securityGroupRule.PortRange != nil { + if securityGroupRule.PortRange.Min != nil { + table.AddRow("START PORT", *securityGroupRule.PortRange.Min) + table.AddSeparator() + } + + if securityGroupRule.PortRange.Max != nil { + table.AddRow("END PORT", *securityGroupRule.PortRange.Max) + table.AddSeparator() + } + } + + if securityGroupRule.Ethertype != nil { + table.AddRow("ETHER TYPE", *securityGroupRule.Ethertype) + table.AddSeparator() + } + + if securityGroupRule.IpRange != nil { + table.AddRow("IP RANGE", *securityGroupRule.IpRange) + table.AddSeparator() + } + + if securityGroupRule.RemoteSecurityGroupId != nil { + table.AddRow("REMOTE SECURITY GROUP", *securityGroupRule.RemoteSecurityGroupId) + table.AddSeparator() + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/security-group/rule/describe/describe_test.go b/internal/cmd/beta/security-group/rule/describe/describe_test.go new file mode 100644 index 000000000..6463ef1fc --- /dev/null +++ b/internal/cmd/beta/security-group/rule/describe/describe_test.go @@ -0,0 +1,246 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testSecurityGroupId = uuid.NewString() +var testSecurityGroupRuleId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testSecurityGroupRuleId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + securityGroupIdFlag: testSecurityGroupId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + SecurityGroupId: utils.Ptr(testSecurityGroupId), + SecurityGroupRuleId: testSecurityGroupRuleId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetSecurityGroupRuleRequest)) iaas.ApiGetSecurityGroupRuleRequest { + request := testClient.GetSecurityGroupRule(testCtx, testProjectId, testSecurityGroupId, testSecurityGroupRuleId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "security group id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, securityGroupIdFlag) + }), + isValid: false, + }, + { + description: "security group id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupIdFlag] = "" + }), + isValid: false, + }, + { + description: "security group id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "security group rule id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "security group rule id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetSecurityGroupRuleRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/rule/list/list.go b/internal/cmd/beta/security-group/rule/list/list.go new file mode 100644 index 000000000..3675dec91 --- /dev/null +++ b/internal/cmd/beta/security-group/rule/list/list.go @@ -0,0 +1,191 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + limitFlag = "limit" + + securityGroupIdFlag = "security-group-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + SecurityGroupId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all security group rules in a security group of a project", + Long: "Lists all security group rules in a security group of a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all security group rules in security group with ID "xxx"`, + "$ stackit beta security-group rule list --security-group-id xxx", + ), + examples.NewExample( + `Lists all security group rules in security group with ID "xxx" in JSON format`, + "$ stackit beta security-group rule list --security-group-id xxx --output-format json", + ), + examples.NewExample( + `Lists up to 10 security group rules in security group with ID "xxx"`, + "$ stackit beta security-group rule list --security-group-id xxx --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list security group rules: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, *model.SecurityGroupId) + if err != nil { + p.Debug(print.ErrorLevel, "get security group name: %v", err) + securityGroupLabel = *model.SecurityGroupId + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + p.Info("No rules found in security group %q for project %q\n", securityGroupLabel, projectLabel) + return nil + } + + // Truncate output + items := *resp.Items + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, `Maximum number of entries to list`) + cmd.Flags().Var(flags.UUIDFlag(), securityGroupIdFlag, `The security group ID`) + + err := flags.MarkFlagsRequired(cmd, securityGroupIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListSecurityGroupRulesRequest { + return apiClient.ListSecurityGroupRules(ctx, model.ProjectId, *model.SecurityGroupId) +} + +func outputResult(p *print.Printer, outputFormat string, securityGroupRules []iaas.SecurityGroupRule) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(securityGroupRules, "", " ") + if err != nil { + return fmt.Errorf("marshal security group rules: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(securityGroupRules, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal security group rules: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "ETHER TYPE", "DIRECTION", "PROTOCOL") + + for _, securityGroupRule := range securityGroupRules { + etherType := "" + if securityGroupRule.Ethertype != nil { + etherType = *securityGroupRule.Ethertype + } + + protocolName := "" + if securityGroupRule.Protocol != nil { + if securityGroupRule.Protocol.Name != nil { + protocolName = *securityGroupRule.Protocol.Name + } + } + + table.AddRow(*securityGroupRule.Id, etherType, *securityGroupRule.Direction, protocolName) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/beta/security-group/rule/list/list_test.go b/internal/cmd/beta/security-group/rule/list/list_test.go new file mode 100644 index 000000000..016039ed7 --- /dev/null +++ b/internal/cmd/beta/security-group/rule/list/list_test.go @@ -0,0 +1,214 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testSecurityGroupId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + securityGroupIdFlag: testSecurityGroupId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + SecurityGroupId: utils.Ptr(testSecurityGroupId), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListSecurityGroupRulesRequest)) iaas.ApiListSecurityGroupRulesRequest { + request := testClient.ListSecurityGroupRules(testCtx, testProjectId, testSecurityGroupId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "security group id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, securityGroupIdFlag) + }), + isValid: false, + }, + { + description: "security group id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupIdFlag] = "" + }), + isValid: false, + }, + { + description: "security group id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[securityGroupIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListSecurityGroupRulesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/rule/security_group_rule.go b/internal/cmd/beta/security-group/rule/security_group_rule.go new file mode 100644 index 000000000..26b3443f5 --- /dev/null +++ b/internal/cmd/beta/security-group/rule/security_group_rule.go @@ -0,0 +1,32 @@ +package rule + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "rule", + Short: "Provides functionality for security group rules", + Long: "Provides functionality for security group rules.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} diff --git a/internal/cmd/beta/security-group/security_group.go b/internal/cmd/beta/security-group/security_group.go new file mode 100644 index 000000000..53f380d90 --- /dev/null +++ b/internal/cmd/beta/security-group/security_group.go @@ -0,0 +1,26 @@ +package securitygroup + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "security-group", + Short: "Provides functionality for security groups", + Long: "Provides functionality for security groups.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(rule.NewCmd(p)) +} diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index fecc0872c..e7a455688 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -8,6 +8,8 @@ import ( ) type IaaSClient interface { + GetSecurityGroupRuleExecute(ctx context.Context, projectId, securityGroupRuleId, securityGroupId string) (*iaas.SecurityGroupRule, error) + GetSecurityGroupExecute(ctx context.Context, projectId, securityGroupId string) (*iaas.SecurityGroup, error) GetPublicIPExecute(ctx context.Context, projectId, publicIpId string) (*iaas.PublicIp, error) GetServerExecute(ctx context.Context, projectId, serverId string) (*iaas.Server, error) GetVolumeExecute(ctx context.Context, projectId, volumeId string) (*iaas.Volume, error) @@ -17,6 +19,23 @@ type IaaSClient interface { GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) } +func GetSecurityGroupRuleName(ctx context.Context, apiClient IaaSClient, projectId, securityGroupRuleId, securityGroupId string) (string, error) { + resp, err := apiClient.GetSecurityGroupRuleExecute(ctx, projectId, securityGroupRuleId, securityGroupId) + if err != nil { + return "", fmt.Errorf("get security group rule: %w", err) + } + securityGroupRuleName := *resp.Ethertype + ", " + *resp.Direction + return securityGroupRuleName, nil +} + +func GetSecurityGroupName(ctx context.Context, apiClient IaaSClient, projectId, securityGroupId string) (string, error) { + resp, err := apiClient.GetSecurityGroupExecute(ctx, projectId, securityGroupId) + if err != nil { + return "", fmt.Errorf("get security group: %w", err) + } + return *resp.Name, nil +} + func GetPublicIP(ctx context.Context, apiClient IaaSClient, projectId, publicIpId string) (ip, associatedResource string, err error) { resp, err := apiClient.GetPublicIPExecute(ctx, projectId, publicIpId) if err != nil { diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index bc0d94299..c7e75a683 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -11,20 +11,38 @@ import ( ) type IaaSClientMocked struct { - GetPublicIpFails bool - GetPublicIpResp *iaas.PublicIp - GetServerFails bool - GetServerResp *iaas.Server - GetVolumeFails bool - GetVolumeResp *iaas.Volume - GetNetworkFails bool - GetNetworkResp *iaas.Network - GetNetworkAreaFails bool - GetNetworkAreaResp *iaas.NetworkArea - GetAttachedProjectsFails bool - GetAttachedProjectsResp *iaas.ProjectListResponse - GetNetworkAreaRangeFails bool - GetNetworkAreaRangeResp *iaas.NetworkRange + GetSecurityGroupRuleFails bool + GetSecurityGroupRuleResp *iaas.SecurityGroupRule + GetSecurityGroupFails bool + GetSecurityGroupResp *iaas.SecurityGroup + GetPublicIpFails bool + GetPublicIpResp *iaas.PublicIp + GetServerFails bool + GetServerResp *iaas.Server + GetVolumeFails bool + GetVolumeResp *iaas.Volume + GetNetworkFails bool + GetNetworkResp *iaas.Network + GetNetworkAreaFails bool + GetNetworkAreaResp *iaas.NetworkArea + GetAttachedProjectsFails bool + GetAttachedProjectsResp *iaas.ProjectListResponse + GetNetworkAreaRangeFails bool + GetNetworkAreaRangeResp *iaas.NetworkRange +} + +func (m *IaaSClientMocked) GetSecurityGroupRuleExecute(_ context.Context, _, _, _ string) (*iaas.SecurityGroupRule, error) { + if m.GetSecurityGroupRuleFails { + return nil, fmt.Errorf("could not get security group rule") + } + return m.GetSecurityGroupRuleResp, nil +} + +func (m *IaaSClientMocked) GetSecurityGroupExecute(_ context.Context, _, _ string) (*iaas.SecurityGroup, error) { + if m.GetSecurityGroupFails { + return nil, fmt.Errorf("could not get security group") + } + return m.GetSecurityGroupResp, nil } func (m *IaaSClientMocked) GetPublicIPExecute(_ context.Context, _, _ string) (*iaas.PublicIp, error) { @@ -76,6 +94,99 @@ func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _ return m.GetNetworkAreaRangeResp, nil } +func TestGetSecurityGroupRuleName(t *testing.T) { + type args struct { + getInstanceFails bool + getInstanceResp *iaas.SecurityGroupRule + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "base", + args: args{ + getInstanceResp: &iaas.SecurityGroupRule{ + Ethertype: utils.Ptr("IPv6"), + Direction: utils.Ptr("ingress"), + }, + }, + want: "IPv6, ingress", + }, + { + name: "get security group rule fails", + args: args{ + getInstanceFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetSecurityGroupRuleFails: tt.args.getInstanceFails, + GetSecurityGroupRuleResp: tt.args.getInstanceResp, + } + got, err := GetSecurityGroupRuleName(context.Background(), m, "", "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetSecurityGroupRuleName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetSecurityGroupRuleName() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetSecurityGroupName(t *testing.T) { + type args struct { + getInstanceFails bool + getInstanceResp *iaas.SecurityGroup + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "base", + args: args{ + getInstanceResp: &iaas.SecurityGroup{ + Name: utils.Ptr("test"), + }, + }, + want: "test", + }, + { + name: "get security group fails", + args: args{ + getInstanceFails: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &IaaSClientMocked{ + GetSecurityGroupFails: tt.args.getInstanceFails, + GetSecurityGroupResp: tt.args.getInstanceResp, + } + got, err := GetSecurityGroupName(context.Background(), m, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetSecurityGroupName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetSecurityGroupName() = %v, want %v", got, tt.want) + } + }) + } +} + func TestGetPublicIp(t *testing.T) { type args struct { getPublicIpFails bool From 9adbcb1fecfb517c91913077edeb608fd81249fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Fri, 13 Dec 2024 11:29:42 +0100 Subject: [PATCH 124/619] Feat/670192 security groups (#531) * feature: add command and sub-commands for security groups * feature: implement create command * feature: add list command * fixup: check name length * fixup: added placeholder for client invocation * feature: implement calling service and output of results * feature: implement calling service and output of results for list * feature: move command to beta package * feature: removed duplicate invocation of API * feature: completed delete command * feature: renamed package to conform to standards * feature: refactored tests to reused actual cobra command * feature: refactored flag initialization * feature: implemented update command * feature: implemented describe command * feature: fixed parsing of global flags * feature: fix list command * feature: fixed describe command * feature: fixed typo * feature: updated generated documentation * feature: fix review comments * feature: refresh documentation * feature: fix a regression in list command * feature: fix regressions * feature: implemented review suggestions * restructed security-group command * feature: updated documentation * feature: restructured sub commands to canonical structure --- docs/stackit_beta.md | 2 +- docs/stackit_beta_security-group.md | 9 +- docs/stackit_beta_security-group_create.md | 46 +++ docs/stackit_beta_security-group_delete.md | 39 +++ docs/stackit_beta_security-group_describe.md | 39 +++ docs/stackit_beta_security-group_list.md | 43 +++ docs/stackit_beta_security-group_rule.md | 2 +- docs/stackit_beta_security-group_update.md | 45 +++ .../cmd/beta/security-group/create/create.go | 169 ++++++++++ .../beta/security-group/create/create_test.go | 266 ++++++++++++++++ .../cmd/beta/security-group/delete/delete.go | 110 +++++++ .../beta/security-group/delete/delete_test.go | 183 +++++++++++ .../beta/security-group/describe/describe.go | 148 +++++++++ .../security-group/describe/describe_test.go | 194 ++++++++++++ internal/cmd/beta/security-group/list/list.go | 151 +++++++++ .../cmd/beta/security-group/list/list_test.go | 207 +++++++++++++ .../cmd/beta/security-group/security_group.go | 21 +- .../cmd/beta/security-group/update/update.go | 150 +++++++++ .../beta/security-group/update/update_test.go | 291 ++++++++++++++++++ internal/pkg/utils/utils.go | 9 + 20 files changed, 2116 insertions(+), 8 deletions(-) create mode 100644 docs/stackit_beta_security-group_create.md create mode 100644 docs/stackit_beta_security-group_delete.md create mode 100644 docs/stackit_beta_security-group_describe.md create mode 100644 docs/stackit_beta_security-group_list.md create mode 100644 docs/stackit_beta_security-group_update.md create mode 100644 internal/cmd/beta/security-group/create/create.go create mode 100644 internal/cmd/beta/security-group/create/create_test.go create mode 100644 internal/cmd/beta/security-group/delete/delete.go create mode 100644 internal/cmd/beta/security-group/delete/delete_test.go create mode 100644 internal/cmd/beta/security-group/describe/describe.go create mode 100644 internal/cmd/beta/security-group/describe/describe_test.go create mode 100644 internal/cmd/beta/security-group/list/list.go create mode 100644 internal/cmd/beta/security-group/list/list_test.go create mode 100644 internal/cmd/beta/security-group/update/update.go create mode 100644 internal/cmd/beta/security-group/update/update_test.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 4ab26fe12..b89e3dbbe 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -45,7 +45,7 @@ stackit beta [flags] * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) * [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces * [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs -* [stackit beta security-group](./stackit_beta_security-group.md) - Provides functionality for security groups +* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups * [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex * [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_security-group.md b/docs/stackit_beta_security-group.md index fcc28bdd7..0c3954e95 100644 --- a/docs/stackit_beta_security-group.md +++ b/docs/stackit_beta_security-group.md @@ -1,10 +1,10 @@ ## stackit beta security-group -Provides functionality for security groups +Manage security groups ### Synopsis -Provides functionality for security groups. +Manage the lifecycle of security groups and rules. ``` stackit beta security-group [flags] @@ -29,5 +29,10 @@ stackit beta security-group [flags] ### SEE ALSO * [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta security-group create](./stackit_beta_security-group_create.md) - Creates security groups +* [stackit beta security-group delete](./stackit_beta_security-group_delete.md) - Deletes a security group +* [stackit beta security-group describe](./stackit_beta_security-group_describe.md) - Describes security groups +* [stackit beta security-group list](./stackit_beta_security-group_list.md) - Lists security groups * [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules +* [stackit beta security-group update](./stackit_beta_security-group_update.md) - Updates a security group diff --git a/docs/stackit_beta_security-group_create.md b/docs/stackit_beta_security-group_create.md new file mode 100644 index 000000000..e2ebd9b21 --- /dev/null +++ b/docs/stackit_beta_security-group_create.md @@ -0,0 +1,46 @@ +## stackit beta security-group create + +Creates security groups + +### Synopsis + +Creates security groups. + +``` +stackit beta security-group create [flags] +``` + +### Examples + +``` + Create a named group + $ stackit beta security-group create --name my-new-group + + Create a named group with labels + $ stackit beta security-group create --name my-new-group --labels label1=value1,label2=value2 +``` + +### Options + +``` + --description string An optional description of the security group. + -h, --help Help for "stackit beta security-group create" + --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) + --name string The name of the security group. + --stateful Create a stateful or a stateless security group +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups + diff --git a/docs/stackit_beta_security-group_delete.md b/docs/stackit_beta_security-group_delete.md new file mode 100644 index 000000000..dd3d7935f --- /dev/null +++ b/docs/stackit_beta_security-group_delete.md @@ -0,0 +1,39 @@ +## stackit beta security-group delete + +Deletes a security group + +### Synopsis + +Deletes a security group by its internal ID. + +``` +stackit beta security-group delete [flags] +``` + +### Examples + +``` + Delete a named group with ID "xxx" + $ stackit beta security-group delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta security-group delete" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups + diff --git a/docs/stackit_beta_security-group_describe.md b/docs/stackit_beta_security-group_describe.md new file mode 100644 index 000000000..b1856566d --- /dev/null +++ b/docs/stackit_beta_security-group_describe.md @@ -0,0 +1,39 @@ +## stackit beta security-group describe + +Describes security groups + +### Synopsis + +Describes security groups by its internal ID. + +``` +stackit beta security-group describe [flags] +``` + +### Examples + +``` + Describe group "xxx" + $ stackit beta security-group describe xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta security-group 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups + diff --git a/docs/stackit_beta_security-group_list.md b/docs/stackit_beta_security-group_list.md new file mode 100644 index 000000000..f64f6ec99 --- /dev/null +++ b/docs/stackit_beta_security-group_list.md @@ -0,0 +1,43 @@ +## stackit beta security-group list + +Lists security groups + +### Synopsis + +Lists security groups by its internal ID. + +``` +stackit beta security-group list [flags] +``` + +### Examples + +``` + List all groups + $ stackit beta security-group list + + List groups with labels + $ stackit beta security-group list --label-selector label1=value1,label2=value2 +``` + +### Options + +``` + -h, --help Help for "stackit beta security-group list" + --label-selector string Filter by label +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups + diff --git a/docs/stackit_beta_security-group_rule.md b/docs/stackit_beta_security-group_rule.md index a680f5bfc..8d47d0b21 100644 --- a/docs/stackit_beta_security-group_rule.md +++ b/docs/stackit_beta_security-group_rule.md @@ -28,7 +28,7 @@ stackit beta security-group rule [flags] ### SEE ALSO -* [stackit beta security-group](./stackit_beta_security-group.md) - Provides functionality for security groups +* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups * [stackit beta security-group rule create](./stackit_beta_security-group_rule_create.md) - Creates a security group rule * [stackit beta security-group rule delete](./stackit_beta_security-group_rule_delete.md) - Deletes a security group rule * [stackit beta security-group rule describe](./stackit_beta_security-group_rule_describe.md) - Shows details of a security group rule diff --git a/docs/stackit_beta_security-group_update.md b/docs/stackit_beta_security-group_update.md new file mode 100644 index 000000000..acba6414e --- /dev/null +++ b/docs/stackit_beta_security-group_update.md @@ -0,0 +1,45 @@ +## stackit beta security-group update + +Updates a security group + +### Synopsis + +Updates a named security group + +``` +stackit beta security-group update [flags] +``` + +### Examples + +``` + Update the name of group "xxx" + $ stackit beta security-group update xxx --name my-new-name + + Update the labels of group "xxx" + $ stackit beta security-group update xxx --labels label1=value1,label2=value2 +``` + +### Options + +``` + --description string An optional description of the security group. + -h, --help Help for "stackit beta security-group update" + --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) + --name string The name of the security group. +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups + diff --git a/internal/cmd/beta/security-group/create/create.go b/internal/cmd/beta/security-group/create/create.go new file mode 100644 index 000000000..e70273a44 --- /dev/null +++ b/internal/cmd/beta/security-group/create/create.go @@ -0,0 +1,169 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + nameFlag = "name" + descriptionFlag = "description" + statefulFlag = "stateful" + labelsFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Labels *map[string]string + Description *string + Name *string + Stateful *bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates security groups", + Long: "Creates security groups.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample(`Create a named group`, `$ stackit beta security-group create --name my-new-group`), + examples.NewExample(`Create a named group with labels`, `$ stackit beta security-group create --name my-new-group --labels label1=value1,label2=value2`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create the security group %q?", *model.Name) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + group, err := request.Execute() + if err != nil { + return fmt.Errorf("create security group: %w", err) + } + + if err := outputResult(p, model, group); err != nil { + return err + } + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "The name of the security group.") + cmd.Flags().String(descriptionFlag, "", "An optional description of the security group.") + cmd.Flags().Bool(statefulFlag, false, "Create a stateful or a stateless security group") + cmd.Flags().StringToString(labelsFlag, nil, "Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...'") + + if err := flags.MarkFlagsRequired(cmd, nameFlag); err != nil { + cobra.CheckErr(err) + } +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + name := flags.FlagToStringValue(p, cmd, nameFlag) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: &name, + + Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + Stateful: flags.FlagToBoolPointer(p, cmd, statefulFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateSecurityGroupRequest { + request := apiClient.CreateSecurityGroup(ctx, model.ProjectId) + + var labelsMap *map[string]any + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + payload := iaas.CreateSecurityGroupPayload{ + Description: model.Description, + Labels: labelsMap, + Name: model.Name, + Stateful: model.Stateful, + } + + return request.CreateSecurityGroupPayload(payload) +} + +func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal security group: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal security group: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created security group %q\n", *model.Name) + return nil + } +} diff --git a/internal/cmd/beta/security-group/create/create_test.go b/internal/cmd/beta/security-group/create/create_test.go new file mode 100644 index 000000000..1833e5c57 --- /dev/null +++ b/internal/cmd/beta/security-group/create/create_test.go @@ -0,0 +1,266 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testName = "new-security-group" + testDescription = "a test description" + testLabels = map[string]string{ + "fooKey": "fooValue", + "barKey": "barValue", + "bazKey": "bazValue", + } + testStateful = true +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + descriptionFlag: testDescription, + labelsFlag: "fooKey=fooValue,barKey=barValue,bazKey=bazValue", + statefulFlag: "true", + nameFlag: testName, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + Labels: &testLabels, + Description: &testDescription, + Name: &testName, + Stateful: &testStateful, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func toStringAnyMapPtr(m map[string]string) map[string]any { + if m == nil { + return nil + } + result := map[string]any{} + for k, v := range m { + result[k] = v + } + return result +} +func fixtureRequest(mods ...func(request *iaas.ApiCreateSecurityGroupRequest)) iaas.ApiCreateSecurityGroupRequest { + request := testClient.CreateSecurityGroup(testCtx, testProjectId) + + request = request.CreateSecurityGroupPayload(iaas.CreateSecurityGroupPayload{ + Description: &testDescription, + Labels: utils.Ptr(toStringAnyMapPtr(testLabels)), + Name: &testName, + Rules: nil, + Stateful: &testStateful, + }) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "name missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + { + description: "no labels", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelsFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + }, + { + description: "single label", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelsFlag] = "foo=bar" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = &map[string]string{ + "foo": "bar", + } + }), + }, + { + description: "stateless security group", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[statefulFlag] = "false" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Stateful = utils.Ptr(false) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateSecurityGroupRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no labels", + model: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateSecurityGroupRequest) { + *request = request.CreateSecurityGroupPayload(iaas.CreateSecurityGroupPayload{ + Description: &testDescription, + Labels: nil, + Name: &testName, + Stateful: &testStateful, + }) + }), + }, + { + description: "stateless security group", + model: fixtureInputModel(func(model *inputModel) { + model.Stateful = utils.Ptr(false) + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateSecurityGroupRequest) { + *request = request.CreateSecurityGroupPayload(iaas.CreateSecurityGroupPayload{ + Description: &testDescription, + Labels: utils.Ptr(toStringAnyMapPtr(testLabels)), + Name: &testName, + Stateful: utils.Ptr(false), + }) + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/delete/delete.go b/internal/cmd/beta/security-group/delete/delete.go new file mode 100644 index 000000000..580dbd96f --- /dev/null +++ b/internal/cmd/beta/security-group/delete/delete.go @@ -0,0 +1,110 @@ +package delete + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SecurityGroupId string +} + +const groupIdArg = "GROUP_ID" + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a security group", + Long: "Deletes a security group by its internal ID.", + Args: args.SingleArg(groupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample(`Delete a named group with ID "xxx"`, `$ stackit beta security-group delete xxx`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + groupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) + if err != nil { + p.Warn("get security group name: %v", err) + groupLabel = model.SecurityGroupId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete the security group %q for %q?", groupLabel, projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + if err := request.Execute(); err != nil { + return fmt.Errorf("delete security group: %w", err) + } + p.Info("Deleted security group %q for %q\n", groupLabel, projectLabel) + + return nil + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SecurityGroupId: cliArgs[0], + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteSecurityGroupRequest { + request := apiClient.DeleteSecurityGroup(ctx, model.ProjectId, model.SecurityGroupId) + return request +} diff --git a/internal/cmd/beta/security-group/delete/delete_test.go b/internal/cmd/beta/security-group/delete/delete_test.go new file mode 100644 index 000000000..7666e1585 --- /dev/null +++ b/internal/cmd/beta/security-group/delete/delete_test.go @@ -0,0 +1,183 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testGroupId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + SecurityGroupId: testGroupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteSecurityGroupRequest)) iaas.ApiDeleteSecurityGroupRequest { + request := testClient.DeleteSecurityGroup(testCtx, testProjectId, testGroupId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + args []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + args: []string{testGroupId}, + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "no arguments", + flagValues: fixtureFlagValues(), + args: nil, + isValid: false, + }, + { + description: "multiple arguments", + flagValues: fixtureFlagValues(), + args: []string{"foo", "bar"}, + isValid: false, + }, + { + description: "invalid group id", + flagValues: fixtureFlagValues(), + args: []string{"foo"}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + cmd.SetArgs(tt.args) + + 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) + } + } + + if err := cmd.ValidateArgs(tt.args); err != nil { + if !tt.isValid { + return + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd, tt.args) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteSecurityGroupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/describe/describe.go b/internal/cmd/beta/security-group/describe/describe.go new file mode 100644 index 000000000..68cd63eff --- /dev/null +++ b/internal/cmd/beta/security-group/describe/describe.go @@ -0,0 +1,148 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SecurityGroupId string +} + +const groupIdArg = "GROUP_ID" + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Describes security groups", + Long: "Describes security groups by its internal ID.", + Args: args.SingleArg(groupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample(`Describe group "xxx"`, `$ stackit beta security-group describe xxx`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + group, err := request.Execute() + if err != nil { + return fmt.Errorf("get security group: %w", err) + } + + if err := outputResult(p, model, group); err != nil { + return err + } + + return nil + }, + } + + return cmd +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetSecurityGroupRequest { + request := apiClient.GetSecurityGroup(ctx, model.ProjectId, model.SecurityGroupId) + return request +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SecurityGroupId: cliArgs[0], + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal security group: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal security group: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + if id := resp.Id; id != nil { + table.AddRow("ID", *id) + } + table.AddSeparator() + + if name := resp.Name; name != nil { + table.AddRow("NAME", *name) + table.AddSeparator() + } + + if description := resp.Description; description != nil { + table.AddRow("DESCRIPTION", *description) + table.AddSeparator() + } + + if resp.Labels != nil && len(*resp.Labels) > 0 { + labels := []string{} + for key, value := range *resp.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } + + if err := table.Display(p); err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/security-group/describe/describe_test.go b/internal/cmd/beta/security-group/describe/describe_test.go new file mode 100644 index 000000000..13a98fc84 --- /dev/null +++ b/internal/cmd/beta/security-group/describe/describe_test.go @@ -0,0 +1,194 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testSecurityGroupId = []string{uuid.NewString()} +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + SecurityGroupId: testSecurityGroupId[0], + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetSecurityGroupRequest)) iaas.ApiGetSecurityGroupRequest { + request := testClient.GetSecurityGroup(testCtx, testProjectId, testSecurityGroupId[0]) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + isValid bool + args []string + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + args: testSecurityGroupId, + isValid: true, + }, + { + description: "no values", + flagValues: map[string]string{}, + args: testSecurityGroupId, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + args: testSecurityGroupId, + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + args: testSecurityGroupId, + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + args: testSecurityGroupId, + isValid: false, + }, + { + description: "no group id passed", + flagValues: fixtureFlagValues(), + args: nil, + isValid: false, + }, + { + description: "multiple group ids passed", + flagValues: fixtureFlagValues(), + args: []string{uuid.NewString(), uuid.NewString()}, + isValid: false, + }, + { + description: "invalid group id passed", + flagValues: fixtureFlagValues(), + args: []string{"foobar"}, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + if err := cmd.ValidateArgs(tt.args); err != nil { + if !tt.isValid { + return + } + } + + model, err := parseInput(p, cmd, tt.args) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetSecurityGroupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/list/list.go b/internal/cmd/beta/security-group/list/list.go new file mode 100644 index 000000000..6c2bf6fcf --- /dev/null +++ b/internal/cmd/beta/security-group/list/list.go @@ -0,0 +1,151 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + LabelSelector *string +} + +const ( + labelSelectorFlag = "label-selector" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists security groups", + Long: "Lists security groups by its internal ID.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample(`List all groups`, `$ stackit beta security-group list`), + examples.NewExample(`List groups with labels`, `$ stackit beta security-group list --label-selector label1=value1,label2=value2`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + response, err := request.Execute() + if err != nil { + return fmt.Errorf("list security group: %w", err) + } + + if items := response.GetItems(); items == nil || len(*items) == 0 { + p.Info("No security groups found for project %q", projectLabel) + } else { + if err := outputResult(p, model.OutputFormat, *items); err != nil { + return fmt.Errorf("output security groups: %w", err) + } + } + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListSecurityGroupsRequest { + request := apiClient.ListSecurityGroups(ctx, model.ProjectId) + if model.LabelSelector != nil { + request = request.LabelSelector(*model.LabelSelector) + } + + return request +} +func outputResult(p *print.Printer, outputFormat string, items []iaas.SecurityGroup) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(items, "", " ") + if err != nil { + return fmt.Errorf("marshal PostgreSQL Flex instance list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal PostgreSQL Flex instance list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "STATEFUL") + for _, item := range items { + table.AddRow(utils.PtrString(item.Id), utils.PtrString(item.Name), utils.PtrString(item.Stateful)) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/security-group/list/list_test.go b/internal/cmd/beta/security-group/list/list_test.go new file mode 100644 index 000000000..c6f3a0c93 --- /dev/null +++ b/internal/cmd/beta/security-group/list/list_test.go @@ -0,0 +1,207 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testLabels = "fooKey=fooValue,barKey=barValue,bazKey=bazValue" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + labelSelectorFlag: testLabels, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + LabelSelector: utils.Ptr(testLabels), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListSecurityGroupsRequest)) iaas.ApiListSecurityGroupsRequest { + request := testClient.ListSecurityGroups(testCtx, testProjectId) + request = request.LabelSelector(testLabels) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "no labels", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelSelectorFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = nil + }), + }, + { + description: "single label", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "foo=bar" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("foo=bar") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListSecurityGroupsRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no labels", + model: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("") + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiListSecurityGroupsRequest) { + *request = request.LabelSelector("") + }), + }, + { + description: "single label", + model: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("foo=bar") + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiListSecurityGroupsRequest) { + *request = request.LabelSelector("foo=bar") + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/security_group.go b/internal/cmd/beta/security-group/security_group.go index 53f380d90..34e4bb73e 100644 --- a/internal/cmd/beta/security-group/security_group.go +++ b/internal/cmd/beta/security-group/security_group.go @@ -1,9 +1,15 @@ -package securitygroup +package security_group import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" @@ -12,8 +18,8 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "security-group", - Short: "Provides functionality for security groups", - Long: "Provides functionality for security groups.", + Short: "Manage security groups", + Long: "Manage the lifecycle of security groups and rules.", Args: args.NoArgs, Run: utils.CmdHelp, } @@ -22,5 +28,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(rule.NewCmd(p)) + cmd.AddCommand( + rule.NewCmd(p), + create.NewCmd(p), + delete.NewCmd(p), + describe.NewCmd(p), + list.NewCmd(p), + update.NewCmd(p), + ) } diff --git a/internal/cmd/beta/security-group/update/update.go b/internal/cmd/beta/security-group/update/update.go new file mode 100644 index 000000000..961229053 --- /dev/null +++ b/internal/cmd/beta/security-group/update/update.go @@ -0,0 +1,150 @@ +package update + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Labels *map[string]string + Description *string + Name *string + SecurityGroupId string +} + +const groupNameArg = "GROUP_ID" + +const ( + nameArg = "name" + descriptionArg = "description" + labelsArg = "labels" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a security group", + Long: "Updates a named security group", + Args: args.SingleArg(groupNameArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample(`Update the name of group "xxx"`, `$ stackit beta security-group update xxx --name my-new-name`), + examples.NewExample(`Update the labels of group "xxx"`, `$ stackit beta security-group update xxx --labels label1=value1,label2=value2`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + groupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) + if err != nil { + p.Warn("cannot retrieve groupname: %v", err) + groupLabel = model.SecurityGroupId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update the security group %q?", groupLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update security group: %w", err) + } + p.Info("Updated security group \"%v\" for %q\n", utils.PtrString(resp.Name), projectLabel) + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameArg, "", "The name of the security group.") + cmd.Flags().String(descriptionArg, "", "An optional description of the security group.") + cmd.Flags().StringToString(labelsArg, nil, "Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...'") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Labels: flags.FlagToStringToStringPointer(p, cmd, labelsArg), + Description: flags.FlagToStringPointer(p, cmd, descriptionArg), + Name: flags.FlagToStringPointer(p, cmd, nameArg), + SecurityGroupId: cliArgs[0], + } + + if model.Labels == nil && model.Description == nil && model.Name == nil { + return nil, fmt.Errorf("no flags have been passed") + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateSecurityGroupRequest { + request := apiClient.UpdateSecurityGroup(ctx, model.ProjectId, model.SecurityGroupId) + payload := iaas.NewUpdateSecurityGroupPayload() + payload.Description = model.Description + var labelsMap *map[string]any + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + payload.Labels = labelsMap + payload.Name = model.Name + request = request.UpdateSecurityGroupPayload(*payload) + + return request +} diff --git a/internal/cmd/beta/security-group/update/update_test.go b/internal/cmd/beta/security-group/update/update_test.go new file mode 100644 index 000000000..f27cbfc25 --- /dev/null +++ b/internal/cmd/beta/security-group/update/update_test.go @@ -0,0 +1,291 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testGroupId = []string{uuid.NewString()} + testName = "new-security-group" + testDescription = "a test description" + testLabels = map[string]string{ + "fooKey": "fooValue", + "barKey": "barValue", + "bazKey": "bazValue", + } +) + +func toStringAnyMapPtr(m map[string]string) map[string]any { + if m == nil { + return nil + } + result := map[string]any{} + for k, v := range m { + result[k] = v + } + return result +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + descriptionArg: testDescription, + labelsArg: "fooKey=fooValue,barKey=barValue,bazKey=bazValue", + nameArg: testName, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + Labels: &testLabels, + Description: &testDescription, + Name: &testName, + SecurityGroupId: testGroupId[0], + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateSecurityGroupRequest)) iaas.ApiUpdateSecurityGroupRequest { + request := testClient.UpdateSecurityGroup(testCtx, testProjectId, testGroupId[0]) + request = request.UpdateSecurityGroupPayload(iaas.UpdateSecurityGroupPayload{ + Description: &testDescription, + Labels: utils.Ptr(toStringAnyMapPtr(testLabels)), + Name: &testName, + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + args []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + args: testGroupId, + expectedModel: fixtureInputModel(), + }, + { + description: "no values but valid group id", + flagValues: map[string]string{ + projectIdFlag: testProjectId, + }, + args: testGroupId, + isValid: false, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + model.Name = nil + model.Description = nil + }), + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + args: testGroupId, + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + args: testGroupId, + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + args: testGroupId, + isValid: false, + }, + { + description: "no name passed", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameArg) + }), + args: testGroupId, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = nil + }), + isValid: true, + }, + { + description: "no description passed", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, descriptionArg) + }), + args: testGroupId, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Description = nil + }), + isValid: true, + }, + { + description: "no labels", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelsArg) + }), + args: testGroupId, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + isValid: true, + }, + { + description: "single label", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelsArg] = "foo=bar" + }), + args: testGroupId, + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = &map[string]string{ + "foo": "bar", + } + }), + }, + { + description: "no group id passed", + flagValues: fixtureFlagValues(), + args: nil, + isValid: false, + }, + { + description: "invalid group id passed", + flagValues: fixtureFlagValues(), + args: []string{"foobar"}, + isValid: false, + }, + { + description: "multiple group ids passed", + flagValues: fixtureFlagValues(), + args: []string{uuid.NewString(), uuid.NewString()}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot configure global flags: %v", err) + } + + for flag, value := range tt.flagValues { + if err := cmd.Flags().Set(flag, value); err != nil { + if !tt.isValid { + return + } + t.Fatalf("setting flag --%s=%s: %v", flag, value, err) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + if err := cmd.ValidateArgs(tt.args); err != nil { + if !tt.isValid { + return + } + } + + model, err := parseInput(p, cmd, tt.args) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateSecurityGroupRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no labels", + model: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateSecurityGroupRequest) { + *request = request.UpdateSecurityGroupPayload(iaas.UpdateSecurityGroupPayload{ + Description: &testDescription, + Labels: nil, + Name: &testName, + }) + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index 205bff1cf..dc1cfeffb 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -16,6 +16,15 @@ func Ptr[T any](v T) *T { return &v } +// PtrString creates a string representation of a passed object pointer or returns +// an empty string, if the passed object is _nil_. +func PtrString[T any](t *T) string { + if t != nil { + return fmt.Sprintf("%v", *t) + } + return "" +} + // Int64Ptr returns a pointer to an int64 // Needed because the Ptr function only returns pointer to int func Int64Ptr(i int64) *int64 { From 8065324798085257432b57ed6f39aac46dc693b3 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 13 Dec 2024 15:11:37 +0100 Subject: [PATCH 125/619] Onboard IaaS server action commands (#536) Supported commands: start, stop, reboot, deallocate, resize, console, log, rescue, unrescue Signed-off-by: Alexander Dahmen --- docs/stackit_beta_server.md | 9 + docs/stackit_beta_server_console.md | 42 ++++ docs/stackit_beta_server_deallocate.md | 39 +++ docs/stackit_beta_server_log.md | 46 ++++ docs/stackit_beta_server_reboot.md | 43 ++++ docs/stackit_beta_server_rescue.md | 40 ++++ docs/stackit_beta_server_resize.md | 40 ++++ docs/stackit_beta_server_start.md | 39 +++ docs/stackit_beta_server_stop.md | 39 +++ docs/stackit_beta_server_unrescue.md | 39 +++ internal/cmd/beta/server/console/console.go | 140 +++++++++++ .../cmd/beta/server/console/console_test.go | 208 ++++++++++++++++ .../cmd/beta/server/deallocate/deallocate.go | 127 ++++++++++ .../beta/server/deallocate/deallocate_test.go | 208 ++++++++++++++++ internal/cmd/beta/server/log/log.go | 165 +++++++++++++ internal/cmd/beta/server/log/log_test.go | 222 +++++++++++++++++ internal/cmd/beta/server/reboot/reboot.go | 131 ++++++++++ .../cmd/beta/server/reboot/reboot_test.go | 219 +++++++++++++++++ internal/cmd/beta/server/rescue/rescue.go | 144 +++++++++++ .../cmd/beta/server/rescue/rescue_test.go | 225 ++++++++++++++++++ internal/cmd/beta/server/resize/resize.go | 144 +++++++++++ .../cmd/beta/server/resize/resize_test.go | 224 +++++++++++++++++ internal/cmd/beta/server/server.go | 18 ++ internal/cmd/beta/server/start/start.go | 119 +++++++++ internal/cmd/beta/server/start/start_test.go | 208 ++++++++++++++++ internal/cmd/beta/server/stop/stop.go | 127 ++++++++++ internal/cmd/beta/server/stop/stop_test.go | 208 ++++++++++++++++ internal/cmd/beta/server/unrescue/unrescue.go | 127 ++++++++++ .../cmd/beta/server/unrescue/unrescue_test.go | 208 ++++++++++++++++ 29 files changed, 3548 insertions(+) create mode 100644 docs/stackit_beta_server_console.md create mode 100644 docs/stackit_beta_server_deallocate.md create mode 100644 docs/stackit_beta_server_log.md create mode 100644 docs/stackit_beta_server_reboot.md create mode 100644 docs/stackit_beta_server_rescue.md create mode 100644 docs/stackit_beta_server_resize.md create mode 100644 docs/stackit_beta_server_start.md create mode 100644 docs/stackit_beta_server_stop.md create mode 100644 docs/stackit_beta_server_unrescue.md create mode 100644 internal/cmd/beta/server/console/console.go create mode 100644 internal/cmd/beta/server/console/console_test.go create mode 100644 internal/cmd/beta/server/deallocate/deallocate.go create mode 100644 internal/cmd/beta/server/deallocate/deallocate_test.go create mode 100644 internal/cmd/beta/server/log/log.go create mode 100644 internal/cmd/beta/server/log/log_test.go create mode 100644 internal/cmd/beta/server/reboot/reboot.go create mode 100644 internal/cmd/beta/server/reboot/reboot_test.go create mode 100644 internal/cmd/beta/server/rescue/rescue.go create mode 100644 internal/cmd/beta/server/rescue/rescue_test.go create mode 100644 internal/cmd/beta/server/resize/resize.go create mode 100644 internal/cmd/beta/server/resize/resize_test.go create mode 100644 internal/cmd/beta/server/start/start.go create mode 100644 internal/cmd/beta/server/start/start_test.go create mode 100644 internal/cmd/beta/server/stop/stop.go create mode 100644 internal/cmd/beta/server/stop/stop_test.go create mode 100644 internal/cmd/beta/server/unrescue/unrescue.go create mode 100644 internal/cmd/beta/server/unrescue/unrescue_test.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index b8f078aad..6ec25fc7a 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -31,13 +31,22 @@ stackit beta server [flags] * [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands * [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups * [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command +* [stackit beta server console](./stackit_beta_server_console.md) - Gets a URL for server remote console * [stackit beta server create](./stackit_beta_server_create.md) - Creates a server +* [stackit beta server deallocate](./stackit_beta_server_deallocate.md) - Deallocates an existing server * [stackit beta server delete](./stackit_beta_server_delete.md) - Deletes a server * [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project +* [stackit beta server log](./stackit_beta_server_log.md) - Gets server console log * [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers * [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers +* [stackit beta server reboot](./stackit_beta_server_reboot.md) - Reboots a server +* [stackit beta server rescue](./stackit_beta_server_rescue.md) - Rescues an existing server +* [stackit beta server resize](./stackit_beta_server_resize.md) - Resizes the server to the given machine type * [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers +* [stackit beta server start](./stackit_beta_server_start.md) - Starts an existing server or allocates the server if deallocated +* [stackit beta server stop](./stackit_beta_server_stop.md) - Stops an existing server +* [stackit beta server unrescue](./stackit_beta_server_unrescue.md) - Unrescues an existing server * [stackit beta server update](./stackit_beta_server_update.md) - Updates a server * [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_console.md b/docs/stackit_beta_server_console.md new file mode 100644 index 000000000..5fccb3d5b --- /dev/null +++ b/docs/stackit_beta_server_console.md @@ -0,0 +1,42 @@ +## stackit beta server console + +Gets a URL for server remote console + +### Synopsis + +Gets a URL for server remote console. + +``` +stackit beta server console [flags] +``` + +### Examples + +``` + Get a URL for the server remote console with server ID "xxx" + $ stackit beta server console xxx + + Get a URL for the server remote console with server ID "xxx" in JSON format + $ stackit beta server console xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server console" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/docs/stackit_beta_server_deallocate.md b/docs/stackit_beta_server_deallocate.md new file mode 100644 index 000000000..96323db32 --- /dev/null +++ b/docs/stackit_beta_server_deallocate.md @@ -0,0 +1,39 @@ +## stackit beta server deallocate + +Deallocates an existing server + +### Synopsis + +Deallocates an existing server. + +``` +stackit beta server deallocate [flags] +``` + +### Examples + +``` + Deallocate an existing server with ID "xxx" + $ stackit beta server deallocate xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta server deallocate" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/docs/stackit_beta_server_log.md b/docs/stackit_beta_server_log.md new file mode 100644 index 000000000..b9cad0a9c --- /dev/null +++ b/docs/stackit_beta_server_log.md @@ -0,0 +1,46 @@ +## stackit beta server log + +Gets server console log + +### Synopsis + +Gets server console log. + +``` +stackit beta server log [flags] +``` + +### Examples + +``` + Get server console log for the server with ID "xxx" + $ stackit beta server log xxx + + Get server console log for the server with ID "xxx" and limit output lines to 1000 + $ stackit beta server log xxx --length 1000 + + Get server console log for the server with ID "xxx" in JSON format + $ stackit beta server log xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server log" + --length int Maximum number of lines to list (default 2000) +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/docs/stackit_beta_server_reboot.md b/docs/stackit_beta_server_reboot.md new file mode 100644 index 000000000..a100c8a0d --- /dev/null +++ b/docs/stackit_beta_server_reboot.md @@ -0,0 +1,43 @@ +## stackit beta server reboot + +Reboots a server + +### Synopsis + +Reboots a server. + +``` +stackit beta server reboot [flags] +``` + +### Examples + +``` + Perform a soft reboot of a server with ID "xxx" + $ stackit beta server reboot xxx + + Perform a hard reboot of a server with ID "xxx" + $ stackit beta server reboot xxx --hard +``` + +### Options + +``` + -b, --hard Performs a hard reboot. (default false) + -h, --help Help for "stackit beta server reboot" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/docs/stackit_beta_server_rescue.md b/docs/stackit_beta_server_rescue.md new file mode 100644 index 000000000..2064a6ad6 --- /dev/null +++ b/docs/stackit_beta_server_rescue.md @@ -0,0 +1,40 @@ +## stackit beta server rescue + +Rescues an existing server + +### Synopsis + +Rescues an existing server. + +``` +stackit beta server rescue [flags] +``` + +### Examples + +``` + Rescue an existing server with ID "xxx" using image with ID "yyy" as boot volume + $ stackit beta server rescue xxx --image-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server rescue" + --image-id string The image ID to be used for a temporary boot volume. +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/docs/stackit_beta_server_resize.md b/docs/stackit_beta_server_resize.md new file mode 100644 index 000000000..4ef3e6715 --- /dev/null +++ b/docs/stackit_beta_server_resize.md @@ -0,0 +1,40 @@ +## stackit beta server resize + +Resizes the server to the given machine type + +### Synopsis + +Resizes the server to the given machine type. + +``` +stackit beta server resize [flags] +``` + +### Examples + +``` + Resize a server with ID "xxx" to machine type "yyy" + $ stackit beta server resize xxx --machine-type yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta server resize" + --machine-type string Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/docs/stackit_beta_server_start.md b/docs/stackit_beta_server_start.md new file mode 100644 index 000000000..7a811400c --- /dev/null +++ b/docs/stackit_beta_server_start.md @@ -0,0 +1,39 @@ +## stackit beta server start + +Starts an existing server or allocates the server if deallocated + +### Synopsis + +Starts an existing server or allocates the server if deallocated. + +``` +stackit beta server start [flags] +``` + +### Examples + +``` + Start an existing server with ID "xxx" + $ stackit beta server start xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta server start" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/docs/stackit_beta_server_stop.md b/docs/stackit_beta_server_stop.md new file mode 100644 index 000000000..1521146b0 --- /dev/null +++ b/docs/stackit_beta_server_stop.md @@ -0,0 +1,39 @@ +## stackit beta server stop + +Stops an existing server + +### Synopsis + +Stops an existing server. + +``` +stackit beta server stop [flags] +``` + +### Examples + +``` + Stop an existing server with ID "xxx" + $ stackit beta server stop xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta server stop" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/docs/stackit_beta_server_unrescue.md b/docs/stackit_beta_server_unrescue.md new file mode 100644 index 000000000..06020bdb6 --- /dev/null +++ b/docs/stackit_beta_server_unrescue.md @@ -0,0 +1,39 @@ +## stackit beta server unrescue + +Unrescues an existing server + +### Synopsis + +Unrescues an existing server. + +``` +stackit beta server unrescue [flags] +``` + +### Examples + +``` + Unrescue an existing server with ID "xxx" + $ stackit beta server unrescue xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta server unrescue" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers + diff --git a/internal/cmd/beta/server/console/console.go b/internal/cmd/beta/server/console/console.go new file mode 100644 index 000000000..9bc862cdf --- /dev/null +++ b/internal/cmd/beta/server/console/console.go @@ -0,0 +1,140 @@ +package console + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + + "github.com/goccy/go-yaml" + "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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "console", + Short: "Gets a URL for server remote console", + Long: "Gets a URL for server remote console.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get a URL for the server remote console with server ID "xxx"`, + "$ stackit beta server console xxx", + ), + examples.NewExample( + `Get a URL for the server remote console with server ID "xxx" in JSON format`, + "$ stackit beta server console xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("server console: %w", err) + } + + return outputResult(p, model, serverLabel, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetServerConsoleRequest { + return apiClient.GetServerConsole(ctx, model.ProjectId, model.ServerId) +} + +func outputResult(p *print.Printer, model *inputModel, serverLabel string, serverUrl *iaas.ServerConsoleUrl) error { + outputFormat := model.OutputFormat + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(serverUrl, "", " ") + if err != nil { + return fmt.Errorf("marshal url: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(serverUrl, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal url: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + // unescape url in order to get rid of e.g. %40 + unescapedURL, err := url.PathUnescape(*serverUrl.GetUrl()) + if err != nil { + return fmt.Errorf("unescape url: %w", err) + } + + p.Outputf("Remote console URL %q for server %q\n", unescapedURL, serverLabel) + + return nil + } +} diff --git a/internal/cmd/beta/server/console/console_test.go b/internal/cmd/beta/server/console/console_test.go new file mode 100644 index 000000000..1dfc48384 --- /dev/null +++ b/internal/cmd/beta/server/console/console_test.go @@ -0,0 +1,208 @@ +package console + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetServerConsoleRequest)) iaas.ApiGetServerConsoleRequest { + request := testClient.GetServerConsole(testCtx, testProjectId, testServerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetServerConsoleRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/deallocate/deallocate.go b/internal/cmd/beta/server/deallocate/deallocate.go new file mode 100644 index 000000000..6396f2e0b --- /dev/null +++ b/internal/cmd/beta/server/deallocate/deallocate.go @@ -0,0 +1,127 @@ +package deallocate + +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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "deallocate", + Short: "Deallocates an existing server", + Long: "Deallocates an existing server.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Deallocate an existing server with ID "xxx"`, + "$ stackit beta server deallocate xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to deallocate server %q?", serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("server deallocate: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Deallocating server") + _, err = wait.DeallocateServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for server deallocating: %w", err) + } + s.Stop() + } + + operationState := "Deallocated" + if model.Async { + operationState = "Triggered deallocation of" + } + p.Info("%s server %q\n", operationState, serverLabel) + + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeallocateServerRequest { + return apiClient.DeallocateServer(ctx, model.ProjectId, model.ServerId) +} diff --git a/internal/cmd/beta/server/deallocate/deallocate_test.go b/internal/cmd/beta/server/deallocate/deallocate_test.go new file mode 100644 index 000000000..6ededf983 --- /dev/null +++ b/internal/cmd/beta/server/deallocate/deallocate_test.go @@ -0,0 +1,208 @@ +package deallocate + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeallocateServerRequest)) iaas.ApiDeallocateServerRequest { + request := testClient.DeallocateServer(testCtx, testProjectId, testServerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeallocateServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/log/log.go b/internal/cmd/beta/server/log/log.go new file mode 100644 index 000000000..7cfffcb84 --- /dev/null +++ b/internal/cmd/beta/server/log/log.go @@ -0,0 +1,165 @@ +package log + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" + + lengthLimitFlag = "length" + defaultLengthLimit = 2000 // lines +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + Length *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "log", + Short: "Gets server console log", + Long: "Gets server console log.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get server console log for the server with ID "xxx"`, + "$ stackit beta server log xxx", + ), + examples.NewExample( + `Get server console log for the server with ID "xxx" and limit output lines to 1000`, + "$ stackit beta server log xxx --length 1000", + ), + examples.NewExample( + `Get server console log for the server with ID "xxx" in JSON format`, + "$ stackit beta server log xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("server log: %w", err) + } + + log := *resp.GetOutput() + lines := strings.Split(log, "\n") + + if len(lines) > int(*model.Length) { + // Truncate output and show most recent logs + start := len(lines) - int(*model.Length) + return outputResult(p, model, serverLabel, strings.Join(lines[start:], "\n")) + } + + return outputResult(p, model, serverLabel, log) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(lengthLimitFlag, defaultLengthLimit, "Maximum number of lines to list") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + length := flags.FlagWithDefaultToInt64Value(p, cmd, lengthLimitFlag) + if length < 0 { + return nil, &errors.FlagValidationError{ + Flag: lengthLimitFlag, + Details: "must not be negative", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + Length: utils.Ptr(length), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetServerLogRequest { + return apiClient.GetServerLog(ctx, model.ProjectId, model.ServerId) +} + +func outputResult(p *print.Printer, model *inputModel, serverLabel, log string) error { + outputFormat := model.OutputFormat + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(log, "", " ") + if err != nil { + return fmt.Errorf("marshal url: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(log, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal url: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Log for server %q\n%s", serverLabel, log) + return nil + } +} diff --git a/internal/cmd/beta/server/log/log_test.go b/internal/cmd/beta/server/log/log_test.go new file mode 100644 index 000000000..5e10870d6 --- /dev/null +++ b/internal/cmd/beta/server/log/log_test.go @@ -0,0 +1,222 @@ +package log + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + lengthLimitFlag: "3000", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + Length: utils.Ptr(int64(3000)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetServerLogRequest)) iaas.ApiGetServerLogRequest { + request := testClient.GetServerLog(testCtx, testProjectId, testServerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "optional length missing (test default value)", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, lengthLimitFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Length = utils.Ptr(int64(2000)) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetServerLogRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/reboot/reboot.go b/internal/cmd/beta/server/reboot/reboot.go new file mode 100644 index 000000000..6983e7531 --- /dev/null +++ b/internal/cmd/beta/server/reboot/reboot.go @@ -0,0 +1,131 @@ +package reboot + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" + + hardRebootFlag = "hard" + defaultHardReboot = false + hardRebootAction = "hard" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + HardReboot bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "reboot", + Short: "Reboots a server", + Long: "Reboots a server.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Perform a soft reboot of a server with ID "xxx"`, + "$ stackit beta server reboot xxx", + ), + examples.NewExample( + `Perform a hard reboot of a server with ID "xxx"`, + "$ stackit beta server reboot xxx --hard", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to reboot server %q?", serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("server reboot: %w", err) + } + + p.Info("Server %q rebooted\n", serverLabel) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().BoolP(hardRebootFlag, "b", defaultHardReboot, "Performs a hard reboot. (default false)") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + HardReboot: flags.FlagToBoolValue(p, cmd, hardRebootFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRebootServerRequest { + req := apiClient.RebootServer(ctx, model.ProjectId, model.ServerId) + // if hard reboot is set the action must be set (soft is default) + if model.HardReboot { + req = req.Action(hardRebootAction) + } + return req +} diff --git a/internal/cmd/beta/server/reboot/reboot_test.go b/internal/cmd/beta/server/reboot/reboot_test.go new file mode 100644 index 000000000..c4444fa85 --- /dev/null +++ b/internal/cmd/beta/server/reboot/reboot_test.go @@ -0,0 +1,219 @@ +package reboot + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + hardRebootFlag: "false", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + HardReboot: false, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiRebootServerRequest)) iaas.ApiRebootServerRequest { + request := testClient.RebootServer(testCtx, testProjectId, testServerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRebootServerRequest + }{ + { + description: "base (soft reboot)", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "hard reboot is set", + model: fixtureInputModel(func(model *inputModel) { + model.HardReboot = true + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiRebootServerRequest) { + *request = request.Action("hard") + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/rescue/rescue.go b/internal/cmd/beta/server/rescue/rescue.go new file mode 100644 index 000000000..b658f4ace --- /dev/null +++ b/internal/cmd/beta/server/rescue/rescue.go @@ -0,0 +1,144 @@ +package rescue + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" + + imageIdFlag = "image-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + ImageId *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "rescue", + Short: "Rescues an existing server", + Long: "Rescues an existing server.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Rescue an existing server with ID "xxx" using image with ID "yyy" as boot volume`, + "$ stackit beta server rescue xxx --image-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to rescue server %q?", serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("server rescue: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Rescuing server") + _, err = wait.RescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for server rescuing: %w", err) + } + s.Stop() + } + + operationState := "Rescued" + if model.Async { + operationState = "Triggered rescue of" + } + p.Info("%s server %q. Image %q is used as temporary boot image\n", operationState, serverLabel, *model.ImageId) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), imageIdFlag, "The image ID to be used for a temporary boot volume.") + + err := flags.MarkFlagsRequired(cmd, imageIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + ImageId: flags.FlagToStringPointer(p, cmd, imageIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRescueServerRequest { + req := apiClient.RescueServer(ctx, model.ProjectId, model.ServerId) + payload := iaas.RescueServerPayload{ + Image: model.ImageId, + } + return req.RescueServerPayload(payload) +} diff --git a/internal/cmd/beta/server/rescue/rescue_test.go b/internal/cmd/beta/server/rescue/rescue_test.go new file mode 100644 index 000000000..9d17daf78 --- /dev/null +++ b/internal/cmd/beta/server/rescue/rescue_test.go @@ -0,0 +1,225 @@ +package rescue + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testImageId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + imageIdFlag: testImageId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + ImageId: utils.Ptr(testImageId), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiRescueServerRequest)) iaas.ApiRescueServerRequest { + request := testClient.RescueServer(testCtx, testProjectId, testServerId) + request = request.RescueServerPayload(iaas.RescueServerPayload{ + Image: utils.Ptr(testImageId), + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "required image id flag missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, imageIdFlag) + }), + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRescueServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/resize/resize.go b/internal/cmd/beta/server/resize/resize.go new file mode 100644 index 000000000..95b5b3e00 --- /dev/null +++ b/internal/cmd/beta/server/resize/resize.go @@ -0,0 +1,144 @@ +package resize + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" + + machineTypeFlag = "machine-type" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + MachineType *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "resize", + Short: "Resizes the server to the given machine type", + Long: "Resizes the server to the given machine type.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Resize a server with ID "xxx" to machine type "yyy"`, + "$ stackit beta server resize xxx --machine-type yyy", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to resize server %q to machine type %q?", serverLabel, *model.MachineType) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("server resize: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Resizing server") + _, err = wait.ResizeServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for server resizing: %w", err) + } + s.Stop() + } + + operationState := "Resized" + if model.Async { + operationState = "Triggered resize of" + } + p.Info("%s server %q\n", operationState, serverLabel) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(machineTypeFlag, "", "Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html") + + err := flags.MarkFlagsRequired(cmd, machineTypeFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + MachineType: flags.FlagToStringPointer(p, cmd, machineTypeFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiResizeServerRequest { + req := apiClient.ResizeServer(ctx, model.ProjectId, model.ServerId) + payload := iaas.ResizeServerPayload{ + MachineType: model.MachineType, + } + return req.ResizeServerPayload(payload) +} diff --git a/internal/cmd/beta/server/resize/resize_test.go b/internal/cmd/beta/server/resize/resize_test.go new file mode 100644 index 000000000..a93d8fdc1 --- /dev/null +++ b/internal/cmd/beta/server/resize/resize_test.go @@ -0,0 +1,224 @@ +package resize + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + machineTypeFlag: "t1.2", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + MachineType: utils.Ptr("t1.2"), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiResizeServerRequest)) iaas.ApiResizeServerRequest { + request := testClient.ResizeServer(testCtx, testProjectId, testServerId) + request = request.ResizeServerPayload(iaas.ResizeServerPayload{ + MachineType: utils.Ptr("t1.2"), + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "required machine type flag missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, machineTypeFlag) + }), + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiResizeServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 9b96c1322..6d75b27d5 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -3,13 +3,22 @@ package server import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/console" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/deallocate" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/log" networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/reboot" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/rescue" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/resize" serviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/start" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/stop" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/unrescue" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume" @@ -44,4 +53,13 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(update.NewCmd(p)) cmd.AddCommand(volume.NewCmd(p)) cmd.AddCommand(networkinterface.NewCmd(p)) + cmd.AddCommand(console.NewCmd(p)) + cmd.AddCommand(log.NewCmd(p)) + cmd.AddCommand(start.NewCmd(p)) + cmd.AddCommand(stop.NewCmd(p)) + cmd.AddCommand(reboot.NewCmd(p)) + cmd.AddCommand(deallocate.NewCmd(p)) + cmd.AddCommand(resize.NewCmd(p)) + cmd.AddCommand(rescue.NewCmd(p)) + cmd.AddCommand(unrescue.NewCmd(p)) } diff --git a/internal/cmd/beta/server/start/start.go b/internal/cmd/beta/server/start/start.go new file mode 100644 index 000000000..764d3c5d9 --- /dev/null +++ b/internal/cmd/beta/server/start/start.go @@ -0,0 +1,119 @@ +package start + +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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "start", + Short: "Starts an existing server or allocates the server if deallocated", + Long: "Starts an existing server or allocates the server if deallocated.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Start an existing server with ID "xxx"`, + "$ stackit beta server start xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("server start: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Starting server") + _, err = wait.StartServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for server starting: %w", err) + } + s.Stop() + } + + operationState := "Started" + if model.Async { + operationState = "Triggered start of" + } + p.Info("%s server %q\n", operationState, serverLabel) + + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiStartServerRequest { + return apiClient.StartServer(ctx, model.ProjectId, model.ServerId) +} diff --git a/internal/cmd/beta/server/start/start_test.go b/internal/cmd/beta/server/start/start_test.go new file mode 100644 index 000000000..f90b6048d --- /dev/null +++ b/internal/cmd/beta/server/start/start_test.go @@ -0,0 +1,208 @@ +package start + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiStartServerRequest)) iaas.ApiStartServerRequest { + request := testClient.StartServer(testCtx, testProjectId, testServerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiStartServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/stop/stop.go b/internal/cmd/beta/server/stop/stop.go new file mode 100644 index 000000000..a8fc651e6 --- /dev/null +++ b/internal/cmd/beta/server/stop/stop.go @@ -0,0 +1,127 @@ +package stop + +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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "stop", + Short: "Stops an existing server", + Long: "Stops an existing server.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Stop an existing server with ID "xxx"`, + "$ stackit beta server stop xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to stop server %q?", serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("server stop: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Stopping server") + _, err = wait.StopServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for server stopping: %w", err) + } + s.Stop() + } + + operationState := "Stopped" + if model.Async { + operationState = "Triggered stop of" + } + p.Info("%s server %q\n", operationState, serverLabel) + + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiStopServerRequest { + return apiClient.StopServer(ctx, model.ProjectId, model.ServerId) +} diff --git a/internal/cmd/beta/server/stop/stop_test.go b/internal/cmd/beta/server/stop/stop_test.go new file mode 100644 index 000000000..a4e889181 --- /dev/null +++ b/internal/cmd/beta/server/stop/stop_test.go @@ -0,0 +1,208 @@ +package stop + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiStopServerRequest)) iaas.ApiStopServerRequest { + request := testClient.StopServer(testCtx, testProjectId, testServerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiStopServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/unrescue/unrescue.go b/internal/cmd/beta/server/unrescue/unrescue.go new file mode 100644 index 000000000..c41d9f0c7 --- /dev/null +++ b/internal/cmd/beta/server/unrescue/unrescue.go @@ -0,0 +1,127 @@ +package unrescue + +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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + + "github.com/spf13/cobra" +) + +const ( + serverIdArg = "SERVER_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "unrescue", + Short: "Unrescues an existing server", + Long: "Unrescues an existing server.", + Args: args.SingleArg(serverIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Unrescue an existing server with ID "xxx"`, + "$ stackit beta server unrescue xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + serverLabel = model.ServerId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to unrescue server %q?", serverLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("server unrescue: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Unrescuing server") + _, err = wait.UnrescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for server unrescuing: %w", err) + } + s.Stop() + } + + operationState := "Unrescued" + if model.Async { + operationState = "Triggered unrescue of" + } + p.Info("%s server %q\n", operationState, serverLabel) + + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + serverId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: serverId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUnrescueServerRequest { + return apiClient.UnrescueServer(ctx, model.ProjectId, model.ServerId) +} diff --git a/internal/cmd/beta/server/unrescue/unrescue_test.go b/internal/cmd/beta/server/unrescue/unrescue_test.go new file mode 100644 index 000000000..82f75a370 --- /dev/null +++ b/internal/cmd/beta/server/unrescue/unrescue_test.go @@ -0,0 +1,208 @@ +package unrescue + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testServerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUnrescueServerRequest)) iaas.ApiUnrescueServerRequest { + request := testClient.UnrescueServer(testCtx, testProjectId, testServerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "server id invalid 1", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "server id invalid 2", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "invalid-uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUnrescueServerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} From 7e4fd4f5d149759de8313ec94e00111720322f41 Mon Sep 17 00:00:00 2001 From: Marcel <72880145+marceljk@users.noreply.github.com> Date: Tue, 17 Dec 2024 08:44:27 +0100 Subject: [PATCH 126/619] Add command to import config profiles (#539) * Add command to import config profiles --- docs/stackit_config_profile.md | 1 + docs/stackit_config_profile_import.md | 45 +++++++ internal/cmd/config/profile/import/import.go | 106 ++++++++++++++++ .../cmd/config/profile/import/import_test.go | 118 ++++++++++++++++++ .../profile/import/template/profile.json | 33 +++++ internal/cmd/config/profile/profile.go | 2 + internal/pkg/config/profiles.go | 67 ++++++++++ internal/pkg/config/profiles_test.go | 67 ++++++++++ .../pkg/config/template/test_profile.json | 33 +++++ internal/pkg/errors/errors.go | 13 ++ 10 files changed, 485 insertions(+) create mode 100644 docs/stackit_config_profile_import.md create mode 100644 internal/cmd/config/profile/import/import.go create mode 100644 internal/cmd/config/profile/import/import_test.go create mode 100644 internal/cmd/config/profile/import/template/profile.json create mode 100644 internal/pkg/config/template/test_profile.json diff --git a/docs/stackit_config_profile.md b/docs/stackit_config_profile.md index 947f3cc9c..415ac9d06 100644 --- a/docs/stackit_config_profile.md +++ b/docs/stackit_config_profile.md @@ -34,6 +34,7 @@ stackit config profile [flags] * [stackit config](./stackit_config.md) - Provides functionality for CLI configuration options * [stackit config profile create](./stackit_config_profile_create.md) - Creates a CLI configuration profile * [stackit config profile delete](./stackit_config_profile_delete.md) - Delete a CLI configuration profile +* [stackit config profile import](./stackit_config_profile_import.md) - Imports a CLI configuration profile * [stackit config profile list](./stackit_config_profile_list.md) - Lists all CLI configuration profiles * [stackit config profile set](./stackit_config_profile_set.md) - Set a CLI configuration profile * [stackit config profile unset](./stackit_config_profile_unset.md) - Unset the current active CLI configuration profile diff --git a/docs/stackit_config_profile_import.md b/docs/stackit_config_profile_import.md new file mode 100644 index 000000000..d2cbd1262 --- /dev/null +++ b/docs/stackit_config_profile_import.md @@ -0,0 +1,45 @@ +## stackit config profile import + +Imports a CLI configuration profile + +### Synopsis + +Imports a CLI configuration profile. + +``` +stackit config profile import [flags] +``` + +### Examples + +``` + Import a config with name "PROFILE_NAME" from file "./config.json" + $ stackit config profile import --name PROFILE_NAME --config `@./config.json` + + Import a config with name "PROFILE_NAME" from file "./config.json" and do not set as active + $ stackit config profile import --name PROFILE_NAME --config `@./config.json` --no-set +``` + +### Options + +``` + -c, --config string File where configuration will be imported from + -h, --help Help for "stackit config profile import" + --name string Profile name + --no-set Set the imported profile not as active +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit config profile](./stackit_config_profile.md) - Manage the CLI configuration profiles + diff --git a/internal/cmd/config/profile/import/import.go b/internal/cmd/config/profile/import/import.go new file mode 100644 index 000000000..d57cb1929 --- /dev/null +++ b/internal/cmd/config/profile/import/import.go @@ -0,0 +1,106 @@ +package importProfile + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" +) + +const ( + nameFlag = "name" + configFlag = "config" + noSetFlag = "no-set" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ProfileName string + Config string + NoSet bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "import", + Short: "Imports a CLI configuration profile", + Long: "Imports a CLI configuration profile.", + Example: examples.Build( + examples.NewExample( + `Import a config with name "PROFILE_NAME" from file "./config.json"`, + "$ stackit config profile import --name PROFILE_NAME --config `@./config.json`", + ), + examples.NewExample( + `Import a config with name "PROFILE_NAME" from file "./config.json" and do not set as active`, + "$ stackit config profile import --name PROFILE_NAME --config `@./config.json` --no-set", + ), + ), + Args: args.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + err = config.ImportProfile(p, model.ProfileName, model.Config, !model.NoSet) + if err != nil { + return err + } + + p.Info("Successfully imported profile %q\n", model.ProfileName) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "Profile name") + cmd.Flags().VarP(flags.ReadFromFileFlag(), configFlag, "c", "File where configuration will be imported from") + cmd.Flags().Bool(noSetFlag, false, "Set the imported profile not as active") + + cobra.CheckErr(cmd.MarkFlagRequired(nameFlag)) + cobra.CheckErr(cmd.MarkFlagRequired(configFlag)) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + model := &inputModel{ + GlobalFlagModel: globalFlags, + ProfileName: flags.FlagToStringValue(p, cmd, nameFlag), + Config: flags.FlagToStringValue(p, cmd, configFlag), + NoSet: flags.FlagToBoolValue(p, cmd, noSetFlag), + } + + if model.Config == "" { + return nil, &errors.FlagValidationError{ + Flag: configFlag, + Details: "must not be empty", + } + } + + if model.ProfileName == "" { + return nil, &errors.FlagValidationError{ + Flag: nameFlag, + Details: "must not be empty", + } + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return model, nil +} diff --git a/internal/cmd/config/profile/import/import_test.go b/internal/cmd/config/profile/import/import_test.go new file mode 100644 index 000000000..7e028ab59 --- /dev/null +++ b/internal/cmd/config/profile/import/import_test.go @@ -0,0 +1,118 @@ +package importProfile + +import ( + _ "embed" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" +) + +const testProfile = "test-profile" +const testConfig = "@./template/profile.json" +const testNoSet = false + +//go:embed template/profile.json +var testConfigContent string + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + nameFlag: testProfile, + configFlag: testConfig, + noSetFlag: strconv.FormatBool(testNoSet), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + ProfileName: testProfile, + Config: testConfigContent, + NoSet: testNoSet, + } + for _, mod := range mods { + mod(model) + } + return model +} + +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: "no flags", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "invalid path", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[configFlag] = "@./template/invalid-file" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + t.Fatalf("error parsing input: %v", err) + } + } + + if !tt.isValid { + t.Fatalf("did not fail on invalid input") + } + diff := cmp.Diff(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/config/profile/import/template/profile.json b/internal/cmd/config/profile/import/template/profile.json new file mode 100644 index 000000000..ab56ce66b --- /dev/null +++ b/internal/cmd/config/profile/import/template/profile.json @@ -0,0 +1,33 @@ +{ + "allowed_url_domain": "stackit.cloud", + "async": false, + "authorization_custom_endpoint": "", + "dns_custom_endpoint": "", + "iaas_custom_endpoint": "", + "identity_provider_custom_client_id": "", + "identity_provider_custom_well_known_configuration": "", + "load_balancer_custom_endpoint": "", + "logme_custom_endpoint": "", + "mariadb_custom_endpoint": "", + "mongodbflex_custom_endpoint": "", + "object_storage_custom_endpoint": "", + "observability_custom_endpoint": "", + "opensearch_custom_endpoint": "", + "output_format": "", + "postgresflex_custom_endpoint": "", + "project_id": "", + "project_name": "", + "rabbitmq_custom_endpoint": "", + "redis_custom_endpoint": "", + "resource_manager_custom_endpoint": "", + "runcommand_custom_endpoint": "", + "secrets_manager_custom_endpoint": "", + "serverbackup_custom_endpoint": "", + "service_account_custom_endpoint": "", + "service_enablement_custom_endpoint": "", + "session_time_limit": "2h", + "ske_custom_endpoint": "", + "sqlserverflex_custom_endpoint": "", + "token_custom_endpoint": "", + "verbosity": "info" +} \ No newline at end of file diff --git a/internal/cmd/config/profile/profile.go b/internal/cmd/config/profile/profile.go index 3a4233ec4..c24d3a921 100644 --- a/internal/cmd/config/profile/profile.go +++ b/internal/cmd/config/profile/profile.go @@ -5,6 +5,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/create" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/delete" + importProfile "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/import" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/list" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/set" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/unset" @@ -38,4 +39,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(create.NewCmd(p)) cmd.AddCommand(list.NewCmd(p)) cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(importProfile.NewCmd(p)) } diff --git a/internal/pkg/config/profiles.go b/internal/pkg/config/profiles.go index 69a1144cf..f7b6c5f70 100644 --- a/internal/pkg/config/profiles.go +++ b/internal/pkg/config/profiles.go @@ -1,6 +1,7 @@ package config import ( + "encoding/json" "fmt" "os" "path/filepath" @@ -330,3 +331,69 @@ func DeleteProfile(p *print.Printer, profile string) error { return nil } + +// ImportProfile imports a profile configuration +// It imports the profile with the name profileName and a config json. +// If setAsActive is true, it set the new profile as the active profile. +func ImportProfile(p *print.Printer, profileName, config string, setAsActive bool) error { + err := ValidateProfile(profileName) + if err != nil || profileName == DefaultProfileName { + return &errors.InvalidProfileNameError{Profile: profileName} + } + + exists, err := ProfileExists(profileName) + if err != nil { + return fmt.Errorf("check if profile exists: %w", err) + } + if exists { + return &errors.ProfileAlreadyExistsError{Profile: profileName} + } + + importConfig := &map[string]interface{}{} + err = json.Unmarshal([]byte(config), importConfig) + if err != nil { + return fmt.Errorf("unmarshal config: %w", err) + } + + configFolderPath = GetProfileFolderPath(profileName) + err = os.MkdirAll(configFolderPath, 0o750) + if err != nil { + return fmt.Errorf("create config folder: %w", err) + } + + content, err := json.MarshalIndent(importConfig, "", " ") + if err != nil { + cleanupErr := os.RemoveAll(configFolderPath) + if cleanupErr != nil { + return fmt.Errorf("json marshal config: %w, cleanup directories: %w", err, cleanupErr) + } + return fmt.Errorf("marshal config file: %w", err) + } + + filePath := getConfigFilePath(configFolderPath) + err = os.WriteFile(filePath, content, 0o600) + if err != nil { + cleanupErr := os.RemoveAll(configFolderPath) + if cleanupErr != nil { + return fmt.Errorf("write config file: %w, cleanup directories: %w", err, cleanupErr) + } + return fmt.Errorf("write config file: %w", err) + } + + if p.IsVerbosityDebug() { + p.Debug(print.DebugLevel, "profile %q imported", profileName) + } + + if setAsActive { + err := SetProfile(&print.Printer{}, profileName) + if err != nil { + return fmt.Errorf("set active profile: %w", err) + } + } + + if p.IsVerbosityDebug() { + p.Debug(print.DebugLevel, "active profile %q is now active", profileName) + } + + return nil +} diff --git a/internal/pkg/config/profiles_test.go b/internal/pkg/config/profiles_test.go index bb96918c3..9700ea978 100644 --- a/internal/pkg/config/profiles_test.go +++ b/internal/pkg/config/profiles_test.go @@ -1,10 +1,17 @@ package config import ( + _ "embed" + "fmt" "path/filepath" "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/print" ) +//go:embed template/test_profile.json +var templateConfig string + func TestValidateProfile(t *testing.T) { tests := []struct { description string @@ -115,3 +122,63 @@ func TestGetProfileFolderPath(t *testing.T) { }) } } + +func TestImportProfile(t *testing.T) { + tests := []struct { + description string + profile string + config string + setAsActive bool + isValid bool + }{ + { + description: "valid profile", + profile: "profile-name", + config: templateConfig, + setAsActive: false, + isValid: true, + }, + { + description: "invalid profile name", + profile: "invalid-profile-&", + config: templateConfig, + setAsActive: false, + isValid: false, + }, + { + description: "invalid config", + profile: "my-profile", + config: `{ "invalid": "json }`, + setAsActive: false, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + err := ImportProfile(p, tt.profile, tt.config, tt.setAsActive) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("profile should be valid but got error: %v\n", err) + } + + if !tt.isValid { + t.Fatalf("profile should be invalid but got no error\n") + } + }) + + t.Cleanup(func() { + p := print.NewPrinter() + err := DeleteProfile(p, tt.profile) + if err != nil { + if !tt.isValid { + return + } + fmt.Printf("could not clean up imported profile: %v\n", err) + } + }) + } +} diff --git a/internal/pkg/config/template/test_profile.json b/internal/pkg/config/template/test_profile.json new file mode 100644 index 000000000..ab56ce66b --- /dev/null +++ b/internal/pkg/config/template/test_profile.json @@ -0,0 +1,33 @@ +{ + "allowed_url_domain": "stackit.cloud", + "async": false, + "authorization_custom_endpoint": "", + "dns_custom_endpoint": "", + "iaas_custom_endpoint": "", + "identity_provider_custom_client_id": "", + "identity_provider_custom_well_known_configuration": "", + "load_balancer_custom_endpoint": "", + "logme_custom_endpoint": "", + "mariadb_custom_endpoint": "", + "mongodbflex_custom_endpoint": "", + "object_storage_custom_endpoint": "", + "observability_custom_endpoint": "", + "opensearch_custom_endpoint": "", + "output_format": "", + "postgresflex_custom_endpoint": "", + "project_id": "", + "project_name": "", + "rabbitmq_custom_endpoint": "", + "redis_custom_endpoint": "", + "resource_manager_custom_endpoint": "", + "runcommand_custom_endpoint": "", + "secrets_manager_custom_endpoint": "", + "serverbackup_custom_endpoint": "", + "service_account_custom_endpoint": "", + "service_enablement_custom_endpoint": "", + "session_time_limit": "2h", + "ske_custom_endpoint": "", + "sqlserverflex_custom_endpoint": "", + "token_custom_endpoint": "", + "verbosity": "info" +} \ No newline at end of file diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index 324abbadf..d61a8d9da 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -150,6 +150,11 @@ To enable it, run: IAAS_SERVER_NIC_ATTACH_MISSING_NIC_ID = `The "network-interface-id" flag must be provided if the "create" flag is not provided.` IAAS_SERVER_NIC_DETACH_MISSING_NIC_ID = `The "network-interface-id" flag must be provided if the "delete" flag is not provided.` + + PROFILE_ALREADY_EXISTS = `profile %[1]q already exists. + +To delete it, run: + $ stackit config profile delete %[1]s` ) type ServerNicAttachMissingNicIdError struct { @@ -437,3 +442,11 @@ type ServiceDisabledError struct { func (e *ServiceDisabledError) Error() string { return fmt.Sprintf(SERVICE_DISABLED, e.Service) } + +type ProfileAlreadyExistsError struct { + Profile string +} + +func (e *ProfileAlreadyExistsError) Error() string { + return fmt.Sprintf(PROFILE_ALREADY_EXISTS, e.Profile) +} From bded0948242ab4af41b8fdc2efddadd783cc2054 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 17 Dec 2024 08:49:35 +0100 Subject: [PATCH 127/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.18.0 (#542) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8d1d08da4..efac77d7a 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 diff --git a/go.sum b/go.sum index 64de80743..85bb7acfc 100644 --- a/go.sum +++ b/go.sum @@ -124,8 +124,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 h1:WXSIE4Kf github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0 h1:NypnmRbvjCX7ANJej1epwmopBEjkMzklJT3SY5iVwWg= github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0 h1:geyW780gqNxzSsPvmlxy3kUUJaRA4eiF9V3b2Ibcdjs= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0 h1:7QPYi7OZXUSO1uOtp1UXeCbxK0BGJbmjp71kaQOrMa8= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 h1:V0UGP7JEa4Q8SsZFUJsKgLGaoPruLn2KVKnqQtaoWCU= From 985d5620d954a9ca54253d9c617c0a8da972bc06 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 17 Dec 2024 08:58:34 +0100 Subject: [PATCH 128/619] fix(deps): update module github.com/lmittmann/tint to v1.0.6 (#541) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index efac77d7a..2b9695862 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jedib0t/go-pretty/v6 v6.6.4 - github.com/lmittmann/tint v1.0.5 + github.com/lmittmann/tint v1.0.6 github.com/mattn/go-colorable v0.1.13 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index 85bb7acfc..882eff07c 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw= -github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.0.6 h1:vkkuDAZXc0EFGNzYjWcV0h7eEX+uujH48f/ifSkJWgc= +github.com/lmittmann/tint v1.0.6/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= From b7b890f9809fee9c74905c52efe1671dbb247648 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 17 Dec 2024 09:09:11 +0100 Subject: [PATCH 129/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.6.5 (#538) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2b9695862..639d1632a 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.4 + github.com/jedib0t/go-pretty/v6 v6.6.5 github.com/lmittmann/tint v1.0.6 github.com/mattn/go-colorable v0.1.13 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index 882eff07c..98ffb00f8 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.4 h1:B51RjA+Sytv0C0Je7PHGDXZBF2JpS5dZEWWRueBLP6U= -github.com/jedib0t/go-pretty/v6 v6.6.4/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.5 h1:9PgMJOVBedpgYLI56jQRJYqngxYAAzfEUua+3NgSqAo= +github.com/jedib0t/go-pretty/v6 v6.6.5/go.mod h1:Uq/HrbhuFty5WSVNfjpQQe47x16RwVGXIveNGEyGtHs= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= From c794a3d5b3a12ce2a32ea43eb96e21b82de00a31 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 17 Dec 2024 09:13:40 +0100 Subject: [PATCH 130/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.10 (#537) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 639d1632a..8812aac9d 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.8 + github.com/goccy/go-yaml v1.15.10 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 98ffb00f8..f40bb8088 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.8 h1:0UhHxTWCcHQh4lZPIOdKY0ENpuBTAnx4n0L07VnbFag= -github.com/goccy/go-yaml v1.15.8/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.10 h1:9exV2CDYm/FWHPptIIgcDiPQS+X/4uTR+HEl+GF9xJU= +github.com/goccy/go-yaml v1.15.10/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 4b05d860c9341929fd8990b30dd09a39229aa604 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:35:15 +0100 Subject: [PATCH 131/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.11 (#545) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8812aac9d..7b9a5182d 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.10 + github.com/goccy/go-yaml v1.15.11 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index f40bb8088..f80369ccf 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.10 h1:9exV2CDYm/FWHPptIIgcDiPQS+X/4uTR+HEl+GF9xJU= -github.com/goccy/go-yaml v1.15.10/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.11 h1:XeEd/2INF0TXXWMzJ9ALqJLGjGDl4PIi1gmrK+7KpAs= +github.com/goccy/go-yaml v1.15.11/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From d117bb5eea68eb914c8726aa0a748c21580a8b9e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:43:13 +0100 Subject: [PATCH 132/619] fix(deps): update stackit sdk modules (#543) Co-authored-by: Renovate Bot --- go.mod | 30 ++++++++++++++--------------- go.sum | 60 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/go.mod b/go.mod index 7b9a5182d..78a6abd80 100644 --- a/go.mod +++ b/go.mod @@ -16,20 +16,20 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/stackitcloud/stackit-sdk-go/core v0.14.0 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.0 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.1 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.22.0 golang.org/x/oauth2 v0.24.0 @@ -79,12 +79,12 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.0 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.0 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.0 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.0 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.1 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect diff --git a/go.sum b/go.sum index f80369ccf..608704e6d 100644 --- a/go.sum +++ b/go.sum @@ -120,48 +120,48 @@ github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stackitcloud/stackit-sdk-go/core v0.14.0 h1:oBwwzrEHDTlZpRoQwmMQpNA8bWciTrtGkiN29nx14Z0= github.com/stackitcloud/stackit-sdk-go/core v0.14.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0 h1:WXSIE4KfdHzaiiD0MF8CsoIv8I+Two/Bf/r28tYhRCU= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.0/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0 h1:NypnmRbvjCX7ANJej1epwmopBEjkMzklJT3SY5iVwWg= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1 h1:sK7FZHN1tF8D/7rbWLhu4DX0qrAP5Psn2NusnwbCsEM= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 h1:nzOZQ2X6joM2iStePoACZeYvXFBQIBjkYE9sLanOGvE= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0 h1:7QPYi7OZXUSO1uOtp1UXeCbxK0BGJbmjp71kaQOrMa8= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 h1:V0UGP7JEa4Q8SsZFUJsKgLGaoPruLn2KVKnqQtaoWCU= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0/go.mod h1:+NlUMcid2dEFSmqtbXJrcT57iP0oTdnIXHOQku0E04A= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.0 h1:Q59bOPYEI9HeFA4vFrpQN2z/KwbW9MFi7L4BJ2o40k8= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.0/go.mod h1:nuZK6OXyZ4zlGsC1gZDj9+ajJzzFi9vVgSSRQlEJAqA= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0 h1:UYCEVpuv0Yq/sITf6yNCdJZw8PicWJJLT1TzBOego9g= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.0/go.mod h1:CvGSm9Goma2O1xkA0LEJbHfZpGlhy0AXJnMPpMmRdMM= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.0 h1:pCuhlSsRUW/3YV/u7l8iWJCjGBXANboVFdW5WanASOg= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.0/go.mod h1:V2LEHKyTaaiEBi9L3v62mNQ7xyJSred4OK+himLJOZQ= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.0 h1:5UZrI0qs8CNAmv/Szhes6ebjQ4YrzShpanviJsX3gbg= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.0/go.mod h1:okcRTrNDTI3d7MQcYJMliK0qoXeLq0b1wvZuEqgJIWE= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0 h1:KFP7xkVGU8b7tB6Rk3arKM8y9Q8OlSB9B5hVi0e1Xvo= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.0/go.mod h1:U45gFwIAAdXWL/Wlp9rY3iPVWFHLGILz1C3Qc62o8KM= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.1 h1:ogo7Ce4wA9ln/Z0VwvckH0FT5/i7d9/34bG85aayHn8= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.1/go.mod h1:+NlUMcid2dEFSmqtbXJrcT57iP0oTdnIXHOQku0E04A= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1 h1:J+GLgfDIDnNpq/z6ev1whfLbOwUn5XgSKh3aE2auHIs= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1/go.mod h1:nuZK6OXyZ4zlGsC1gZDj9+ajJzzFi9vVgSSRQlEJAqA= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1 h1:BCzShNI9TX6vZ8Q5vLzdG32gOdgcAwMWjEpy2AGHdnI= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1/go.mod h1:CvGSm9Goma2O1xkA0LEJbHfZpGlhy0AXJnMPpMmRdMM= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1 h1:Df3fTAHaVgyiiyp9LyTTQI8jXSVeGo49eW5ya4AATCY= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1/go.mod h1:V2LEHKyTaaiEBi9L3v62mNQ7xyJSred4OK+himLJOZQ= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 h1:sIz4wJIz6/9Eh6nSoi2sQ+Ef53iOrFsqLKIp2oRkmgo= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1/go.mod h1:okcRTrNDTI3d7MQcYJMliK0qoXeLq0b1wvZuEqgJIWE= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 h1:hwRkCCUSWMhKTc7fLakL89V6+9xkxsFQlRthVmrvi1U= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1/go.mod h1:U45gFwIAAdXWL/Wlp9rY3iPVWFHLGILz1C3Qc62o8KM= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 h1:aRVPIaTtM2zyep3k22lu6ARG0j0P1N/7fjH7TS6ucio= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0/go.mod h1:JnhCZzXprN/em1Uxpvl1ITMf6Hl/8N/4y5zNsRqEGlA= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.0 h1:823zATqn83jngf4XOzXxjoT338FhMUv9h+65dfk/SjY= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.0/go.mod h1:42oYZOqin+rIUrUqgtCIE4wzCWWY30H4UFhzvo1Wg2w= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.0 h1:GVBQbLvJlIViURciLiX8z9zpbTuHAg2dGwVdwWSEqac= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.0/go.mod h1:YJdkyuY7aK/clfE3lQDz7O369JLPcg0FO4yfCIPNUNE= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.0 h1:AScIIoDpq1rxpjW248Ahn/KZS5dCZ4xggjAES9M5XSI= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.0/go.mod h1:9Om4A5FI/wXZE/8zu5wF8eRBb70VddyPfnj/nlYXHX0= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0 h1:tb0w+0imdJhsaoWCBOuie8bu335ZbxruwR01Yx7FmRE= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.0/go.mod h1:LgCIIj7jA2lWX4DI3bxUYD+m0TbWCr1VgAyBYNJeghc= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0 h1:HrnEgRPt3eD/tEHyzDWyCRxNFzb9g/FLYfwIEEQZ+Rg= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.0/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1 h1:6XfGxsPFqci/geSDd1gCtiaRJun85X5JepXn4edobXQ= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1/go.mod h1:42oYZOqin+rIUrUqgtCIE4wzCWWY30H4UFhzvo1Wg2w= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1 h1:/EVm0bD9a3KCk9aj/v2ivJIURlGsTr4O2OwMQ4ey3e4= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1/go.mod h1:YJdkyuY7aK/clfE3lQDz7O369JLPcg0FO4yfCIPNUNE= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1 h1:bICGCqRsGEzqidVCgQIH3hxB+SX1vJapZgrSP5nhvBo= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1/go.mod h1:9Om4A5FI/wXZE/8zu5wF8eRBb70VddyPfnj/nlYXHX0= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 h1:qAKT20siGhkIIg4gY0JBPD7TU+I/6UieYcivGU7hVKc= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1/go.mod h1:LgCIIj7jA2lWX4DI3bxUYD+m0TbWCr1VgAyBYNJeghc= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 h1:qShB0OuNR8EOffY36/DfJs/Yk12syy38xkE88Z15f4k= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0 h1:Tlps8vBQmQ1mx2YFbzOzMIyWtXGJy7X3N9Qk3qk88Cc= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0/go.mod h1:+807U5ZLXns+CEbyIg483wNEwV10vaN6GjMnSZhw/64= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0/go.mod h1:zyg0hpiNdZLRbelkJb2KDf9OHQKLqqcTpePQ1qHL5dE= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0 h1:ssEywzCS8IdRtzyxweLUKBG5GFbgwjNWJh++wGqigJM= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.0/go.mod h1:A4+9KslxCA31JvxnT+O/GC67eAOdw+iqhBzewZZaCD0= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0 h1:1ByAgO10fxWF+UZ+RkJeAiv+h5AgqrzYz6r86Pn/BWE= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.0/go.mod h1:ui+yRLddE9mknzjZa45boyaU1ZomQuZy3p7wuwOufCY= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.1 h1:Gw68D2U+cAh20sRX2GvhLCSvRVvbKF52Ew7FQ/AoCXc= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.1/go.mod h1:A4+9KslxCA31JvxnT+O/GC67eAOdw+iqhBzewZZaCD0= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.1 h1:26MyaOGc3Sn4yuR3zoOOOFfb4MTbDV9PJwzU8yulWNc= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.1/go.mod h1:ui+yRLddE9mknzjZa45boyaU1ZomQuZy3p7wuwOufCY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= From 7e7d6d3f78be95e6c16a592d2d66cc864e594052 Mon Sep 17 00:00:00 2001 From: Marcel <72880145+marceljk@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:49:18 +0100 Subject: [PATCH 133/619] Onboard command to export config profiles (#544) * Add functionality and command to export config profiles --- docs/stackit_config_profile.md | 1 + docs/stackit_config_profile_export.md | 43 +++++ internal/cmd/config/profile/export/export.go | 97 +++++++++++ .../cmd/config/profile/export/export_test.go | 154 ++++++++++++++++++ internal/cmd/config/profile/profile.go | 2 + internal/pkg/config/config.go | 6 +- internal/pkg/config/profiles.go | 39 +++++ internal/pkg/config/profiles_test.go | 88 ++++++++++ internal/pkg/errors/errors.go | 21 +++ 9 files changed, 450 insertions(+), 1 deletion(-) create mode 100644 docs/stackit_config_profile_export.md create mode 100644 internal/cmd/config/profile/export/export.go create mode 100644 internal/cmd/config/profile/export/export_test.go diff --git a/docs/stackit_config_profile.md b/docs/stackit_config_profile.md index 415ac9d06..3e89ab27a 100644 --- a/docs/stackit_config_profile.md +++ b/docs/stackit_config_profile.md @@ -34,6 +34,7 @@ stackit config profile [flags] * [stackit config](./stackit_config.md) - Provides functionality for CLI configuration options * [stackit config profile create](./stackit_config_profile_create.md) - Creates a CLI configuration profile * [stackit config profile delete](./stackit_config_profile_delete.md) - Delete a CLI configuration profile +* [stackit config profile export](./stackit_config_profile_export.md) - Exports a CLI configuration profile * [stackit config profile import](./stackit_config_profile_import.md) - Imports a CLI configuration profile * [stackit config profile list](./stackit_config_profile_list.md) - Lists all CLI configuration profiles * [stackit config profile set](./stackit_config_profile_set.md) - Set a CLI configuration profile diff --git a/docs/stackit_config_profile_export.md b/docs/stackit_config_profile_export.md new file mode 100644 index 000000000..86265e493 --- /dev/null +++ b/docs/stackit_config_profile_export.md @@ -0,0 +1,43 @@ +## stackit config profile export + +Exports a CLI configuration profile + +### Synopsis + +Exports a CLI configuration profile. + +``` +stackit config profile export PROFILE_NAME [flags] +``` + +### Examples + +``` + Export a profile with name "PROFILE_NAME" to a file in your current directory + $ stackit config profile export PROFILE_NAME + + Export a profile with name "PROFILE_NAME"" to a specific file path FILE_PATH + $ stackit config profile export PROFILE_NAME --file-path FILE_PATH +``` + +### Options + +``` + -f, --file-path string If set, writes the config to the given file path. If unset, writes the config to you current directory with the name of the profile. E.g. '--file-path ~/my-config.json' + -h, --help Help for "stackit config profile export" +``` + +### 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 + --verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info") +``` + +### SEE ALSO + +* [stackit config profile](./stackit_config_profile.md) - Manage the CLI configuration profiles + diff --git a/internal/cmd/config/profile/export/export.go b/internal/cmd/config/profile/export/export.go new file mode 100644 index 000000000..9aa585971 --- /dev/null +++ b/internal/cmd/config/profile/export/export.go @@ -0,0 +1,97 @@ +package export + +import ( + "fmt" + "path/filepath" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/spf13/cobra" +) + +const ( + profileNameArg = "PROFILE_NAME" + + filePathFlag = "file-path" + + configFileExtension = "json" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ProfileName string + FilePath string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("export %s", profileNameArg), + Short: "Exports a CLI configuration profile", + Long: "Exports a CLI configuration profile.", + Example: examples.Build( + examples.NewExample( + `Export a profile with name "PROFILE_NAME" to a file in your current directory`, + "$ stackit config profile export PROFILE_NAME", + ), + examples.NewExample( + `Export a profile with name "PROFILE_NAME"" to a specific file path FILE_PATH`, + "$ stackit config profile export PROFILE_NAME --file-path FILE_PATH", + ), + ), + Args: args.SingleArg(profileNameArg, nil), + RunE: func(cmd *cobra.Command, args []string) error { + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + err = config.ExportProfile(p, model.ProfileName, model.FilePath) + if err != nil { + return fmt.Errorf("could not export profile: %w", err) + } + + p.Info("Exported profile %q to %q\n", model.ProfileName, model.FilePath) + + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(filePathFlag, "f", "", "If set, writes the config to the given file path. If unset, writes the config to you current directory with the name of the profile. E.g. '--file-path ~/my-config.json'") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + profileName := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + ProfileName: profileName, + FilePath: flags.FlagToStringValue(p, cmd, filePathFlag), + } + + // If filePath contains does not contain a file name, then add a default name + if model.FilePath == "" { + exportFileName := fmt.Sprintf("%s.%s", model.ProfileName, configFileExtension) + model.FilePath = filepath.Join(model.FilePath, exportFileName) + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} diff --git a/internal/cmd/config/profile/export/export_test.go b/internal/cmd/config/profile/export/export_test.go new file mode 100644 index 000000000..4dffd3a22 --- /dev/null +++ b/internal/cmd/config/profile/export/export_test.go @@ -0,0 +1,154 @@ +package export + +import ( + "fmt" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" +) + +const ( + testProfileArg = "default" + testExportPath = "/tmp/stackit-profiles/" + testProfileArg + ".json" +) + +func fixtureArgValues(mods ...func(args []string)) []string { + args := []string{ + testProfileArg, + } + for _, mod := range mods { + mod(args) + } + return args +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + filePathFlag: testExportPath, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(inputModel *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + ProfileName: testProfileArg, + FilePath: testExportPath, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argsValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argsValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argsValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no args", + argsValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flags", + argsValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.FilePath = fmt.Sprintf("%s.json", testProfileArg) + }), + }, + { + description: "custom file-path without file extension", + argsValues: fixtureArgValues(), + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[filePathFlag] = "./my-exported-config" + }), + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.FilePath = "./my-exported-config" + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argsValues) + 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.argsValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} diff --git a/internal/cmd/config/profile/profile.go b/internal/cmd/config/profile/profile.go index c24d3a921..848a60382 100644 --- a/internal/cmd/config/profile/profile.go +++ b/internal/cmd/config/profile/profile.go @@ -5,6 +5,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/create" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/export" importProfile "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/import" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/list" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/set" @@ -40,4 +41,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(list.NewCmd(p)) cmd.AddCommand(delete.NewCmd(p)) cmd.AddCommand(importProfile.NewCmd(p)) + cmd.AddCommand(export.NewCmd(p)) } diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index b64762d83..91ce0bb5a 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -105,7 +105,11 @@ var configFolderPath string var profileFilePath string func InitConfig() { - defaultConfigFolderPath = getInitialConfigDir() + initConfig(getInitialConfigDir()) +} + +func initConfig(configPath string) { + defaultConfigFolderPath = configPath profileFilePath = getInitialProfileFilePath() // Profile file path is in the default config folder configProfile, err := GetProfile() diff --git a/internal/pkg/config/profiles.go b/internal/pkg/config/profiles.go index f7b6c5f70..db47ce5d3 100644 --- a/internal/pkg/config/profiles.go +++ b/internal/pkg/config/profiles.go @@ -397,3 +397,42 @@ func ImportProfile(p *print.Printer, profileName, config string, setAsActive boo return nil } + +// ExportProfile exports a profile configuration +// Is exports the profile to the exportPath. The exportPath must contain the filename. +func ExportProfile(p *print.Printer, profile, exportPath string) error { + err := ValidateProfile(profile) + if err != nil { + return fmt.Errorf("validate profile name: %w", err) + } + + exists, err := ProfileExists(profile) + if err != nil { + return fmt.Errorf("check if profile exists: %w", err) + } + if !exists { + return &errors.ProfileDoesNotExistError{Profile: profile} + } + + profilePath := GetProfileFolderPath(profile) + configFile := getConfigFilePath(profilePath) + + stats, err := os.Stat(exportPath) + if err == nil { + if stats.IsDir() { + return fmt.Errorf("export path %q is a directory. Please specify a full path", exportPath) + } + return &errors.FileAlreadyExistsError{Filename: exportPath} + } + + err = fileutils.CopyFile(configFile, exportPath) + if err != nil { + return fmt.Errorf("export config file to %q: %w", exportPath, err) + } + + if p != nil { + p.Debug(print.DebugLevel, "exported profile %q to %q", profile, exportPath) + } + + return nil +} diff --git a/internal/pkg/config/profiles_test.go b/internal/pkg/config/profiles_test.go index 9700ea978..327c9dcf8 100644 --- a/internal/pkg/config/profiles_test.go +++ b/internal/pkg/config/profiles_test.go @@ -3,6 +3,7 @@ package config import ( _ "embed" "fmt" + "os" "path/filepath" "testing" @@ -182,3 +183,90 @@ func TestImportProfile(t *testing.T) { }) } } + +func TestExportProfile(t *testing.T) { + // Create directory where the export configs should be stored + testDir, err := os.MkdirTemp(os.TempDir(), "stackit-cli-test") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + func(path string) { + err := os.RemoveAll(path) + if err != nil { + fmt.Printf("could not clean up temp dir: %v\n", err) + } + }(testDir) + }) + + // Create test config directory + testConfigFolderPath := filepath.Join(testDir, "config") + initConfig(testConfigFolderPath) + err = Write() + if err != nil { + t.Fatalf("could not write profile, %v", err) + } + + // Create prerequisite profile + p := print.NewPrinter() + profileName := "export-profile-test" + err = CreateProfile(p, profileName, true, false) + if err != nil { + t.Fatalf("could not create prerequisite profile, %v", err) + } + t.Cleanup(func() { + func(p *print.Printer, profile string) { + err := DeleteProfile(p, profile) + if err != nil { + fmt.Printf("could not clean up prerequisite profile %q, %v", profileName, err) + } + }(p, profileName) + }) + + tests := []struct { + description string + profile string + filePath string + isValid bool + }{ + { + description: "valid profile", + profile: profileName, + filePath: filepath.Join(testDir, fmt.Sprintf("custom-name.%s", configFileExtension)), + isValid: true, + }, + { + description: "invalid profile", + profile: "invalid-my-profile", + isValid: false, + }, + { + description: "not existing path", + profile: profileName, + filePath: filepath.Join(testDir, "invalid", "path", fmt.Sprintf("custom-name.%s", configFileExtension)), + isValid: false, + }, + { + description: "export without file extension", + profile: profileName, + filePath: filepath.Join(testDir, "file-without-extension"), + isValid: true, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + err := ExportProfile(p, tt.profile, tt.filePath) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("export should be valid but got error: %v\n", err) + } + if !tt.isValid { + t.Fatalf("export should be invalid but got no error\n") + } + }) + } +} diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index d61a8d9da..e67efde5b 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -155,6 +155,13 @@ To enable it, run: To delete it, run: $ stackit config profile delete %[1]s` + + PROFILE_DOES_NOT_EXIST = `The profile %q does not exist. + +To list all profiles, run: + $ stackit config profile list` + + FILE_ALREADY_EXISTS = `file %q already exists in the export path. Delete the existing file or define a different export path` ) type ServerNicAttachMissingNicIdError struct { @@ -450,3 +457,17 @@ type ProfileAlreadyExistsError struct { func (e *ProfileAlreadyExistsError) Error() string { return fmt.Sprintf(PROFILE_ALREADY_EXISTS, e.Profile) } + +type ProfileDoesNotExistError struct { + Profile string +} + +func (e *ProfileDoesNotExistError) Error() string { + return fmt.Sprintf(PROFILE_DOES_NOT_EXIST, e.Profile) +} + +type FileAlreadyExistsError struct { + Filename string +} + +func (e *FileAlreadyExistsError) Error() string { return fmt.Sprintf(FILE_ALREADY_EXISTS, e.Filename) } From f6f5afe8bbf665f784cda56cb134c7de1c9e81d9 Mon Sep 17 00:00:00 2001 From: GokceGK <161626272+GokceGK@users.noreply.github.com> Date: Mon, 6 Jan 2025 11:14:00 +0100 Subject: [PATCH 134/619] Fix command usages (#540) * fix server describe command usage * fix command usages --- docs/stackit_beta_key-pair_delete.md | 2 +- docs/stackit_beta_key-pair_describe.md | 2 +- docs/stackit_beta_key-pair_update.md | 2 +- docs/stackit_beta_network-area_delete.md | 2 +- docs/stackit_beta_network-area_describe.md | 2 +- docs/stackit_beta_network-area_network-range_delete.md | 2 +- docs/stackit_beta_network-area_network-range_describe.md | 2 +- docs/stackit_beta_network-area_route_delete.md | 2 +- docs/stackit_beta_network-area_route_describe.md | 2 +- docs/stackit_beta_network-area_route_update.md | 2 +- docs/stackit_beta_network-area_update.md | 2 +- docs/stackit_beta_network-interface_delete.md | 2 +- docs/stackit_beta_network-interface_describe.md | 2 +- docs/stackit_beta_network-interface_update.md | 2 +- docs/stackit_beta_network_delete.md | 2 +- docs/stackit_beta_network_describe.md | 2 +- docs/stackit_beta_network_update.md | 2 +- docs/stackit_beta_public-ip_associate.md | 2 +- docs/stackit_beta_public-ip_delete.md | 2 +- docs/stackit_beta_public-ip_describe.md | 2 +- docs/stackit_beta_public-ip_disassociate.md | 2 +- docs/stackit_beta_public-ip_update.md | 2 +- docs/stackit_beta_security-group_delete.md | 2 +- docs/stackit_beta_security-group_describe.md | 2 +- docs/stackit_beta_security-group_rule_delete.md | 2 +- docs/stackit_beta_security-group_rule_describe.md | 2 +- docs/stackit_beta_security-group_update.md | 2 +- docs/stackit_beta_server_console.md | 2 +- docs/stackit_beta_server_deallocate.md | 2 +- docs/stackit_beta_server_delete.md | 2 +- docs/stackit_beta_server_describe.md | 2 +- docs/stackit_beta_server_log.md | 2 +- docs/stackit_beta_server_public-ip_attach.md | 2 +- docs/stackit_beta_server_public-ip_detach.md | 2 +- docs/stackit_beta_server_reboot.md | 2 +- docs/stackit_beta_server_rescue.md | 2 +- docs/stackit_beta_server_resize.md | 2 +- docs/stackit_beta_server_service-account_attach.md | 2 +- docs/stackit_beta_server_service-account_detach.md | 2 +- docs/stackit_beta_server_start.md | 2 +- docs/stackit_beta_server_stop.md | 2 +- docs/stackit_beta_server_unrescue.md | 2 +- docs/stackit_beta_server_update.md | 2 +- docs/stackit_beta_server_volume_attach.md | 2 +- docs/stackit_beta_server_volume_describe.md | 2 +- docs/stackit_beta_server_volume_detach.md | 2 +- docs/stackit_beta_server_volume_update.md | 2 +- docs/stackit_beta_volume_delete.md | 2 +- docs/stackit_beta_volume_describe.md | 2 +- docs/stackit_beta_volume_performance-class_describe.md | 2 +- docs/stackit_beta_volume_resize.md | 2 +- docs/stackit_beta_volume_update.md | 2 +- docs/stackit_dns_zone_clone.md | 2 +- docs/stackit_load-balancer_observability-credentials_update.md | 2 +- internal/cmd/beta/key-pair/delete/delete.go | 2 +- internal/cmd/beta/key-pair/describe/describe.go | 2 +- internal/cmd/beta/key-pair/update/update.go | 2 +- internal/cmd/beta/network-area/delete/delete.go | 2 +- internal/cmd/beta/network-area/describe/describe.go | 2 +- internal/cmd/beta/network-area/network-range/delete/delete.go | 2 +- .../cmd/beta/network-area/network-range/describe/describe.go | 2 +- internal/cmd/beta/network-area/route/delete/delete.go | 2 +- internal/cmd/beta/network-area/route/describe/describe.go | 2 +- internal/cmd/beta/network-area/route/update/update.go | 2 +- internal/cmd/beta/network-area/update/update.go | 2 +- internal/cmd/beta/network-interface/delete/delete.go | 2 +- internal/cmd/beta/network-interface/describe/describe.go | 2 +- internal/cmd/beta/network-interface/update/update.go | 2 +- internal/cmd/beta/network/delete/delete.go | 2 +- internal/cmd/beta/network/describe/describe.go | 2 +- internal/cmd/beta/network/update/update.go | 2 +- internal/cmd/beta/public-ip/associate/associate.go | 2 +- internal/cmd/beta/public-ip/delete/delete.go | 2 +- internal/cmd/beta/public-ip/describe/describe.go | 2 +- internal/cmd/beta/public-ip/disassociate/disassociate.go | 2 +- internal/cmd/beta/public-ip/update/update.go | 2 +- internal/cmd/beta/security-group/delete/delete.go | 2 +- internal/cmd/beta/security-group/describe/describe.go | 2 +- internal/cmd/beta/security-group/rule/delete/delete.go | 2 +- internal/cmd/beta/security-group/rule/describe/describe.go | 2 +- internal/cmd/beta/security-group/update/update.go | 2 +- internal/cmd/beta/server/console/console.go | 2 +- internal/cmd/beta/server/deallocate/deallocate.go | 2 +- internal/cmd/beta/server/delete/delete.go | 2 +- internal/cmd/beta/server/describe/describe.go | 2 +- internal/cmd/beta/server/log/log.go | 2 +- internal/cmd/beta/server/public-ip/attach/attach.go | 2 +- internal/cmd/beta/server/public-ip/detach/detach.go | 2 +- internal/cmd/beta/server/reboot/reboot.go | 2 +- internal/cmd/beta/server/rescue/rescue.go | 2 +- internal/cmd/beta/server/resize/resize.go | 2 +- internal/cmd/beta/server/service-account/attach/attach.go | 2 +- internal/cmd/beta/server/service-account/detach/detach.go | 2 +- internal/cmd/beta/server/start/start.go | 2 +- internal/cmd/beta/server/stop/stop.go | 2 +- internal/cmd/beta/server/unrescue/unrescue.go | 2 +- internal/cmd/beta/server/update/update.go | 2 +- internal/cmd/beta/server/volume/attach/attach.go | 2 +- internal/cmd/beta/server/volume/describe/describe.go | 2 +- internal/cmd/beta/server/volume/detach/detach.go | 2 +- internal/cmd/beta/server/volume/update/update.go | 2 +- internal/cmd/beta/volume/delete/delete.go | 2 +- internal/cmd/beta/volume/describe/describe.go | 2 +- internal/cmd/beta/volume/performance-class/describe/describe.go | 2 +- internal/cmd/beta/volume/resize/resize.go | 2 +- internal/cmd/beta/volume/update/update.go | 2 +- internal/cmd/dns/zone/clone/clone.go | 2 +- .../load-balancer/observability-credentials/update/update.go | 2 +- 108 files changed, 108 insertions(+), 108 deletions(-) diff --git a/docs/stackit_beta_key-pair_delete.md b/docs/stackit_beta_key-pair_delete.md index 15de8a582..5782405ea 100644 --- a/docs/stackit_beta_key-pair_delete.md +++ b/docs/stackit_beta_key-pair_delete.md @@ -7,7 +7,7 @@ Deletes a key pair Deletes a key pair. ``` -stackit beta key-pair delete [flags] +stackit beta key-pair delete KEY_PAIR_NAME [flags] ``` ### Examples diff --git a/docs/stackit_beta_key-pair_describe.md b/docs/stackit_beta_key-pair_describe.md index 54b0189bc..49ce675b5 100644 --- a/docs/stackit_beta_key-pair_describe.md +++ b/docs/stackit_beta_key-pair_describe.md @@ -7,7 +7,7 @@ Describes a key pair Describes a key pair. ``` -stackit beta key-pair describe [flags] +stackit beta key-pair describe KEY_PAIR_NAME [flags] ``` ### Examples diff --git a/docs/stackit_beta_key-pair_update.md b/docs/stackit_beta_key-pair_update.md index 1dc94a8e8..0170c9c2f 100644 --- a/docs/stackit_beta_key-pair_update.md +++ b/docs/stackit_beta_key-pair_update.md @@ -7,7 +7,7 @@ Updates a key pair Updates a key pair. ``` -stackit beta key-pair update [flags] +stackit beta key-pair update KEY_PAIR_NAME [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-area_delete.md b/docs/stackit_beta_network-area_delete.md index 656d2ec32..14e65e8e8 100644 --- a/docs/stackit_beta_network-area_delete.md +++ b/docs/stackit_beta_network-area_delete.md @@ -9,7 +9,7 @@ If the SNA is attached to any projects, the deletion will fail ``` -stackit beta network-area delete [flags] +stackit beta network-area delete AREA_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-area_describe.md b/docs/stackit_beta_network-area_describe.md index 31e86ddeb..ef3b9e690 100644 --- a/docs/stackit_beta_network-area_describe.md +++ b/docs/stackit_beta_network-area_describe.md @@ -7,7 +7,7 @@ Shows details of a STACKIT Network Area Shows details of a STACKIT Network Area in an organization. ``` -stackit beta network-area describe [flags] +stackit beta network-area describe AREA_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-area_network-range_delete.md b/docs/stackit_beta_network-area_network-range_delete.md index 1d8588478..225713bfc 100644 --- a/docs/stackit_beta_network-area_network-range_delete.md +++ b/docs/stackit_beta_network-area_network-range_delete.md @@ -7,7 +7,7 @@ Deletes a network range in a STACKIT Network Area (SNA) Deletes a network range in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-range delete [flags] +stackit beta network-area network-range delete NETWORK_RANGE_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-area_network-range_describe.md b/docs/stackit_beta_network-area_network-range_describe.md index ef5244d0e..7d6292464 100644 --- a/docs/stackit_beta_network-area_network-range_describe.md +++ b/docs/stackit_beta_network-area_network-range_describe.md @@ -7,7 +7,7 @@ Shows details of a network range in a STACKIT Network Area (SNA) Shows details of a network range in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-range describe [flags] +stackit beta network-area network-range describe NETWORK_RANGE_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-area_route_delete.md b/docs/stackit_beta_network-area_route_delete.md index 9fa746057..adfdf1d10 100644 --- a/docs/stackit_beta_network-area_route_delete.md +++ b/docs/stackit_beta_network-area_route_delete.md @@ -7,7 +7,7 @@ Deletes a static route in a STACKIT Network Area (SNA) Deletes a static route in a STACKIT Network Area (SNA). ``` -stackit beta network-area route delete [flags] +stackit beta network-area route delete ROUTE_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-area_route_describe.md b/docs/stackit_beta_network-area_route_describe.md index 7561134ca..838ed9ced 100644 --- a/docs/stackit_beta_network-area_route_describe.md +++ b/docs/stackit_beta_network-area_route_describe.md @@ -7,7 +7,7 @@ Shows details of a static route in a STACKIT Network Area (SNA) Shows details of a static route in a STACKIT Network Area (SNA). ``` -stackit beta network-area route describe [flags] +stackit beta network-area route describe ROUTE_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-area_route_update.md b/docs/stackit_beta_network-area_route_update.md index e52a914ad..0fee0b1d5 100644 --- a/docs/stackit_beta_network-area_route_update.md +++ b/docs/stackit_beta_network-area_route_update.md @@ -9,7 +9,7 @@ This command is currently asynchonous only due to limitations in the waiting fun ``` -stackit beta network-area route update [flags] +stackit beta network-area route update ROUTE_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-area_update.md b/docs/stackit_beta_network-area_update.md index 2beecc037..b1c591c1a 100644 --- a/docs/stackit_beta_network-area_update.md +++ b/docs/stackit_beta_network-area_update.md @@ -7,7 +7,7 @@ Updates a STACKIT Network Area (SNA) Updates a STACKIT Network Area (SNA) in an organization. ``` -stackit beta network-area update [flags] +stackit beta network-area update AREA_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-interface_delete.md b/docs/stackit_beta_network-interface_delete.md index a30564843..5b7b81abd 100644 --- a/docs/stackit_beta_network-interface_delete.md +++ b/docs/stackit_beta_network-interface_delete.md @@ -7,7 +7,7 @@ Deletes a network interface Deletes a network interface. ``` -stackit beta network-interface delete [flags] +stackit beta network-interface delete NIC_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-interface_describe.md b/docs/stackit_beta_network-interface_describe.md index 3f99be8f9..2e316d691 100644 --- a/docs/stackit_beta_network-interface_describe.md +++ b/docs/stackit_beta_network-interface_describe.md @@ -7,7 +7,7 @@ Describes a network interface Describes a network interface. ``` -stackit beta network-interface describe [flags] +stackit beta network-interface describe NIC_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network-interface_update.md b/docs/stackit_beta_network-interface_update.md index 5be029a85..136905c05 100644 --- a/docs/stackit_beta_network-interface_update.md +++ b/docs/stackit_beta_network-interface_update.md @@ -7,7 +7,7 @@ Updates a network interface Updates a network interface. ``` -stackit beta network-interface update [flags] +stackit beta network-interface update NIC_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network_delete.md b/docs/stackit_beta_network_delete.md index a2ff9cc84..7992621a9 100644 --- a/docs/stackit_beta_network_delete.md +++ b/docs/stackit_beta_network_delete.md @@ -9,7 +9,7 @@ If the network is still in use, the deletion will fail ``` -stackit beta network delete [flags] +stackit beta network delete NETWORK_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network_describe.md b/docs/stackit_beta_network_describe.md index ed449330c..ccac8a132 100644 --- a/docs/stackit_beta_network_describe.md +++ b/docs/stackit_beta_network_describe.md @@ -7,7 +7,7 @@ Shows details of a network Shows details of a network. ``` -stackit beta network describe [flags] +stackit beta network describe NETWORK_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_network_update.md b/docs/stackit_beta_network_update.md index 9f14775bd..484168086 100644 --- a/docs/stackit_beta_network_update.md +++ b/docs/stackit_beta_network_update.md @@ -7,7 +7,7 @@ Updates a network Updates a network. ``` -stackit beta network update [flags] +stackit beta network update NETWORK_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_public-ip_associate.md b/docs/stackit_beta_public-ip_associate.md index 7a7cf8788..19e9d87b7 100644 --- a/docs/stackit_beta_public-ip_associate.md +++ b/docs/stackit_beta_public-ip_associate.md @@ -7,7 +7,7 @@ Associates a Public IP with a network interface or a virtual IP Associates a Public IP with a network interface or a virtual IP. ``` -stackit beta public-ip associate [flags] +stackit beta public-ip associate PUBLIC_IP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_public-ip_delete.md b/docs/stackit_beta_public-ip_delete.md index ef5fb53c0..1052b0445 100644 --- a/docs/stackit_beta_public-ip_delete.md +++ b/docs/stackit_beta_public-ip_delete.md @@ -9,7 +9,7 @@ If the public IP is still in use, the deletion will fail ``` -stackit beta public-ip delete [flags] +stackit beta public-ip delete PUBLIC_IP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_public-ip_describe.md b/docs/stackit_beta_public-ip_describe.md index 4a0e85986..9ff1b5a1c 100644 --- a/docs/stackit_beta_public-ip_describe.md +++ b/docs/stackit_beta_public-ip_describe.md @@ -7,7 +7,7 @@ Shows details of a Public IP Shows details of a Public IP. ``` -stackit beta public-ip describe [flags] +stackit beta public-ip describe PUBLIC_IP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_public-ip_disassociate.md b/docs/stackit_beta_public-ip_disassociate.md index 65c7cf8ac..cf11a2ee1 100644 --- a/docs/stackit_beta_public-ip_disassociate.md +++ b/docs/stackit_beta_public-ip_disassociate.md @@ -7,7 +7,7 @@ Disassociates a Public IP from a network interface or a virtual IP Disassociates a Public IP from a network interface or a virtual IP. ``` -stackit beta public-ip disassociate [flags] +stackit beta public-ip disassociate PUBLIC_IP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_public-ip_update.md b/docs/stackit_beta_public-ip_update.md index 37c8ef7ed..c2ed8a2f9 100644 --- a/docs/stackit_beta_public-ip_update.md +++ b/docs/stackit_beta_public-ip_update.md @@ -7,7 +7,7 @@ Updates a Public IP Updates a Public IP. ``` -stackit beta public-ip update [flags] +stackit beta public-ip update PUBLIC_IP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_security-group_delete.md b/docs/stackit_beta_security-group_delete.md index dd3d7935f..fd4a74191 100644 --- a/docs/stackit_beta_security-group_delete.md +++ b/docs/stackit_beta_security-group_delete.md @@ -7,7 +7,7 @@ Deletes a security group Deletes a security group by its internal ID. ``` -stackit beta security-group delete [flags] +stackit beta security-group delete GROUP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_security-group_describe.md b/docs/stackit_beta_security-group_describe.md index b1856566d..05fa5ec4b 100644 --- a/docs/stackit_beta_security-group_describe.md +++ b/docs/stackit_beta_security-group_describe.md @@ -7,7 +7,7 @@ Describes security groups Describes security groups by its internal ID. ``` -stackit beta security-group describe [flags] +stackit beta security-group describe GROUP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_security-group_rule_delete.md b/docs/stackit_beta_security-group_rule_delete.md index fd56a81d6..29ac6eb08 100644 --- a/docs/stackit_beta_security-group_rule_delete.md +++ b/docs/stackit_beta_security-group_rule_delete.md @@ -9,7 +9,7 @@ If the security group rule is still in use, the deletion will fail ``` -stackit beta security-group rule delete [flags] +stackit beta security-group rule delete SECURITY_GROUP_RULE_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_security-group_rule_describe.md b/docs/stackit_beta_security-group_rule_describe.md index eaa29cc08..80fdf707b 100644 --- a/docs/stackit_beta_security-group_rule_describe.md +++ b/docs/stackit_beta_security-group_rule_describe.md @@ -7,7 +7,7 @@ Shows details of a security group rule Shows details of a security group rule. ``` -stackit beta security-group rule describe [flags] +stackit beta security-group rule describe SECURITY_GROUP_RULE_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_security-group_update.md b/docs/stackit_beta_security-group_update.md index acba6414e..43ca56c33 100644 --- a/docs/stackit_beta_security-group_update.md +++ b/docs/stackit_beta_security-group_update.md @@ -7,7 +7,7 @@ Updates a security group Updates a named security group ``` -stackit beta security-group update [flags] +stackit beta security-group update GROUP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_console.md b/docs/stackit_beta_server_console.md index 5fccb3d5b..2b63b6b7b 100644 --- a/docs/stackit_beta_server_console.md +++ b/docs/stackit_beta_server_console.md @@ -7,7 +7,7 @@ Gets a URL for server remote console Gets a URL for server remote console. ``` -stackit beta server console [flags] +stackit beta server console SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_deallocate.md b/docs/stackit_beta_server_deallocate.md index 96323db32..b8bb41fb2 100644 --- a/docs/stackit_beta_server_deallocate.md +++ b/docs/stackit_beta_server_deallocate.md @@ -7,7 +7,7 @@ Deallocates an existing server Deallocates an existing server. ``` -stackit beta server deallocate [flags] +stackit beta server deallocate SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_delete.md b/docs/stackit_beta_server_delete.md index d12115e26..6cce083cf 100644 --- a/docs/stackit_beta_server_delete.md +++ b/docs/stackit_beta_server_delete.md @@ -9,7 +9,7 @@ If the server is still in use, the deletion will fail ``` -stackit beta server delete [flags] +stackit beta server delete SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_describe.md b/docs/stackit_beta_server_describe.md index fc35fbda0..0a8a22bf0 100644 --- a/docs/stackit_beta_server_describe.md +++ b/docs/stackit_beta_server_describe.md @@ -7,7 +7,7 @@ Shows details of a server Shows details of a server. ``` -stackit beta server describe [flags] +stackit beta server describe SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_log.md b/docs/stackit_beta_server_log.md index b9cad0a9c..81776e792 100644 --- a/docs/stackit_beta_server_log.md +++ b/docs/stackit_beta_server_log.md @@ -7,7 +7,7 @@ Gets server console log Gets server console log. ``` -stackit beta server log [flags] +stackit beta server log SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_public-ip_attach.md b/docs/stackit_beta_server_public-ip_attach.md index 2bd1f1914..49152da8d 100644 --- a/docs/stackit_beta_server_public-ip_attach.md +++ b/docs/stackit_beta_server_public-ip_attach.md @@ -7,7 +7,7 @@ Attaches a public IP to a server Attaches a public IP to a server. ``` -stackit beta server public-ip attach [flags] +stackit beta server public-ip attach PUBLIC_IP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_public-ip_detach.md b/docs/stackit_beta_server_public-ip_detach.md index 375ed68b6..15ff28399 100644 --- a/docs/stackit_beta_server_public-ip_detach.md +++ b/docs/stackit_beta_server_public-ip_detach.md @@ -7,7 +7,7 @@ Detaches a public IP from a server Detaches a public IP from a server. ``` -stackit beta server public-ip detach [flags] +stackit beta server public-ip detach PUBLIC_IP_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_reboot.md b/docs/stackit_beta_server_reboot.md index a100c8a0d..e1f728a77 100644 --- a/docs/stackit_beta_server_reboot.md +++ b/docs/stackit_beta_server_reboot.md @@ -7,7 +7,7 @@ Reboots a server Reboots a server. ``` -stackit beta server reboot [flags] +stackit beta server reboot SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_rescue.md b/docs/stackit_beta_server_rescue.md index 2064a6ad6..5c81b6d93 100644 --- a/docs/stackit_beta_server_rescue.md +++ b/docs/stackit_beta_server_rescue.md @@ -7,7 +7,7 @@ Rescues an existing server Rescues an existing server. ``` -stackit beta server rescue [flags] +stackit beta server rescue SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_resize.md b/docs/stackit_beta_server_resize.md index 4ef3e6715..ed1f8f3cf 100644 --- a/docs/stackit_beta_server_resize.md +++ b/docs/stackit_beta_server_resize.md @@ -7,7 +7,7 @@ Resizes the server to the given machine type Resizes the server to the given machine type. ``` -stackit beta server resize [flags] +stackit beta server resize SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_service-account_attach.md b/docs/stackit_beta_server_service-account_attach.md index 5d00495df..d472569ec 100644 --- a/docs/stackit_beta_server_service-account_attach.md +++ b/docs/stackit_beta_server_service-account_attach.md @@ -7,7 +7,7 @@ Attach a service account to a server Attach a service account to a server ``` -stackit beta server service-account attach [flags] +stackit beta server service-account attach SERVICE_ACCOUNT_EMAIL [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_service-account_detach.md b/docs/stackit_beta_server_service-account_detach.md index 88276a8ce..e1ecb569a 100644 --- a/docs/stackit_beta_server_service-account_detach.md +++ b/docs/stackit_beta_server_service-account_detach.md @@ -7,7 +7,7 @@ Detach a service account from a server Detach a service account from a server ``` -stackit beta server service-account detach [flags] +stackit beta server service-account detach SERVICE_ACCOUNT_EMAIL [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_start.md b/docs/stackit_beta_server_start.md index 7a811400c..48526e4f7 100644 --- a/docs/stackit_beta_server_start.md +++ b/docs/stackit_beta_server_start.md @@ -7,7 +7,7 @@ Starts an existing server or allocates the server if deallocated Starts an existing server or allocates the server if deallocated. ``` -stackit beta server start [flags] +stackit beta server start SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_stop.md b/docs/stackit_beta_server_stop.md index 1521146b0..30c32d1b6 100644 --- a/docs/stackit_beta_server_stop.md +++ b/docs/stackit_beta_server_stop.md @@ -7,7 +7,7 @@ Stops an existing server Stops an existing server. ``` -stackit beta server stop [flags] +stackit beta server stop SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_unrescue.md b/docs/stackit_beta_server_unrescue.md index 06020bdb6..2143f7b74 100644 --- a/docs/stackit_beta_server_unrescue.md +++ b/docs/stackit_beta_server_unrescue.md @@ -7,7 +7,7 @@ Unrescues an existing server Unrescues an existing server. ``` -stackit beta server unrescue [flags] +stackit beta server unrescue SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_update.md b/docs/stackit_beta_server_update.md index 499208bc3..aad88cf33 100644 --- a/docs/stackit_beta_server_update.md +++ b/docs/stackit_beta_server_update.md @@ -7,7 +7,7 @@ Updates a server Updates a server. ``` -stackit beta server update [flags] +stackit beta server update SERVER_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_volume_attach.md b/docs/stackit_beta_server_volume_attach.md index 060fa0774..4ac70301f 100644 --- a/docs/stackit_beta_server_volume_attach.md +++ b/docs/stackit_beta_server_volume_attach.md @@ -7,7 +7,7 @@ Attaches a volume to a server Attaches a volume to a server. ``` -stackit beta server volume attach [flags] +stackit beta server volume attach VOLUME_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_volume_describe.md b/docs/stackit_beta_server_volume_describe.md index 3c31daa2b..e9836eadd 100644 --- a/docs/stackit_beta_server_volume_describe.md +++ b/docs/stackit_beta_server_volume_describe.md @@ -7,7 +7,7 @@ Describes a server volume attachment Describes a server volume attachment. ``` -stackit beta server volume describe [flags] +stackit beta server volume describe VOLUME_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_volume_detach.md b/docs/stackit_beta_server_volume_detach.md index a45c8a636..04519c691 100644 --- a/docs/stackit_beta_server_volume_detach.md +++ b/docs/stackit_beta_server_volume_detach.md @@ -7,7 +7,7 @@ Detaches a volume from a server Detaches a volume from a server. ``` -stackit beta server volume detach [flags] +stackit beta server volume detach VOLUME_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_server_volume_update.md b/docs/stackit_beta_server_volume_update.md index 18d45a4ac..29b7b51b6 100644 --- a/docs/stackit_beta_server_volume_update.md +++ b/docs/stackit_beta_server_volume_update.md @@ -7,7 +7,7 @@ Updates an attached volume of a server Updates an attached volume of a server. ``` -stackit beta server volume update [flags] +stackit beta server volume update VOLUME_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_volume_delete.md b/docs/stackit_beta_volume_delete.md index d3de5b62d..8291c5459 100644 --- a/docs/stackit_beta_volume_delete.md +++ b/docs/stackit_beta_volume_delete.md @@ -9,7 +9,7 @@ If the volume is still in use, the deletion will fail ``` -stackit beta volume delete [flags] +stackit beta volume delete VOLUME_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_volume_describe.md b/docs/stackit_beta_volume_describe.md index 72e77fc96..3b08c72aa 100644 --- a/docs/stackit_beta_volume_describe.md +++ b/docs/stackit_beta_volume_describe.md @@ -7,7 +7,7 @@ Shows details of a volume Shows details of a volume. ``` -stackit beta volume describe [flags] +stackit beta volume describe VOLUME_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_volume_performance-class_describe.md b/docs/stackit_beta_volume_performance-class_describe.md index 902755ea4..fb446880c 100644 --- a/docs/stackit_beta_volume_performance-class_describe.md +++ b/docs/stackit_beta_volume_performance-class_describe.md @@ -7,7 +7,7 @@ Shows details of a volume performance class Shows details of a volume performance class. ``` -stackit beta volume performance-class describe [flags] +stackit beta volume performance-class describe VOLUME_PERFORMANCE_CLASS [flags] ``` ### Examples diff --git a/docs/stackit_beta_volume_resize.md b/docs/stackit_beta_volume_resize.md index a609c7c85..f543b8d5d 100644 --- a/docs/stackit_beta_volume_resize.md +++ b/docs/stackit_beta_volume_resize.md @@ -7,7 +7,7 @@ Resizes a volume Resizes a volume. ``` -stackit beta volume resize [flags] +stackit beta volume resize VOLUME_ID [flags] ``` ### Examples diff --git a/docs/stackit_beta_volume_update.md b/docs/stackit_beta_volume_update.md index f85b37388..ca90b1ed0 100644 --- a/docs/stackit_beta_volume_update.md +++ b/docs/stackit_beta_volume_update.md @@ -7,7 +7,7 @@ Updates a volume Updates a volume. ``` -stackit beta volume update [flags] +stackit beta volume update VOLUME_ID [flags] ``` ### Examples diff --git a/docs/stackit_dns_zone_clone.md b/docs/stackit_dns_zone_clone.md index db3d15ef4..d6a6133c7 100644 --- a/docs/stackit_dns_zone_clone.md +++ b/docs/stackit_dns_zone_clone.md @@ -7,7 +7,7 @@ Clones a DNS zone Clones an existing DNS zone with all record sets to a new zone with a different name. ``` -stackit dns zone clone [flags] +stackit dns zone clone ZONE_ID [flags] ``` ### Examples diff --git a/docs/stackit_load-balancer_observability-credentials_update.md b/docs/stackit_load-balancer_observability-credentials_update.md index 53fa1cd02..e10bf5821 100644 --- a/docs/stackit_load-balancer_observability-credentials_update.md +++ b/docs/stackit_load-balancer_observability-credentials_update.md @@ -7,7 +7,7 @@ Updates observability credentials for Load Balancer Updates existing observability credentials (username and password) for Load Balancer. The credentials can be for Observability or another monitoring tool. ``` -stackit load-balancer observability-credentials update [flags] +stackit load-balancer observability-credentials update CREDENTIALS_REF [flags] ``` ### Examples diff --git a/internal/cmd/beta/key-pair/delete/delete.go b/internal/cmd/beta/key-pair/delete/delete.go index 0cc0c77bc..e1144dd5d 100644 --- a/internal/cmd/beta/key-pair/delete/delete.go +++ b/internal/cmd/beta/key-pair/delete/delete.go @@ -25,7 +25,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", keyPairNameArg), Short: "Deletes a key pair", Long: "Deletes a key pair.", Args: args.SingleArg(keyPairNameArg, nil), diff --git a/internal/cmd/beta/key-pair/describe/describe.go b/internal/cmd/beta/key-pair/describe/describe.go index f45f11dff..7f7a8e7b6 100644 --- a/internal/cmd/beta/key-pair/describe/describe.go +++ b/internal/cmd/beta/key-pair/describe/describe.go @@ -35,7 +35,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", keyPairNameArg), Short: "Describes a key pair", Long: "Describes a key pair.", Args: args.SingleArg(keyPairNameArg, nil), diff --git a/internal/cmd/beta/key-pair/update/update.go b/internal/cmd/beta/key-pair/update/update.go index 483cd7798..39b6abacf 100644 --- a/internal/cmd/beta/key-pair/update/update.go +++ b/internal/cmd/beta/key-pair/update/update.go @@ -31,7 +31,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", keyPairNameArg), Short: "Updates a key pair", Long: "Updates a key pair.", Args: args.SingleArg(keyPairNameArg, nil), diff --git a/internal/cmd/beta/network-area/delete/delete.go b/internal/cmd/beta/network-area/delete/delete.go index ca1afcb4d..db4ddd117 100644 --- a/internal/cmd/beta/network-area/delete/delete.go +++ b/internal/cmd/beta/network-area/delete/delete.go @@ -32,7 +32,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", areaIdArg), Short: "Deletes a STACKIT Network Area (SNA)", Long: fmt.Sprintf("%s\n%s\n", "Deletes a STACKIT Network Area (SNA) in an organization.", diff --git a/internal/cmd/beta/network-area/describe/describe.go b/internal/cmd/beta/network-area/describe/describe.go index cd13cfaae..1332572a6 100644 --- a/internal/cmd/beta/network-area/describe/describe.go +++ b/internal/cmd/beta/network-area/describe/describe.go @@ -36,7 +36,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", areaIdArg), Short: "Shows details of a STACKIT Network Area", Long: "Shows details of a STACKIT Network Area in an organization.", Args: args.SingleArg(areaIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network-area/network-range/delete/delete.go b/internal/cmd/beta/network-area/network-range/delete/delete.go index b42d26f4a..90fb8a486 100644 --- a/internal/cmd/beta/network-area/network-range/delete/delete.go +++ b/internal/cmd/beta/network-area/network-range/delete/delete.go @@ -33,7 +33,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", networkRangeIdArg), Short: "Deletes a network range in a STACKIT Network Area (SNA)", Long: "Deletes a network range in a STACKIT Network Area (SNA).", Args: args.SingleArg(networkRangeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network-area/network-range/describe/describe.go b/internal/cmd/beta/network-area/network-range/describe/describe.go index aedc34a26..ed75127f9 100644 --- a/internal/cmd/beta/network-area/network-range/describe/describe.go +++ b/internal/cmd/beta/network-area/network-range/describe/describe.go @@ -35,7 +35,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", networkRangeIdArg), Short: "Shows details of a network range in a STACKIT Network Area (SNA)", Long: "Shows details of a network range in a STACKIT Network Area (SNA).", Args: args.SingleArg(networkRangeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network-area/route/delete/delete.go b/internal/cmd/beta/network-area/route/delete/delete.go index b927be8c9..48dad6918 100644 --- a/internal/cmd/beta/network-area/route/delete/delete.go +++ b/internal/cmd/beta/network-area/route/delete/delete.go @@ -33,7 +33,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", routeIdArg), Short: "Deletes a static route in a STACKIT Network Area (SNA)", Long: "Deletes a static route in a STACKIT Network Area (SNA).", Args: args.SingleArg(routeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network-area/route/describe/describe.go b/internal/cmd/beta/network-area/route/describe/describe.go index f20fced9d..aa9dbb7c5 100644 --- a/internal/cmd/beta/network-area/route/describe/describe.go +++ b/internal/cmd/beta/network-area/route/describe/describe.go @@ -36,7 +36,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", routeIdArg), Short: "Shows details of a static route in a STACKIT Network Area (SNA)", Long: "Shows details of a static route in a STACKIT Network Area (SNA).", Args: args.SingleArg(routeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network-area/route/update/update.go b/internal/cmd/beta/network-area/route/update/update.go index 4a04ca654..bf11fc1a6 100644 --- a/internal/cmd/beta/network-area/route/update/update.go +++ b/internal/cmd/beta/network-area/route/update/update.go @@ -38,7 +38,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", routeIdArg), Short: "Updates a static route in a STACKIT Network Area (SNA)", Long: fmt.Sprintf("%s\n%s\n", "Updates a static route in a STACKIT Network Area (SNA).", diff --git a/internal/cmd/beta/network-area/update/update.go b/internal/cmd/beta/network-area/update/update.go index 5c595ab15..c59a80af1 100644 --- a/internal/cmd/beta/network-area/update/update.go +++ b/internal/cmd/beta/network-area/update/update.go @@ -45,7 +45,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", areaIdArg), Short: "Updates a STACKIT Network Area (SNA)", Long: "Updates a STACKIT Network Area (SNA) in an organization.", Args: args.SingleArg(areaIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network-interface/delete/delete.go b/internal/cmd/beta/network-interface/delete/delete.go index 72adc082a..2597e9402 100644 --- a/internal/cmd/beta/network-interface/delete/delete.go +++ b/internal/cmd/beta/network-interface/delete/delete.go @@ -29,7 +29,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", nicIdArg), Short: "Deletes a network interface", Long: "Deletes a network interface.", Args: args.SingleArg(nicIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network-interface/describe/describe.go b/internal/cmd/beta/network-interface/describe/describe.go index 45702c3df..92da8a62d 100644 --- a/internal/cmd/beta/network-interface/describe/describe.go +++ b/internal/cmd/beta/network-interface/describe/describe.go @@ -34,7 +34,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", nicIdArg), Short: "Describes a network interface", Long: "Describes a network interface.", Args: args.SingleArg(nicIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network-interface/update/update.go b/internal/cmd/beta/network-interface/update/update.go index 130a68a91..5128e26cc 100644 --- a/internal/cmd/beta/network-interface/update/update.go +++ b/internal/cmd/beta/network-interface/update/update.go @@ -49,7 +49,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", nicIdArg), Short: "Updates a network interface", Long: "Updates a network interface.", Args: args.SingleArg(nicIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network/delete/delete.go b/internal/cmd/beta/network/delete/delete.go index 1e399e17c..001aefa84 100644 --- a/internal/cmd/beta/network/delete/delete.go +++ b/internal/cmd/beta/network/delete/delete.go @@ -30,7 +30,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", networkIdArg), Short: "Deletes a network", Long: fmt.Sprintf("%s\n%s\n", "Deletes a network.", diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/beta/network/describe/describe.go index 854fd65b0..31982a366 100644 --- a/internal/cmd/beta/network/describe/describe.go +++ b/internal/cmd/beta/network/describe/describe.go @@ -31,7 +31,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", networkIdArg), Short: "Shows details of a network", Long: "Shows details of a network.", Args: args.SingleArg(networkIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/beta/network/update/update.go index 710205cd7..9c7b6247d 100644 --- a/internal/cmd/beta/network/update/update.go +++ b/internal/cmd/beta/network/update/update.go @@ -46,7 +46,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", networkIdArg), Short: "Updates a network", Long: "Updates a network.", Args: args.SingleArg(networkIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/public-ip/associate/associate.go b/internal/cmd/beta/public-ip/associate/associate.go index 9e82108e9..7233b827c 100644 --- a/internal/cmd/beta/public-ip/associate/associate.go +++ b/internal/cmd/beta/public-ip/associate/associate.go @@ -32,7 +32,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "associate", + Use: fmt.Sprintf("associate %s", publicIpIdArg), Short: "Associates a Public IP with a network interface or a virtual IP", Long: "Associates a Public IP with a network interface or a virtual IP.", Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/public-ip/delete/delete.go b/internal/cmd/beta/public-ip/delete/delete.go index 28e625e23..bd87419da 100644 --- a/internal/cmd/beta/public-ip/delete/delete.go +++ b/internal/cmd/beta/public-ip/delete/delete.go @@ -27,7 +27,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", publicIpIdArg), Short: "Deletes a Public IP", Long: fmt.Sprintf("%s\n%s\n", "Deletes a Public IP.", diff --git a/internal/cmd/beta/public-ip/describe/describe.go b/internal/cmd/beta/public-ip/describe/describe.go index 9e47ab890..fe85c6902 100644 --- a/internal/cmd/beta/public-ip/describe/describe.go +++ b/internal/cmd/beta/public-ip/describe/describe.go @@ -32,7 +32,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", publicIpIdArg), Short: "Shows details of a Public IP", Long: "Shows details of a Public IP.", Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/public-ip/disassociate/disassociate.go b/internal/cmd/beta/public-ip/disassociate/disassociate.go index fe47bcdb0..0ad28d773 100644 --- a/internal/cmd/beta/public-ip/disassociate/disassociate.go +++ b/internal/cmd/beta/public-ip/disassociate/disassociate.go @@ -28,7 +28,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "disassociate", + Use: fmt.Sprintf("disassociate %s", publicIpIdArg), Short: "Disassociates a Public IP from a network interface or a virtual IP", Long: "Disassociates a Public IP from a network interface or a virtual IP.", Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/public-ip/update/update.go b/internal/cmd/beta/public-ip/update/update.go index ff7899e89..58c77e73c 100644 --- a/internal/cmd/beta/public-ip/update/update.go +++ b/internal/cmd/beta/public-ip/update/update.go @@ -35,7 +35,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", publicIpIdArg), Short: "Updates a Public IP", Long: "Updates a Public IP.", Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/security-group/delete/delete.go b/internal/cmd/beta/security-group/delete/delete.go index 580dbd96f..80f91882c 100644 --- a/internal/cmd/beta/security-group/delete/delete.go +++ b/internal/cmd/beta/security-group/delete/delete.go @@ -26,7 +26,7 @@ const groupIdArg = "GROUP_ID" func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", groupIdArg), Short: "Deletes a security group", Long: "Deletes a security group by its internal ID.", Args: args.SingleArg(groupIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/security-group/describe/describe.go b/internal/cmd/beta/security-group/describe/describe.go index 68cd63eff..10533c1da 100644 --- a/internal/cmd/beta/security-group/describe/describe.go +++ b/internal/cmd/beta/security-group/describe/describe.go @@ -28,7 +28,7 @@ const groupIdArg = "GROUP_ID" func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", groupIdArg), Short: "Describes security groups", Long: "Describes security groups by its internal ID.", Args: args.SingleArg(groupIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/security-group/rule/delete/delete.go b/internal/cmd/beta/security-group/rule/delete/delete.go index b28ade08e..035866bed 100644 --- a/internal/cmd/beta/security-group/rule/delete/delete.go +++ b/internal/cmd/beta/security-group/rule/delete/delete.go @@ -31,7 +31,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", securityGroupRuleIdArg), Short: "Deletes a security group rule", Long: fmt.Sprintf("%s\n%s\n", "Deletes a security group rule.", diff --git a/internal/cmd/beta/security-group/rule/describe/describe.go b/internal/cmd/beta/security-group/rule/describe/describe.go index 93f7df60c..bc1b7abd3 100644 --- a/internal/cmd/beta/security-group/rule/describe/describe.go +++ b/internal/cmd/beta/security-group/rule/describe/describe.go @@ -34,7 +34,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", securityGroupRuleIdArg), Short: "Shows details of a security group rule", Long: "Shows details of a security group rule.", Args: args.SingleArg(securityGroupRuleIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/security-group/update/update.go b/internal/cmd/beta/security-group/update/update.go index 961229053..faec421f5 100644 --- a/internal/cmd/beta/security-group/update/update.go +++ b/internal/cmd/beta/security-group/update/update.go @@ -36,7 +36,7 @@ const ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", groupNameArg), Short: "Updates a security group", Long: "Updates a named security group", Args: args.SingleArg(groupNameArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/console/console.go b/internal/cmd/beta/server/console/console.go index 9bc862cdf..1e9bf05e3 100644 --- a/internal/cmd/beta/server/console/console.go +++ b/internal/cmd/beta/server/console/console.go @@ -31,7 +31,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "console", + Use: fmt.Sprintf("console %s", serverIdArg), Short: "Gets a URL for server remote console", Long: "Gets a URL for server remote console.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/deallocate/deallocate.go b/internal/cmd/beta/server/deallocate/deallocate.go index 6396f2e0b..0bfe4205a 100644 --- a/internal/cmd/beta/server/deallocate/deallocate.go +++ b/internal/cmd/beta/server/deallocate/deallocate.go @@ -30,7 +30,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "deallocate", + Use: fmt.Sprintf("deallocate %s", serverIdArg), Short: "Deallocates an existing server", Long: "Deallocates an existing server.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/delete/delete.go b/internal/cmd/beta/server/delete/delete.go index c82059193..43b2a77cb 100644 --- a/internal/cmd/beta/server/delete/delete.go +++ b/internal/cmd/beta/server/delete/delete.go @@ -30,7 +30,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", serverIdArg), Short: "Deletes a server", Long: fmt.Sprintf("%s\n%s\n", "Deletes a server.", diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/beta/server/describe/describe.go index b425a227d..d7937851b 100644 --- a/internal/cmd/beta/server/describe/describe.go +++ b/internal/cmd/beta/server/describe/describe.go @@ -32,7 +32,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", serverIdArg), Short: "Shows details of a server", Long: "Shows details of a server.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/log/log.go b/internal/cmd/beta/server/log/log.go index 7cfffcb84..20e791b27 100644 --- a/internal/cmd/beta/server/log/log.go +++ b/internal/cmd/beta/server/log/log.go @@ -36,7 +36,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "log", + Use: fmt.Sprintf("log %s", serverIdArg), Short: "Gets server console log", Long: "Gets server console log.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/public-ip/attach/attach.go b/internal/cmd/beta/server/public-ip/attach/attach.go index 28c0b15b2..47d55e750 100644 --- a/internal/cmd/beta/server/public-ip/attach/attach.go +++ b/internal/cmd/beta/server/public-ip/attach/attach.go @@ -31,7 +31,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "attach", + Use: fmt.Sprintf("attach %s", publicIpIdArg), Short: "Attaches a public IP to a server", Long: "Attaches a public IP to a server.", Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/public-ip/detach/detach.go b/internal/cmd/beta/server/public-ip/detach/detach.go index 9a9533df2..d476db50f 100644 --- a/internal/cmd/beta/server/public-ip/detach/detach.go +++ b/internal/cmd/beta/server/public-ip/detach/detach.go @@ -31,7 +31,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "detach", + Use: fmt.Sprintf("detach %s", publicIpIdArg), Short: "Detaches a public IP from a server", Long: "Detaches a public IP from a server.", Args: args.SingleArg(publicIpIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/reboot/reboot.go b/internal/cmd/beta/server/reboot/reboot.go index 6983e7531..d5ec2bae5 100644 --- a/internal/cmd/beta/server/reboot/reboot.go +++ b/internal/cmd/beta/server/reboot/reboot.go @@ -34,7 +34,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "reboot", + Use: fmt.Sprintf("reboot %s", serverIdArg), Short: "Reboots a server", Long: "Reboots a server.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/rescue/rescue.go b/internal/cmd/beta/server/rescue/rescue.go index b658f4ace..b634587fe 100644 --- a/internal/cmd/beta/server/rescue/rescue.go +++ b/internal/cmd/beta/server/rescue/rescue.go @@ -34,7 +34,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "rescue", + Use: fmt.Sprintf("rescue %s", serverIdArg), Short: "Rescues an existing server", Long: "Rescues an existing server.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/resize/resize.go b/internal/cmd/beta/server/resize/resize.go index 95b5b3e00..105967c6e 100644 --- a/internal/cmd/beta/server/resize/resize.go +++ b/internal/cmd/beta/server/resize/resize.go @@ -34,7 +34,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "resize", + Use: fmt.Sprintf("resize %s", serverIdArg), Short: "Resizes the server to the given machine type", Long: "Resizes the server to the given machine type.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/service-account/attach/attach.go b/internal/cmd/beta/server/service-account/attach/attach.go index c5cffdbad..00dd4ac8c 100644 --- a/internal/cmd/beta/server/service-account/attach/attach.go +++ b/internal/cmd/beta/server/service-account/attach/attach.go @@ -33,7 +33,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "attach", + Use: fmt.Sprintf("attach %s", serviceAccMailArg), Short: "Attach a service account to a server", Long: "Attach a service account to a server", Args: args.SingleArg(serviceAccMailArg, nil), diff --git a/internal/cmd/beta/server/service-account/detach/detach.go b/internal/cmd/beta/server/service-account/detach/detach.go index 99e95506c..954463974 100644 --- a/internal/cmd/beta/server/service-account/detach/detach.go +++ b/internal/cmd/beta/server/service-account/detach/detach.go @@ -33,7 +33,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "detach", + Use: fmt.Sprintf("detach %s", serviceAccMailArg), Short: "Detach a service account from a server", Long: "Detach a service account from a server", Args: args.SingleArg(serviceAccMailArg, nil), diff --git a/internal/cmd/beta/server/start/start.go b/internal/cmd/beta/server/start/start.go index 764d3c5d9..9c8447982 100644 --- a/internal/cmd/beta/server/start/start.go +++ b/internal/cmd/beta/server/start/start.go @@ -30,7 +30,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "start", + Use: fmt.Sprintf("start %s", serverIdArg), Short: "Starts an existing server or allocates the server if deallocated", Long: "Starts an existing server or allocates the server if deallocated.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/stop/stop.go b/internal/cmd/beta/server/stop/stop.go index a8fc651e6..d16a636de 100644 --- a/internal/cmd/beta/server/stop/stop.go +++ b/internal/cmd/beta/server/stop/stop.go @@ -30,7 +30,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "stop", + Use: fmt.Sprintf("stop %s", serverIdArg), Short: "Stops an existing server", Long: "Stops an existing server.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/unrescue/unrescue.go b/internal/cmd/beta/server/unrescue/unrescue.go index c41d9f0c7..39a7040f7 100644 --- a/internal/cmd/beta/server/unrescue/unrescue.go +++ b/internal/cmd/beta/server/unrescue/unrescue.go @@ -30,7 +30,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "unrescue", + Use: fmt.Sprintf("unrescue %s", serverIdArg), Short: "Unrescues an existing server", Long: "Unrescues an existing server.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/update/update.go b/internal/cmd/beta/server/update/update.go index 127cb67ca..6d4a39d7f 100644 --- a/internal/cmd/beta/server/update/update.go +++ b/internal/cmd/beta/server/update/update.go @@ -36,7 +36,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", serverIdArg), Short: "Updates a server", Long: "Updates a server.", Args: args.SingleArg(serverIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/volume/attach/attach.go b/internal/cmd/beta/server/volume/attach/attach.go index c417265d7..ba020e467 100644 --- a/internal/cmd/beta/server/volume/attach/attach.go +++ b/internal/cmd/beta/server/volume/attach/attach.go @@ -37,7 +37,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "attach", + Use: fmt.Sprintf("attach %s", volumeIdArg), Short: "Attaches a volume to a server", Long: "Attaches a volume to a server.", Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/volume/describe/describe.go b/internal/cmd/beta/server/volume/describe/describe.go index 94fa6dd82..d5e4a3146 100644 --- a/internal/cmd/beta/server/volume/describe/describe.go +++ b/internal/cmd/beta/server/volume/describe/describe.go @@ -33,7 +33,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", volumeIdArg), Short: "Describes a server volume attachment", Long: "Describes a server volume attachment.", Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/volume/detach/detach.go b/internal/cmd/beta/server/volume/detach/detach.go index 6e80517f6..8e07fd216 100644 --- a/internal/cmd/beta/server/volume/detach/detach.go +++ b/internal/cmd/beta/server/volume/detach/detach.go @@ -31,7 +31,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "detach", + Use: fmt.Sprintf("detach %s", volumeIdArg), Short: "Detaches a volume from a server", Long: "Detaches a volume from a server.", Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/server/volume/update/update.go b/internal/cmd/beta/server/volume/update/update.go index 5ab7d58de..41252e79f 100644 --- a/internal/cmd/beta/server/volume/update/update.go +++ b/internal/cmd/beta/server/volume/update/update.go @@ -37,7 +37,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", volumeIdArg), Short: "Updates an attached volume of a server", Long: "Updates an attached volume of a server.", Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/volume/delete/delete.go b/internal/cmd/beta/volume/delete/delete.go index ce170565c..ca52fa148 100644 --- a/internal/cmd/beta/volume/delete/delete.go +++ b/internal/cmd/beta/volume/delete/delete.go @@ -30,7 +30,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "delete", + Use: fmt.Sprintf("delete %s", volumeIdArg), Short: "Deletes a volume", Long: fmt.Sprintf("%s\n%s\n", "Deletes a volume.", diff --git a/internal/cmd/beta/volume/describe/describe.go b/internal/cmd/beta/volume/describe/describe.go index a8780c11b..3f70f6fea 100644 --- a/internal/cmd/beta/volume/describe/describe.go +++ b/internal/cmd/beta/volume/describe/describe.go @@ -32,7 +32,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", volumeIdArg), Short: "Shows details of a volume", Long: "Shows details of a volume.", Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/volume/performance-class/describe/describe.go b/internal/cmd/beta/volume/performance-class/describe/describe.go index a316babba..fa9625853 100644 --- a/internal/cmd/beta/volume/performance-class/describe/describe.go +++ b/internal/cmd/beta/volume/performance-class/describe/describe.go @@ -30,7 +30,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "describe", + Use: fmt.Sprintf("describe %s", volumePerformanceClassArg), Short: "Shows details of a volume performance class", Long: "Shows details of a volume performance class.", Args: args.SingleArg(volumePerformanceClassArg, nil), diff --git a/internal/cmd/beta/volume/resize/resize.go b/internal/cmd/beta/volume/resize/resize.go index 043ca14fe..fdcd882a2 100644 --- a/internal/cmd/beta/volume/resize/resize.go +++ b/internal/cmd/beta/volume/resize/resize.go @@ -32,7 +32,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "resize", + Use: fmt.Sprintf("resize %s", volumeIdArg), Short: "Resizes a volume", Long: "Resizes a volume.", Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/beta/volume/update/update.go b/internal/cmd/beta/volume/update/update.go index 34bbc61f5..3288062ff 100644 --- a/internal/cmd/beta/volume/update/update.go +++ b/internal/cmd/beta/volume/update/update.go @@ -38,7 +38,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", volumeIdArg), Short: "Updates a volume", Long: "Updates a volume.", Args: args.SingleArg(volumeIdArg, utils.ValidateUUID), diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index b0cc72f7f..e1af7022a 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -41,7 +41,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "clone", + Use: fmt.Sprintf("clone %s", zoneIdArg), Short: "Clones a DNS zone", Long: "Clones an existing DNS zone with all record sets to a new zone with a different name.", Args: args.SingleArg(zoneIdArg, utils.ValidateUUID), diff --git a/internal/cmd/load-balancer/observability-credentials/update/update.go b/internal/cmd/load-balancer/observability-credentials/update/update.go index 3372266d5..8c3d7ebbc 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update.go @@ -37,7 +37,7 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "update", + Use: fmt.Sprintf("update %s", credentialsRefArg), Short: "Updates observability credentials for Load Balancer", Long: "Updates existing observability credentials (username and password) for Load Balancer. The credentials can be for Observability or another monitoring tool.", Args: args.SingleArg(credentialsRefArg, nil), From e004f9d3b0d86a54372b91c8fa9c23b2e00f646f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 6 Jan 2025 11:14:38 +0100 Subject: [PATCH 135/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.13 (#546) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 78a6abd80..28a43cd0e 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.11 + github.com/goccy/go-yaml v1.15.13 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 608704e6d..4ec595f9e 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.11 h1:XeEd/2INF0TXXWMzJ9ALqJLGjGDl4PIi1gmrK+7KpAs= -github.com/goccy/go-yaml v1.15.11/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.13 h1:Xd87Yddmr2rC1SLLTm2MNDcTjeO/GYo0JGiww6gSTDg= +github.com/goccy/go-yaml v1.15.13/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 2090c145799daa58d16175ecfe67efa89fee4e2f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:21:18 +0100 Subject: [PATCH 136/619] fix(deps): update stackit sdk modules (#547) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 28a43cd0e..55dba0f4f 100644 --- a/go.mod +++ b/go.mod @@ -15,10 +15,10 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 - github.com/stackitcloud/stackit-sdk-go/core v0.14.0 + github.com/stackitcloud/stackit-sdk-go/core v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 diff --git a/go.sum b/go.sum index 4ec595f9e..8147aeed0 100644 --- a/go.sum +++ b/go.sum @@ -118,14 +118,14 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= -github.com/stackitcloud/stackit-sdk-go/core v0.14.0 h1:oBwwzrEHDTlZpRoQwmMQpNA8bWciTrtGkiN29nx14Z0= -github.com/stackitcloud/stackit-sdk-go/core v0.14.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= +github.com/stackitcloud/stackit-sdk-go/core v0.15.0 h1:oMP6L616/bP3b/B1Me7Ptu637dAJKr7NO3Rd3UwqpvE= +github.com/stackitcloud/stackit-sdk-go/core v0.15.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1 h1:sK7FZHN1tF8D/7rbWLhu4DX0qrAP5Psn2NusnwbCsEM= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 h1:nzOZQ2X6joM2iStePoACZeYvXFBQIBjkYE9sLanOGvE= github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0 h1:7QPYi7OZXUSO1uOtp1UXeCbxK0BGJbmjp71kaQOrMa8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.18.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 h1:o9OAGh4mdYY5LZYZiJio0KYUhqPSpBY4vT08piGx0pI= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.1 h1:ogo7Ce4wA9ln/Z0VwvckH0FT5/i7d9/34bG85aayHn8= From a3fca07ccbf3f161a7fa1b43fe8b60d0ba7ea8fa Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:24:44 +0100 Subject: [PATCH 137/619] fix(deps): update module golang.org/x/oauth2 to v0.25.0 (#548) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 55dba0f4f..b5a115140 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.22.0 - golang.org/x/oauth2 v0.24.0 + golang.org/x/oauth2 v0.25.0 golang.org/x/term v0.27.0 golang.org/x/text v0.21.0 k8s.io/apimachinery v0.31.3 diff --git a/go.sum b/go.sum index 8147aeed0..c8ce137bd 100644 --- a/go.sum +++ b/go.sum @@ -198,8 +198,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 66226f5d033ce19cc81732d19ed3a7eeecf9c880 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 7 Jan 2025 19:39:12 +0100 Subject: [PATCH 138/619] fix(deps): update module golang.org/x/term to v0.28.0 (#549) Co-authored-by: Renovate Bot Co-authored-by: Marcel <72880145+marceljk@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index b5a115140..538c43782 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.22.0 golang.org/x/oauth2 v0.25.0 - golang.org/x/term v0.27.0 + golang.org/x/term v0.28.0 golang.org/x/text v0.21.0 k8s.io/apimachinery v0.31.3 k8s.io/client-go v0.31.3 @@ -88,7 +88,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/sys v0.28.0 // indirect + golang.org/x/sys v0.29.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index c8ce137bd..9b95109da 100644 --- a/go.sum +++ b/go.sum @@ -208,10 +208,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= From b69663fd9660ca53975b9f0c6a284a6abc16fc4c Mon Sep 17 00:00:00 2001 From: Vicente Pinto Date: Fri, 10 Jan 2025 09:04:19 +0000 Subject: [PATCH 139/619] Fix multi-table pager display (#551) * Fix multi-table pager display * Fix lint g --- internal/cmd/beta/server/describe/describe.go | 17 ++-- .../cmd/beta/sqlserverflex/options/options.go | 92 +++++++------------ .../cmd/load-balancer/describe/describe.go | 22 +++-- internal/cmd/mongodbflex/options/options.go | 48 ++++------ internal/cmd/postgresflex/options/options.go | 48 ++++------ internal/cmd/ske/options/options.go | 74 +++++++-------- internal/pkg/tables/tables.go | 11 +++ 7 files changed, 135 insertions(+), 177 deletions(-) diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/beta/server/describe/describe.go index d7937851b..639b0a320 100644 --- a/internal/cmd/beta/server/describe/describe.go +++ b/internal/cmd/beta/server/describe/describe.go @@ -125,6 +125,8 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro return nil default: + content := []tables.Table{} + table := tables.NewTable() table.SetTitle("Server") @@ -182,10 +184,7 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro table.AddSeparator() } - err := table.Display(p) - if err != nil { - return fmt.Errorf("render table: %w", err) - } + content = append(content, table) if server.Nics != nil && len(*server.Nics) > 0 { nicsTable := tables.NewTable() @@ -201,10 +200,12 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro nicsTable.AddSeparator() } - err := nicsTable.Display(p) - if err != nil { - return fmt.Errorf("render table: %w", err) - } + content = append(content, nicsTable) + } + + err := tables.DisplayTables(p, content) + if err != nil { + return fmt.Errorf("render table: %w", err) } return nil diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index 2624bffaa..1a3763735 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -300,28 +300,28 @@ func outputResult(p *print.Printer, model *inputModel, flavors *sqlserverflex.Li } func outputResultAsTable(p *print.Printer, model *inputModel, options *options) error { - content := "" - if model.Flavors { - content += renderFlavors(*options.Flavors) + content := []tables.Table{} + if model.Flavors && len(*options.Flavors) != 0 { + content = append(content, buildFlavorsTable(*options.Flavors)) } - if model.Versions { - content += renderVersions(*options.Versions) + if model.Versions && len(*options.Versions) != 0 { + content = append(content, buildVersionsTable(*options.Versions)) } - if model.Storages { - content += renderStorages(options.Storages.Storages) + if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) != 0 { + content = append(content, buildStoragesTable(*options.Storages.Storages)) } - if model.UserRoles { - content += renderUserRoles(options.UserRoles) + if model.UserRoles && len(options.UserRoles.UserRoles) != 0 { + content = append(content, buildUserRoles(options.UserRoles)) } - if model.DBCompatibilities { - content += renderDBCompatibilities(options.DBCompatibilities) + if model.DBCompatibilities && len(options.DBCompatibilities.DBCompatibilities) != 0 { + content = append(content, buildDBCompatibilitiesTable(options.DBCompatibilities.DBCompatibilities)) } // Rendered at last because table is very long - if model.DBCollations { - content += renderDBCollations(options.DBCollations) + if model.DBCollations && len(options.DBCollations.DBCollations) != 0 { + content = append(content, buildDBCollationsTable(options.DBCollations.DBCollations)) } - err := p.PagerDisplay(content) + err := tables.DisplayTables(p, content) if err != nil { return fmt.Errorf("display output: %w", err) } @@ -329,11 +329,7 @@ func outputResultAsTable(p *print.Printer, model *inputModel, options *options) return nil } -func renderFlavors(flavors []sqlserverflex.InstanceFlavorEntry) string { - if len(flavors) == 0 { - return "" - } - +func buildFlavorsTable(flavors []sqlserverflex.InstanceFlavorEntry) tables.Table { table := tables.NewTable() table.SetTitle("Flavors") table.SetHeader("ID", "CPU", "MEMORY", "DESCRIPTION", "VALID INSTANCE TYPES") @@ -341,14 +337,10 @@ func renderFlavors(flavors []sqlserverflex.InstanceFlavorEntry) string { f := flavors[i] table.AddRow(*f.Id, *f.Cpu, *f.Memory, *f.Description, *f.Categories) } - return table.Render() + return table } -func renderVersions(versions []string) string { - if len(versions) == 0 { - return "" - } - +func buildVersionsTable(versions []string) tables.Table { table := tables.NewTable() table.SetTitle("Versions") table.SetHeader("VERSION") @@ -356,64 +348,48 @@ func renderVersions(versions []string) string { v := versions[i] table.AddRow(v) } - return table.Render() + return table } -func renderStorages(resp *sqlserverflex.ListStoragesResponse) string { - if resp.StorageClasses == nil || len(*resp.StorageClasses) == 0 { - return "" - } - storageClasses := *resp.StorageClasses - +func buildStoragesTable(storagesResp sqlserverflex.ListStoragesResponse) tables.Table { + storages := *storagesResp.StorageClasses table := tables.NewTable() table.SetTitle("Storages") table.SetHeader("MINIMUM", "MAXIMUM", "STORAGE CLASS") - for i := range storageClasses { - sc := storageClasses[i] - table.AddRow(*resp.StorageRange.Min, *resp.StorageRange.Max, sc) + for i := range storages { + sc := storages[i] + table.AddRow(*storagesResp.StorageRange.Min, *storagesResp.StorageRange.Max, sc) } table.EnableAutoMergeOnColumns(1, 2, 3) - return table.Render() + return table } -func renderUserRoles(roles *instanceUserRoles) string { - if len(roles.UserRoles) == 0 { - return "" - } - +func buildUserRoles(roles *instanceUserRoles) tables.Table { table := tables.NewTable() table.SetTitle("User Roles") table.SetHeader("ROLE") for i := range roles.UserRoles { table.AddRow(roles.UserRoles[i]) } - return table.Render() + return table } -func renderDBCollations(dbCollations *instanceDBCollations) string { - if len(dbCollations.DBCollations) == 0 { - return "" - } - +func buildDBCollationsTable(dbCollations []sqlserverflex.MssqlDatabaseCollation) tables.Table { table := tables.NewTable() table.SetTitle("DB Collations") table.SetHeader("NAME", "DESCRIPTION") - for i := range dbCollations.DBCollations { - table.AddRow(*dbCollations.DBCollations[i].CollationName, *dbCollations.DBCollations[i].Description) + for i := range dbCollations { + table.AddRow(dbCollations[i].CollationName, dbCollations[i].Description) } - return table.Render() + return table } -func renderDBCompatibilities(dbCompatibilities *instanceDBCompatibilities) string { - if len(dbCompatibilities.DBCompatibilities) == 0 { - return "" - } - +func buildDBCompatibilitiesTable(dbCompatibilities []sqlserverflex.MssqlDatabaseCompatibility) tables.Table { table := tables.NewTable() table.SetTitle("DB Compatibilities") table.SetHeader("COMPATIBILITY LEVEL", "DESCRIPTION") - for i := range dbCompatibilities.DBCompatibilities { - table.AddRow(*dbCompatibilities.DBCompatibilities[i].CompatibilityLevel, *dbCompatibilities.DBCompatibilities[i].Description) + for i := range dbCompatibilities { + table.AddRow(dbCompatibilities[i].CompatibilityLevel, dbCompatibilities[i].Description) } - return table.Render() + return table } diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index d5cf4dec9..d08e5a99e 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -121,17 +121,19 @@ func outputResult(p *print.Printer, outputFormat string, loadBalancer *loadbalan } func outputResultAsTable(p *print.Printer, loadBalancer *loadbalancer.LoadBalancer) error { - content := renderLoadBalancer(loadBalancer) + content := []tables.Table{} + + content = append(content, buildLoadBalancerTable(loadBalancer)) if loadBalancer.Listeners != nil { - content += renderListeners(*loadBalancer.Listeners) + content = append(content, buildListenersTable(*loadBalancer.Listeners)) } if loadBalancer.TargetPools != nil { - content += renderTargetPools(*loadBalancer.TargetPools) + content = append(content, buildTargetPoolsTable(*loadBalancer.TargetPools)) } - err := p.PagerDisplay(content) + err := tables.DisplayTables(p, content) if err != nil { return fmt.Errorf("display output: %w", err) } @@ -139,7 +141,7 @@ func outputResultAsTable(p *print.Printer, loadBalancer *loadbalancer.LoadBalanc return nil } -func renderLoadBalancer(loadBalancer *loadbalancer.LoadBalancer) string { +func buildLoadBalancerTable(loadBalancer *loadbalancer.LoadBalancer) tables.Table { acl := []string{} privateAccessOnly := false if loadBalancer.Options != nil { @@ -187,10 +189,10 @@ func renderLoadBalancer(loadBalancer *loadbalancer.LoadBalancer) string { table.AddRow("ATTACHED NETWORK ID", networkId) table.AddSeparator() table.AddRow("ACL", acl) - return table.Render() + return table } -func renderListeners(listeners []loadbalancer.Listener) string { +func buildListenersTable(listeners []loadbalancer.Listener) tables.Table { table := tables.NewTable() table.SetTitle("Listeners") table.SetHeader("NAME", "PORT", "PROTOCOL", "TARGET POOL") @@ -198,15 +200,15 @@ func renderListeners(listeners []loadbalancer.Listener) string { listener := listeners[i] table.AddRow(*listener.Name, *listener.Port, *listener.Protocol, *listener.TargetPool) } - return table.Render() + return table } -func renderTargetPools(targetPools []loadbalancer.TargetPool) string { +func buildTargetPoolsTable(targetPools []loadbalancer.TargetPool) tables.Table { table := tables.NewTable() table.SetTitle("Target Pools") table.SetHeader("NAME", "PORT", "TARGETS") for _, targetPool := range targetPools { table.AddRow(*targetPool.Name, *targetPool.TargetPort, len(*targetPool.Targets)) } - return table.Render() + return table } diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 53b62932b..e58a5e311 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -206,18 +206,18 @@ func outputResult(p *print.Printer, model *inputModel, flavors *mongodbflex.List } func outputResultAsTable(p *print.Printer, model *inputModel, options *options) error { - content := "" - if model.Flavors { - content += renderFlavors(*options.Flavors) + content := []tables.Table{} + if model.Flavors && len(*options.Flavors) != 0 { + content = append(content, buildFlavorsTable(*options.Flavors)) } - if model.Versions { - content += renderVersions(*options.Versions) + if model.Versions && len(*options.Versions) != 0 { + content = append(content, buildVersionsTable(*options.Versions)) } - if model.Storages { - content += renderStorages(options.Storages.Storages) + if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) == 0 { + content = append(content, buildStoragesTable(*options.Storages.Storages)) } - err := p.PagerDisplay(content) + err := tables.DisplayTables(p, content) if err != nil { return fmt.Errorf("display output: %w", err) } @@ -225,11 +225,7 @@ func outputResultAsTable(p *print.Printer, model *inputModel, options *options) return nil } -func renderFlavors(flavors []mongodbflex.HandlersInfraFlavor) string { - if len(flavors) == 0 { - return "" - } - +func buildFlavorsTable(flavors []mongodbflex.HandlersInfraFlavor) tables.Table { table := tables.NewTable() table.SetTitle("Flavors") table.SetHeader("ID", "CPU", "MEMORY", "DESCRIPTION", "VALID INSTANCE TYPES") @@ -237,14 +233,10 @@ func renderFlavors(flavors []mongodbflex.HandlersInfraFlavor) string { f := flavors[i] table.AddRow(*f.Id, *f.Cpu, *f.Memory, *f.Description, *f.Categories) } - return table.Render() + return table } -func renderVersions(versions []string) string { - if len(versions) == 0 { - return "" - } - +func buildVersionsTable(versions []string) tables.Table { table := tables.NewTable() table.SetTitle("Versions") table.SetHeader("VERSION") @@ -252,22 +244,18 @@ func renderVersions(versions []string) string { v := versions[i] table.AddRow(v) } - return table.Render() + return table } -func renderStorages(resp *mongodbflex.ListStoragesResponse) string { - if resp.StorageClasses == nil || len(*resp.StorageClasses) == 0 { - return "" - } - storageClasses := *resp.StorageClasses - +func buildStoragesTable(storagesResp mongodbflex.ListStoragesResponse) tables.Table { + storages := *storagesResp.StorageClasses table := tables.NewTable() table.SetTitle("Storages") table.SetHeader("MINIMUM", "MAXIMUM", "STORAGE CLASS") - for i := range storageClasses { - sc := storageClasses[i] - table.AddRow(*resp.StorageRange.Min, *resp.StorageRange.Max, sc) + for i := range storages { + sc := storages[i] + table.AddRow(*storagesResp.StorageRange.Min, *storagesResp.StorageRange.Max, sc) } table.EnableAutoMergeOnColumns(1, 2, 3) - return table.Render() + return table } diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index 3dc3ee205..f5833d151 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -206,18 +206,18 @@ func outputResult(p *print.Printer, model *inputModel, flavors *postgresflex.Lis } func outputResultAsTable(p *print.Printer, model *inputModel, options *options) error { - content := "" - if model.Flavors { - content += renderFlavors(*options.Flavors) + content := []tables.Table{} + if model.Flavors && len(*options.Flavors) != 0 { + content = append(content, buildFlavorsTable(*options.Flavors)) } - if model.Versions { - content += renderVersions(*options.Versions) + if model.Versions && len(*options.Versions) != 0 { + content = append(content, buildVersionsTable(*options.Versions)) } - if model.Storages { - content += renderStorages(options.Storages.Storages) + if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) == 0 { + content = append(content, buildStoragesTable(*options.Storages.Storages)) } - err := p.PagerDisplay(content) + err := tables.DisplayTables(p, content) if err != nil { return fmt.Errorf("display output: %w", err) } @@ -225,11 +225,7 @@ func outputResultAsTable(p *print.Printer, model *inputModel, options *options) return nil } -func renderFlavors(flavors []postgresflex.Flavor) string { - if len(flavors) == 0 { - return "" - } - +func buildFlavorsTable(flavors []postgresflex.Flavor) tables.Table { table := tables.NewTable() table.SetTitle("Flavors") table.SetHeader("ID", "CPU", "MEMORY", "DESCRIPTION") @@ -237,14 +233,10 @@ func renderFlavors(flavors []postgresflex.Flavor) string { f := flavors[i] table.AddRow(*f.Id, *f.Cpu, *f.Memory, *f.Description) } - return table.Render() + return table } -func renderVersions(versions []string) string { - if len(versions) == 0 { - return "" - } - +func buildVersionsTable(versions []string) tables.Table { table := tables.NewTable() table.SetTitle("Versions") table.SetHeader("VERSION") @@ -252,22 +244,18 @@ func renderVersions(versions []string) string { v := versions[i] table.AddRow(v) } - return table.Render() + return table } -func renderStorages(resp *postgresflex.ListStoragesResponse) string { - if resp.StorageClasses == nil || len(*resp.StorageClasses) == 0 { - return "" - } - storageClasses := *resp.StorageClasses - +func buildStoragesTable(storagesResp postgresflex.ListStoragesResponse) tables.Table { + storages := *storagesResp.StorageClasses table := tables.NewTable() table.SetTitle("Storages") table.SetHeader("MINIMUM", "MAXIMUM", "STORAGE CLASS") - for i := range storageClasses { - sc := storageClasses[i] - table.AddRow(*resp.StorageRange.Min, *resp.StorageRange.Max, sc) + for i := range storages { + sc := storages[i] + table.AddRow(*storagesResp.StorageRange.Min, *storagesResp.StorageRange.Max, sc) } table.EnableAutoMergeOnColumns(1, 2, 3) - return table.Render() + return table } diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index 4982eaa49..fd0976997 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -178,20 +178,32 @@ func outputResult(p *print.Printer, model *inputModel, options *ske.ProviderOpti } func outputResultAsTable(p *print.Printer, options *ske.ProviderOptions) error { - content := "" - content += renderAvailabilityZones(options) + content := []tables.Table{} + if options.AvailabilityZones != nil && len(*options.AvailabilityZones) != 0 { + content = append(content, buildAvailabilityZonesTable(options)) + } - kubernetesVersionsRendered, err := renderKubernetesVersions(options) - if err != nil { - return fmt.Errorf("render Kubernetes versions: %w", err) + if options.KubernetesVersions != nil && len(*options.KubernetesVersions) != 0 { + kubernetesVersionsTable, err := buildKubernetesVersionsTable(options) + if err != nil { + return fmt.Errorf("build Kubernetes versions table: %w", err) + } + content = append(content, kubernetesVersionsTable) + } + + if options.MachineImages != nil && len(*options.MachineImages) != 0 { + content = append(content, buildMachineImagesTable(options)) } - content += kubernetesVersionsRendered - content += renderMachineImages(options) - content += renderMachineTypes(options) - content += renderVolumeTypes(options) + if options.MachineTypes != nil && len(*options.MachineTypes) != 0 { + content = append(content, buildMachineTypesTable(options)) + } - err = p.PagerDisplay(content) + if options.VolumeTypes != nil && len(*options.VolumeTypes) != 0 { + content = append(content, buildVolumeTypesTable(options)) + } + + err := tables.DisplayTables(p, content) if err != nil { return fmt.Errorf("display output: %w", err) } @@ -199,11 +211,7 @@ func outputResultAsTable(p *print.Printer, options *ske.ProviderOptions) error { return nil } -func renderAvailabilityZones(resp *ske.ProviderOptions) string { - if resp.AvailabilityZones == nil { - return "" - } - +func buildAvailabilityZonesTable(resp *ske.ProviderOptions) tables.Table { zones := *resp.AvailabilityZones table := tables.NewTable() @@ -213,14 +221,10 @@ func renderAvailabilityZones(resp *ske.ProviderOptions) string { z := zones[i] table.AddRow(*z.Name) } - return table.Render() + return table } -func renderKubernetesVersions(resp *ske.ProviderOptions) (string, error) { - if resp.KubernetesVersions == nil { - return "", nil - } - +func buildKubernetesVersionsTable(resp *ske.ProviderOptions) (tables.Table, error) { versions := *resp.KubernetesVersions table := tables.NewTable() @@ -230,7 +234,7 @@ func renderKubernetesVersions(resp *ske.ProviderOptions) (string, error) { v := versions[i] featureGate, err := json.Marshal(*v.FeatureGates) if err != nil { - return "", fmt.Errorf("marshal featureGates of Kubernetes version %q: %w", *v.Version, err) + return table, fmt.Errorf("marshal featureGates of Kubernetes version %q: %w", *v.Version, err) } expirationDate := "" if v.ExpirationDate != nil { @@ -238,14 +242,10 @@ func renderKubernetesVersions(resp *ske.ProviderOptions) (string, error) { } table.AddRow(*v.Version, *v.State, expirationDate, string(featureGate)) } - return table.Render(), nil + return table, nil } -func renderMachineImages(resp *ske.ProviderOptions) string { - if resp.MachineImages == nil { - return "" - } - +func buildMachineImagesTable(resp *ske.ProviderOptions) tables.Table { images := *resp.MachineImages table := tables.NewTable() @@ -271,14 +271,10 @@ func renderMachineImages(resp *ske.ProviderOptions) string { } } table.EnableAutoMergeOnColumns(1) - return table.Render() + return table } -func renderMachineTypes(resp *ske.ProviderOptions) string { - if resp.MachineTypes == nil { - return "" - } - +func buildMachineTypesTable(resp *ske.ProviderOptions) tables.Table { types := *resp.MachineTypes table := tables.NewTable() @@ -288,14 +284,10 @@ func renderMachineTypes(resp *ske.ProviderOptions) string { t := types[i] table.AddRow(*t.Name, *t.Cpu, *t.Memory) } - return table.Render() + return table } -func renderVolumeTypes(resp *ske.ProviderOptions) string { - if resp.VolumeTypes == nil { - return "" - } - +func buildVolumeTypesTable(resp *ske.ProviderOptions) tables.Table { types := *resp.VolumeTypes table := tables.NewTable() @@ -305,5 +297,5 @@ func renderVolumeTypes(resp *ske.ProviderOptions) string { z := types[i] table.AddRow(*z.Name) } - return table.Render() + return table } diff --git a/internal/pkg/tables/tables.go b/internal/pkg/tables/tables.go index de8e0b397..19f1eacd2 100644 --- a/internal/pkg/tables/tables.go +++ b/internal/pkg/tables/tables.go @@ -78,3 +78,14 @@ func (t *Table) Render() string { func (t *Table) Display(p *print.Printer) error { return p.PagerDisplay(t.Render()) } + +// Displays multiple tables in the command's stdout +func DisplayTables(p *print.Printer, tables []Table) error { + renderedTables := "" + + for _, t := range tables { + renderedTables += t.Render() + } + + return p.PagerDisplay(renderedTables) +} From 5ba6565ed25409e166d56cbf90732537388d79db Mon Sep 17 00:00:00 2001 From: Marcel <72880145+marceljk@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:05:53 +0100 Subject: [PATCH 140/619] Onboard "region" global flag for region-specific requests (#550) * Add "region" global flag and set/unset option of "region" * Replace hardcoded region in client configuration with the value from the "region" flag * Update docs --- docs/stackit.md | 1 + docs/stackit_auth.md | 1 + docs/stackit_auth_activate-service-account.md | 1 + docs/stackit_auth_login.md | 1 + docs/stackit_auth_logout.md | 1 + docs/stackit_beta.md | 1 + docs/stackit_beta_key-pair.md | 1 + docs/stackit_beta_key-pair_create.md | 1 + docs/stackit_beta_key-pair_delete.md | 1 + docs/stackit_beta_key-pair_describe.md | 1 + docs/stackit_beta_key-pair_list.md | 1 + docs/stackit_beta_key-pair_update.md | 1 + docs/stackit_beta_network-area.md | 1 + docs/stackit_beta_network-area_create.md | 1 + docs/stackit_beta_network-area_delete.md | 1 + docs/stackit_beta_network-area_describe.md | 1 + docs/stackit_beta_network-area_list.md | 1 + docs/stackit_beta_network-area_network-range.md | 1 + docs/stackit_beta_network-area_network-range_create.md | 1 + docs/stackit_beta_network-area_network-range_delete.md | 1 + docs/stackit_beta_network-area_network-range_describe.md | 1 + docs/stackit_beta_network-area_network-range_list.md | 1 + docs/stackit_beta_network-area_route.md | 1 + docs/stackit_beta_network-area_route_create.md | 1 + docs/stackit_beta_network-area_route_delete.md | 1 + docs/stackit_beta_network-area_route_describe.md | 1 + docs/stackit_beta_network-area_route_list.md | 1 + docs/stackit_beta_network-area_route_update.md | 1 + docs/stackit_beta_network-area_update.md | 1 + docs/stackit_beta_network-interface.md | 1 + docs/stackit_beta_network-interface_create.md | 1 + docs/stackit_beta_network-interface_delete.md | 1 + docs/stackit_beta_network-interface_describe.md | 1 + docs/stackit_beta_network-interface_list.md | 1 + docs/stackit_beta_network-interface_update.md | 1 + docs/stackit_beta_network.md | 1 + docs/stackit_beta_network_create.md | 1 + docs/stackit_beta_network_delete.md | 1 + docs/stackit_beta_network_describe.md | 1 + docs/stackit_beta_network_list.md | 1 + docs/stackit_beta_network_update.md | 1 + docs/stackit_beta_public-ip.md | 1 + docs/stackit_beta_public-ip_associate.md | 1 + docs/stackit_beta_public-ip_create.md | 1 + docs/stackit_beta_public-ip_delete.md | 1 + docs/stackit_beta_public-ip_describe.md | 1 + docs/stackit_beta_public-ip_disassociate.md | 1 + docs/stackit_beta_public-ip_list.md | 1 + docs/stackit_beta_public-ip_update.md | 1 + docs/stackit_beta_security-group.md | 1 + docs/stackit_beta_security-group_create.md | 1 + docs/stackit_beta_security-group_delete.md | 1 + docs/stackit_beta_security-group_describe.md | 1 + docs/stackit_beta_security-group_list.md | 1 + docs/stackit_beta_security-group_rule.md | 1 + docs/stackit_beta_security-group_rule_create.md | 1 + docs/stackit_beta_security-group_rule_delete.md | 1 + docs/stackit_beta_security-group_rule_describe.md | 1 + docs/stackit_beta_security-group_rule_list.md | 1 + docs/stackit_beta_security-group_update.md | 1 + docs/stackit_beta_server.md | 1 + docs/stackit_beta_server_backup.md | 1 + docs/stackit_beta_server_backup_create.md | 1 + docs/stackit_beta_server_backup_delete.md | 1 + docs/stackit_beta_server_backup_describe.md | 1 + docs/stackit_beta_server_backup_disable.md | 1 + docs/stackit_beta_server_backup_enable.md | 1 + docs/stackit_beta_server_backup_list.md | 1 + docs/stackit_beta_server_backup_restore.md | 1 + docs/stackit_beta_server_backup_schedule.md | 1 + docs/stackit_beta_server_backup_schedule_create.md | 1 + docs/stackit_beta_server_backup_schedule_delete.md | 1 + docs/stackit_beta_server_backup_schedule_describe.md | 1 + docs/stackit_beta_server_backup_schedule_list.md | 1 + docs/stackit_beta_server_backup_schedule_update.md | 1 + docs/stackit_beta_server_backup_volume-backup.md | 1 + docs/stackit_beta_server_backup_volume-backup_delete.md | 1 + docs/stackit_beta_server_backup_volume-backup_restore.md | 1 + docs/stackit_beta_server_command.md | 1 + docs/stackit_beta_server_command_create.md | 1 + docs/stackit_beta_server_command_describe.md | 1 + docs/stackit_beta_server_command_list.md | 1 + docs/stackit_beta_server_command_template.md | 1 + docs/stackit_beta_server_command_template_describe.md | 1 + docs/stackit_beta_server_command_template_list.md | 1 + docs/stackit_beta_server_console.md | 1 + docs/stackit_beta_server_create.md | 1 + docs/stackit_beta_server_deallocate.md | 1 + docs/stackit_beta_server_delete.md | 1 + docs/stackit_beta_server_describe.md | 1 + docs/stackit_beta_server_list.md | 1 + docs/stackit_beta_server_log.md | 1 + docs/stackit_beta_server_network-interface.md | 1 + docs/stackit_beta_server_network-interface_attach.md | 1 + docs/stackit_beta_server_network-interface_detach.md | 1 + docs/stackit_beta_server_network-interface_list.md | 1 + docs/stackit_beta_server_public-ip.md | 1 + docs/stackit_beta_server_public-ip_attach.md | 1 + docs/stackit_beta_server_public-ip_detach.md | 1 + docs/stackit_beta_server_reboot.md | 1 + docs/stackit_beta_server_rescue.md | 1 + docs/stackit_beta_server_resize.md | 1 + docs/stackit_beta_server_service-account.md | 1 + docs/stackit_beta_server_service-account_attach.md | 1 + docs/stackit_beta_server_service-account_detach.md | 1 + docs/stackit_beta_server_service-account_list.md | 1 + docs/stackit_beta_server_start.md | 1 + docs/stackit_beta_server_stop.md | 1 + docs/stackit_beta_server_unrescue.md | 1 + docs/stackit_beta_server_update.md | 1 + docs/stackit_beta_server_volume.md | 1 + docs/stackit_beta_server_volume_attach.md | 1 + docs/stackit_beta_server_volume_describe.md | 1 + docs/stackit_beta_server_volume_detach.md | 1 + docs/stackit_beta_server_volume_list.md | 1 + docs/stackit_beta_server_volume_update.md | 1 + docs/stackit_beta_sqlserverflex.md | 1 + docs/stackit_beta_sqlserverflex_database.md | 1 + docs/stackit_beta_sqlserverflex_database_create.md | 1 + docs/stackit_beta_sqlserverflex_database_delete.md | 1 + docs/stackit_beta_sqlserverflex_database_describe.md | 1 + docs/stackit_beta_sqlserverflex_database_list.md | 1 + docs/stackit_beta_sqlserverflex_instance.md | 1 + docs/stackit_beta_sqlserverflex_instance_create.md | 1 + docs/stackit_beta_sqlserverflex_instance_delete.md | 1 + docs/stackit_beta_sqlserverflex_instance_describe.md | 1 + docs/stackit_beta_sqlserverflex_instance_list.md | 1 + docs/stackit_beta_sqlserverflex_instance_update.md | 1 + docs/stackit_beta_sqlserverflex_options.md | 1 + docs/stackit_beta_sqlserverflex_user.md | 1 + docs/stackit_beta_sqlserverflex_user_create.md | 1 + docs/stackit_beta_sqlserverflex_user_delete.md | 1 + docs/stackit_beta_sqlserverflex_user_describe.md | 1 + docs/stackit_beta_sqlserverflex_user_list.md | 1 + docs/stackit_beta_sqlserverflex_user_reset-password.md | 1 + docs/stackit_beta_volume.md | 1 + docs/stackit_beta_volume_create.md | 1 + docs/stackit_beta_volume_delete.md | 1 + docs/stackit_beta_volume_describe.md | 1 + docs/stackit_beta_volume_list.md | 1 + docs/stackit_beta_volume_performance-class.md | 1 + docs/stackit_beta_volume_performance-class_describe.md | 1 + docs/stackit_beta_volume_performance-class_list.md | 1 + docs/stackit_beta_volume_resize.md | 1 + docs/stackit_beta_volume_update.md | 1 + docs/stackit_config.md | 1 + docs/stackit_config_list.md | 1 + docs/stackit_config_profile.md | 1 + docs/stackit_config_profile_create.md | 1 + docs/stackit_config_profile_delete.md | 1 + docs/stackit_config_profile_export.md | 1 + docs/stackit_config_profile_import.md | 1 + docs/stackit_config_profile_list.md | 1 + docs/stackit_config_profile_set.md | 1 + docs/stackit_config_profile_unset.md | 1 + docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + docs/stackit_curl.md | 1 + docs/stackit_dns.md | 1 + docs/stackit_dns_record-set.md | 1 + docs/stackit_dns_record-set_create.md | 1 + docs/stackit_dns_record-set_delete.md | 1 + docs/stackit_dns_record-set_describe.md | 1 + docs/stackit_dns_record-set_list.md | 1 + docs/stackit_dns_record-set_update.md | 1 + docs/stackit_dns_zone.md | 1 + docs/stackit_dns_zone_clone.md | 1 + docs/stackit_dns_zone_create.md | 1 + docs/stackit_dns_zone_delete.md | 1 + docs/stackit_dns_zone_describe.md | 1 + docs/stackit_dns_zone_list.md | 1 + docs/stackit_dns_zone_update.md | 1 + docs/stackit_load-balancer.md | 1 + docs/stackit_load-balancer_create.md | 1 + docs/stackit_load-balancer_delete.md | 1 + docs/stackit_load-balancer_describe.md | 1 + docs/stackit_load-balancer_generate-payload.md | 1 + docs/stackit_load-balancer_list.md | 1 + docs/stackit_load-balancer_observability-credentials.md | 1 + ...tackit_load-balancer_observability-credentials_add.md | 1 + ...it_load-balancer_observability-credentials_cleanup.md | 1 + ...kit_load-balancer_observability-credentials_delete.md | 1 + ...t_load-balancer_observability-credentials_describe.md | 1 + ...ackit_load-balancer_observability-credentials_list.md | 1 + ...kit_load-balancer_observability-credentials_update.md | 1 + docs/stackit_load-balancer_quota.md | 1 + docs/stackit_load-balancer_target-pool.md | 1 + docs/stackit_load-balancer_target-pool_add-target.md | 1 + docs/stackit_load-balancer_target-pool_describe.md | 1 + docs/stackit_load-balancer_target-pool_remove-target.md | 1 + docs/stackit_load-balancer_update.md | 1 + docs/stackit_logme.md | 1 + docs/stackit_logme_credentials.md | 1 + docs/stackit_logme_credentials_create.md | 1 + docs/stackit_logme_credentials_delete.md | 1 + docs/stackit_logme_credentials_describe.md | 1 + docs/stackit_logme_credentials_list.md | 1 + docs/stackit_logme_instance.md | 1 + docs/stackit_logme_instance_create.md | 1 + docs/stackit_logme_instance_delete.md | 1 + docs/stackit_logme_instance_describe.md | 1 + docs/stackit_logme_instance_list.md | 1 + docs/stackit_logme_instance_update.md | 1 + docs/stackit_logme_plans.md | 1 + docs/stackit_mariadb.md | 1 + docs/stackit_mariadb_credentials.md | 1 + docs/stackit_mariadb_credentials_create.md | 1 + docs/stackit_mariadb_credentials_delete.md | 1 + docs/stackit_mariadb_credentials_describe.md | 1 + docs/stackit_mariadb_credentials_list.md | 1 + docs/stackit_mariadb_instance.md | 1 + docs/stackit_mariadb_instance_create.md | 1 + docs/stackit_mariadb_instance_delete.md | 1 + docs/stackit_mariadb_instance_describe.md | 1 + docs/stackit_mariadb_instance_list.md | 1 + docs/stackit_mariadb_instance_update.md | 1 + docs/stackit_mariadb_plans.md | 1 + docs/stackit_mongodbflex.md | 1 + docs/stackit_mongodbflex_backup.md | 1 + docs/stackit_mongodbflex_backup_describe.md | 1 + docs/stackit_mongodbflex_backup_list.md | 1 + docs/stackit_mongodbflex_backup_restore-jobs.md | 1 + docs/stackit_mongodbflex_backup_restore.md | 1 + docs/stackit_mongodbflex_backup_schedule.md | 1 + docs/stackit_mongodbflex_backup_update-schedule.md | 1 + docs/stackit_mongodbflex_instance.md | 1 + docs/stackit_mongodbflex_instance_create.md | 1 + docs/stackit_mongodbflex_instance_delete.md | 1 + docs/stackit_mongodbflex_instance_describe.md | 1 + docs/stackit_mongodbflex_instance_list.md | 1 + docs/stackit_mongodbflex_instance_update.md | 1 + docs/stackit_mongodbflex_options.md | 1 + docs/stackit_mongodbflex_user.md | 1 + docs/stackit_mongodbflex_user_create.md | 1 + docs/stackit_mongodbflex_user_delete.md | 1 + docs/stackit_mongodbflex_user_describe.md | 1 + docs/stackit_mongodbflex_user_list.md | 1 + docs/stackit_mongodbflex_user_reset-password.md | 1 + docs/stackit_mongodbflex_user_update.md | 1 + docs/stackit_object-storage.md | 1 + docs/stackit_object-storage_bucket.md | 1 + docs/stackit_object-storage_bucket_create.md | 1 + docs/stackit_object-storage_bucket_delete.md | 1 + docs/stackit_object-storage_bucket_describe.md | 1 + docs/stackit_object-storage_bucket_list.md | 1 + docs/stackit_object-storage_credentials-group.md | 1 + docs/stackit_object-storage_credentials-group_create.md | 1 + docs/stackit_object-storage_credentials-group_delete.md | 1 + docs/stackit_object-storage_credentials-group_list.md | 1 + docs/stackit_object-storage_credentials.md | 1 + docs/stackit_object-storage_credentials_create.md | 1 + docs/stackit_object-storage_credentials_delete.md | 1 + docs/stackit_object-storage_credentials_list.md | 1 + docs/stackit_object-storage_disable.md | 1 + docs/stackit_object-storage_enable.md | 1 + docs/stackit_observability.md | 1 + docs/stackit_observability_credentials.md | 1 + docs/stackit_observability_credentials_create.md | 1 + docs/stackit_observability_credentials_delete.md | 1 + docs/stackit_observability_credentials_list.md | 1 + docs/stackit_observability_grafana.md | 1 + docs/stackit_observability_grafana_describe.md | 1 + docs/stackit_observability_grafana_public-read-access.md | 1 + ...t_observability_grafana_public-read-access_disable.md | 1 + ...it_observability_grafana_public-read-access_enable.md | 1 + docs/stackit_observability_grafana_single-sign-on.md | 1 + ...ackit_observability_grafana_single-sign-on_disable.md | 1 + ...tackit_observability_grafana_single-sign-on_enable.md | 1 + docs/stackit_observability_instance.md | 1 + docs/stackit_observability_instance_create.md | 1 + docs/stackit_observability_instance_delete.md | 1 + docs/stackit_observability_instance_describe.md | 1 + docs/stackit_observability_instance_list.md | 1 + docs/stackit_observability_instance_update.md | 1 + docs/stackit_observability_plans.md | 1 + docs/stackit_observability_scrape-config.md | 1 + docs/stackit_observability_scrape-config_create.md | 1 + docs/stackit_observability_scrape-config_delete.md | 1 + docs/stackit_observability_scrape-config_describe.md | 1 + ...ackit_observability_scrape-config_generate-payload.md | 1 + docs/stackit_observability_scrape-config_list.md | 1 + docs/stackit_observability_scrape-config_update.md | 1 + docs/stackit_opensearch.md | 1 + docs/stackit_opensearch_credentials.md | 1 + docs/stackit_opensearch_credentials_create.md | 1 + docs/stackit_opensearch_credentials_delete.md | 1 + docs/stackit_opensearch_credentials_describe.md | 1 + docs/stackit_opensearch_credentials_list.md | 1 + docs/stackit_opensearch_instance.md | 1 + docs/stackit_opensearch_instance_create.md | 1 + docs/stackit_opensearch_instance_delete.md | 1 + docs/stackit_opensearch_instance_describe.md | 1 + docs/stackit_opensearch_instance_list.md | 1 + docs/stackit_opensearch_instance_update.md | 1 + docs/stackit_opensearch_plans.md | 1 + docs/stackit_organization.md | 1 + docs/stackit_organization_member.md | 1 + docs/stackit_organization_member_add.md | 1 + docs/stackit_organization_member_list.md | 1 + docs/stackit_organization_member_remove.md | 1 + docs/stackit_organization_role.md | 1 + docs/stackit_organization_role_list.md | 1 + docs/stackit_postgresflex.md | 1 + docs/stackit_postgresflex_backup.md | 1 + docs/stackit_postgresflex_backup_describe.md | 1 + docs/stackit_postgresflex_backup_list.md | 1 + docs/stackit_postgresflex_backup_update-schedule.md | 1 + docs/stackit_postgresflex_instance.md | 1 + docs/stackit_postgresflex_instance_clone.md | 1 + docs/stackit_postgresflex_instance_create.md | 1 + docs/stackit_postgresflex_instance_delete.md | 1 + docs/stackit_postgresflex_instance_describe.md | 1 + docs/stackit_postgresflex_instance_list.md | 1 + docs/stackit_postgresflex_instance_update.md | 1 + docs/stackit_postgresflex_options.md | 1 + docs/stackit_postgresflex_user.md | 1 + docs/stackit_postgresflex_user_create.md | 1 + docs/stackit_postgresflex_user_delete.md | 1 + docs/stackit_postgresflex_user_describe.md | 1 + docs/stackit_postgresflex_user_list.md | 1 + docs/stackit_postgresflex_user_reset-password.md | 1 + docs/stackit_postgresflex_user_update.md | 1 + docs/stackit_project.md | 1 + docs/stackit_project_create.md | 1 + docs/stackit_project_delete.md | 1 + docs/stackit_project_describe.md | 1 + docs/stackit_project_list.md | 1 + docs/stackit_project_member.md | 1 + docs/stackit_project_member_add.md | 1 + docs/stackit_project_member_list.md | 1 + docs/stackit_project_member_remove.md | 1 + docs/stackit_project_role.md | 1 + docs/stackit_project_role_list.md | 1 + docs/stackit_project_update.md | 1 + docs/stackit_rabbitmq.md | 1 + docs/stackit_rabbitmq_credentials.md | 1 + docs/stackit_rabbitmq_credentials_create.md | 1 + docs/stackit_rabbitmq_credentials_delete.md | 1 + docs/stackit_rabbitmq_credentials_describe.md | 1 + docs/stackit_rabbitmq_credentials_list.md | 1 + docs/stackit_rabbitmq_instance.md | 1 + docs/stackit_rabbitmq_instance_create.md | 1 + docs/stackit_rabbitmq_instance_delete.md | 1 + docs/stackit_rabbitmq_instance_describe.md | 1 + docs/stackit_rabbitmq_instance_list.md | 1 + docs/stackit_rabbitmq_instance_update.md | 1 + docs/stackit_rabbitmq_plans.md | 1 + docs/stackit_redis.md | 1 + docs/stackit_redis_credentials.md | 1 + docs/stackit_redis_credentials_create.md | 1 + docs/stackit_redis_credentials_delete.md | 1 + docs/stackit_redis_credentials_describe.md | 1 + docs/stackit_redis_credentials_list.md | 1 + docs/stackit_redis_instance.md | 1 + docs/stackit_redis_instance_create.md | 1 + docs/stackit_redis_instance_delete.md | 1 + docs/stackit_redis_instance_describe.md | 1 + docs/stackit_redis_instance_list.md | 1 + docs/stackit_redis_instance_update.md | 1 + docs/stackit_redis_plans.md | 1 + docs/stackit_secrets-manager.md | 1 + docs/stackit_secrets-manager_instance.md | 1 + docs/stackit_secrets-manager_instance_create.md | 1 + docs/stackit_secrets-manager_instance_delete.md | 1 + docs/stackit_secrets-manager_instance_describe.md | 1 + docs/stackit_secrets-manager_instance_list.md | 1 + docs/stackit_secrets-manager_instance_update.md | 1 + docs/stackit_secrets-manager_user.md | 1 + docs/stackit_secrets-manager_user_create.md | 1 + docs/stackit_secrets-manager_user_delete.md | 1 + docs/stackit_secrets-manager_user_describe.md | 1 + docs/stackit_secrets-manager_user_list.md | 1 + docs/stackit_secrets-manager_user_update.md | 1 + docs/stackit_service-account.md | 1 + docs/stackit_service-account_create.md | 1 + docs/stackit_service-account_delete.md | 1 + docs/stackit_service-account_get-jwks.md | 1 + docs/stackit_service-account_key.md | 1 + docs/stackit_service-account_key_create.md | 1 + docs/stackit_service-account_key_delete.md | 1 + docs/stackit_service-account_key_describe.md | 1 + docs/stackit_service-account_key_list.md | 1 + docs/stackit_service-account_key_update.md | 1 + docs/stackit_service-account_list.md | 1 + docs/stackit_service-account_token.md | 1 + docs/stackit_service-account_token_create.md | 1 + docs/stackit_service-account_token_list.md | 1 + docs/stackit_service-account_token_revoke.md | 1 + docs/stackit_ske.md | 1 + docs/stackit_ske_cluster.md | 1 + docs/stackit_ske_cluster_create.md | 1 + docs/stackit_ske_cluster_delete.md | 1 + docs/stackit_ske_cluster_describe.md | 1 + docs/stackit_ske_cluster_generate-payload.md | 1 + docs/stackit_ske_cluster_list.md | 1 + docs/stackit_ske_cluster_update.md | 1 + docs/stackit_ske_credentials.md | 1 + docs/stackit_ske_credentials_complete-rotation.md | 1 + docs/stackit_ske_credentials_start-rotation.md | 1 + docs/stackit_ske_describe.md | 1 + docs/stackit_ske_disable.md | 1 + docs/stackit_ske_enable.md | 1 + docs/stackit_ske_kubeconfig.md | 1 + docs/stackit_ske_kubeconfig_create.md | 1 + docs/stackit_ske_kubeconfig_login.md | 1 + docs/stackit_ske_options.md | 1 + internal/cmd/config/unset/unset.go | 7 +++++++ internal/pkg/config/config.go | 4 ++++ internal/pkg/globalflags/global_flags.go | 9 +++++++++ internal/pkg/services/iaas/client/client.go | 3 ++- internal/pkg/services/load-balancer/client/client.go | 3 ++- internal/pkg/services/logme/client/client.go | 3 ++- internal/pkg/services/mariadb/client/client.go | 3 ++- internal/pkg/services/mongodbflex/client/client.go | 3 ++- internal/pkg/services/object-storage/client/client.go | 3 ++- internal/pkg/services/observability/client/client.go | 3 ++- internal/pkg/services/opensearch/client/client.go | 3 ++- internal/pkg/services/postgresflex/client/client.go | 3 ++- internal/pkg/services/rabbitmq/client/client.go | 3 ++- internal/pkg/services/redis/client/client.go | 3 ++- internal/pkg/services/runcommand/client/client.go | 3 ++- internal/pkg/services/secrets-manager/client/client.go | 3 ++- internal/pkg/services/serverbackup/client/client.go | 3 ++- .../pkg/services/service-enablement/client/client.go | 3 ++- internal/pkg/services/ske/client/client.go | 3 ++- internal/pkg/services/sqlserverflex/client/client.go | 3 ++- 426 files changed, 460 insertions(+), 17 deletions(-) diff --git a/docs/stackit.md b/docs/stackit.md index 8ec49c754..f7ba5cb48 100644 --- a/docs/stackit.md +++ b/docs/stackit.md @@ -20,6 +20,7 @@ stackit [flags] -h, --help Help for "stackit" -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") -v, --version Show "stackit" version ``` diff --git a/docs/stackit_auth.md b/docs/stackit_auth.md index 9561fb5ae..5c891583a 100644 --- a/docs/stackit_auth.md +++ b/docs/stackit_auth.md @@ -23,6 +23,7 @@ stackit auth [flags] --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") ``` diff --git a/docs/stackit_auth_activate-service-account.md b/docs/stackit_auth_activate-service-account.md index e39102530..8e8b7ac81 100644 --- a/docs/stackit_auth_activate-service-account.md +++ b/docs/stackit_auth_activate-service-account.md @@ -41,6 +41,7 @@ stackit auth activate-service-account [flags] --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") ``` diff --git a/docs/stackit_auth_login.md b/docs/stackit_auth_login.md index 5175c94b6..8b08bc947 100644 --- a/docs/stackit_auth_login.md +++ b/docs/stackit_auth_login.md @@ -31,6 +31,7 @@ stackit auth login [flags] --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") ``` diff --git a/docs/stackit_auth_logout.md b/docs/stackit_auth_logout.md index 8e9cdf8f1..4361a9925 100644 --- a/docs/stackit_auth_logout.md +++ b/docs/stackit_auth_logout.md @@ -30,6 +30,7 @@ stackit auth logout [flags] --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") ``` diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index b89e3dbbe..d27cf4df6 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -34,6 +34,7 @@ stackit beta [flags] --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") ``` diff --git a/docs/stackit_beta_key-pair.md b/docs/stackit_beta_key-pair.md index dfbdaa355..49b9a7a77 100644 --- a/docs/stackit_beta_key-pair.md +++ b/docs/stackit_beta_key-pair.md @@ -23,6 +23,7 @@ stackit beta key-pair [flags] --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") ``` diff --git a/docs/stackit_beta_key-pair_create.md b/docs/stackit_beta_key-pair_create.md index 72ce7dfdf..4ddc33586 100644 --- a/docs/stackit_beta_key-pair_create.md +++ b/docs/stackit_beta_key-pair_create.md @@ -42,6 +42,7 @@ stackit beta key-pair create [flags] --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") ``` diff --git a/docs/stackit_beta_key-pair_delete.md b/docs/stackit_beta_key-pair_delete.md index 5782405ea..b998b9cd9 100644 --- a/docs/stackit_beta_key-pair_delete.md +++ b/docs/stackit_beta_key-pair_delete.md @@ -30,6 +30,7 @@ stackit beta key-pair delete KEY_PAIR_NAME [flags] --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") ``` diff --git a/docs/stackit_beta_key-pair_describe.md b/docs/stackit_beta_key-pair_describe.md index 49ce675b5..5275e8c37 100644 --- a/docs/stackit_beta_key-pair_describe.md +++ b/docs/stackit_beta_key-pair_describe.md @@ -34,6 +34,7 @@ stackit beta key-pair describe KEY_PAIR_NAME [flags] --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") ``` diff --git a/docs/stackit_beta_key-pair_list.md b/docs/stackit_beta_key-pair_list.md index 8b04bdbe2..c77f3fee1 100644 --- a/docs/stackit_beta_key-pair_list.md +++ b/docs/stackit_beta_key-pair_list.md @@ -41,6 +41,7 @@ stackit beta key-pair list [flags] --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") ``` diff --git a/docs/stackit_beta_key-pair_update.md b/docs/stackit_beta_key-pair_update.md index 0170c9c2f..8735cb03c 100644 --- a/docs/stackit_beta_key-pair_update.md +++ b/docs/stackit_beta_key-pair_update.md @@ -31,6 +31,7 @@ stackit beta key-pair update KEY_PAIR_NAME [flags] --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") ``` diff --git a/docs/stackit_beta_network-area.md b/docs/stackit_beta_network-area.md index 793bb2cd4..3cee4fbbb 100644 --- a/docs/stackit_beta_network-area.md +++ b/docs/stackit_beta_network-area.md @@ -23,6 +23,7 @@ stackit beta network-area [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_create.md b/docs/stackit_beta_network-area_create.md index decb37c1e..ed018d657 100644 --- a/docs/stackit_beta_network-area_create.md +++ b/docs/stackit_beta_network-area_create.md @@ -44,6 +44,7 @@ stackit beta network-area create [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_delete.md b/docs/stackit_beta_network-area_delete.md index 14e65e8e8..0d9a2d8ef 100644 --- a/docs/stackit_beta_network-area_delete.md +++ b/docs/stackit_beta_network-area_delete.md @@ -33,6 +33,7 @@ stackit beta network-area delete AREA_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_describe.md b/docs/stackit_beta_network-area_describe.md index ef3b9e690..985dd3e51 100644 --- a/docs/stackit_beta_network-area_describe.md +++ b/docs/stackit_beta_network-area_describe.md @@ -38,6 +38,7 @@ stackit beta network-area describe AREA_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_list.md b/docs/stackit_beta_network-area_list.md index d7a4861fe..a76462e33 100644 --- a/docs/stackit_beta_network-area_list.md +++ b/docs/stackit_beta_network-area_list.md @@ -38,6 +38,7 @@ stackit beta network-area list [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_network-range.md b/docs/stackit_beta_network-area_network-range.md index 3c4ab566f..a93af6120 100644 --- a/docs/stackit_beta_network-area_network-range.md +++ b/docs/stackit_beta_network-area_network-range.md @@ -23,6 +23,7 @@ stackit beta network-area network-range [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_network-range_create.md b/docs/stackit_beta_network-area_network-range_create.md index 2bb284744..43cd57c8f 100644 --- a/docs/stackit_beta_network-area_network-range_create.md +++ b/docs/stackit_beta_network-area_network-range_create.md @@ -33,6 +33,7 @@ stackit beta network-area network-range create [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_network-range_delete.md b/docs/stackit_beta_network-area_network-range_delete.md index 225713bfc..f9c6bf043 100644 --- a/docs/stackit_beta_network-area_network-range_delete.md +++ b/docs/stackit_beta_network-area_network-range_delete.md @@ -32,6 +32,7 @@ stackit beta network-area network-range delete NETWORK_RANGE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_network-range_describe.md b/docs/stackit_beta_network-area_network-range_describe.md index 7d6292464..021805445 100644 --- a/docs/stackit_beta_network-area_network-range_describe.md +++ b/docs/stackit_beta_network-area_network-range_describe.md @@ -32,6 +32,7 @@ stackit beta network-area network-range describe NETWORK_RANGE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_network-range_list.md b/docs/stackit_beta_network-area_network-range_list.md index 0bd85ee5e..75a599d51 100644 --- a/docs/stackit_beta_network-area_network-range_list.md +++ b/docs/stackit_beta_network-area_network-range_list.md @@ -39,6 +39,7 @@ stackit beta network-area network-range list [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_route.md b/docs/stackit_beta_network-area_route.md index 767afefe3..d107ddab2 100644 --- a/docs/stackit_beta_network-area_route.md +++ b/docs/stackit_beta_network-area_route.md @@ -23,6 +23,7 @@ stackit beta network-area route [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_route_create.md b/docs/stackit_beta_network-area_route_create.md index 41a7d30c1..787e5dff5 100644 --- a/docs/stackit_beta_network-area_route_create.md +++ b/docs/stackit_beta_network-area_route_create.md @@ -40,6 +40,7 @@ stackit beta network-area route create [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_route_delete.md b/docs/stackit_beta_network-area_route_delete.md index adfdf1d10..9e9eef46c 100644 --- a/docs/stackit_beta_network-area_route_delete.md +++ b/docs/stackit_beta_network-area_route_delete.md @@ -32,6 +32,7 @@ stackit beta network-area route delete ROUTE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_route_describe.md b/docs/stackit_beta_network-area_route_describe.md index 838ed9ced..0cc8d9ca4 100644 --- a/docs/stackit_beta_network-area_route_describe.md +++ b/docs/stackit_beta_network-area_route_describe.md @@ -35,6 +35,7 @@ stackit beta network-area route describe ROUTE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_route_list.md b/docs/stackit_beta_network-area_route_list.md index b4228f464..e3181ff69 100644 --- a/docs/stackit_beta_network-area_route_list.md +++ b/docs/stackit_beta_network-area_route_list.md @@ -39,6 +39,7 @@ stackit beta network-area route list [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_route_update.md b/docs/stackit_beta_network-area_route_update.md index 0fee0b1d5..4f9fc4e2a 100644 --- a/docs/stackit_beta_network-area_route_update.md +++ b/docs/stackit_beta_network-area_route_update.md @@ -35,6 +35,7 @@ stackit beta network-area route update ROUTE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-area_update.md b/docs/stackit_beta_network-area_update.md index b1c591c1a..3616afaef 100644 --- a/docs/stackit_beta_network-area_update.md +++ b/docs/stackit_beta_network-area_update.md @@ -36,6 +36,7 @@ stackit beta network-area update AREA_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-interface.md b/docs/stackit_beta_network-interface.md index 1d46a14e6..920b310a7 100644 --- a/docs/stackit_beta_network-interface.md +++ b/docs/stackit_beta_network-interface.md @@ -23,6 +23,7 @@ stackit beta network-interface [flags] --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") ``` diff --git a/docs/stackit_beta_network-interface_create.md b/docs/stackit_beta_network-interface_create.md index a9bf2c2d3..87914073a 100644 --- a/docs/stackit_beta_network-interface_create.md +++ b/docs/stackit_beta_network-interface_create.md @@ -41,6 +41,7 @@ stackit beta network-interface create [flags] --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") ``` diff --git a/docs/stackit_beta_network-interface_delete.md b/docs/stackit_beta_network-interface_delete.md index 5b7b81abd..a6047d548 100644 --- a/docs/stackit_beta_network-interface_delete.md +++ b/docs/stackit_beta_network-interface_delete.md @@ -31,6 +31,7 @@ stackit beta network-interface delete NIC_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-interface_describe.md b/docs/stackit_beta_network-interface_describe.md index 2e316d691..a5940b7cd 100644 --- a/docs/stackit_beta_network-interface_describe.md +++ b/docs/stackit_beta_network-interface_describe.md @@ -37,6 +37,7 @@ stackit beta network-interface describe NIC_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network-interface_list.md b/docs/stackit_beta_network-interface_list.md index 12e76737b..4e5272349 100644 --- a/docs/stackit_beta_network-interface_list.md +++ b/docs/stackit_beta_network-interface_list.md @@ -42,6 +42,7 @@ stackit beta network-interface list [flags] --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") ``` diff --git a/docs/stackit_beta_network-interface_update.md b/docs/stackit_beta_network-interface_update.md index 136905c05..e9c1b6ec7 100644 --- a/docs/stackit_beta_network-interface_update.md +++ b/docs/stackit_beta_network-interface_update.md @@ -42,6 +42,7 @@ stackit beta network-interface update NIC_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network.md b/docs/stackit_beta_network.md index 0a5636c39..78bf7e4d1 100644 --- a/docs/stackit_beta_network.md +++ b/docs/stackit_beta_network.md @@ -23,6 +23,7 @@ stackit beta network [flags] --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") ``` diff --git a/docs/stackit_beta_network_create.md b/docs/stackit_beta_network_create.md index 6b7df5370..11e816773 100644 --- a/docs/stackit_beta_network_create.md +++ b/docs/stackit_beta_network_create.md @@ -54,6 +54,7 @@ stackit beta network create [flags] --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") ``` diff --git a/docs/stackit_beta_network_delete.md b/docs/stackit_beta_network_delete.md index 7992621a9..e3c76d9d7 100644 --- a/docs/stackit_beta_network_delete.md +++ b/docs/stackit_beta_network_delete.md @@ -32,6 +32,7 @@ stackit beta network delete NETWORK_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network_describe.md b/docs/stackit_beta_network_describe.md index ccac8a132..cad1ecd51 100644 --- a/docs/stackit_beta_network_describe.md +++ b/docs/stackit_beta_network_describe.md @@ -33,6 +33,7 @@ stackit beta network describe NETWORK_ID [flags] --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") ``` diff --git a/docs/stackit_beta_network_list.md b/docs/stackit_beta_network_list.md index 5d5aef8b3..0aa13029c 100644 --- a/docs/stackit_beta_network_list.md +++ b/docs/stackit_beta_network_list.md @@ -37,6 +37,7 @@ stackit beta network list [flags] --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") ``` diff --git a/docs/stackit_beta_network_update.md b/docs/stackit_beta_network_update.md index 484168086..24b1326d2 100644 --- a/docs/stackit_beta_network_update.md +++ b/docs/stackit_beta_network_update.md @@ -46,6 +46,7 @@ stackit beta network update NETWORK_ID [flags] --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") ``` diff --git a/docs/stackit_beta_public-ip.md b/docs/stackit_beta_public-ip.md index 8d4ff0737..53811f4f4 100644 --- a/docs/stackit_beta_public-ip.md +++ b/docs/stackit_beta_public-ip.md @@ -23,6 +23,7 @@ stackit beta public-ip [flags] --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") ``` diff --git a/docs/stackit_beta_public-ip_associate.md b/docs/stackit_beta_public-ip_associate.md index 19e9d87b7..0eaf2f6b4 100644 --- a/docs/stackit_beta_public-ip_associate.md +++ b/docs/stackit_beta_public-ip_associate.md @@ -31,6 +31,7 @@ stackit beta public-ip associate PUBLIC_IP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_public-ip_create.md b/docs/stackit_beta_public-ip_create.md index 03399d78e..023de706d 100644 --- a/docs/stackit_beta_public-ip_create.md +++ b/docs/stackit_beta_public-ip_create.md @@ -38,6 +38,7 @@ stackit beta public-ip create [flags] --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") ``` diff --git a/docs/stackit_beta_public-ip_delete.md b/docs/stackit_beta_public-ip_delete.md index 1052b0445..265df7727 100644 --- a/docs/stackit_beta_public-ip_delete.md +++ b/docs/stackit_beta_public-ip_delete.md @@ -32,6 +32,7 @@ stackit beta public-ip delete PUBLIC_IP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_public-ip_describe.md b/docs/stackit_beta_public-ip_describe.md index 9ff1b5a1c..9925d2602 100644 --- a/docs/stackit_beta_public-ip_describe.md +++ b/docs/stackit_beta_public-ip_describe.md @@ -33,6 +33,7 @@ stackit beta public-ip describe PUBLIC_IP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_public-ip_disassociate.md b/docs/stackit_beta_public-ip_disassociate.md index cf11a2ee1..d26de87f0 100644 --- a/docs/stackit_beta_public-ip_disassociate.md +++ b/docs/stackit_beta_public-ip_disassociate.md @@ -30,6 +30,7 @@ stackit beta public-ip disassociate PUBLIC_IP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_public-ip_list.md b/docs/stackit_beta_public-ip_list.md index 7e237c8c8..845a82973 100644 --- a/docs/stackit_beta_public-ip_list.md +++ b/docs/stackit_beta_public-ip_list.md @@ -41,6 +41,7 @@ stackit beta public-ip list [flags] --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") ``` diff --git a/docs/stackit_beta_public-ip_update.md b/docs/stackit_beta_public-ip_update.md index c2ed8a2f9..4344b32a4 100644 --- a/docs/stackit_beta_public-ip_update.md +++ b/docs/stackit_beta_public-ip_update.md @@ -34,6 +34,7 @@ stackit beta public-ip update PUBLIC_IP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_security-group.md b/docs/stackit_beta_security-group.md index 0c3954e95..88b2b69ac 100644 --- a/docs/stackit_beta_security-group.md +++ b/docs/stackit_beta_security-group.md @@ -23,6 +23,7 @@ stackit beta security-group [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_create.md b/docs/stackit_beta_security-group_create.md index e2ebd9b21..4c806e71b 100644 --- a/docs/stackit_beta_security-group_create.md +++ b/docs/stackit_beta_security-group_create.md @@ -37,6 +37,7 @@ stackit beta security-group create [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_delete.md b/docs/stackit_beta_security-group_delete.md index fd4a74191..ce64513cb 100644 --- a/docs/stackit_beta_security-group_delete.md +++ b/docs/stackit_beta_security-group_delete.md @@ -30,6 +30,7 @@ stackit beta security-group delete GROUP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_describe.md b/docs/stackit_beta_security-group_describe.md index 05fa5ec4b..d2a3f9131 100644 --- a/docs/stackit_beta_security-group_describe.md +++ b/docs/stackit_beta_security-group_describe.md @@ -30,6 +30,7 @@ stackit beta security-group describe GROUP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_list.md b/docs/stackit_beta_security-group_list.md index f64f6ec99..c70d22c89 100644 --- a/docs/stackit_beta_security-group_list.md +++ b/docs/stackit_beta_security-group_list.md @@ -34,6 +34,7 @@ stackit beta security-group list [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_rule.md b/docs/stackit_beta_security-group_rule.md index 8d47d0b21..0d53cb64a 100644 --- a/docs/stackit_beta_security-group_rule.md +++ b/docs/stackit_beta_security-group_rule.md @@ -23,6 +23,7 @@ stackit beta security-group rule [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_rule_create.md b/docs/stackit_beta_security-group_rule_create.md index 7fba6fe31..54e40d327 100644 --- a/docs/stackit_beta_security-group_rule_create.md +++ b/docs/stackit_beta_security-group_rule_create.md @@ -51,6 +51,7 @@ stackit beta security-group rule create [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_rule_delete.md b/docs/stackit_beta_security-group_rule_delete.md index 29ac6eb08..9489102a5 100644 --- a/docs/stackit_beta_security-group_rule_delete.md +++ b/docs/stackit_beta_security-group_rule_delete.md @@ -33,6 +33,7 @@ stackit beta security-group rule delete SECURITY_GROUP_RULE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_rule_describe.md b/docs/stackit_beta_security-group_rule_describe.md index 80fdf707b..d23c66138 100644 --- a/docs/stackit_beta_security-group_rule_describe.md +++ b/docs/stackit_beta_security-group_rule_describe.md @@ -34,6 +34,7 @@ stackit beta security-group rule describe SECURITY_GROUP_RULE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_rule_list.md b/docs/stackit_beta_security-group_rule_list.md index 02fef7466..c3ef60e01 100644 --- a/docs/stackit_beta_security-group_rule_list.md +++ b/docs/stackit_beta_security-group_rule_list.md @@ -38,6 +38,7 @@ stackit beta security-group rule list [flags] --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") ``` diff --git a/docs/stackit_beta_security-group_update.md b/docs/stackit_beta_security-group_update.md index 43ca56c33..fa3bad995 100644 --- a/docs/stackit_beta_security-group_update.md +++ b/docs/stackit_beta_security-group_update.md @@ -36,6 +36,7 @@ stackit beta security-group update GROUP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index 6ec25fc7a..d3abb34f4 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -23,6 +23,7 @@ stackit beta server [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup.md b/docs/stackit_beta_server_backup.md index 324a45e9c..232ae497b 100644 --- a/docs/stackit_beta_server_backup.md +++ b/docs/stackit_beta_server_backup.md @@ -23,6 +23,7 @@ stackit beta server backup [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_create.md b/docs/stackit_beta_server_backup_create.md index 734fc5f96..a98bbd909 100644 --- a/docs/stackit_beta_server_backup_create.md +++ b/docs/stackit_beta_server_backup_create.md @@ -37,6 +37,7 @@ stackit beta server backup create [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_delete.md b/docs/stackit_beta_server_backup_delete.md index 681311431..fb5da015b 100644 --- a/docs/stackit_beta_server_backup_delete.md +++ b/docs/stackit_beta_server_backup_delete.md @@ -31,6 +31,7 @@ stackit beta server backup delete BACKUP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_describe.md b/docs/stackit_beta_server_backup_describe.md index 232c6a656..bdd5c4ff6 100644 --- a/docs/stackit_beta_server_backup_describe.md +++ b/docs/stackit_beta_server_backup_describe.md @@ -34,6 +34,7 @@ stackit beta server backup describe BACKUP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_disable.md b/docs/stackit_beta_server_backup_disable.md index 813a3ca15..21766dd43 100644 --- a/docs/stackit_beta_server_backup_disable.md +++ b/docs/stackit_beta_server_backup_disable.md @@ -31,6 +31,7 @@ stackit beta server backup disable [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_enable.md b/docs/stackit_beta_server_backup_enable.md index 0f347dda1..decc76394 100644 --- a/docs/stackit_beta_server_backup_enable.md +++ b/docs/stackit_beta_server_backup_enable.md @@ -31,6 +31,7 @@ stackit beta server backup enable [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_list.md b/docs/stackit_beta_server_backup_list.md index 35940e3b6..1e573787b 100644 --- a/docs/stackit_beta_server_backup_list.md +++ b/docs/stackit_beta_server_backup_list.md @@ -35,6 +35,7 @@ stackit beta server backup list [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_restore.md b/docs/stackit_beta_server_backup_restore.md index c2440165f..8402b25c3 100644 --- a/docs/stackit_beta_server_backup_restore.md +++ b/docs/stackit_beta_server_backup_restore.md @@ -36,6 +36,7 @@ stackit beta server backup restore BACKUP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_schedule.md b/docs/stackit_beta_server_backup_schedule.md index 0acb68691..07e666b18 100644 --- a/docs/stackit_beta_server_backup_schedule.md +++ b/docs/stackit_beta_server_backup_schedule.md @@ -23,6 +23,7 @@ stackit beta server backup schedule [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_schedule_create.md b/docs/stackit_beta_server_backup_schedule_create.md index 216dc17ff..c875687ac 100644 --- a/docs/stackit_beta_server_backup_schedule_create.md +++ b/docs/stackit_beta_server_backup_schedule_create.md @@ -40,6 +40,7 @@ stackit beta server backup schedule create [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_schedule_delete.md b/docs/stackit_beta_server_backup_schedule_delete.md index 4df85027d..44610dc7d 100644 --- a/docs/stackit_beta_server_backup_schedule_delete.md +++ b/docs/stackit_beta_server_backup_schedule_delete.md @@ -31,6 +31,7 @@ stackit beta server backup schedule delete SCHEDULE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_schedule_describe.md b/docs/stackit_beta_server_backup_schedule_describe.md index 0dcd83a5f..95f8d5047 100644 --- a/docs/stackit_beta_server_backup_schedule_describe.md +++ b/docs/stackit_beta_server_backup_schedule_describe.md @@ -34,6 +34,7 @@ stackit beta server backup schedule describe BACKUP_SCHEDULE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_schedule_list.md b/docs/stackit_beta_server_backup_schedule_list.md index 5c53c99ae..89fa03e20 100644 --- a/docs/stackit_beta_server_backup_schedule_list.md +++ b/docs/stackit_beta_server_backup_schedule_list.md @@ -35,6 +35,7 @@ stackit beta server backup schedule list [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_schedule_update.md b/docs/stackit_beta_server_backup_schedule_update.md index a4192f936..a9bcec886 100644 --- a/docs/stackit_beta_server_backup_schedule_update.md +++ b/docs/stackit_beta_server_backup_schedule_update.md @@ -40,6 +40,7 @@ stackit beta server backup schedule update SCHEDULE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_volume-backup.md b/docs/stackit_beta_server_backup_volume-backup.md index 5e1cad643..302577f4a 100644 --- a/docs/stackit_beta_server_backup_volume-backup.md +++ b/docs/stackit_beta_server_backup_volume-backup.md @@ -23,6 +23,7 @@ stackit beta server backup volume-backup [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_volume-backup_delete.md b/docs/stackit_beta_server_backup_volume-backup_delete.md index 7e58424c7..9c4e18a98 100644 --- a/docs/stackit_beta_server_backup_volume-backup_delete.md +++ b/docs/stackit_beta_server_backup_volume-backup_delete.md @@ -32,6 +32,7 @@ stackit beta server backup volume-backup delete VOLUME_BACKUP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_backup_volume-backup_restore.md b/docs/stackit_beta_server_backup_volume-backup_restore.md index c1f6c1be0..784b7c70e 100644 --- a/docs/stackit_beta_server_backup_volume-backup_restore.md +++ b/docs/stackit_beta_server_backup_volume-backup_restore.md @@ -33,6 +33,7 @@ stackit beta server backup volume-backup restore VOLUME_BACKUP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_command.md b/docs/stackit_beta_server_command.md index eaa91d013..8f128f4ec 100644 --- a/docs/stackit_beta_server_command.md +++ b/docs/stackit_beta_server_command.md @@ -23,6 +23,7 @@ stackit beta server command [flags] --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") ``` diff --git a/docs/stackit_beta_server_command_create.md b/docs/stackit_beta_server_command_create.md index 4bc354e96..e91b8e9fa 100644 --- a/docs/stackit_beta_server_command_create.md +++ b/docs/stackit_beta_server_command_create.md @@ -36,6 +36,7 @@ stackit beta server command create [flags] --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") ``` diff --git a/docs/stackit_beta_server_command_describe.md b/docs/stackit_beta_server_command_describe.md index fc1311adb..3f5407c5e 100644 --- a/docs/stackit_beta_server_command_describe.md +++ b/docs/stackit_beta_server_command_describe.md @@ -34,6 +34,7 @@ stackit beta server command describe COMMAND_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_command_list.md b/docs/stackit_beta_server_command_list.md index b5a866aff..dca46c0eb 100644 --- a/docs/stackit_beta_server_command_list.md +++ b/docs/stackit_beta_server_command_list.md @@ -35,6 +35,7 @@ stackit beta server command list [flags] --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") ``` diff --git a/docs/stackit_beta_server_command_template.md b/docs/stackit_beta_server_command_template.md index 0d5de8aa6..2f49f653f 100644 --- a/docs/stackit_beta_server_command_template.md +++ b/docs/stackit_beta_server_command_template.md @@ -23,6 +23,7 @@ stackit beta server command template [flags] --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") ``` diff --git a/docs/stackit_beta_server_command_template_describe.md b/docs/stackit_beta_server_command_template_describe.md index 629d1855a..beab674f4 100644 --- a/docs/stackit_beta_server_command_template_describe.md +++ b/docs/stackit_beta_server_command_template_describe.md @@ -34,6 +34,7 @@ stackit beta server command template describe COMMAND_TEMPLATE_NAME [flags] --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") ``` diff --git a/docs/stackit_beta_server_command_template_list.md b/docs/stackit_beta_server_command_template_list.md index db7f59e44..730f9ad12 100644 --- a/docs/stackit_beta_server_command_template_list.md +++ b/docs/stackit_beta_server_command_template_list.md @@ -34,6 +34,7 @@ stackit beta server command template list [flags] --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") ``` diff --git a/docs/stackit_beta_server_console.md b/docs/stackit_beta_server_console.md index 2b63b6b7b..df3143cea 100644 --- a/docs/stackit_beta_server_console.md +++ b/docs/stackit_beta_server_console.md @@ -33,6 +33,7 @@ stackit beta server console SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_create.md b/docs/stackit_beta_server_create.md index 7f8865139..c98d6895b 100644 --- a/docs/stackit_beta_server_create.md +++ b/docs/stackit_beta_server_create.md @@ -72,6 +72,7 @@ stackit beta server create [flags] --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") ``` diff --git a/docs/stackit_beta_server_deallocate.md b/docs/stackit_beta_server_deallocate.md index b8bb41fb2..c083e1f4a 100644 --- a/docs/stackit_beta_server_deallocate.md +++ b/docs/stackit_beta_server_deallocate.md @@ -30,6 +30,7 @@ stackit beta server deallocate SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_delete.md b/docs/stackit_beta_server_delete.md index 6cce083cf..b25341fde 100644 --- a/docs/stackit_beta_server_delete.md +++ b/docs/stackit_beta_server_delete.md @@ -32,6 +32,7 @@ stackit beta server delete SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_describe.md b/docs/stackit_beta_server_describe.md index 0a8a22bf0..3fb94e9cc 100644 --- a/docs/stackit_beta_server_describe.md +++ b/docs/stackit_beta_server_describe.md @@ -33,6 +33,7 @@ stackit beta server describe SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_list.md b/docs/stackit_beta_server_list.md index f2ed97364..ca0092ffb 100644 --- a/docs/stackit_beta_server_list.md +++ b/docs/stackit_beta_server_list.md @@ -41,6 +41,7 @@ stackit beta server list [flags] --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") ``` diff --git a/docs/stackit_beta_server_log.md b/docs/stackit_beta_server_log.md index 81776e792..0c15a8547 100644 --- a/docs/stackit_beta_server_log.md +++ b/docs/stackit_beta_server_log.md @@ -37,6 +37,7 @@ stackit beta server log SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_network-interface.md b/docs/stackit_beta_server_network-interface.md index 53547f83c..d2029b1e6 100644 --- a/docs/stackit_beta_server_network-interface.md +++ b/docs/stackit_beta_server_network-interface.md @@ -23,6 +23,7 @@ stackit beta server network-interface [flags] --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") ``` diff --git a/docs/stackit_beta_server_network-interface_attach.md b/docs/stackit_beta_server_network-interface_attach.md index e376d5c90..af58fe6c8 100644 --- a/docs/stackit_beta_server_network-interface_attach.md +++ b/docs/stackit_beta_server_network-interface_attach.md @@ -37,6 +37,7 @@ stackit beta server network-interface attach [flags] --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") ``` diff --git a/docs/stackit_beta_server_network-interface_detach.md b/docs/stackit_beta_server_network-interface_detach.md index e90a3165e..f6859346a 100644 --- a/docs/stackit_beta_server_network-interface_detach.md +++ b/docs/stackit_beta_server_network-interface_detach.md @@ -37,6 +37,7 @@ stackit beta server network-interface detach [flags] --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") ``` diff --git a/docs/stackit_beta_server_network-interface_list.md b/docs/stackit_beta_server_network-interface_list.md index 433374769..a184557eb 100644 --- a/docs/stackit_beta_server_network-interface_list.md +++ b/docs/stackit_beta_server_network-interface_list.md @@ -38,6 +38,7 @@ stackit beta server network-interface list [flags] --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") ``` diff --git a/docs/stackit_beta_server_public-ip.md b/docs/stackit_beta_server_public-ip.md index 9cc341e4c..2572a6214 100644 --- a/docs/stackit_beta_server_public-ip.md +++ b/docs/stackit_beta_server_public-ip.md @@ -23,6 +23,7 @@ stackit beta server public-ip [flags] --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") ``` diff --git a/docs/stackit_beta_server_public-ip_attach.md b/docs/stackit_beta_server_public-ip_attach.md index 49152da8d..ce1a537e2 100644 --- a/docs/stackit_beta_server_public-ip_attach.md +++ b/docs/stackit_beta_server_public-ip_attach.md @@ -31,6 +31,7 @@ stackit beta server public-ip attach PUBLIC_IP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_public-ip_detach.md b/docs/stackit_beta_server_public-ip_detach.md index 15ff28399..af84a000a 100644 --- a/docs/stackit_beta_server_public-ip_detach.md +++ b/docs/stackit_beta_server_public-ip_detach.md @@ -31,6 +31,7 @@ stackit beta server public-ip detach PUBLIC_IP_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_reboot.md b/docs/stackit_beta_server_reboot.md index e1f728a77..e425e2f51 100644 --- a/docs/stackit_beta_server_reboot.md +++ b/docs/stackit_beta_server_reboot.md @@ -34,6 +34,7 @@ stackit beta server reboot SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_rescue.md b/docs/stackit_beta_server_rescue.md index 5c81b6d93..06983d133 100644 --- a/docs/stackit_beta_server_rescue.md +++ b/docs/stackit_beta_server_rescue.md @@ -31,6 +31,7 @@ stackit beta server rescue SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_resize.md b/docs/stackit_beta_server_resize.md index ed1f8f3cf..73a94c785 100644 --- a/docs/stackit_beta_server_resize.md +++ b/docs/stackit_beta_server_resize.md @@ -31,6 +31,7 @@ stackit beta server resize SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_service-account.md b/docs/stackit_beta_server_service-account.md index 294f369d9..08509cf0e 100644 --- a/docs/stackit_beta_server_service-account.md +++ b/docs/stackit_beta_server_service-account.md @@ -23,6 +23,7 @@ stackit beta server service-account [flags] --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") ``` diff --git a/docs/stackit_beta_server_service-account_attach.md b/docs/stackit_beta_server_service-account_attach.md index d472569ec..4e0998bf9 100644 --- a/docs/stackit_beta_server_service-account_attach.md +++ b/docs/stackit_beta_server_service-account_attach.md @@ -31,6 +31,7 @@ stackit beta server service-account attach SERVICE_ACCOUNT_EMAIL [flags] --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") ``` diff --git a/docs/stackit_beta_server_service-account_detach.md b/docs/stackit_beta_server_service-account_detach.md index e1ecb569a..7f674e634 100644 --- a/docs/stackit_beta_server_service-account_detach.md +++ b/docs/stackit_beta_server_service-account_detach.md @@ -31,6 +31,7 @@ stackit beta server service-account detach SERVICE_ACCOUNT_EMAIL [flags] --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") ``` diff --git a/docs/stackit_beta_server_service-account_list.md b/docs/stackit_beta_server_service-account_list.md index 64f993e2d..a6fa2498c 100644 --- a/docs/stackit_beta_server_service-account_list.md +++ b/docs/stackit_beta_server_service-account_list.md @@ -38,6 +38,7 @@ stackit beta server service-account list [flags] --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") ``` diff --git a/docs/stackit_beta_server_start.md b/docs/stackit_beta_server_start.md index 48526e4f7..06dd1b651 100644 --- a/docs/stackit_beta_server_start.md +++ b/docs/stackit_beta_server_start.md @@ -30,6 +30,7 @@ stackit beta server start SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_stop.md b/docs/stackit_beta_server_stop.md index 30c32d1b6..51928947f 100644 --- a/docs/stackit_beta_server_stop.md +++ b/docs/stackit_beta_server_stop.md @@ -30,6 +30,7 @@ stackit beta server stop SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_unrescue.md b/docs/stackit_beta_server_unrescue.md index 2143f7b74..573ad1a6e 100644 --- a/docs/stackit_beta_server_unrescue.md +++ b/docs/stackit_beta_server_unrescue.md @@ -30,6 +30,7 @@ stackit beta server unrescue SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_update.md b/docs/stackit_beta_server_update.md index aad88cf33..44b1e3ce4 100644 --- a/docs/stackit_beta_server_update.md +++ b/docs/stackit_beta_server_update.md @@ -35,6 +35,7 @@ stackit beta server update SERVER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_volume.md b/docs/stackit_beta_server_volume.md index 42b0bc958..6bd09c8c1 100644 --- a/docs/stackit_beta_server_volume.md +++ b/docs/stackit_beta_server_volume.md @@ -23,6 +23,7 @@ stackit beta server volume [flags] --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") ``` diff --git a/docs/stackit_beta_server_volume_attach.md b/docs/stackit_beta_server_volume_attach.md index 4ac70301f..89f6fe054 100644 --- a/docs/stackit_beta_server_volume_attach.md +++ b/docs/stackit_beta_server_volume_attach.md @@ -35,6 +35,7 @@ stackit beta server volume attach VOLUME_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_volume_describe.md b/docs/stackit_beta_server_volume_describe.md index e9836eadd..df99e10a1 100644 --- a/docs/stackit_beta_server_volume_describe.md +++ b/docs/stackit_beta_server_volume_describe.md @@ -37,6 +37,7 @@ stackit beta server volume describe VOLUME_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_volume_detach.md b/docs/stackit_beta_server_volume_detach.md index 04519c691..45b72bc30 100644 --- a/docs/stackit_beta_server_volume_detach.md +++ b/docs/stackit_beta_server_volume_detach.md @@ -31,6 +31,7 @@ stackit beta server volume detach VOLUME_ID [flags] --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") ``` diff --git a/docs/stackit_beta_server_volume_list.md b/docs/stackit_beta_server_volume_list.md index 68970d53c..b21e59ca8 100644 --- a/docs/stackit_beta_server_volume_list.md +++ b/docs/stackit_beta_server_volume_list.md @@ -34,6 +34,7 @@ stackit beta server volume list [flags] --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") ``` diff --git a/docs/stackit_beta_server_volume_update.md b/docs/stackit_beta_server_volume_update.md index 29b7b51b6..88f94fe6f 100644 --- a/docs/stackit_beta_server_volume_update.md +++ b/docs/stackit_beta_server_volume_update.md @@ -32,6 +32,7 @@ stackit beta server volume update VOLUME_ID [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex.md b/docs/stackit_beta_sqlserverflex.md index a832ef36e..1e630a067 100644 --- a/docs/stackit_beta_sqlserverflex.md +++ b/docs/stackit_beta_sqlserverflex.md @@ -23,6 +23,7 @@ stackit beta sqlserverflex [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_database.md b/docs/stackit_beta_sqlserverflex_database.md index 60dc3674a..19a1d9052 100644 --- a/docs/stackit_beta_sqlserverflex_database.md +++ b/docs/stackit_beta_sqlserverflex_database.md @@ -23,6 +23,7 @@ stackit beta sqlserverflex database [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_database_create.md b/docs/stackit_beta_sqlserverflex_database_create.md index 4f4fdab41..a34712040 100644 --- a/docs/stackit_beta_sqlserverflex_database_create.md +++ b/docs/stackit_beta_sqlserverflex_database_create.md @@ -33,6 +33,7 @@ stackit beta sqlserverflex database create DATABASE_NAME [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_database_delete.md b/docs/stackit_beta_sqlserverflex_database_delete.md index b2c6bc471..ebd5ab0a1 100644 --- a/docs/stackit_beta_sqlserverflex_database_delete.md +++ b/docs/stackit_beta_sqlserverflex_database_delete.md @@ -32,6 +32,7 @@ stackit beta sqlserverflex database delete DATABASE_NAME [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_database_describe.md b/docs/stackit_beta_sqlserverflex_database_describe.md index 97715ae2b..290284e23 100644 --- a/docs/stackit_beta_sqlserverflex_database_describe.md +++ b/docs/stackit_beta_sqlserverflex_database_describe.md @@ -34,6 +34,7 @@ stackit beta sqlserverflex database describe DATABASE_NAME [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_database_list.md b/docs/stackit_beta_sqlserverflex_database_list.md index 637f262e1..73797c240 100644 --- a/docs/stackit_beta_sqlserverflex_database_list.md +++ b/docs/stackit_beta_sqlserverflex_database_list.md @@ -38,6 +38,7 @@ stackit beta sqlserverflex database list [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_instance.md b/docs/stackit_beta_sqlserverflex_instance.md index 6e6680392..5ab816add 100644 --- a/docs/stackit_beta_sqlserverflex_instance.md +++ b/docs/stackit_beta_sqlserverflex_instance.md @@ -23,6 +23,7 @@ stackit beta sqlserverflex instance [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_instance_create.md b/docs/stackit_beta_sqlserverflex_instance_create.md index 2fc42b52c..99ee21d4c 100644 --- a/docs/stackit_beta_sqlserverflex_instance_create.md +++ b/docs/stackit_beta_sqlserverflex_instance_create.md @@ -47,6 +47,7 @@ stackit beta sqlserverflex instance create [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_instance_delete.md b/docs/stackit_beta_sqlserverflex_instance_delete.md index 376b12278..548bfb952 100644 --- a/docs/stackit_beta_sqlserverflex_instance_delete.md +++ b/docs/stackit_beta_sqlserverflex_instance_delete.md @@ -30,6 +30,7 @@ stackit beta sqlserverflex instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_instance_describe.md b/docs/stackit_beta_sqlserverflex_instance_describe.md index cb761789a..42e6a2e3d 100644 --- a/docs/stackit_beta_sqlserverflex_instance_describe.md +++ b/docs/stackit_beta_sqlserverflex_instance_describe.md @@ -33,6 +33,7 @@ stackit beta sqlserverflex instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_instance_list.md b/docs/stackit_beta_sqlserverflex_instance_list.md index 716547fed..133a1836d 100644 --- a/docs/stackit_beta_sqlserverflex_instance_list.md +++ b/docs/stackit_beta_sqlserverflex_instance_list.md @@ -37,6 +37,7 @@ stackit beta sqlserverflex instance list [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_instance_update.md b/docs/stackit_beta_sqlserverflex_instance_update.md index 93b3379b8..740628789 100644 --- a/docs/stackit_beta_sqlserverflex_instance_update.md +++ b/docs/stackit_beta_sqlserverflex_instance_update.md @@ -40,6 +40,7 @@ stackit beta sqlserverflex instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_options.md b/docs/stackit_beta_sqlserverflex_options.md index dd4a7063b..b7035249e 100644 --- a/docs/stackit_beta_sqlserverflex_options.md +++ b/docs/stackit_beta_sqlserverflex_options.md @@ -48,6 +48,7 @@ stackit beta sqlserverflex options [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_user.md b/docs/stackit_beta_sqlserverflex_user.md index afdf81727..b922dba2a 100644 --- a/docs/stackit_beta_sqlserverflex_user.md +++ b/docs/stackit_beta_sqlserverflex_user.md @@ -23,6 +23,7 @@ stackit beta sqlserverflex user [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_user_create.md b/docs/stackit_beta_sqlserverflex_user_create.md index 4b3a00c46..26c07f913 100644 --- a/docs/stackit_beta_sqlserverflex_user_create.md +++ b/docs/stackit_beta_sqlserverflex_user_create.md @@ -44,6 +44,7 @@ stackit beta sqlserverflex user create [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_user_delete.md b/docs/stackit_beta_sqlserverflex_user_delete.md index ff3d7d647..9ec1d1581 100644 --- a/docs/stackit_beta_sqlserverflex_user_delete.md +++ b/docs/stackit_beta_sqlserverflex_user_delete.md @@ -32,6 +32,7 @@ stackit beta sqlserverflex user delete USER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_user_describe.md b/docs/stackit_beta_sqlserverflex_user_describe.md index 802160cff..b4499f2fa 100644 --- a/docs/stackit_beta_sqlserverflex_user_describe.md +++ b/docs/stackit_beta_sqlserverflex_user_describe.md @@ -36,6 +36,7 @@ stackit beta sqlserverflex user describe USER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_user_list.md b/docs/stackit_beta_sqlserverflex_user_list.md index a640a144f..5a7b79d61 100644 --- a/docs/stackit_beta_sqlserverflex_user_list.md +++ b/docs/stackit_beta_sqlserverflex_user_list.md @@ -38,6 +38,7 @@ stackit beta sqlserverflex user list [flags] --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") ``` diff --git a/docs/stackit_beta_sqlserverflex_user_reset-password.md b/docs/stackit_beta_sqlserverflex_user_reset-password.md index 25085596b..210e885bc 100644 --- a/docs/stackit_beta_sqlserverflex_user_reset-password.md +++ b/docs/stackit_beta_sqlserverflex_user_reset-password.md @@ -32,6 +32,7 @@ stackit beta sqlserverflex user reset-password USER_ID [flags] --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") ``` diff --git a/docs/stackit_beta_volume.md b/docs/stackit_beta_volume.md index 4fe120bab..3d3611aa9 100644 --- a/docs/stackit_beta_volume.md +++ b/docs/stackit_beta_volume.md @@ -23,6 +23,7 @@ stackit beta volume [flags] --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") ``` diff --git a/docs/stackit_beta_volume_create.md b/docs/stackit_beta_volume_create.md index c7ce43275..e2d41da46 100644 --- a/docs/stackit_beta_volume_create.md +++ b/docs/stackit_beta_volume_create.md @@ -47,6 +47,7 @@ stackit beta volume create [flags] --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") ``` diff --git a/docs/stackit_beta_volume_delete.md b/docs/stackit_beta_volume_delete.md index 8291c5459..8cf666298 100644 --- a/docs/stackit_beta_volume_delete.md +++ b/docs/stackit_beta_volume_delete.md @@ -32,6 +32,7 @@ stackit beta volume delete VOLUME_ID [flags] --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") ``` diff --git a/docs/stackit_beta_volume_describe.md b/docs/stackit_beta_volume_describe.md index 3b08c72aa..f6556c1cf 100644 --- a/docs/stackit_beta_volume_describe.md +++ b/docs/stackit_beta_volume_describe.md @@ -33,6 +33,7 @@ stackit beta volume describe VOLUME_ID [flags] --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") ``` diff --git a/docs/stackit_beta_volume_list.md b/docs/stackit_beta_volume_list.md index 1f0c84b29..c6f33ad92 100644 --- a/docs/stackit_beta_volume_list.md +++ b/docs/stackit_beta_volume_list.md @@ -41,6 +41,7 @@ stackit beta volume list [flags] --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") ``` diff --git a/docs/stackit_beta_volume_performance-class.md b/docs/stackit_beta_volume_performance-class.md index 3c92fdc51..7df645369 100644 --- a/docs/stackit_beta_volume_performance-class.md +++ b/docs/stackit_beta_volume_performance-class.md @@ -23,6 +23,7 @@ stackit beta volume performance-class [flags] --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") ``` diff --git a/docs/stackit_beta_volume_performance-class_describe.md b/docs/stackit_beta_volume_performance-class_describe.md index fb446880c..ed8fa7942 100644 --- a/docs/stackit_beta_volume_performance-class_describe.md +++ b/docs/stackit_beta_volume_performance-class_describe.md @@ -33,6 +33,7 @@ stackit beta volume performance-class describe VOLUME_PERFORMANCE_CLASS [flags] --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") ``` diff --git a/docs/stackit_beta_volume_performance-class_list.md b/docs/stackit_beta_volume_performance-class_list.md index a4a12222e..ed595ca77 100644 --- a/docs/stackit_beta_volume_performance-class_list.md +++ b/docs/stackit_beta_volume_performance-class_list.md @@ -41,6 +41,7 @@ stackit beta volume performance-class list [flags] --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") ``` diff --git a/docs/stackit_beta_volume_resize.md b/docs/stackit_beta_volume_resize.md index f543b8d5d..4df6abbcf 100644 --- a/docs/stackit_beta_volume_resize.md +++ b/docs/stackit_beta_volume_resize.md @@ -31,6 +31,7 @@ stackit beta volume resize VOLUME_ID [flags] --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") ``` diff --git a/docs/stackit_beta_volume_update.md b/docs/stackit_beta_volume_update.md index ca90b1ed0..ce82c2fe0 100644 --- a/docs/stackit_beta_volume_update.md +++ b/docs/stackit_beta_volume_update.md @@ -39,6 +39,7 @@ stackit beta volume update VOLUME_ID [flags] --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") ``` diff --git a/docs/stackit_config.md b/docs/stackit_config.md index 7a5d45296..664b5dcd7 100644 --- a/docs/stackit_config.md +++ b/docs/stackit_config.md @@ -28,6 +28,7 @@ stackit config [flags] --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") ``` diff --git a/docs/stackit_config_list.md b/docs/stackit_config_list.md index f8b68be6e..6d08e1888 100644 --- a/docs/stackit_config_list.md +++ b/docs/stackit_config_list.md @@ -39,6 +39,7 @@ stackit config list [flags] --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") ``` diff --git a/docs/stackit_config_profile.md b/docs/stackit_config_profile.md index 3e89ab27a..6407d11db 100644 --- a/docs/stackit_config_profile.md +++ b/docs/stackit_config_profile.md @@ -26,6 +26,7 @@ stackit config profile [flags] --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") ``` diff --git a/docs/stackit_config_profile_create.md b/docs/stackit_config_profile_create.md index 5f9a45af3..595c96fad 100644 --- a/docs/stackit_config_profile_create.md +++ b/docs/stackit_config_profile_create.md @@ -39,6 +39,7 @@ stackit config profile create PROFILE [flags] --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") ``` diff --git a/docs/stackit_config_profile_delete.md b/docs/stackit_config_profile_delete.md index 4de5f7545..770e3563e 100644 --- a/docs/stackit_config_profile_delete.md +++ b/docs/stackit_config_profile_delete.md @@ -31,6 +31,7 @@ stackit config profile delete PROFILE [flags] --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") ``` diff --git a/docs/stackit_config_profile_export.md b/docs/stackit_config_profile_export.md index 86265e493..906a20eac 100644 --- a/docs/stackit_config_profile_export.md +++ b/docs/stackit_config_profile_export.md @@ -34,6 +34,7 @@ stackit config profile export PROFILE_NAME [flags] --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") ``` diff --git a/docs/stackit_config_profile_import.md b/docs/stackit_config_profile_import.md index d2cbd1262..86f253fc8 100644 --- a/docs/stackit_config_profile_import.md +++ b/docs/stackit_config_profile_import.md @@ -36,6 +36,7 @@ stackit config profile import [flags] --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") ``` diff --git a/docs/stackit_config_profile_list.md b/docs/stackit_config_profile_list.md index 9a8985341..ba39080d0 100644 --- a/docs/stackit_config_profile_list.md +++ b/docs/stackit_config_profile_list.md @@ -33,6 +33,7 @@ stackit config profile list [flags] --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") ``` diff --git a/docs/stackit_config_profile_set.md b/docs/stackit_config_profile_set.md index a39604ff1..64f6126b2 100644 --- a/docs/stackit_config_profile_set.md +++ b/docs/stackit_config_profile_set.md @@ -33,6 +33,7 @@ stackit config profile set PROFILE [flags] --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") ``` diff --git a/docs/stackit_config_profile_unset.md b/docs/stackit_config_profile_unset.md index 410469005..5895391b0 100644 --- a/docs/stackit_config_profile_unset.md +++ b/docs/stackit_config_profile_unset.md @@ -31,6 +31,7 @@ stackit config profile unset [flags] --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") ``` diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 85c02b0bf..d8e1f20a5 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -65,6 +65,7 @@ stackit config set [flags] --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") ``` diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 254184b5d..933bacc3d 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -46,6 +46,7 @@ stackit config unset [flags] --project-id Project ID --rabbitmq-custom-endpoint RabbitMQ API base URL. If unset, uses the default base URL --redis-custom-endpoint Redis API base URL. If unset, uses the default base URL + --region Region --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL --runcommand-custom-endpoint Server Command base URL. If unset, uses the default base URL --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL diff --git a/docs/stackit_curl.md b/docs/stackit_curl.md index 27938ca6d..4dd7f453f 100644 --- a/docs/stackit_curl.md +++ b/docs/stackit_curl.md @@ -45,6 +45,7 @@ stackit curl URL [flags] --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") ``` diff --git a/docs/stackit_dns.md b/docs/stackit_dns.md index 07d1fa87c..a3e7279ba 100644 --- a/docs/stackit_dns.md +++ b/docs/stackit_dns.md @@ -23,6 +23,7 @@ stackit dns [flags] --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") ``` diff --git a/docs/stackit_dns_record-set.md b/docs/stackit_dns_record-set.md index 241199be6..8796d62f2 100644 --- a/docs/stackit_dns_record-set.md +++ b/docs/stackit_dns_record-set.md @@ -23,6 +23,7 @@ stackit dns record-set [flags] --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") ``` diff --git a/docs/stackit_dns_record-set_create.md b/docs/stackit_dns_record-set_create.md index 0d8cb5a53..f692b80ad 100644 --- a/docs/stackit_dns_record-set_create.md +++ b/docs/stackit_dns_record-set_create.md @@ -36,6 +36,7 @@ stackit dns record-set create [flags] --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") ``` diff --git a/docs/stackit_dns_record-set_delete.md b/docs/stackit_dns_record-set_delete.md index c831ba208..487c5a621 100644 --- a/docs/stackit_dns_record-set_delete.md +++ b/docs/stackit_dns_record-set_delete.md @@ -31,6 +31,7 @@ stackit dns record-set delete RECORD_SET_ID [flags] --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") ``` diff --git a/docs/stackit_dns_record-set_describe.md b/docs/stackit_dns_record-set_describe.md index a29428708..fb9ab8873 100644 --- a/docs/stackit_dns_record-set_describe.md +++ b/docs/stackit_dns_record-set_describe.md @@ -34,6 +34,7 @@ stackit dns record-set describe RECORD_SET_ID [flags] --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") ``` diff --git a/docs/stackit_dns_record-set_list.md b/docs/stackit_dns_record-set_list.md index 738c77f14..75cc555a2 100644 --- a/docs/stackit_dns_record-set_list.md +++ b/docs/stackit_dns_record-set_list.md @@ -50,6 +50,7 @@ stackit dns record-set list [flags] --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") ``` diff --git a/docs/stackit_dns_record-set_update.md b/docs/stackit_dns_record-set_update.md index ff150283f..9d369c4f6 100644 --- a/docs/stackit_dns_record-set_update.md +++ b/docs/stackit_dns_record-set_update.md @@ -35,6 +35,7 @@ stackit dns record-set update RECORD_SET_ID [flags] --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") ``` diff --git a/docs/stackit_dns_zone.md b/docs/stackit_dns_zone.md index bc46f8a62..a5e705ded 100644 --- a/docs/stackit_dns_zone.md +++ b/docs/stackit_dns_zone.md @@ -23,6 +23,7 @@ stackit dns zone [flags] --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") ``` diff --git a/docs/stackit_dns_zone_clone.md b/docs/stackit_dns_zone_clone.md index d6a6133c7..2b944f077 100644 --- a/docs/stackit_dns_zone_clone.md +++ b/docs/stackit_dns_zone_clone.md @@ -40,6 +40,7 @@ stackit dns zone clone ZONE_ID [flags] --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") ``` diff --git a/docs/stackit_dns_zone_create.md b/docs/stackit_dns_zone_create.md index 2ac88572c..081628e19 100644 --- a/docs/stackit_dns_zone_create.md +++ b/docs/stackit_dns_zone_create.md @@ -46,6 +46,7 @@ stackit dns zone create [flags] --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") ``` diff --git a/docs/stackit_dns_zone_delete.md b/docs/stackit_dns_zone_delete.md index 04f96576f..466d51f72 100644 --- a/docs/stackit_dns_zone_delete.md +++ b/docs/stackit_dns_zone_delete.md @@ -30,6 +30,7 @@ stackit dns zone delete ZONE_ID [flags] --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") ``` diff --git a/docs/stackit_dns_zone_describe.md b/docs/stackit_dns_zone_describe.md index f65163566..896a3ef9d 100644 --- a/docs/stackit_dns_zone_describe.md +++ b/docs/stackit_dns_zone_describe.md @@ -33,6 +33,7 @@ stackit dns zone describe ZONE_ID [flags] --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") ``` diff --git a/docs/stackit_dns_zone_list.md b/docs/stackit_dns_zone_list.md index 099a67cf2..bb9e01fd1 100644 --- a/docs/stackit_dns_zone_list.md +++ b/docs/stackit_dns_zone_list.md @@ -46,6 +46,7 @@ stackit dns zone list [flags] --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") ``` diff --git a/docs/stackit_dns_zone_update.md b/docs/stackit_dns_zone_update.md index 334d7fbec..240885c1b 100644 --- a/docs/stackit_dns_zone_update.md +++ b/docs/stackit_dns_zone_update.md @@ -40,6 +40,7 @@ stackit dns zone update ZONE_ID [flags] --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") ``` diff --git a/docs/stackit_load-balancer.md b/docs/stackit_load-balancer.md index 8c154e2b8..77c14b00f 100644 --- a/docs/stackit_load-balancer.md +++ b/docs/stackit_load-balancer.md @@ -23,6 +23,7 @@ stackit load-balancer [flags] --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") ``` diff --git a/docs/stackit_load-balancer_create.md b/docs/stackit_load-balancer_create.md index 054947308..4172ccb4d 100644 --- a/docs/stackit_load-balancer_create.md +++ b/docs/stackit_load-balancer_create.md @@ -41,6 +41,7 @@ stackit load-balancer create [flags] --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") ``` diff --git a/docs/stackit_load-balancer_delete.md b/docs/stackit_load-balancer_delete.md index 4c8c895a9..07ee2712c 100644 --- a/docs/stackit_load-balancer_delete.md +++ b/docs/stackit_load-balancer_delete.md @@ -30,6 +30,7 @@ stackit load-balancer delete LOAD_BALANCER_NAME [flags] --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") ``` diff --git a/docs/stackit_load-balancer_describe.md b/docs/stackit_load-balancer_describe.md index de7abebc8..8f3bd5da1 100644 --- a/docs/stackit_load-balancer_describe.md +++ b/docs/stackit_load-balancer_describe.md @@ -33,6 +33,7 @@ stackit load-balancer describe LOAD_BALANCER_NAME [flags] --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") ``` diff --git a/docs/stackit_load-balancer_generate-payload.md b/docs/stackit_load-balancer_generate-payload.md index 07636cb2e..2cf2b15c7 100644 --- a/docs/stackit_load-balancer_generate-payload.md +++ b/docs/stackit_load-balancer_generate-payload.md @@ -43,6 +43,7 @@ stackit load-balancer generate-payload [flags] --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") ``` diff --git a/docs/stackit_load-balancer_list.md b/docs/stackit_load-balancer_list.md index b73422bf6..3cc3749e9 100644 --- a/docs/stackit_load-balancer_list.md +++ b/docs/stackit_load-balancer_list.md @@ -37,6 +37,7 @@ stackit load-balancer list [flags] --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") ``` diff --git a/docs/stackit_load-balancer_observability-credentials.md b/docs/stackit_load-balancer_observability-credentials.md index 6a9806d41..ae2e58a8e 100644 --- a/docs/stackit_load-balancer_observability-credentials.md +++ b/docs/stackit_load-balancer_observability-credentials.md @@ -23,6 +23,7 @@ stackit load-balancer observability-credentials [flags] --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") ``` diff --git a/docs/stackit_load-balancer_observability-credentials_add.md b/docs/stackit_load-balancer_observability-credentials_add.md index 8f86b2aad..97afccbf4 100644 --- a/docs/stackit_load-balancer_observability-credentials_add.md +++ b/docs/stackit_load-balancer_observability-credentials_add.md @@ -36,6 +36,7 @@ stackit load-balancer observability-credentials add [flags] --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") ``` diff --git a/docs/stackit_load-balancer_observability-credentials_cleanup.md b/docs/stackit_load-balancer_observability-credentials_cleanup.md index f22f88994..58fcbe82e 100644 --- a/docs/stackit_load-balancer_observability-credentials_cleanup.md +++ b/docs/stackit_load-balancer_observability-credentials_cleanup.md @@ -30,6 +30,7 @@ stackit load-balancer observability-credentials cleanup [flags] --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") ``` diff --git a/docs/stackit_load-balancer_observability-credentials_delete.md b/docs/stackit_load-balancer_observability-credentials_delete.md index 7c2965552..a2fcf8018 100644 --- a/docs/stackit_load-balancer_observability-credentials_delete.md +++ b/docs/stackit_load-balancer_observability-credentials_delete.md @@ -30,6 +30,7 @@ stackit load-balancer observability-credentials delete CREDENTIALS_REF [flags] --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") ``` diff --git a/docs/stackit_load-balancer_observability-credentials_describe.md b/docs/stackit_load-balancer_observability-credentials_describe.md index 5feb0a190..c8ed19750 100644 --- a/docs/stackit_load-balancer_observability-credentials_describe.md +++ b/docs/stackit_load-balancer_observability-credentials_describe.md @@ -30,6 +30,7 @@ stackit load-balancer observability-credentials describe CREDENTIALS_REF [flags] --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") ``` diff --git a/docs/stackit_load-balancer_observability-credentials_list.md b/docs/stackit_load-balancer_observability-credentials_list.md index 893fecdbf..2e86129d0 100644 --- a/docs/stackit_load-balancer_observability-credentials_list.md +++ b/docs/stackit_load-balancer_observability-credentials_list.md @@ -45,6 +45,7 @@ stackit load-balancer observability-credentials list [flags] --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") ``` diff --git a/docs/stackit_load-balancer_observability-credentials_update.md b/docs/stackit_load-balancer_observability-credentials_update.md index e10bf5821..c0d95a31d 100644 --- a/docs/stackit_load-balancer_observability-credentials_update.md +++ b/docs/stackit_load-balancer_observability-credentials_update.md @@ -36,6 +36,7 @@ stackit load-balancer observability-credentials update CREDENTIALS_REF [flags] --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") ``` diff --git a/docs/stackit_load-balancer_quota.md b/docs/stackit_load-balancer_quota.md index 9ffb0b5e3..62541ec3e 100644 --- a/docs/stackit_load-balancer_quota.md +++ b/docs/stackit_load-balancer_quota.md @@ -30,6 +30,7 @@ stackit load-balancer quota [flags] --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") ``` diff --git a/docs/stackit_load-balancer_target-pool.md b/docs/stackit_load-balancer_target-pool.md index cce372cee..8356f0436 100644 --- a/docs/stackit_load-balancer_target-pool.md +++ b/docs/stackit_load-balancer_target-pool.md @@ -23,6 +23,7 @@ stackit load-balancer target-pool [flags] --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") ``` diff --git a/docs/stackit_load-balancer_target-pool_add-target.md b/docs/stackit_load-balancer_target-pool_add-target.md index c5de949df..b6e1e8109 100644 --- a/docs/stackit_load-balancer_target-pool_add-target.md +++ b/docs/stackit_load-balancer_target-pool_add-target.md @@ -34,6 +34,7 @@ stackit load-balancer target-pool add-target TARGET_IP [flags] --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") ``` diff --git a/docs/stackit_load-balancer_target-pool_describe.md b/docs/stackit_load-balancer_target-pool_describe.md index 25564de96..67fbe0580 100644 --- a/docs/stackit_load-balancer_target-pool_describe.md +++ b/docs/stackit_load-balancer_target-pool_describe.md @@ -34,6 +34,7 @@ stackit load-balancer target-pool describe TARGET_POOL_NAME [flags] --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") ``` diff --git a/docs/stackit_load-balancer_target-pool_remove-target.md b/docs/stackit_load-balancer_target-pool_remove-target.md index af638f939..2d95b7abf 100644 --- a/docs/stackit_load-balancer_target-pool_remove-target.md +++ b/docs/stackit_load-balancer_target-pool_remove-target.md @@ -32,6 +32,7 @@ stackit load-balancer target-pool remove-target TARGET_IP [flags] --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") ``` diff --git a/docs/stackit_load-balancer_update.md b/docs/stackit_load-balancer_update.md index a2d9b771f..fc577b35b 100644 --- a/docs/stackit_load-balancer_update.md +++ b/docs/stackit_load-balancer_update.md @@ -41,6 +41,7 @@ stackit load-balancer update LOAD_BALANCER_NAME [flags] --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") ``` diff --git a/docs/stackit_logme.md b/docs/stackit_logme.md index 38a1419ab..edd1ec1e7 100644 --- a/docs/stackit_logme.md +++ b/docs/stackit_logme.md @@ -23,6 +23,7 @@ stackit logme [flags] --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") ``` diff --git a/docs/stackit_logme_credentials.md b/docs/stackit_logme_credentials.md index 0d2712c1d..f510d9854 100644 --- a/docs/stackit_logme_credentials.md +++ b/docs/stackit_logme_credentials.md @@ -23,6 +23,7 @@ stackit logme credentials [flags] --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") ``` diff --git a/docs/stackit_logme_credentials_create.md b/docs/stackit_logme_credentials_create.md index 2dc853cec..f20a9c583 100644 --- a/docs/stackit_logme_credentials_create.md +++ b/docs/stackit_logme_credentials_create.md @@ -35,6 +35,7 @@ stackit logme credentials create [flags] --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") ``` diff --git a/docs/stackit_logme_credentials_delete.md b/docs/stackit_logme_credentials_delete.md index 020b53c99..0925c4cbd 100644 --- a/docs/stackit_logme_credentials_delete.md +++ b/docs/stackit_logme_credentials_delete.md @@ -31,6 +31,7 @@ stackit logme credentials delete CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_logme_credentials_describe.md b/docs/stackit_logme_credentials_describe.md index a882a1c70..96940297b 100644 --- a/docs/stackit_logme_credentials_describe.md +++ b/docs/stackit_logme_credentials_describe.md @@ -34,6 +34,7 @@ stackit logme credentials describe CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_logme_credentials_list.md b/docs/stackit_logme_credentials_list.md index 2ae3d2bfa..3cd2a5164 100644 --- a/docs/stackit_logme_credentials_list.md +++ b/docs/stackit_logme_credentials_list.md @@ -38,6 +38,7 @@ stackit logme credentials list [flags] --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") ``` diff --git a/docs/stackit_logme_instance.md b/docs/stackit_logme_instance.md index 90c389041..54144eb80 100644 --- a/docs/stackit_logme_instance.md +++ b/docs/stackit_logme_instance.md @@ -23,6 +23,7 @@ stackit logme instance [flags] --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") ``` diff --git a/docs/stackit_logme_instance_create.md b/docs/stackit_logme_instance_create.md index 281d13e9b..a0af8584d 100644 --- a/docs/stackit_logme_instance_create.md +++ b/docs/stackit_logme_instance_create.md @@ -47,6 +47,7 @@ stackit logme instance create [flags] --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") ``` diff --git a/docs/stackit_logme_instance_delete.md b/docs/stackit_logme_instance_delete.md index 94bc52c53..34e9a8fc9 100644 --- a/docs/stackit_logme_instance_delete.md +++ b/docs/stackit_logme_instance_delete.md @@ -30,6 +30,7 @@ stackit logme instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_logme_instance_describe.md b/docs/stackit_logme_instance_describe.md index 26241ca7a..c9f0f9bcc 100644 --- a/docs/stackit_logme_instance_describe.md +++ b/docs/stackit_logme_instance_describe.md @@ -33,6 +33,7 @@ stackit logme instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_logme_instance_list.md b/docs/stackit_logme_instance_list.md index 9180286b2..20673a368 100644 --- a/docs/stackit_logme_instance_list.md +++ b/docs/stackit_logme_instance_list.md @@ -37,6 +37,7 @@ stackit logme instance list [flags] --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") ``` diff --git a/docs/stackit_logme_instance_update.md b/docs/stackit_logme_instance_update.md index d6ac88f29..02e3bb975 100644 --- a/docs/stackit_logme_instance_update.md +++ b/docs/stackit_logme_instance_update.md @@ -43,6 +43,7 @@ stackit logme instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_logme_plans.md b/docs/stackit_logme_plans.md index f2450971f..87f7db2a3 100644 --- a/docs/stackit_logme_plans.md +++ b/docs/stackit_logme_plans.md @@ -37,6 +37,7 @@ stackit logme plans [flags] --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") ``` diff --git a/docs/stackit_mariadb.md b/docs/stackit_mariadb.md index 18d6875c2..b40107270 100644 --- a/docs/stackit_mariadb.md +++ b/docs/stackit_mariadb.md @@ -23,6 +23,7 @@ stackit mariadb [flags] --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") ``` diff --git a/docs/stackit_mariadb_credentials.md b/docs/stackit_mariadb_credentials.md index 34f79706f..ccfa3e470 100644 --- a/docs/stackit_mariadb_credentials.md +++ b/docs/stackit_mariadb_credentials.md @@ -23,6 +23,7 @@ stackit mariadb credentials [flags] --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") ``` diff --git a/docs/stackit_mariadb_credentials_create.md b/docs/stackit_mariadb_credentials_create.md index beb6159c6..e611ebeff 100644 --- a/docs/stackit_mariadb_credentials_create.md +++ b/docs/stackit_mariadb_credentials_create.md @@ -35,6 +35,7 @@ stackit mariadb credentials create [flags] --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") ``` diff --git a/docs/stackit_mariadb_credentials_delete.md b/docs/stackit_mariadb_credentials_delete.md index 812c4f7bc..e1b7bbee7 100644 --- a/docs/stackit_mariadb_credentials_delete.md +++ b/docs/stackit_mariadb_credentials_delete.md @@ -31,6 +31,7 @@ stackit mariadb credentials delete CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_mariadb_credentials_describe.md b/docs/stackit_mariadb_credentials_describe.md index 79b828146..12f440607 100644 --- a/docs/stackit_mariadb_credentials_describe.md +++ b/docs/stackit_mariadb_credentials_describe.md @@ -34,6 +34,7 @@ stackit mariadb credentials describe CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_mariadb_credentials_list.md b/docs/stackit_mariadb_credentials_list.md index cc49e23c4..99120fda8 100644 --- a/docs/stackit_mariadb_credentials_list.md +++ b/docs/stackit_mariadb_credentials_list.md @@ -38,6 +38,7 @@ stackit mariadb credentials list [flags] --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") ``` diff --git a/docs/stackit_mariadb_instance.md b/docs/stackit_mariadb_instance.md index 2da27c38b..3ace44fc6 100644 --- a/docs/stackit_mariadb_instance.md +++ b/docs/stackit_mariadb_instance.md @@ -23,6 +23,7 @@ stackit mariadb instance [flags] --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") ``` diff --git a/docs/stackit_mariadb_instance_create.md b/docs/stackit_mariadb_instance_create.md index 3a8a063b9..63bb11865 100644 --- a/docs/stackit_mariadb_instance_create.md +++ b/docs/stackit_mariadb_instance_create.md @@ -47,6 +47,7 @@ stackit mariadb instance create [flags] --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") ``` diff --git a/docs/stackit_mariadb_instance_delete.md b/docs/stackit_mariadb_instance_delete.md index 564057900..39ea03e35 100644 --- a/docs/stackit_mariadb_instance_delete.md +++ b/docs/stackit_mariadb_instance_delete.md @@ -30,6 +30,7 @@ stackit mariadb instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_mariadb_instance_describe.md b/docs/stackit_mariadb_instance_describe.md index 13c5014e1..e864c29a6 100644 --- a/docs/stackit_mariadb_instance_describe.md +++ b/docs/stackit_mariadb_instance_describe.md @@ -33,6 +33,7 @@ stackit mariadb instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_mariadb_instance_list.md b/docs/stackit_mariadb_instance_list.md index 301787ef6..2990fbc24 100644 --- a/docs/stackit_mariadb_instance_list.md +++ b/docs/stackit_mariadb_instance_list.md @@ -37,6 +37,7 @@ stackit mariadb instance list [flags] --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") ``` diff --git a/docs/stackit_mariadb_instance_update.md b/docs/stackit_mariadb_instance_update.md index 1c7712c00..2de6c1026 100644 --- a/docs/stackit_mariadb_instance_update.md +++ b/docs/stackit_mariadb_instance_update.md @@ -43,6 +43,7 @@ stackit mariadb instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_mariadb_plans.md b/docs/stackit_mariadb_plans.md index 4ad4db981..f17b09ecd 100644 --- a/docs/stackit_mariadb_plans.md +++ b/docs/stackit_mariadb_plans.md @@ -37,6 +37,7 @@ stackit mariadb plans [flags] --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") ``` diff --git a/docs/stackit_mongodbflex.md b/docs/stackit_mongodbflex.md index 3d6810d68..7f0746976 100644 --- a/docs/stackit_mongodbflex.md +++ b/docs/stackit_mongodbflex.md @@ -23,6 +23,7 @@ stackit mongodbflex [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_backup.md b/docs/stackit_mongodbflex_backup.md index de46caf3a..e89b79ae5 100644 --- a/docs/stackit_mongodbflex_backup.md +++ b/docs/stackit_mongodbflex_backup.md @@ -23,6 +23,7 @@ stackit mongodbflex backup [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_backup_describe.md b/docs/stackit_mongodbflex_backup_describe.md index bb422f064..287f325b4 100644 --- a/docs/stackit_mongodbflex_backup_describe.md +++ b/docs/stackit_mongodbflex_backup_describe.md @@ -34,6 +34,7 @@ stackit mongodbflex backup describe BACKUP_ID [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_backup_list.md b/docs/stackit_mongodbflex_backup_list.md index 611ae3a22..87fa406ea 100644 --- a/docs/stackit_mongodbflex_backup_list.md +++ b/docs/stackit_mongodbflex_backup_list.md @@ -38,6 +38,7 @@ stackit mongodbflex backup list [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_backup_restore-jobs.md b/docs/stackit_mongodbflex_backup_restore-jobs.md index 8b909182b..c91bcaf2f 100644 --- a/docs/stackit_mongodbflex_backup_restore-jobs.md +++ b/docs/stackit_mongodbflex_backup_restore-jobs.md @@ -38,6 +38,7 @@ stackit mongodbflex backup restore-jobs [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_backup_restore.md b/docs/stackit_mongodbflex_backup_restore.md index 18dadd1a3..b506f1ce6 100644 --- a/docs/stackit_mongodbflex_backup_restore.md +++ b/docs/stackit_mongodbflex_backup_restore.md @@ -42,6 +42,7 @@ stackit mongodbflex backup restore [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_backup_schedule.md b/docs/stackit_mongodbflex_backup_schedule.md index 945d5081b..fff1ef32c 100644 --- a/docs/stackit_mongodbflex_backup_schedule.md +++ b/docs/stackit_mongodbflex_backup_schedule.md @@ -34,6 +34,7 @@ stackit mongodbflex backup schedule [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_backup_update-schedule.md b/docs/stackit_mongodbflex_backup_update-schedule.md index 872f52835..cfa492a84 100644 --- a/docs/stackit_mongodbflex_backup_update-schedule.md +++ b/docs/stackit_mongodbflex_backup_update-schedule.md @@ -42,6 +42,7 @@ stackit mongodbflex backup update-schedule [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_instance.md b/docs/stackit_mongodbflex_instance.md index c38c90538..962f4bc8e 100644 --- a/docs/stackit_mongodbflex_instance.md +++ b/docs/stackit_mongodbflex_instance.md @@ -23,6 +23,7 @@ stackit mongodbflex instance [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_instance_create.md b/docs/stackit_mongodbflex_instance_create.md index 2b424836f..151ff2dad 100644 --- a/docs/stackit_mongodbflex_instance_create.md +++ b/docs/stackit_mongodbflex_instance_create.md @@ -46,6 +46,7 @@ stackit mongodbflex instance create [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_instance_delete.md b/docs/stackit_mongodbflex_instance_delete.md index 88718bb37..39d313068 100644 --- a/docs/stackit_mongodbflex_instance_delete.md +++ b/docs/stackit_mongodbflex_instance_delete.md @@ -30,6 +30,7 @@ stackit mongodbflex instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_instance_describe.md b/docs/stackit_mongodbflex_instance_describe.md index 870da5e13..b37bd3605 100644 --- a/docs/stackit_mongodbflex_instance_describe.md +++ b/docs/stackit_mongodbflex_instance_describe.md @@ -33,6 +33,7 @@ stackit mongodbflex instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_instance_list.md b/docs/stackit_mongodbflex_instance_list.md index 3b3995ed6..5abfe9cbc 100644 --- a/docs/stackit_mongodbflex_instance_list.md +++ b/docs/stackit_mongodbflex_instance_list.md @@ -37,6 +37,7 @@ stackit mongodbflex instance list [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_instance_update.md b/docs/stackit_mongodbflex_instance_update.md index ef64d5088..a9475fbeb 100644 --- a/docs/stackit_mongodbflex_instance_update.md +++ b/docs/stackit_mongodbflex_instance_update.md @@ -43,6 +43,7 @@ stackit mongodbflex instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_options.md b/docs/stackit_mongodbflex_options.md index b695104a8..d01544608 100644 --- a/docs/stackit_mongodbflex_options.md +++ b/docs/stackit_mongodbflex_options.md @@ -41,6 +41,7 @@ stackit mongodbflex options [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_user.md b/docs/stackit_mongodbflex_user.md index 7b45211b7..ce6528aa4 100644 --- a/docs/stackit_mongodbflex_user.md +++ b/docs/stackit_mongodbflex_user.md @@ -23,6 +23,7 @@ stackit mongodbflex user [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_user_create.md b/docs/stackit_mongodbflex_user_create.md index 6a6645be0..8c42b3bb2 100644 --- a/docs/stackit_mongodbflex_user_create.md +++ b/docs/stackit_mongodbflex_user_create.md @@ -40,6 +40,7 @@ stackit mongodbflex user create [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_user_delete.md b/docs/stackit_mongodbflex_user_delete.md index 6297faa1f..bf792ddea 100644 --- a/docs/stackit_mongodbflex_user_delete.md +++ b/docs/stackit_mongodbflex_user_delete.md @@ -32,6 +32,7 @@ stackit mongodbflex user delete USER_ID [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_user_describe.md b/docs/stackit_mongodbflex_user_describe.md index 1a0b65443..15642c9c2 100644 --- a/docs/stackit_mongodbflex_user_describe.md +++ b/docs/stackit_mongodbflex_user_describe.md @@ -36,6 +36,7 @@ stackit mongodbflex user describe USER_ID [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_user_list.md b/docs/stackit_mongodbflex_user_list.md index df3305a73..804abfe11 100644 --- a/docs/stackit_mongodbflex_user_list.md +++ b/docs/stackit_mongodbflex_user_list.md @@ -38,6 +38,7 @@ stackit mongodbflex user list [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_user_reset-password.md b/docs/stackit_mongodbflex_user_reset-password.md index e269e1ff7..183885b5f 100644 --- a/docs/stackit_mongodbflex_user_reset-password.md +++ b/docs/stackit_mongodbflex_user_reset-password.md @@ -32,6 +32,7 @@ stackit mongodbflex user reset-password USER_ID [flags] --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") ``` diff --git a/docs/stackit_mongodbflex_user_update.md b/docs/stackit_mongodbflex_user_update.md index 3702eb36c..bcbdfa54f 100644 --- a/docs/stackit_mongodbflex_user_update.md +++ b/docs/stackit_mongodbflex_user_update.md @@ -33,6 +33,7 @@ stackit mongodbflex user update USER_ID [flags] --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") ``` diff --git a/docs/stackit_object-storage.md b/docs/stackit_object-storage.md index 5d7def58c..5caa02380 100644 --- a/docs/stackit_object-storage.md +++ b/docs/stackit_object-storage.md @@ -23,6 +23,7 @@ stackit object-storage [flags] --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") ``` diff --git a/docs/stackit_object-storage_bucket.md b/docs/stackit_object-storage_bucket.md index 54a2cfdf8..ac5d3b600 100644 --- a/docs/stackit_object-storage_bucket.md +++ b/docs/stackit_object-storage_bucket.md @@ -23,6 +23,7 @@ stackit object-storage bucket [flags] --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") ``` diff --git a/docs/stackit_object-storage_bucket_create.md b/docs/stackit_object-storage_bucket_create.md index f22115b06..1c07eb540 100644 --- a/docs/stackit_object-storage_bucket_create.md +++ b/docs/stackit_object-storage_bucket_create.md @@ -30,6 +30,7 @@ stackit object-storage bucket create BUCKET_NAME [flags] --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") ``` diff --git a/docs/stackit_object-storage_bucket_delete.md b/docs/stackit_object-storage_bucket_delete.md index 56380a641..d512e4625 100644 --- a/docs/stackit_object-storage_bucket_delete.md +++ b/docs/stackit_object-storage_bucket_delete.md @@ -30,6 +30,7 @@ stackit object-storage bucket delete BUCKET_NAME [flags] --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") ``` diff --git a/docs/stackit_object-storage_bucket_describe.md b/docs/stackit_object-storage_bucket_describe.md index 7520a8217..256269aa9 100644 --- a/docs/stackit_object-storage_bucket_describe.md +++ b/docs/stackit_object-storage_bucket_describe.md @@ -33,6 +33,7 @@ stackit object-storage bucket describe BUCKET_NAME [flags] --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") ``` diff --git a/docs/stackit_object-storage_bucket_list.md b/docs/stackit_object-storage_bucket_list.md index 11cd639fb..b77f0eecb 100644 --- a/docs/stackit_object-storage_bucket_list.md +++ b/docs/stackit_object-storage_bucket_list.md @@ -37,6 +37,7 @@ stackit object-storage bucket list [flags] --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") ``` diff --git a/docs/stackit_object-storage_credentials-group.md b/docs/stackit_object-storage_credentials-group.md index 30db660a7..d20daee64 100644 --- a/docs/stackit_object-storage_credentials-group.md +++ b/docs/stackit_object-storage_credentials-group.md @@ -23,6 +23,7 @@ stackit object-storage credentials-group [flags] --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") ``` diff --git a/docs/stackit_object-storage_credentials-group_create.md b/docs/stackit_object-storage_credentials-group_create.md index 291be494a..2dd99a88e 100644 --- a/docs/stackit_object-storage_credentials-group_create.md +++ b/docs/stackit_object-storage_credentials-group_create.md @@ -31,6 +31,7 @@ stackit object-storage credentials-group create [flags] --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") ``` diff --git a/docs/stackit_object-storage_credentials-group_delete.md b/docs/stackit_object-storage_credentials-group_delete.md index d9d94802a..4d97f4722 100644 --- a/docs/stackit_object-storage_credentials-group_delete.md +++ b/docs/stackit_object-storage_credentials-group_delete.md @@ -30,6 +30,7 @@ stackit object-storage credentials-group delete CREDENTIALS_GROUP_ID [flags] --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") ``` diff --git a/docs/stackit_object-storage_credentials-group_list.md b/docs/stackit_object-storage_credentials-group_list.md index bd91a8942..2cb925069 100644 --- a/docs/stackit_object-storage_credentials-group_list.md +++ b/docs/stackit_object-storage_credentials-group_list.md @@ -37,6 +37,7 @@ stackit object-storage credentials-group list [flags] --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") ``` diff --git a/docs/stackit_object-storage_credentials.md b/docs/stackit_object-storage_credentials.md index 6d602dd20..2427b5f42 100644 --- a/docs/stackit_object-storage_credentials.md +++ b/docs/stackit_object-storage_credentials.md @@ -23,6 +23,7 @@ stackit object-storage credentials [flags] --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") ``` diff --git a/docs/stackit_object-storage_credentials_create.md b/docs/stackit_object-storage_credentials_create.md index 6e91d075a..95df0d984 100644 --- a/docs/stackit_object-storage_credentials_create.md +++ b/docs/stackit_object-storage_credentials_create.md @@ -35,6 +35,7 @@ stackit object-storage credentials create [flags] --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") ``` diff --git a/docs/stackit_object-storage_credentials_delete.md b/docs/stackit_object-storage_credentials_delete.md index b14154ec8..91768a44e 100644 --- a/docs/stackit_object-storage_credentials_delete.md +++ b/docs/stackit_object-storage_credentials_delete.md @@ -31,6 +31,7 @@ stackit object-storage credentials delete CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_object-storage_credentials_list.md b/docs/stackit_object-storage_credentials_list.md index 647c024b5..08c2e94c2 100644 --- a/docs/stackit_object-storage_credentials_list.md +++ b/docs/stackit_object-storage_credentials_list.md @@ -38,6 +38,7 @@ stackit object-storage credentials list [flags] --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") ``` diff --git a/docs/stackit_object-storage_disable.md b/docs/stackit_object-storage_disable.md index e386c006f..c9aef3194 100644 --- a/docs/stackit_object-storage_disable.md +++ b/docs/stackit_object-storage_disable.md @@ -30,6 +30,7 @@ stackit object-storage disable [flags] --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") ``` diff --git a/docs/stackit_object-storage_enable.md b/docs/stackit_object-storage_enable.md index 6bf93bb80..9de05bfb3 100644 --- a/docs/stackit_object-storage_enable.md +++ b/docs/stackit_object-storage_enable.md @@ -30,6 +30,7 @@ stackit object-storage enable [flags] --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") ``` diff --git a/docs/stackit_observability.md b/docs/stackit_observability.md index 2a4390ed8..393f10ff0 100644 --- a/docs/stackit_observability.md +++ b/docs/stackit_observability.md @@ -23,6 +23,7 @@ stackit observability [flags] --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") ``` diff --git a/docs/stackit_observability_credentials.md b/docs/stackit_observability_credentials.md index 0cadd8d0a..661db4f24 100644 --- a/docs/stackit_observability_credentials.md +++ b/docs/stackit_observability_credentials.md @@ -23,6 +23,7 @@ stackit observability credentials [flags] --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") ``` diff --git a/docs/stackit_observability_credentials_create.md b/docs/stackit_observability_credentials_create.md index 0967926ff..e850b8418 100644 --- a/docs/stackit_observability_credentials_create.md +++ b/docs/stackit_observability_credentials_create.md @@ -32,6 +32,7 @@ stackit observability credentials create [flags] --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") ``` diff --git a/docs/stackit_observability_credentials_delete.md b/docs/stackit_observability_credentials_delete.md index cc15e7982..98b927431 100644 --- a/docs/stackit_observability_credentials_delete.md +++ b/docs/stackit_observability_credentials_delete.md @@ -31,6 +31,7 @@ stackit observability credentials delete USERNAME [flags] --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") ``` diff --git a/docs/stackit_observability_credentials_list.md b/docs/stackit_observability_credentials_list.md index de0dcb268..905f6658d 100644 --- a/docs/stackit_observability_credentials_list.md +++ b/docs/stackit_observability_credentials_list.md @@ -38,6 +38,7 @@ stackit observability credentials list [flags] --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") ``` diff --git a/docs/stackit_observability_grafana.md b/docs/stackit_observability_grafana.md index 8b75aa44d..57f7a6440 100644 --- a/docs/stackit_observability_grafana.md +++ b/docs/stackit_observability_grafana.md @@ -23,6 +23,7 @@ stackit observability grafana [flags] --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") ``` diff --git a/docs/stackit_observability_grafana_describe.md b/docs/stackit_observability_grafana_describe.md index 99e09204e..4eea4982a 100644 --- a/docs/stackit_observability_grafana_describe.md +++ b/docs/stackit_observability_grafana_describe.md @@ -39,6 +39,7 @@ stackit observability grafana describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_observability_grafana_public-read-access.md b/docs/stackit_observability_grafana_public-read-access.md index e72c5666f..39db9ef60 100644 --- a/docs/stackit_observability_grafana_public-read-access.md +++ b/docs/stackit_observability_grafana_public-read-access.md @@ -24,6 +24,7 @@ stackit observability grafana public-read-access [flags] --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") ``` diff --git a/docs/stackit_observability_grafana_public-read-access_disable.md b/docs/stackit_observability_grafana_public-read-access_disable.md index b05fc0370..02566e9f8 100644 --- a/docs/stackit_observability_grafana_public-read-access_disable.md +++ b/docs/stackit_observability_grafana_public-read-access_disable.md @@ -31,6 +31,7 @@ stackit observability grafana public-read-access disable INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_observability_grafana_public-read-access_enable.md b/docs/stackit_observability_grafana_public-read-access_enable.md index 0394314b1..7b71bbb4e 100644 --- a/docs/stackit_observability_grafana_public-read-access_enable.md +++ b/docs/stackit_observability_grafana_public-read-access_enable.md @@ -31,6 +31,7 @@ stackit observability grafana public-read-access enable INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_observability_grafana_single-sign-on.md b/docs/stackit_observability_grafana_single-sign-on.md index 2e0bb01c6..dfba3ff2e 100644 --- a/docs/stackit_observability_grafana_single-sign-on.md +++ b/docs/stackit_observability_grafana_single-sign-on.md @@ -24,6 +24,7 @@ stackit observability grafana single-sign-on [flags] --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") ``` diff --git a/docs/stackit_observability_grafana_single-sign-on_disable.md b/docs/stackit_observability_grafana_single-sign-on_disable.md index b6d772489..e4907acfa 100644 --- a/docs/stackit_observability_grafana_single-sign-on_disable.md +++ b/docs/stackit_observability_grafana_single-sign-on_disable.md @@ -31,6 +31,7 @@ stackit observability grafana single-sign-on disable INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_observability_grafana_single-sign-on_enable.md b/docs/stackit_observability_grafana_single-sign-on_enable.md index 08c5cf52f..f083b1536 100644 --- a/docs/stackit_observability_grafana_single-sign-on_enable.md +++ b/docs/stackit_observability_grafana_single-sign-on_enable.md @@ -31,6 +31,7 @@ stackit observability grafana single-sign-on enable INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_observability_instance.md b/docs/stackit_observability_instance.md index 81786a254..4b7350a5f 100644 --- a/docs/stackit_observability_instance.md +++ b/docs/stackit_observability_instance.md @@ -23,6 +23,7 @@ stackit observability instance [flags] --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") ``` diff --git a/docs/stackit_observability_instance_create.md b/docs/stackit_observability_instance_create.md index d47991c32..994fda4ba 100644 --- a/docs/stackit_observability_instance_create.md +++ b/docs/stackit_observability_instance_create.md @@ -36,6 +36,7 @@ stackit observability instance create [flags] --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") ``` diff --git a/docs/stackit_observability_instance_delete.md b/docs/stackit_observability_instance_delete.md index 1264e0f54..30005abe4 100644 --- a/docs/stackit_observability_instance_delete.md +++ b/docs/stackit_observability_instance_delete.md @@ -30,6 +30,7 @@ stackit observability instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_observability_instance_describe.md b/docs/stackit_observability_instance_describe.md index 737612923..d8f50173c 100644 --- a/docs/stackit_observability_instance_describe.md +++ b/docs/stackit_observability_instance_describe.md @@ -33,6 +33,7 @@ stackit observability instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_observability_instance_list.md b/docs/stackit_observability_instance_list.md index 0fffefae1..18062dfa0 100644 --- a/docs/stackit_observability_instance_list.md +++ b/docs/stackit_observability_instance_list.md @@ -37,6 +37,7 @@ stackit observability instance list [flags] --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") ``` diff --git a/docs/stackit_observability_instance_update.md b/docs/stackit_observability_instance_update.md index fd9619949..fdbcc88f4 100644 --- a/docs/stackit_observability_instance_update.md +++ b/docs/stackit_observability_instance_update.md @@ -39,6 +39,7 @@ stackit observability instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_observability_plans.md b/docs/stackit_observability_plans.md index 1ad146a22..c0fb3846d 100644 --- a/docs/stackit_observability_plans.md +++ b/docs/stackit_observability_plans.md @@ -37,6 +37,7 @@ stackit observability plans [flags] --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") ``` diff --git a/docs/stackit_observability_scrape-config.md b/docs/stackit_observability_scrape-config.md index 64d51d10e..cecb2058b 100644 --- a/docs/stackit_observability_scrape-config.md +++ b/docs/stackit_observability_scrape-config.md @@ -23,6 +23,7 @@ stackit observability scrape-config [flags] --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") ``` diff --git a/docs/stackit_observability_scrape-config_create.md b/docs/stackit_observability_scrape-config_create.md index 3a282c93a..f8db966bb 100644 --- a/docs/stackit_observability_scrape-config_create.md +++ b/docs/stackit_observability_scrape-config_create.md @@ -46,6 +46,7 @@ stackit observability scrape-config create [flags] --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") ``` diff --git a/docs/stackit_observability_scrape-config_delete.md b/docs/stackit_observability_scrape-config_delete.md index 3f7167e13..1ea9678ee 100644 --- a/docs/stackit_observability_scrape-config_delete.md +++ b/docs/stackit_observability_scrape-config_delete.md @@ -31,6 +31,7 @@ stackit observability scrape-config delete JOB_NAME [flags] --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") ``` diff --git a/docs/stackit_observability_scrape-config_describe.md b/docs/stackit_observability_scrape-config_describe.md index 000edbbb2..de6ad62cd 100644 --- a/docs/stackit_observability_scrape-config_describe.md +++ b/docs/stackit_observability_scrape-config_describe.md @@ -34,6 +34,7 @@ stackit observability scrape-config describe JOB_NAME [flags] --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") ``` diff --git a/docs/stackit_observability_scrape-config_generate-payload.md b/docs/stackit_observability_scrape-config_generate-payload.md index 99979b410..2cc4d0ad0 100644 --- a/docs/stackit_observability_scrape-config_generate-payload.md +++ b/docs/stackit_observability_scrape-config_generate-payload.md @@ -49,6 +49,7 @@ stackit observability scrape-config generate-payload [flags] --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") ``` diff --git a/docs/stackit_observability_scrape-config_list.md b/docs/stackit_observability_scrape-config_list.md index e798101ae..0db93b027 100644 --- a/docs/stackit_observability_scrape-config_list.md +++ b/docs/stackit_observability_scrape-config_list.md @@ -38,6 +38,7 @@ stackit observability scrape-config list [flags] --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") ``` diff --git a/docs/stackit_observability_scrape-config_update.md b/docs/stackit_observability_scrape-config_update.md index c8370af7e..a92e5cfb5 100644 --- a/docs/stackit_observability_scrape-config_update.md +++ b/docs/stackit_observability_scrape-config_update.md @@ -42,6 +42,7 @@ stackit observability scrape-config update JOB_NAME [flags] --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") ``` diff --git a/docs/stackit_opensearch.md b/docs/stackit_opensearch.md index 30af3bd1f..c83f878ba 100644 --- a/docs/stackit_opensearch.md +++ b/docs/stackit_opensearch.md @@ -23,6 +23,7 @@ stackit opensearch [flags] --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") ``` diff --git a/docs/stackit_opensearch_credentials.md b/docs/stackit_opensearch_credentials.md index 13358215e..2af0661e5 100644 --- a/docs/stackit_opensearch_credentials.md +++ b/docs/stackit_opensearch_credentials.md @@ -23,6 +23,7 @@ stackit opensearch credentials [flags] --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") ``` diff --git a/docs/stackit_opensearch_credentials_create.md b/docs/stackit_opensearch_credentials_create.md index c90ae9f11..dce634d44 100644 --- a/docs/stackit_opensearch_credentials_create.md +++ b/docs/stackit_opensearch_credentials_create.md @@ -35,6 +35,7 @@ stackit opensearch credentials create [flags] --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") ``` diff --git a/docs/stackit_opensearch_credentials_delete.md b/docs/stackit_opensearch_credentials_delete.md index e19e2a091..34af83bbd 100644 --- a/docs/stackit_opensearch_credentials_delete.md +++ b/docs/stackit_opensearch_credentials_delete.md @@ -31,6 +31,7 @@ stackit opensearch credentials delete CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_opensearch_credentials_describe.md b/docs/stackit_opensearch_credentials_describe.md index bb0095b67..5f7c93e61 100644 --- a/docs/stackit_opensearch_credentials_describe.md +++ b/docs/stackit_opensearch_credentials_describe.md @@ -34,6 +34,7 @@ stackit opensearch credentials describe CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_opensearch_credentials_list.md b/docs/stackit_opensearch_credentials_list.md index 6aea2e1c7..6cc855daa 100644 --- a/docs/stackit_opensearch_credentials_list.md +++ b/docs/stackit_opensearch_credentials_list.md @@ -38,6 +38,7 @@ stackit opensearch credentials list [flags] --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") ``` diff --git a/docs/stackit_opensearch_instance.md b/docs/stackit_opensearch_instance.md index 26182779c..2b2df6283 100644 --- a/docs/stackit_opensearch_instance.md +++ b/docs/stackit_opensearch_instance.md @@ -23,6 +23,7 @@ stackit opensearch instance [flags] --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") ``` diff --git a/docs/stackit_opensearch_instance_create.md b/docs/stackit_opensearch_instance_create.md index ef67d29f1..77b5aada1 100644 --- a/docs/stackit_opensearch_instance_create.md +++ b/docs/stackit_opensearch_instance_create.md @@ -48,6 +48,7 @@ stackit opensearch instance create [flags] --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") ``` diff --git a/docs/stackit_opensearch_instance_delete.md b/docs/stackit_opensearch_instance_delete.md index 49c4ab8ee..2783bc403 100644 --- a/docs/stackit_opensearch_instance_delete.md +++ b/docs/stackit_opensearch_instance_delete.md @@ -30,6 +30,7 @@ stackit opensearch instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_opensearch_instance_describe.md b/docs/stackit_opensearch_instance_describe.md index 3aafa406d..8246df4f3 100644 --- a/docs/stackit_opensearch_instance_describe.md +++ b/docs/stackit_opensearch_instance_describe.md @@ -33,6 +33,7 @@ stackit opensearch instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_opensearch_instance_list.md b/docs/stackit_opensearch_instance_list.md index a67f9821f..36904c646 100644 --- a/docs/stackit_opensearch_instance_list.md +++ b/docs/stackit_opensearch_instance_list.md @@ -37,6 +37,7 @@ stackit opensearch instance list [flags] --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") ``` diff --git a/docs/stackit_opensearch_instance_update.md b/docs/stackit_opensearch_instance_update.md index 5d688fdc3..8e174c120 100644 --- a/docs/stackit_opensearch_instance_update.md +++ b/docs/stackit_opensearch_instance_update.md @@ -44,6 +44,7 @@ stackit opensearch instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_opensearch_plans.md b/docs/stackit_opensearch_plans.md index f733314ab..5617d7e2b 100644 --- a/docs/stackit_opensearch_plans.md +++ b/docs/stackit_opensearch_plans.md @@ -37,6 +37,7 @@ stackit opensearch plans [flags] --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") ``` diff --git a/docs/stackit_organization.md b/docs/stackit_organization.md index 0fefe9cb2..f1bbaedde 100644 --- a/docs/stackit_organization.md +++ b/docs/stackit_organization.md @@ -24,6 +24,7 @@ stackit organization [flags] --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") ``` diff --git a/docs/stackit_organization_member.md b/docs/stackit_organization_member.md index 496aa4466..9a0c0233d 100644 --- a/docs/stackit_organization_member.md +++ b/docs/stackit_organization_member.md @@ -23,6 +23,7 @@ stackit organization member [flags] --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") ``` diff --git a/docs/stackit_organization_member_add.md b/docs/stackit_organization_member_add.md index 0e5a50491..c3946d22c 100644 --- a/docs/stackit_organization_member_add.md +++ b/docs/stackit_organization_member_add.md @@ -36,6 +36,7 @@ stackit organization member add SUBJECT [flags] --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") ``` diff --git a/docs/stackit_organization_member_list.md b/docs/stackit_organization_member_list.md index 2263ce2a4..feb052304 100644 --- a/docs/stackit_organization_member_list.md +++ b/docs/stackit_organization_member_list.md @@ -40,6 +40,7 @@ stackit organization member list [flags] --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") ``` diff --git a/docs/stackit_organization_member_remove.md b/docs/stackit_organization_member_remove.md index 8c425a22c..f1a876d67 100644 --- a/docs/stackit_organization_member_remove.md +++ b/docs/stackit_organization_member_remove.md @@ -38,6 +38,7 @@ stackit organization member remove SUBJECT [flags] --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") ``` diff --git a/docs/stackit_organization_role.md b/docs/stackit_organization_role.md index 2a5d2f75a..6be031740 100644 --- a/docs/stackit_organization_role.md +++ b/docs/stackit_organization_role.md @@ -23,6 +23,7 @@ stackit organization role [flags] --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") ``` diff --git a/docs/stackit_organization_role_list.md b/docs/stackit_organization_role_list.md index 0228eca5c..265b9967e 100644 --- a/docs/stackit_organization_role_list.md +++ b/docs/stackit_organization_role_list.md @@ -38,6 +38,7 @@ stackit organization role list [flags] --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") ``` diff --git a/docs/stackit_postgresflex.md b/docs/stackit_postgresflex.md index 005ec9f19..125604dea 100644 --- a/docs/stackit_postgresflex.md +++ b/docs/stackit_postgresflex.md @@ -23,6 +23,7 @@ stackit postgresflex [flags] --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") ``` diff --git a/docs/stackit_postgresflex_backup.md b/docs/stackit_postgresflex_backup.md index c1caacfce..2fcac02b7 100644 --- a/docs/stackit_postgresflex_backup.md +++ b/docs/stackit_postgresflex_backup.md @@ -23,6 +23,7 @@ stackit postgresflex backup [flags] --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") ``` diff --git a/docs/stackit_postgresflex_backup_describe.md b/docs/stackit_postgresflex_backup_describe.md index cb5171718..bc506d775 100644 --- a/docs/stackit_postgresflex_backup_describe.md +++ b/docs/stackit_postgresflex_backup_describe.md @@ -34,6 +34,7 @@ stackit postgresflex backup describe BACKUP_ID [flags] --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") ``` diff --git a/docs/stackit_postgresflex_backup_list.md b/docs/stackit_postgresflex_backup_list.md index 92b8373f7..fcdc7a536 100644 --- a/docs/stackit_postgresflex_backup_list.md +++ b/docs/stackit_postgresflex_backup_list.md @@ -38,6 +38,7 @@ stackit postgresflex backup list [flags] --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") ``` diff --git a/docs/stackit_postgresflex_backup_update-schedule.md b/docs/stackit_postgresflex_backup_update-schedule.md index 7971a9b89..50a369194 100644 --- a/docs/stackit_postgresflex_backup_update-schedule.md +++ b/docs/stackit_postgresflex_backup_update-schedule.md @@ -32,6 +32,7 @@ stackit postgresflex backup update-schedule [flags] --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") ``` diff --git a/docs/stackit_postgresflex_instance.md b/docs/stackit_postgresflex_instance.md index 679dfc2a2..bfd19a6c9 100644 --- a/docs/stackit_postgresflex_instance.md +++ b/docs/stackit_postgresflex_instance.md @@ -23,6 +23,7 @@ stackit postgresflex instance [flags] --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") ``` diff --git a/docs/stackit_postgresflex_instance_clone.md b/docs/stackit_postgresflex_instance_clone.md index d158b15b8..ce0203986 100644 --- a/docs/stackit_postgresflex_instance_clone.md +++ b/docs/stackit_postgresflex_instance_clone.md @@ -39,6 +39,7 @@ stackit postgresflex instance clone INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_postgresflex_instance_create.md b/docs/stackit_postgresflex_instance_create.md index ea5c1f247..b4a333ba3 100644 --- a/docs/stackit_postgresflex_instance_create.md +++ b/docs/stackit_postgresflex_instance_create.md @@ -46,6 +46,7 @@ stackit postgresflex instance create [flags] --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") ``` diff --git a/docs/stackit_postgresflex_instance_delete.md b/docs/stackit_postgresflex_instance_delete.md index 0f864709e..17992e627 100644 --- a/docs/stackit_postgresflex_instance_delete.md +++ b/docs/stackit_postgresflex_instance_delete.md @@ -36,6 +36,7 @@ stackit postgresflex instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_postgresflex_instance_describe.md b/docs/stackit_postgresflex_instance_describe.md index 957dd5450..629ffbc9b 100644 --- a/docs/stackit_postgresflex_instance_describe.md +++ b/docs/stackit_postgresflex_instance_describe.md @@ -33,6 +33,7 @@ stackit postgresflex instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_postgresflex_instance_list.md b/docs/stackit_postgresflex_instance_list.md index a05845ba0..9d452376b 100644 --- a/docs/stackit_postgresflex_instance_list.md +++ b/docs/stackit_postgresflex_instance_list.md @@ -37,6 +37,7 @@ stackit postgresflex instance list [flags] --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") ``` diff --git a/docs/stackit_postgresflex_instance_update.md b/docs/stackit_postgresflex_instance_update.md index 75a10e519..844e7d22a 100644 --- a/docs/stackit_postgresflex_instance_update.md +++ b/docs/stackit_postgresflex_instance_update.md @@ -43,6 +43,7 @@ stackit postgresflex instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_postgresflex_options.md b/docs/stackit_postgresflex_options.md index 0638b2ec4..7fa8ee2bd 100644 --- a/docs/stackit_postgresflex_options.md +++ b/docs/stackit_postgresflex_options.md @@ -41,6 +41,7 @@ stackit postgresflex options [flags] --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") ``` diff --git a/docs/stackit_postgresflex_user.md b/docs/stackit_postgresflex_user.md index 2e0d97ffc..b1793c663 100644 --- a/docs/stackit_postgresflex_user.md +++ b/docs/stackit_postgresflex_user.md @@ -23,6 +23,7 @@ stackit postgresflex user [flags] --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") ``` diff --git a/docs/stackit_postgresflex_user_create.md b/docs/stackit_postgresflex_user_create.md index 335038430..fb66d84c3 100644 --- a/docs/stackit_postgresflex_user_create.md +++ b/docs/stackit_postgresflex_user_create.md @@ -39,6 +39,7 @@ stackit postgresflex user create [flags] --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") ``` diff --git a/docs/stackit_postgresflex_user_delete.md b/docs/stackit_postgresflex_user_delete.md index f85225ede..2bdd099d7 100644 --- a/docs/stackit_postgresflex_user_delete.md +++ b/docs/stackit_postgresflex_user_delete.md @@ -33,6 +33,7 @@ stackit postgresflex user delete USER_ID [flags] --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") ``` diff --git a/docs/stackit_postgresflex_user_describe.md b/docs/stackit_postgresflex_user_describe.md index 40e5a5bd9..365b6764b 100644 --- a/docs/stackit_postgresflex_user_describe.md +++ b/docs/stackit_postgresflex_user_describe.md @@ -36,6 +36,7 @@ stackit postgresflex user describe USER_ID [flags] --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") ``` diff --git a/docs/stackit_postgresflex_user_list.md b/docs/stackit_postgresflex_user_list.md index 9db37967d..986fc8567 100644 --- a/docs/stackit_postgresflex_user_list.md +++ b/docs/stackit_postgresflex_user_list.md @@ -38,6 +38,7 @@ stackit postgresflex user list [flags] --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") ``` diff --git a/docs/stackit_postgresflex_user_reset-password.md b/docs/stackit_postgresflex_user_reset-password.md index 857313808..42216c5e8 100644 --- a/docs/stackit_postgresflex_user_reset-password.md +++ b/docs/stackit_postgresflex_user_reset-password.md @@ -32,6 +32,7 @@ stackit postgresflex user reset-password USER_ID [flags] --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") ``` diff --git a/docs/stackit_postgresflex_user_update.md b/docs/stackit_postgresflex_user_update.md index f0a0e5250..d76b18447 100644 --- a/docs/stackit_postgresflex_user_update.md +++ b/docs/stackit_postgresflex_user_update.md @@ -32,6 +32,7 @@ stackit postgresflex user update USER_ID [flags] --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") ``` diff --git a/docs/stackit_project.md b/docs/stackit_project.md index 7f002da38..cd2eb8f46 100644 --- a/docs/stackit_project.md +++ b/docs/stackit_project.md @@ -24,6 +24,7 @@ stackit project [flags] --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") ``` diff --git a/docs/stackit_project_create.md b/docs/stackit_project_create.md index 8f01c8f31..9cc565f2b 100644 --- a/docs/stackit_project_create.md +++ b/docs/stackit_project_create.md @@ -45,6 +45,7 @@ stackit project create [flags] --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") ``` diff --git a/docs/stackit_project_delete.md b/docs/stackit_project_delete.md index 66b60ed00..b6eb31164 100644 --- a/docs/stackit_project_delete.md +++ b/docs/stackit_project_delete.md @@ -33,6 +33,7 @@ stackit project delete [flags] --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") ``` diff --git a/docs/stackit_project_describe.md b/docs/stackit_project_describe.md index a3976ece6..6afced7fc 100644 --- a/docs/stackit_project_describe.md +++ b/docs/stackit_project_describe.md @@ -37,6 +37,7 @@ stackit project describe [flags] --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") ``` diff --git a/docs/stackit_project_list.md b/docs/stackit_project_list.md index 28aa2693b..f4b22b007 100644 --- a/docs/stackit_project_list.md +++ b/docs/stackit_project_list.md @@ -45,6 +45,7 @@ stackit project list [flags] --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") ``` diff --git a/docs/stackit_project_member.md b/docs/stackit_project_member.md index c2021638a..445143fe2 100644 --- a/docs/stackit_project_member.md +++ b/docs/stackit_project_member.md @@ -23,6 +23,7 @@ stackit project member [flags] --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") ``` diff --git a/docs/stackit_project_member_add.md b/docs/stackit_project_member_add.md index 105676243..d3fc54513 100644 --- a/docs/stackit_project_member_add.md +++ b/docs/stackit_project_member_add.md @@ -35,6 +35,7 @@ stackit project member add SUBJECT [flags] --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") ``` diff --git a/docs/stackit_project_member_list.md b/docs/stackit_project_member_list.md index c27436336..18d7874d8 100644 --- a/docs/stackit_project_member_list.md +++ b/docs/stackit_project_member_list.md @@ -39,6 +39,7 @@ stackit project member list [flags] --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") ``` diff --git a/docs/stackit_project_member_remove.md b/docs/stackit_project_member_remove.md index 9c9e46ffe..908e44523 100644 --- a/docs/stackit_project_member_remove.md +++ b/docs/stackit_project_member_remove.md @@ -37,6 +37,7 @@ stackit project member remove SUBJECT [flags] --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") ``` diff --git a/docs/stackit_project_role.md b/docs/stackit_project_role.md index b95577866..d02d2512d 100644 --- a/docs/stackit_project_role.md +++ b/docs/stackit_project_role.md @@ -23,6 +23,7 @@ stackit project role [flags] --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") ``` diff --git a/docs/stackit_project_role_list.md b/docs/stackit_project_role_list.md index 6744c4c8c..90c54d0b1 100644 --- a/docs/stackit_project_role_list.md +++ b/docs/stackit_project_role_list.md @@ -37,6 +37,7 @@ stackit project role list [flags] --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") ``` diff --git a/docs/stackit_project_update.md b/docs/stackit_project_update.md index b057276be..9c64e8f6a 100644 --- a/docs/stackit_project_update.md +++ b/docs/stackit_project_update.md @@ -39,6 +39,7 @@ stackit project update [flags] --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") ``` diff --git a/docs/stackit_rabbitmq.md b/docs/stackit_rabbitmq.md index e3060985c..2e6779ccc 100644 --- a/docs/stackit_rabbitmq.md +++ b/docs/stackit_rabbitmq.md @@ -23,6 +23,7 @@ stackit rabbitmq [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_credentials.md b/docs/stackit_rabbitmq_credentials.md index 96968f4b3..debec8700 100644 --- a/docs/stackit_rabbitmq_credentials.md +++ b/docs/stackit_rabbitmq_credentials.md @@ -23,6 +23,7 @@ stackit rabbitmq credentials [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_credentials_create.md b/docs/stackit_rabbitmq_credentials_create.md index 5221b186e..98f1c8e4c 100644 --- a/docs/stackit_rabbitmq_credentials_create.md +++ b/docs/stackit_rabbitmq_credentials_create.md @@ -35,6 +35,7 @@ stackit rabbitmq credentials create [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_credentials_delete.md b/docs/stackit_rabbitmq_credentials_delete.md index ff8c1e207..9e9cae18e 100644 --- a/docs/stackit_rabbitmq_credentials_delete.md +++ b/docs/stackit_rabbitmq_credentials_delete.md @@ -31,6 +31,7 @@ stackit rabbitmq credentials delete CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_credentials_describe.md b/docs/stackit_rabbitmq_credentials_describe.md index 48fb1b2ab..bd1f9fad3 100644 --- a/docs/stackit_rabbitmq_credentials_describe.md +++ b/docs/stackit_rabbitmq_credentials_describe.md @@ -34,6 +34,7 @@ stackit rabbitmq credentials describe CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_credentials_list.md b/docs/stackit_rabbitmq_credentials_list.md index 105de4d9f..8fe0b14f6 100644 --- a/docs/stackit_rabbitmq_credentials_list.md +++ b/docs/stackit_rabbitmq_credentials_list.md @@ -38,6 +38,7 @@ stackit rabbitmq credentials list [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_instance.md b/docs/stackit_rabbitmq_instance.md index e417d7664..0c6dd7af3 100644 --- a/docs/stackit_rabbitmq_instance.md +++ b/docs/stackit_rabbitmq_instance.md @@ -23,6 +23,7 @@ stackit rabbitmq instance [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_instance_create.md b/docs/stackit_rabbitmq_instance_create.md index bc14709c9..8b00f0fcc 100644 --- a/docs/stackit_rabbitmq_instance_create.md +++ b/docs/stackit_rabbitmq_instance_create.md @@ -48,6 +48,7 @@ stackit rabbitmq instance create [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_instance_delete.md b/docs/stackit_rabbitmq_instance_delete.md index f216d6cd3..4a078fc5e 100644 --- a/docs/stackit_rabbitmq_instance_delete.md +++ b/docs/stackit_rabbitmq_instance_delete.md @@ -30,6 +30,7 @@ stackit rabbitmq instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_instance_describe.md b/docs/stackit_rabbitmq_instance_describe.md index 1aa75f6ef..e2cb8cb74 100644 --- a/docs/stackit_rabbitmq_instance_describe.md +++ b/docs/stackit_rabbitmq_instance_describe.md @@ -33,6 +33,7 @@ stackit rabbitmq instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_instance_list.md b/docs/stackit_rabbitmq_instance_list.md index 5fc3d72f1..196a8f275 100644 --- a/docs/stackit_rabbitmq_instance_list.md +++ b/docs/stackit_rabbitmq_instance_list.md @@ -37,6 +37,7 @@ stackit rabbitmq instance list [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_instance_update.md b/docs/stackit_rabbitmq_instance_update.md index 6976587dc..985781786 100644 --- a/docs/stackit_rabbitmq_instance_update.md +++ b/docs/stackit_rabbitmq_instance_update.md @@ -44,6 +44,7 @@ stackit rabbitmq instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_rabbitmq_plans.md b/docs/stackit_rabbitmq_plans.md index ebd2d6652..fe33723a0 100644 --- a/docs/stackit_rabbitmq_plans.md +++ b/docs/stackit_rabbitmq_plans.md @@ -37,6 +37,7 @@ stackit rabbitmq plans [flags] --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") ``` diff --git a/docs/stackit_redis.md b/docs/stackit_redis.md index 16beda8f8..b371d2389 100644 --- a/docs/stackit_redis.md +++ b/docs/stackit_redis.md @@ -23,6 +23,7 @@ stackit redis [flags] --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") ``` diff --git a/docs/stackit_redis_credentials.md b/docs/stackit_redis_credentials.md index 37c2a269d..323147b4b 100644 --- a/docs/stackit_redis_credentials.md +++ b/docs/stackit_redis_credentials.md @@ -23,6 +23,7 @@ stackit redis credentials [flags] --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") ``` diff --git a/docs/stackit_redis_credentials_create.md b/docs/stackit_redis_credentials_create.md index 18fa56dad..444f9ee1e 100644 --- a/docs/stackit_redis_credentials_create.md +++ b/docs/stackit_redis_credentials_create.md @@ -35,6 +35,7 @@ stackit redis credentials create [flags] --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") ``` diff --git a/docs/stackit_redis_credentials_delete.md b/docs/stackit_redis_credentials_delete.md index a975a0a71..2ff4795cf 100644 --- a/docs/stackit_redis_credentials_delete.md +++ b/docs/stackit_redis_credentials_delete.md @@ -31,6 +31,7 @@ stackit redis credentials delete CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_redis_credentials_describe.md b/docs/stackit_redis_credentials_describe.md index 274c06563..8c3937344 100644 --- a/docs/stackit_redis_credentials_describe.md +++ b/docs/stackit_redis_credentials_describe.md @@ -34,6 +34,7 @@ stackit redis credentials describe CREDENTIALS_ID [flags] --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") ``` diff --git a/docs/stackit_redis_credentials_list.md b/docs/stackit_redis_credentials_list.md index 421d09924..14c162c0b 100644 --- a/docs/stackit_redis_credentials_list.md +++ b/docs/stackit_redis_credentials_list.md @@ -38,6 +38,7 @@ stackit redis credentials list [flags] --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") ``` diff --git a/docs/stackit_redis_instance.md b/docs/stackit_redis_instance.md index d5c956ee8..009415f9b 100644 --- a/docs/stackit_redis_instance.md +++ b/docs/stackit_redis_instance.md @@ -23,6 +23,7 @@ stackit redis instance [flags] --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") ``` diff --git a/docs/stackit_redis_instance_create.md b/docs/stackit_redis_instance_create.md index 92f3892cb..004741d48 100644 --- a/docs/stackit_redis_instance_create.md +++ b/docs/stackit_redis_instance_create.md @@ -47,6 +47,7 @@ stackit redis instance create [flags] --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") ``` diff --git a/docs/stackit_redis_instance_delete.md b/docs/stackit_redis_instance_delete.md index 4ad2da13b..2508659ee 100644 --- a/docs/stackit_redis_instance_delete.md +++ b/docs/stackit_redis_instance_delete.md @@ -30,6 +30,7 @@ stackit redis instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_redis_instance_describe.md b/docs/stackit_redis_instance_describe.md index 35c839779..4f7632ca3 100644 --- a/docs/stackit_redis_instance_describe.md +++ b/docs/stackit_redis_instance_describe.md @@ -33,6 +33,7 @@ stackit redis instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_redis_instance_list.md b/docs/stackit_redis_instance_list.md index e32b8763e..3c97031ac 100644 --- a/docs/stackit_redis_instance_list.md +++ b/docs/stackit_redis_instance_list.md @@ -37,6 +37,7 @@ stackit redis instance list [flags] --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") ``` diff --git a/docs/stackit_redis_instance_update.md b/docs/stackit_redis_instance_update.md index 2971e74b6..801622ed7 100644 --- a/docs/stackit_redis_instance_update.md +++ b/docs/stackit_redis_instance_update.md @@ -43,6 +43,7 @@ stackit redis instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_redis_plans.md b/docs/stackit_redis_plans.md index 5cce98b9a..2dc40245a 100644 --- a/docs/stackit_redis_plans.md +++ b/docs/stackit_redis_plans.md @@ -37,6 +37,7 @@ stackit redis plans [flags] --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") ``` diff --git a/docs/stackit_secrets-manager.md b/docs/stackit_secrets-manager.md index 59e7a99d6..84bb95a52 100644 --- a/docs/stackit_secrets-manager.md +++ b/docs/stackit_secrets-manager.md @@ -23,6 +23,7 @@ stackit secrets-manager [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_instance.md b/docs/stackit_secrets-manager_instance.md index d7857e067..db579c80c 100644 --- a/docs/stackit_secrets-manager_instance.md +++ b/docs/stackit_secrets-manager_instance.md @@ -23,6 +23,7 @@ stackit secrets-manager instance [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_instance_create.md b/docs/stackit_secrets-manager_instance_create.md index d41249ca5..379de7785 100644 --- a/docs/stackit_secrets-manager_instance_create.md +++ b/docs/stackit_secrets-manager_instance_create.md @@ -35,6 +35,7 @@ stackit secrets-manager instance create [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_instance_delete.md b/docs/stackit_secrets-manager_instance_delete.md index 057e9b1ba..0a8b18c6b 100644 --- a/docs/stackit_secrets-manager_instance_delete.md +++ b/docs/stackit_secrets-manager_instance_delete.md @@ -30,6 +30,7 @@ stackit secrets-manager instance delete INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_instance_describe.md b/docs/stackit_secrets-manager_instance_describe.md index d0f6756f5..d2695dc76 100644 --- a/docs/stackit_secrets-manager_instance_describe.md +++ b/docs/stackit_secrets-manager_instance_describe.md @@ -33,6 +33,7 @@ stackit secrets-manager instance describe INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_instance_list.md b/docs/stackit_secrets-manager_instance_list.md index 46cbcd4cd..742dd9000 100644 --- a/docs/stackit_secrets-manager_instance_list.md +++ b/docs/stackit_secrets-manager_instance_list.md @@ -37,6 +37,7 @@ stackit secrets-manager instance list [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_instance_update.md b/docs/stackit_secrets-manager_instance_update.md index 54f4b877c..cf40d3c1a 100644 --- a/docs/stackit_secrets-manager_instance_update.md +++ b/docs/stackit_secrets-manager_instance_update.md @@ -31,6 +31,7 @@ stackit secrets-manager instance update INSTANCE_ID [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_user.md b/docs/stackit_secrets-manager_user.md index 65899e83f..b6ba33cae 100644 --- a/docs/stackit_secrets-manager_user.md +++ b/docs/stackit_secrets-manager_user.md @@ -23,6 +23,7 @@ stackit secrets-manager user [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_user_create.md b/docs/stackit_secrets-manager_user_create.md index 043914508..34f83c324 100644 --- a/docs/stackit_secrets-manager_user_create.md +++ b/docs/stackit_secrets-manager_user_create.md @@ -38,6 +38,7 @@ stackit secrets-manager user create [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_user_delete.md b/docs/stackit_secrets-manager_user_delete.md index 4d0c30091..eb2a28000 100644 --- a/docs/stackit_secrets-manager_user_delete.md +++ b/docs/stackit_secrets-manager_user_delete.md @@ -32,6 +32,7 @@ stackit secrets-manager user delete USER_ID [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_user_describe.md b/docs/stackit_secrets-manager_user_describe.md index 0d4d77739..56ca9f25b 100644 --- a/docs/stackit_secrets-manager_user_describe.md +++ b/docs/stackit_secrets-manager_user_describe.md @@ -34,6 +34,7 @@ stackit secrets-manager user describe USER_ID [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_user_list.md b/docs/stackit_secrets-manager_user_list.md index cb500f260..b610591be 100644 --- a/docs/stackit_secrets-manager_user_list.md +++ b/docs/stackit_secrets-manager_user_list.md @@ -38,6 +38,7 @@ stackit secrets-manager user list [flags] --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") ``` diff --git a/docs/stackit_secrets-manager_user_update.md b/docs/stackit_secrets-manager_user_update.md index a6388f6d1..c181eb96e 100644 --- a/docs/stackit_secrets-manager_user_update.md +++ b/docs/stackit_secrets-manager_user_update.md @@ -36,6 +36,7 @@ stackit secrets-manager user update USER_ID [flags] --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") ``` diff --git a/docs/stackit_service-account.md b/docs/stackit_service-account.md index 4d72ed5e7..fbd524334 100644 --- a/docs/stackit_service-account.md +++ b/docs/stackit_service-account.md @@ -23,6 +23,7 @@ stackit service-account [flags] --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") ``` diff --git a/docs/stackit_service-account_create.md b/docs/stackit_service-account_create.md index 8f9d62ba3..cb1617fc7 100644 --- a/docs/stackit_service-account_create.md +++ b/docs/stackit_service-account_create.md @@ -31,6 +31,7 @@ stackit service-account create [flags] --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") ``` diff --git a/docs/stackit_service-account_delete.md b/docs/stackit_service-account_delete.md index 0e61bef0f..3e011d03f 100644 --- a/docs/stackit_service-account_delete.md +++ b/docs/stackit_service-account_delete.md @@ -30,6 +30,7 @@ stackit service-account delete EMAIL [flags] --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") ``` diff --git a/docs/stackit_service-account_get-jwks.md b/docs/stackit_service-account_get-jwks.md index b09aa4771..2c34e76fb 100644 --- a/docs/stackit_service-account_get-jwks.md +++ b/docs/stackit_service-account_get-jwks.md @@ -30,6 +30,7 @@ stackit service-account get-jwks EMAIL [flags] --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") ``` diff --git a/docs/stackit_service-account_key.md b/docs/stackit_service-account_key.md index ad9ad8aae..bb4306f77 100644 --- a/docs/stackit_service-account_key.md +++ b/docs/stackit_service-account_key.md @@ -23,6 +23,7 @@ stackit service-account key [flags] --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") ``` diff --git a/docs/stackit_service-account_key_create.md b/docs/stackit_service-account_key_create.md index 0f50cf0df..0ebcf7d02 100644 --- a/docs/stackit_service-account_key_create.md +++ b/docs/stackit_service-account_key_create.md @@ -41,6 +41,7 @@ stackit service-account key create [flags] --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") ``` diff --git a/docs/stackit_service-account_key_delete.md b/docs/stackit_service-account_key_delete.md index aa28e8413..b039f82f4 100644 --- a/docs/stackit_service-account_key_delete.md +++ b/docs/stackit_service-account_key_delete.md @@ -31,6 +31,7 @@ stackit service-account key delete KEY_ID [flags] --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") ``` diff --git a/docs/stackit_service-account_key_describe.md b/docs/stackit_service-account_key_describe.md index 58a3b922d..2ff0ac156 100644 --- a/docs/stackit_service-account_key_describe.md +++ b/docs/stackit_service-account_key_describe.md @@ -31,6 +31,7 @@ stackit service-account key describe KEY_ID [flags] --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") ``` diff --git a/docs/stackit_service-account_key_list.md b/docs/stackit_service-account_key_list.md index 811f40454..8ad4ad291 100644 --- a/docs/stackit_service-account_key_list.md +++ b/docs/stackit_service-account_key_list.md @@ -38,6 +38,7 @@ stackit service-account key list [flags] --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") ``` diff --git a/docs/stackit_service-account_key_update.md b/docs/stackit_service-account_key_update.md index 31ec346d6..f16648405 100644 --- a/docs/stackit_service-account_key_update.md +++ b/docs/stackit_service-account_key_update.md @@ -41,6 +41,7 @@ stackit service-account key update KEY_ID [flags] --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") ``` diff --git a/docs/stackit_service-account_list.md b/docs/stackit_service-account_list.md index 1ffec01ad..6e00f821c 100644 --- a/docs/stackit_service-account_list.md +++ b/docs/stackit_service-account_list.md @@ -31,6 +31,7 @@ stackit service-account list [flags] --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") ``` diff --git a/docs/stackit_service-account_token.md b/docs/stackit_service-account_token.md index 7a3a5e066..d417d9095 100644 --- a/docs/stackit_service-account_token.md +++ b/docs/stackit_service-account_token.md @@ -23,6 +23,7 @@ stackit service-account token [flags] --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") ``` diff --git a/docs/stackit_service-account_token_create.md b/docs/stackit_service-account_token_create.md index 49797b420..bcdc6fc41 100644 --- a/docs/stackit_service-account_token_create.md +++ b/docs/stackit_service-account_token_create.md @@ -37,6 +37,7 @@ stackit service-account token create [flags] --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") ``` diff --git a/docs/stackit_service-account_token_list.md b/docs/stackit_service-account_token_list.md index e340adadb..800689e4c 100644 --- a/docs/stackit_service-account_token_list.md +++ b/docs/stackit_service-account_token_list.md @@ -40,6 +40,7 @@ stackit service-account token list [flags] --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") ``` diff --git a/docs/stackit_service-account_token_revoke.md b/docs/stackit_service-account_token_revoke.md index 42a2f5fbb..d295e8168 100644 --- a/docs/stackit_service-account_token_revoke.md +++ b/docs/stackit_service-account_token_revoke.md @@ -33,6 +33,7 @@ stackit service-account token revoke TOKEN_ID [flags] --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") ``` diff --git a/docs/stackit_ske.md b/docs/stackit_ske.md index 5e8404f43..b6a307937 100644 --- a/docs/stackit_ske.md +++ b/docs/stackit_ske.md @@ -23,6 +23,7 @@ stackit ske [flags] --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") ``` diff --git a/docs/stackit_ske_cluster.md b/docs/stackit_ske_cluster.md index d98cd3bf9..7df9ba39e 100644 --- a/docs/stackit_ske_cluster.md +++ b/docs/stackit_ske_cluster.md @@ -23,6 +23,7 @@ stackit ske cluster [flags] --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") ``` diff --git a/docs/stackit_ske_cluster_create.md b/docs/stackit_ske_cluster_create.md index 5b15cb217..fa4e0b492 100644 --- a/docs/stackit_ske_cluster_create.md +++ b/docs/stackit_ske_cluster_create.md @@ -44,6 +44,7 @@ stackit ske cluster create CLUSTER_NAME [flags] --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") ``` diff --git a/docs/stackit_ske_cluster_delete.md b/docs/stackit_ske_cluster_delete.md index c2bb2ccd8..ad2915d87 100644 --- a/docs/stackit_ske_cluster_delete.md +++ b/docs/stackit_ske_cluster_delete.md @@ -30,6 +30,7 @@ stackit ske cluster delete CLUSTER_NAME [flags] --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") ``` diff --git a/docs/stackit_ske_cluster_describe.md b/docs/stackit_ske_cluster_describe.md index 733a9fa83..eb30860a9 100644 --- a/docs/stackit_ske_cluster_describe.md +++ b/docs/stackit_ske_cluster_describe.md @@ -33,6 +33,7 @@ stackit ske cluster describe CLUSTER_NAME [flags] --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") ``` diff --git a/docs/stackit_ske_cluster_generate-payload.md b/docs/stackit_ske_cluster_generate-payload.md index 9a40bb105..d5592293f 100644 --- a/docs/stackit_ske_cluster_generate-payload.md +++ b/docs/stackit_ske_cluster_generate-payload.md @@ -43,6 +43,7 @@ stackit ske cluster generate-payload [flags] --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") ``` diff --git a/docs/stackit_ske_cluster_list.md b/docs/stackit_ske_cluster_list.md index d0438ef6c..a757d19b3 100644 --- a/docs/stackit_ske_cluster_list.md +++ b/docs/stackit_ske_cluster_list.md @@ -37,6 +37,7 @@ stackit ske cluster list [flags] --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") ``` diff --git a/docs/stackit_ske_cluster_update.md b/docs/stackit_ske_cluster_update.md index 0e0482693..5209cc5df 100644 --- a/docs/stackit_ske_cluster_update.md +++ b/docs/stackit_ske_cluster_update.md @@ -41,6 +41,7 @@ stackit ske cluster update CLUSTER_NAME [flags] --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") ``` diff --git a/docs/stackit_ske_credentials.md b/docs/stackit_ske_credentials.md index 51d65fe36..252b629e0 100644 --- a/docs/stackit_ske_credentials.md +++ b/docs/stackit_ske_credentials.md @@ -23,6 +23,7 @@ stackit ske credentials [flags] --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") ``` diff --git a/docs/stackit_ske_credentials_complete-rotation.md b/docs/stackit_ske_credentials_complete-rotation.md index 04fc73052..12536dba5 100644 --- a/docs/stackit_ske_credentials_complete-rotation.md +++ b/docs/stackit_ske_credentials_complete-rotation.md @@ -45,6 +45,7 @@ stackit ske credentials complete-rotation CLUSTER_NAME [flags] --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") ``` diff --git a/docs/stackit_ske_credentials_start-rotation.md b/docs/stackit_ske_credentials_start-rotation.md index 35e3a7f5d..aa8160adf 100644 --- a/docs/stackit_ske_credentials_start-rotation.md +++ b/docs/stackit_ske_credentials_start-rotation.md @@ -49,6 +49,7 @@ stackit ske credentials start-rotation CLUSTER_NAME [flags] --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") ``` diff --git a/docs/stackit_ske_describe.md b/docs/stackit_ske_describe.md index d45433c2d..1cd29f31d 100644 --- a/docs/stackit_ske_describe.md +++ b/docs/stackit_ske_describe.md @@ -30,6 +30,7 @@ stackit ske describe [flags] --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") ``` diff --git a/docs/stackit_ske_disable.md b/docs/stackit_ske_disable.md index c9e973c6b..c86d2b10c 100644 --- a/docs/stackit_ske_disable.md +++ b/docs/stackit_ske_disable.md @@ -30,6 +30,7 @@ stackit ske disable [flags] --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") ``` diff --git a/docs/stackit_ske_enable.md b/docs/stackit_ske_enable.md index 19c88ac2d..ccc25bebb 100644 --- a/docs/stackit_ske_enable.md +++ b/docs/stackit_ske_enable.md @@ -30,6 +30,7 @@ stackit ske enable [flags] --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") ``` diff --git a/docs/stackit_ske_kubeconfig.md b/docs/stackit_ske_kubeconfig.md index d21edc87f..79d8f0381 100644 --- a/docs/stackit_ske_kubeconfig.md +++ b/docs/stackit_ske_kubeconfig.md @@ -23,6 +23,7 @@ stackit ske kubeconfig [flags] --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") ``` diff --git a/docs/stackit_ske_kubeconfig_create.md b/docs/stackit_ske_kubeconfig_create.md index a779cacc0..e49f37c93 100644 --- a/docs/stackit_ske_kubeconfig_create.md +++ b/docs/stackit_ske_kubeconfig_create.md @@ -50,6 +50,7 @@ stackit ske kubeconfig create CLUSTER_NAME [flags] --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") ``` diff --git a/docs/stackit_ske_kubeconfig_login.md b/docs/stackit_ske_kubeconfig_login.md index d7e2d7691..0b5441533 100644 --- a/docs/stackit_ske_kubeconfig_login.md +++ b/docs/stackit_ske_kubeconfig_login.md @@ -36,6 +36,7 @@ stackit ske kubeconfig login [flags] --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") ``` diff --git a/docs/stackit_ske_options.md b/docs/stackit_ske_options.md index 303bbe6e4..76afbe93c 100644 --- a/docs/stackit_ske_options.md +++ b/docs/stackit_ske_options.md @@ -42,6 +42,7 @@ stackit ske options [flags] --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") ``` diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 3e8c37f5c..0890dbc8a 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -18,6 +18,7 @@ const ( asyncFlag = globalflags.AsyncFlag outputFormatFlag = globalflags.OutputFormatFlag projectIdFlag = globalflags.ProjectIdFlag + regionFlag = globalflags.RegionFlag verbosityFlag = globalflags.VerbosityFlag sessionTimeLimitFlag = "session-time-limit" @@ -53,6 +54,7 @@ type inputModel struct { Async bool OutputFormat bool ProjectId bool + Region bool Verbosity bool SessionTimeLimit bool @@ -113,6 +115,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.ProjectId { viper.Set(config.ProjectIdKey, "") } + if model.Region { + viper.Set(config.RegionKey, config.RegionDefault) + } if model.Verbosity { viper.Set(config.VerbosityKey, globalflags.VerbosityDefault) } @@ -211,6 +216,7 @@ func NewCmd(p *print.Printer) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(asyncFlag, false, "Configuration option to run commands asynchronously") cmd.Flags().Bool(projectIdFlag, false, "Project ID") + cmd.Flags().Bool(regionFlag, false, "Region") cmd.Flags().Bool(outputFormatFlag, false, "Output format") cmd.Flags().Bool(verbosityFlag, false, "Verbosity of the CLI") @@ -248,6 +254,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { Async: flags.FlagToBoolValue(p, cmd, asyncFlag), OutputFormat: flags.FlagToBoolValue(p, cmd, outputFormatFlag), ProjectId: flags.FlagToBoolValue(p, cmd, projectIdFlag), + Region: flags.FlagToBoolValue(p, cmd, regionFlag), Verbosity: flags.FlagToBoolValue(p, cmd, verbosityFlag), SessionTimeLimit: flags.FlagToBoolValue(p, cmd, sessionTimeLimitFlag), diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 91ce0bb5a..f72154d92 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -14,6 +14,7 @@ const ( AsyncKey = "async" OutputFormatKey = "output_format" ProjectIdKey = "project_id" + RegionKey = "region" SessionTimeLimitKey = "session_time_limit" VerbosityKey = "verbosity" @@ -48,6 +49,7 @@ const ( DefaultProfileName = "default" AsyncDefault = false + RegionDefault = "eu01" SessionTimeLimitDefault = "2h" AllowedUrlDomainDefault = "stackit.cloud" @@ -68,6 +70,7 @@ var ConfigKeys = []string{ AsyncKey, OutputFormatKey, ProjectIdKey, + RegionKey, SessionTimeLimitKey, VerbosityKey, @@ -158,6 +161,7 @@ func setConfigDefaults() { viper.SetDefault(AsyncKey, AsyncDefault) viper.SetDefault(OutputFormatKey, "") viper.SetDefault(ProjectIdKey, "") + viper.SetDefault(RegionKey, RegionDefault) viper.SetDefault(SessionTimeLimitKey, SessionTimeLimitDefault) viper.SetDefault(IdentityProviderCustomWellKnownConfigurationKey, "") viper.SetDefault(IdentityProviderCustomClientIdKey, "") diff --git a/internal/pkg/globalflags/global_flags.go b/internal/pkg/globalflags/global_flags.go index 47c48ea13..9f53ec4f7 100644 --- a/internal/pkg/globalflags/global_flags.go +++ b/internal/pkg/globalflags/global_flags.go @@ -17,6 +17,7 @@ const ( AssumeYesFlag = "assume-yes" OutputFormatFlag = "output-format" ProjectIdFlag = "project-id" + RegionFlag = "region" VerbosityFlag = "verbosity" DebugVerbosity = string(print.DebugLevel) @@ -35,6 +36,7 @@ type GlobalFlagModel struct { AssumeYes bool OutputFormat string ProjectId string + Region string Verbosity string } @@ -65,6 +67,12 @@ func Configure(flagSet *pflag.FlagSet) error { return fmt.Errorf("bind --%s flag to config: %w", VerbosityFlag, err) } + flagSet.String(RegionFlag, "", "Target region for region-specific requests") + err = viper.BindPFlag(config.RegionKey, flagSet.Lookup(RegionFlag)) + if err != nil { + return fmt.Errorf("bind --%s flag to config: %w", RegionFlag, err) + } + return nil } @@ -74,6 +82,7 @@ func Parse(p *print.Printer, cmd *cobra.Command) *GlobalFlagModel { AssumeYes: flags.FlagToBoolValue(p, cmd, AssumeYesFlag), OutputFormat: viper.GetString(config.OutputFormatKey), ProjectId: viper.GetString(config.ProjectIdKey), + Region: viper.GetString(config.RegionKey), Verbosity: viper.GetString(config.VerbosityKey), } } diff --git a/internal/pkg/services/iaas/client/client.go b/internal/pkg/services/iaas/client/client.go index c9301496b..4f37168e7 100644 --- a/internal/pkg/services/iaas/client/client.go +++ b/internal/pkg/services/iaas/client/client.go @@ -27,7 +27,8 @@ func ConfigureClient(p *print.Printer) (*iaas.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) } if p.IsVerbosityDebug() { diff --git a/internal/pkg/services/load-balancer/client/client.go b/internal/pkg/services/load-balancer/client/client.go index 5a8aa31e4..dc0f51639 100644 --- a/internal/pkg/services/load-balancer/client/client.go +++ b/internal/pkg/services/load-balancer/client/client.go @@ -27,7 +27,8 @@ func ConfigureClient(p *print.Printer) (*loadbalancer.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) } if p.IsVerbosityDebug() { diff --git a/internal/pkg/services/logme/client/client.go b/internal/pkg/services/logme/client/client.go index e99e46bf7..fb3ba17a0 100644 --- a/internal/pkg/services/logme/client/client.go +++ b/internal/pkg/services/logme/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*logme.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.LogMeCustomEndpointKey) diff --git a/internal/pkg/services/mariadb/client/client.go b/internal/pkg/services/mariadb/client/client.go index 4d4dbce7e..d21e32f03 100644 --- a/internal/pkg/services/mariadb/client/client.go +++ b/internal/pkg/services/mariadb/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*mariadb.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.MariaDBCustomEndpointKey) diff --git a/internal/pkg/services/mongodbflex/client/client.go b/internal/pkg/services/mongodbflex/client/client.go index addcfe34a..65f9ec696 100644 --- a/internal/pkg/services/mongodbflex/client/client.go +++ b/internal/pkg/services/mongodbflex/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*mongodbflex.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.MongoDBFlexCustomEndpointKey) diff --git a/internal/pkg/services/object-storage/client/client.go b/internal/pkg/services/object-storage/client/client.go index f1a3a2147..13ca5c470 100644 --- a/internal/pkg/services/object-storage/client/client.go +++ b/internal/pkg/services/object-storage/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*objectstorage.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.ObjectStorageCustomEndpointKey) diff --git a/internal/pkg/services/observability/client/client.go b/internal/pkg/services/observability/client/client.go index a2af05d56..e629915d3 100644 --- a/internal/pkg/services/observability/client/client.go +++ b/internal/pkg/services/observability/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*observability.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.ObservabilityCustomEndpointKey) diff --git a/internal/pkg/services/opensearch/client/client.go b/internal/pkg/services/opensearch/client/client.go index b4036b37c..ce7a8f188 100644 --- a/internal/pkg/services/opensearch/client/client.go +++ b/internal/pkg/services/opensearch/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*opensearch.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.OpenSearchCustomEndpointKey) diff --git a/internal/pkg/services/postgresflex/client/client.go b/internal/pkg/services/postgresflex/client/client.go index 3698b1a46..d40584a4f 100644 --- a/internal/pkg/services/postgresflex/client/client.go +++ b/internal/pkg/services/postgresflex/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*postgresflex.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.PostgresFlexCustomEndpointKey) diff --git a/internal/pkg/services/rabbitmq/client/client.go b/internal/pkg/services/rabbitmq/client/client.go index 821037064..a4a7778ac 100644 --- a/internal/pkg/services/rabbitmq/client/client.go +++ b/internal/pkg/services/rabbitmq/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*rabbitmq.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.RabbitMQCustomEndpointKey) diff --git a/internal/pkg/services/redis/client/client.go b/internal/pkg/services/redis/client/client.go index 90e523c85..039da32f7 100644 --- a/internal/pkg/services/redis/client/client.go +++ b/internal/pkg/services/redis/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*redis.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.RedisCustomEndpointKey) diff --git a/internal/pkg/services/runcommand/client/client.go b/internal/pkg/services/runcommand/client/client.go index e9ef53cb5..5c43e3223 100644 --- a/internal/pkg/services/runcommand/client/client.go +++ b/internal/pkg/services/runcommand/client/client.go @@ -27,7 +27,8 @@ func ConfigureClient(p *print.Printer) (*runcommand.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) } if p.IsVerbosityDebug() { diff --git a/internal/pkg/services/secrets-manager/client/client.go b/internal/pkg/services/secrets-manager/client/client.go index e6aa7f2b5..ad1d8136f 100644 --- a/internal/pkg/services/secrets-manager/client/client.go +++ b/internal/pkg/services/secrets-manager/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*secretsmanager.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.SecretsManagerCustomEndpointKey) diff --git a/internal/pkg/services/serverbackup/client/client.go b/internal/pkg/services/serverbackup/client/client.go index 87a96bc94..589166e13 100644 --- a/internal/pkg/services/serverbackup/client/client.go +++ b/internal/pkg/services/serverbackup/client/client.go @@ -27,7 +27,8 @@ func ConfigureClient(p *print.Printer) (*serverbackup.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) } if p.IsVerbosityDebug() { diff --git a/internal/pkg/services/service-enablement/client/client.go b/internal/pkg/services/service-enablement/client/client.go index 9c260d51b..8fad8c06b 100644 --- a/internal/pkg/services/service-enablement/client/client.go +++ b/internal/pkg/services/service-enablement/client/client.go @@ -27,7 +27,8 @@ func ConfigureClient(p *print.Printer) (*serviceenablement.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - cfgOptions = append(cfgOptions, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, sdkConfig.WithRegion(region)) } if p.IsVerbosityDebug() { diff --git a/internal/pkg/services/ske/client/client.go b/internal/pkg/services/ske/client/client.go index 36175a964..788fcb4c3 100644 --- a/internal/pkg/services/ske/client/client.go +++ b/internal/pkg/services/ske/client/client.go @@ -27,7 +27,8 @@ func ConfigureClient(p *print.Printer) (*ske.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) } if p.IsVerbosityDebug() { diff --git a/internal/pkg/services/sqlserverflex/client/client.go b/internal/pkg/services/sqlserverflex/client/client.go index 0936d16f6..d3789ed5c 100644 --- a/internal/pkg/services/sqlserverflex/client/client.go +++ b/internal/pkg/services/sqlserverflex/client/client.go @@ -21,7 +21,8 @@ func ConfigureClient(p *print.Printer) (*sqlserverflex.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + region := viper.GetString(config.RegionKey) + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) customEndpoint := viper.GetString(config.SQLServerFlexCustomEndpointKey) From a3a07544e5695f8ec9520c770d978bdad143c5ef Mon Sep 17 00:00:00 2001 From: Marcel <72880145+marceljk@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:34:42 +0100 Subject: [PATCH 141/619] Fix: Kubeconfig not written when output format is json (#553) * Fix: Kubeconfig doesn't get written when output format is json - Add flag to disable the writing of kubeconfig --- docs/stackit_ske_kubeconfig_create.md | 4 +++ internal/cmd/ske/kubeconfig/create/create.go | 25 +++++++++++++++---- .../cmd/ske/kubeconfig/create/create_test.go | 21 ++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/docs/stackit_ske_kubeconfig_create.md b/docs/stackit_ske_kubeconfig_create.md index e49f37c93..c6f512ba8 100644 --- a/docs/stackit_ske_kubeconfig_create.md +++ b/docs/stackit_ske_kubeconfig_create.md @@ -32,11 +32,15 @@ stackit ske kubeconfig create CLUSTER_NAME [flags] Create a kubeconfig for the SKE cluster with name "my-cluster" in a custom filepath $ stackit ske kubeconfig create my-cluster --filepath /path/to/config + + Get a kubeconfig for the SKE cluster with name "my-cluster" without writing it to a file. + ``` ### Options ``` + --disable-writing Disable writing to the kubeconfig file. -e, --expiration string Expiration time for the kubeconfig in seconds(s), minutes(m), hours(h), days(d) or months(M). Example: 30d. By default, expiration time is 1h --filepath string Path to create the kubeconfig file. By default, the kubeconfig is created as 'config' in the .kube folder, in the user's home directory. -h, --help Help for "stackit ske kubeconfig create" diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index 53310c43f..be86251ab 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -22,9 +22,10 @@ import ( const ( clusterNameArg = "CLUSTER_NAME" - loginFlag = "login" - expirationFlag = "expiration" - filepathFlag = "filepath" + loginFlag = "login" + expirationFlag = "expiration" + filepathFlag = "filepath" + disableWritingFlag = "disable-writing" ) type inputModel struct { @@ -33,6 +34,7 @@ type inputModel struct { Filepath *string ExpirationTime *string Login bool + DisableWriting bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -63,6 +65,9 @@ func NewCmd(p *print.Printer) *cobra.Command { examples.NewExample( `Create a kubeconfig for the SKE cluster with name "my-cluster" in a custom filepath`, "$ stackit ske kubeconfig create my-cluster --filepath /path/to/config"), + examples.NewExample( + `Get a kubeconfig for the SKE cluster with name "my-cluster" without writing it to a file and format the output as json`, + "$ stackit ske kubeconfig create my-cluster --disable-writing --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -77,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - if !model.AssumeYes { + if !model.AssumeYes && !model.DisableWriting { prompt := fmt.Sprintf("Are you sure you want to create a kubeconfig for SKE cluster %q? This will OVERWRITE your current kubeconfig file, if it exists.", model.ClusterName) err = p.PromptForConfirmation(prompt) if err != nil { @@ -131,7 +136,7 @@ func NewCmd(p *print.Printer) *cobra.Command { kubeconfigPath = *model.Filepath } - if model.OutputFormat != print.JSONOutputFormat { + if !model.DisableWriting { err = skeUtils.WriteConfigFile(kubeconfigPath, kubeconfig) if err != nil { return fmt.Errorf("write kubeconfig file: %w", err) @@ -149,6 +154,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().BoolP(loginFlag, "l", false, "Create a login kubeconfig that obtains valid credentials via the STACKIT CLI. This flag is mutually exclusive with the expiration flag.") cmd.Flags().StringP(expirationFlag, "e", "", "Expiration time for the kubeconfig in seconds(s), minutes(m), hours(h), days(d) or months(M). Example: 30d. By default, expiration time is 1h") cmd.Flags().String(filepathFlag, "", "Path to create the kubeconfig file. By default, the kubeconfig is created as 'config' in the .kube folder, in the user's home directory.") + cmd.Flags().Bool(disableWritingFlag, false, fmt.Sprintf("Disable the writing of kubeconfig. Set the output format to json or yaml using the --%s flag to display the kubeconfig.", globalflags.OutputFormatFlag)) cmd.MarkFlagsMutuallyExclusive(loginFlag, expirationFlag) } @@ -174,12 +180,21 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } } + disableWriting := flags.FlagToBoolValue(p, cmd, disableWritingFlag) + + isInvalidOutputFormat := globalFlags.OutputFormat == "" || globalFlags.OutputFormat == print.NoneOutputFormat || globalFlags.OutputFormat == print.PrettyOutputFormat + if disableWriting && isInvalidOutputFormat { + return nil, fmt.Errorf("when setting the flag --%s, you must specify --%s as one of the values: %s", + disableWritingFlag, globalflags.OutputFormatFlag, fmt.Sprintf("%s, %s", print.JSONOutputFormat, print.YAMLOutputFormat)) + } + model := inputModel{ GlobalFlagModel: globalFlags, ClusterName: clusterName, Filepath: flags.FlagToStringPointer(p, cmd, filepathFlag), ExpirationTime: expTime, Login: flags.FlagToBoolValue(p, cmd, loginFlag), + DisableWriting: disableWriting, } if p.IsVerbosityDebug() { diff --git a/internal/cmd/ske/kubeconfig/create/create_test.go b/internal/cmd/ske/kubeconfig/create/create_test.go index 86fb29ac4..bae59d3bb 100644 --- a/internal/cmd/ske/kubeconfig/create/create_test.go +++ b/internal/cmd/ske/kubeconfig/create/create_test.go @@ -156,6 +156,27 @@ func TestParseInput(t *testing.T) { }), isValid: false, }, + { + description: "disable writing and invalid output format", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[disableWritingFlag] = "true" + }), + isValid: false, + }, + { + description: "disable writing and valid output format", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[disableWritingFlag] = "true" + flagValues[globalflags.OutputFormatFlag] = print.YAMLOutputFormat + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.DisableWriting = true + model.OutputFormat = print.YAMLOutputFormat + }), + isValid: true, + }, } for _, tt := range tests { From 16b1699119382c9706042e927dc371ccc01fe11f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 13 Jan 2025 08:48:27 +0100 Subject: [PATCH 142/619] fix(deps): update module github.com/mattn/go-colorable to v0.1.14 (#554) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 538c43782..646b561a0 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jedib0t/go-pretty/v6 v6.6.5 github.com/lmittmann/tint v1.0.6 - github.com/mattn/go-colorable v0.1.13 + github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 diff --git a/go.sum b/go.sum index 9b95109da..6a54c79ee 100644 --- a/go.sum +++ b/go.sum @@ -74,9 +74,8 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= @@ -206,7 +205,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= From 135cb029bf6703e1a0f2d8199a969f4501d0d3d7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 13 Jan 2025 08:49:27 +0100 Subject: [PATCH 143/619] fix(deps): update stackit sdk modules (#555) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 646b561a0..e0aabaf5b 100644 --- a/go.mod +++ b/go.mod @@ -15,8 +15,8 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 - github.com/stackitcloud/stackit-sdk-go/core v0.15.0 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1 + github.com/stackitcloud/stackit-sdk-go/core v0.15.1 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1 diff --git a/go.sum b/go.sum index 6a54c79ee..b912ad829 100644 --- a/go.sum +++ b/go.sum @@ -117,10 +117,10 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= -github.com/stackitcloud/stackit-sdk-go/core v0.15.0 h1:oMP6L616/bP3b/B1Me7Ptu637dAJKr7NO3Rd3UwqpvE= -github.com/stackitcloud/stackit-sdk-go/core v0.15.0/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1 h1:sK7FZHN1tF8D/7rbWLhu4DX0qrAP5Psn2NusnwbCsEM= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.4.1/go.mod h1:8spVqlPqZrvQQ63Qodbydk3qsZx7lr963ECft+sqFhY= +github.com/stackitcloud/stackit-sdk-go/core v0.15.1 h1:hIj/k/JXEuYmud3VWo3lr7Cfj2hfl4gG9nUIzcaZ9pM= +github.com/stackitcloud/stackit-sdk-go/core v0.15.1/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.0 h1:Phqfx//JkBSFc1cq31d6EDzLDZU5JukaODMlaWpnFQw= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.0/go.mod h1:wP0L4+HKCKei7r26u7w4+tIOOsRwtkz/2RAsLGPXDMU= github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 h1:nzOZQ2X6joM2iStePoACZeYvXFBQIBjkYE9sLanOGvE= github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 h1:o9OAGh4mdYY5LZYZiJio0KYUhqPSpBY4vT08piGx0pI= From 5d5ae24841bcdd01c065a7d8519c61d3725e59a9 Mon Sep 17 00:00:00 2001 From: Vicente Pinto Date: Tue, 14 Jan 2025 09:38:21 +0000 Subject: [PATCH 144/619] Improve README! (#558) --- README.md | 54 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 2bac5e5b5..db0ef81a2 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,15 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/stackitcloud/stackit-cli)](https://goreportcard.com/report/github.com/stackitcloud/stackit-cli) ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/stackitcloud/stackit-cli) [![GitHub License](https://img.shields.io/github/license/stackitcloud/stackit-cli)](https://www.apache.org/licenses/LICENSE-2.0) -Welcome to the [STACKIT](https://www.stackit.de/en) CLI, a command-line interface for the STACKIT services. +Welcome to the STACKIT CLI, a command-line interface for [STACKIT - The German business cloud](https://www.stackit.de/en). + +The STACKIT CLI allows you to manage your STACKIT services and resources as well as perform operations using the command-line or in scripts or automation, such as: + +- Projects, including permissions +- STACKIT Kubernetes Engine clusters +- Servers +- DNS zones and record-sets +- Databases such as PostgreSQL Flex, MongoDB Flex and SQLServer Flex This CLI is in a BETA state. More services and functionality will be supported soon. Your feedback is appreciated! @@ -65,28 +73,28 @@ Help is available for any command by specifying the special flag `--help` (or si Below you can find a list of the STACKIT services already available in the CLI (along with their respective command names) and the ones that are currently planned to be integrated. -| Service | CLI Commands | Status | -| ---------------------------------- |--------------------------------------------------------------------------------------------------------------------------------------------------| ------------------------- | -| Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta security-group`
`beta key-pair` | :white_check_mark: (beta) | -| Authorization | `project`, `organization` | :white_check_mark: | -| DNS | `dns` | :white_check_mark: | -| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | -| Load Balancer | `load-balancer` | :white_check_mark: | -| LogMe | `logme` | :white_check_mark: | -| MariaDB | `mariadb` | :white_check_mark: | -| MongoDB Flex | `mongodbflex` | :white_check_mark: | -| Object Storage | `object-storage` | :white_check_mark: | -| OpenSearch | `opensearch` | :white_check_mark: | -| PostgreSQL Flex | `postgresflex` | :white_check_mark: | -| RabbitMQ | `rabbitmq` | :white_check_mark: | -| Redis | `redis` | :white_check_mark: | -| Resource Manager | `project` | :white_check_mark: | -| Secrets Manager | `secrets-manager` | :white_check_mark: | -| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | -| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | -| Service Account | `service-account` | :white_check_mark: | -| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | +| Service | CLI Commands | Status | +| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | +| Observability | `observability` | :white_check_mark: | +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta security-group`
`beta key-pair` | :white_check_mark: (beta) | +| Authorization | `project`, `organization` | :white_check_mark: | +| DNS | `dns` | :white_check_mark: | +| Kubernetes Engine (SKE) | `ske` | :white_check_mark: | +| Load Balancer | `load-balancer` | :white_check_mark: | +| LogMe | `logme` | :white_check_mark: | +| MariaDB | `mariadb` | :white_check_mark: | +| MongoDB Flex | `mongodbflex` | :white_check_mark: | +| Object Storage | `object-storage` | :white_check_mark: | +| OpenSearch | `opensearch` | :white_check_mark: | +| PostgreSQL Flex | `postgresflex` | :white_check_mark: | +| RabbitMQ | `rabbitmq` | :white_check_mark: | +| Redis | `redis` | :white_check_mark: | +| Resource Manager | `project` | :white_check_mark: | +| Secrets Manager | `secrets-manager` | :white_check_mark: | +| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | +| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | +| Service Account | `service-account` | :white_check_mark: | +| SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | ## Authentication From bc4c8c63fc5f5b8d459cbd4fd5bf958c29e29dd4 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 15 Jan 2025 08:50:43 +0100 Subject: [PATCH 145/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/serverbackup to v0.5.0 (#560) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e0aabaf5b..4b6553eb8 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.1 diff --git a/go.sum b/go.sum index b912ad829..e2800bb6d 100644 --- a/go.sum +++ b/go.sum @@ -151,8 +151,8 @@ github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 h1:qAKT20siGhk github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1/go.mod h1:LgCIIj7jA2lWX4DI3bxUYD+m0TbWCr1VgAyBYNJeghc= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 h1:qShB0OuNR8EOffY36/DfJs/Yk12syy38xkE88Z15f4k= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0 h1:Tlps8vBQmQ1mx2YFbzOzMIyWtXGJy7X3N9Qk3qk88Cc= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.3.0/go.mod h1:+807U5ZLXns+CEbyIg483wNEwV10vaN6GjMnSZhw/64= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 h1:33zKhcNS1bZ2usGnYZ6YE6Vxm7c9U0aC8lDg96UN+e4= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0/go.mod h1:thrCIDBjEHAcihjWUOMJ5mbYVhOWfS/bLTBJ+yl5W4g= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= From b39e32c2c8a25f64e6a6c5eb46f5d8fa319fbfde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Wed, 15 Jan 2025 13:44:33 +0100 Subject: [PATCH 146/619] Support for IaaS images (#559) * feat: implementation of list command * feature: create command * feat: corrected package name * feat: implemented delete command * feat: add describe command * feat: added update command * feat: linter fixes * feat: documentation * Update internal/cmd/beta/image/update/update.go Co-authored-by: Marcel Jacek <72880145+marceljk@users.noreply.github.com> * feat: fix review findings * feat: add progress indicator based on actually uploaded data * feat: added explicit termination of progress indicator * chore: fix review findings * chore: fixed linter hints * chore: fix linting warnings, recreated docs again --------- Co-authored-by: Marcel Jacek <72880145+marceljk@users.noreply.github.com> --- README.md | 2 +- docs/stackit_beta.md | 1 + docs/stackit_beta_image.md | 38 ++ docs/stackit_beta_image_create.md | 64 +++ docs/stackit_beta_image_delete.md | 40 ++ docs/stackit_beta_image_describe.md | 40 ++ docs/stackit_beta_image_list.md | 48 +++ docs/stackit_beta_image_update.md | 63 +++ docs/stackit_ske_kubeconfig_create.md | 6 +- internal/cmd/beta/beta.go | 2 + internal/cmd/beta/image/create/create.go | 400 ++++++++++++++++++ internal/cmd/beta/image/create/create_test.go | 341 +++++++++++++++ internal/cmd/beta/image/delete/delete.go | 110 +++++ internal/cmd/beta/image/delete/delete_test.go | 183 ++++++++ internal/cmd/beta/image/describe/describe.go | 173 ++++++++ .../cmd/beta/image/describe/describe_test.go | 194 +++++++++ internal/cmd/beta/image/image.go | 37 ++ internal/cmd/beta/image/list/list.go | 189 +++++++++ internal/cmd/beta/image/list/list_test.go | 212 ++++++++++ internal/cmd/beta/image/update/update.go | 283 +++++++++++++ internal/cmd/beta/image/update/update_test.go | 383 +++++++++++++++++ internal/pkg/services/iaas/utils/utils.go | 12 + .../pkg/services/iaas/utils/utils_test.go | 53 +++ internal/pkg/utils/strings.go | 26 ++ 24 files changed, 2896 insertions(+), 4 deletions(-) create mode 100644 docs/stackit_beta_image.md create mode 100644 docs/stackit_beta_image_create.md create mode 100644 docs/stackit_beta_image_delete.md create mode 100644 docs/stackit_beta_image_describe.md create mode 100644 docs/stackit_beta_image_list.md create mode 100644 docs/stackit_beta_image_update.md create mode 100644 internal/cmd/beta/image/create/create.go create mode 100644 internal/cmd/beta/image/create/create_test.go create mode 100644 internal/cmd/beta/image/delete/delete.go create mode 100644 internal/cmd/beta/image/delete/delete_test.go create mode 100644 internal/cmd/beta/image/describe/describe.go create mode 100644 internal/cmd/beta/image/describe/describe_test.go create mode 100644 internal/cmd/beta/image/image.go create mode 100644 internal/cmd/beta/image/list/list.go create mode 100644 internal/cmd/beta/image/list/list_test.go create mode 100644 internal/cmd/beta/image/update/update.go create mode 100644 internal/cmd/beta/image/update/update_test.go create mode 100644 internal/pkg/utils/strings.go diff --git a/README.md b/README.md index db0ef81a2..b00887fd9 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Service | CLI Commands | Status | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | | Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta security-group`
`beta key-pair` | :white_check_mark: (beta) | +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta security-group`
`beta key-pair`
`beta image` | :white_check_mark: (beta)| | Authorization | `project`, `organization` | :white_check_mark: | | DNS | `dns` | :white_check_mark: | | Kubernetes Engine (SKE) | `ske` | :white_check_mark: | diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index d27cf4df6..d5ed983dc 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -41,6 +41,7 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit beta image](./stackit_beta_image.md) - Manage server images * [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs * [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) diff --git a/docs/stackit_beta_image.md b/docs/stackit_beta_image.md new file mode 100644 index 000000000..2885055ea --- /dev/null +++ b/docs/stackit_beta_image.md @@ -0,0 +1,38 @@ +## stackit beta image + +Manage server images + +### Synopsis + +Manage the lifecycle of server images. + +``` +stackit beta image [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta image" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta image create](./stackit_beta_image_create.md) - Creates images +* [stackit beta image delete](./stackit_beta_image_delete.md) - Deletes an image +* [stackit beta image describe](./stackit_beta_image_describe.md) - Describes image +* [stackit beta image list](./stackit_beta_image_list.md) - Lists images +* [stackit beta image update](./stackit_beta_image_update.md) - Updates an image + diff --git a/docs/stackit_beta_image_create.md b/docs/stackit_beta_image_create.md new file mode 100644 index 000000000..8044adef0 --- /dev/null +++ b/docs/stackit_beta_image_create.md @@ -0,0 +1,64 @@ +## stackit beta image create + +Creates images + +### Synopsis + +Creates images. + +``` +stackit beta image create [flags] +``` + +### Examples + +``` + Create an image with name 'my-new-image' from a raw disk image located in '/my/raw/image' + $ stackit beta image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image + + Create an image with name 'my-new-image' from a qcow2 image read from '/my/qcow2/image' with labels describing its contents + $ stackit beta image create --name my-new-image --disk-format=qcow2 --local-file-path=/my/qcow2/image --labels os=linux,distro=alpine,version=3.12 +``` + +### Options + +``` + --boot-menu Enables the BIOS bootmenu. + --cdrom-bus string Sets CDROM bus controller type. + --disk-bus string Sets Disk bus controller type. + --disk-format string The disk format of the image. + -h, --help Help for "stackit beta image create" + --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) + --local-file-path string The path to the local disk image file. + --min-disk-size int Size in Gigabyte. + --min-ram int Size in Megabyte. + --name string The name of the image. + --nic-model string Sets virtual nic model. + --no-progress Show no progress indicator for upload. + --os string Enables OS specific optimizations. + --os-distro string Operating System Distribution. + --os-version string Version of the OS. + --protected Protected VM. + --rescue-bus string Sets the device bus when the image is used as a rescue image. + --rescue-device string Sets the device when the image is used as a rescue image. + --secure-boot Enables Secure Boot. + --uefi Enables UEFI boot. + --video-model string Sets Graphic device model. + --virtio-scsi Enables the use of VirtIO SCSI to provide block device access. By default instances use VirtIO Block. +``` + +### 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 beta image](./stackit_beta_image.md) - Manage server images + diff --git a/docs/stackit_beta_image_delete.md b/docs/stackit_beta_image_delete.md new file mode 100644 index 000000000..996596864 --- /dev/null +++ b/docs/stackit_beta_image_delete.md @@ -0,0 +1,40 @@ +## stackit beta image delete + +Deletes an image + +### Synopsis + +Deletes an image by its internal ID. + +``` +stackit beta image delete IMAGE_ID [flags] +``` + +### Examples + +``` + Delete an image with ID "xxx" + $ stackit beta image delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta image delete" +``` + +### 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 beta image](./stackit_beta_image.md) - Manage server images + diff --git a/docs/stackit_beta_image_describe.md b/docs/stackit_beta_image_describe.md new file mode 100644 index 000000000..6e1059166 --- /dev/null +++ b/docs/stackit_beta_image_describe.md @@ -0,0 +1,40 @@ +## stackit beta image describe + +Describes image + +### Synopsis + +Describes an image by its internal ID. + +``` +stackit beta image describe IMAGE_ID [flags] +``` + +### Examples + +``` + Describe image "xxx" + $ stackit beta image describe xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta image 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 beta image](./stackit_beta_image.md) - Manage server images + diff --git a/docs/stackit_beta_image_list.md b/docs/stackit_beta_image_list.md new file mode 100644 index 000000000..19ac93016 --- /dev/null +++ b/docs/stackit_beta_image_list.md @@ -0,0 +1,48 @@ +## stackit beta image list + +Lists images + +### Synopsis + +Lists images by their internal ID. + +``` +stackit beta image list [flags] +``` + +### Examples + +``` + List all images + $ stackit beta image list + + List images with label + $ stackit beta image list --label-selector ARM64,dev + + List the first 10 images + $ stackit beta image list --limit=10 +``` + +### Options + +``` + -h, --help Help for "stackit beta image list" + --label-selector string Filter by label + --limit int Limit the output to the first n elements +``` + +### 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 beta image](./stackit_beta_image.md) - Manage server images + diff --git a/docs/stackit_beta_image_update.md b/docs/stackit_beta_image_update.md new file mode 100644 index 000000000..760d561de --- /dev/null +++ b/docs/stackit_beta_image_update.md @@ -0,0 +1,63 @@ +## stackit beta image update + +Updates an image + +### Synopsis + +Updates an image + +``` +stackit beta image update IMAGE_ID [flags] +``` + +### Examples + +``` + Update the name of an image with ID "xxx" + $ stackit beta image update xxx --name my-new-name + + Update the labels of an image with ID "xxx" + $ stackit beta image update xxx --labels label1=value1,label2=value2 +``` + +### Options + +``` + --boot-menu Enables the BIOS bootmenu. + --cdrom-bus string Sets CDROM bus controller type. + --disk-bus string Sets Disk bus controller type. + --disk-format string The disk format of the image. + -h, --help Help for "stackit beta image update" + --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) + --local-file-path string The path to the local disk image file. + --min-disk-size int Size in Gigabyte. + --min-ram int Size in Megabyte. + --name string The name of the image. + --nic-model string Sets virtual nic model. + --os string Enables OS specific optimizations. + --os-distro string Operating System Distribution. + --os-version string Version of the OS. + --protected Protected VM. + --rescue-bus string Sets the device bus when the image is used as a rescue image. + --rescue-device string Sets the device when the image is used as a rescue image. + --secure-boot Enables Secure Boot. + --uefi Enables UEFI boot. + --video-model string Sets Graphic device model. + --virtio-scsi Enables the use of VirtIO SCSI to provide block device access. By default instances use VirtIO Block. +``` + +### 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 beta image](./stackit_beta_image.md) - Manage server images + diff --git a/docs/stackit_ske_kubeconfig_create.md b/docs/stackit_ske_kubeconfig_create.md index c6f512ba8..b63225e7e 100644 --- a/docs/stackit_ske_kubeconfig_create.md +++ b/docs/stackit_ske_kubeconfig_create.md @@ -33,14 +33,14 @@ stackit ske kubeconfig create CLUSTER_NAME [flags] Create a kubeconfig for the SKE cluster with name "my-cluster" in a custom filepath $ stackit ske kubeconfig create my-cluster --filepath /path/to/config - Get a kubeconfig for the SKE cluster with name "my-cluster" without writing it to a file. - + Get a kubeconfig for the SKE cluster with name "my-cluster" without writing it to a file and format the output as json + $ stackit ske kubeconfig create my-cluster --disable-writing --output-format json ``` ### Options ``` - --disable-writing Disable writing to the kubeconfig file. + --disable-writing Disable the writing of kubeconfig. Set the output format to json or yaml using the --output-format flag to display the kubeconfig. -e, --expiration string Expiration time for the kubeconfig in seconds(s), minutes(m), hours(h), days(d) or months(M). Example: 30d. By default, expiration time is 1h --filepath string Path to create the kubeconfig file. By default, the kubeconfig is created as 'config' in the .kube folder, in the user's home directory. -h, --help Help for "stackit ske kubeconfig create" diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 0ec43d0f2..966e5f414 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,6 +3,7 @@ package beta import ( "fmt" + image "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image" keypair "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network" networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" @@ -52,4 +53,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(publicip.NewCmd(p)) cmd.AddCommand(securitygroup.NewCmd(p)) cmd.AddCommand(keypair.NewCmd(p)) + cmd.AddCommand(image.NewCmd(p)) } diff --git a/internal/cmd/beta/image/create/create.go b/internal/cmd/beta/image/create/create.go new file mode 100644 index 000000000..fee5907c5 --- /dev/null +++ b/internal/cmd/beta/image/create/create.go @@ -0,0 +1,400 @@ +package create + +import ( + "bufio" + "context" + "encoding/json" + goerrors "errors" + "fmt" + "io" + "net/http" + "os" + "time" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + nameFlag = "name" + diskFormatFlag = "disk-format" + localFilePathFlag = "local-file-path" + noProgressIndicatorFlag = "no-progress" + + bootMenuFlag = "boot-menu" + cdromBusFlag = "cdrom-bus" + diskBusFlag = "disk-bus" + nicModelFlag = "nic-model" + operatingSystemFlag = "os" + operatingSystemDistroFlag = "os-distro" + operatingSystemVersionFlag = "os-version" + rescueBusFlag = "rescue-bus" + rescueDeviceFlag = "rescue-device" + secureBootFlag = "secure-boot" + uefiFlag = "uefi" + videoModelFlag = "video-model" + virtioScsiFlag = "virtio-scsi" + + labelsFlag = "labels" + + minDiskSizeFlag = "min-disk-size" + minRamFlag = "min-ram" + protectedFlag = "protected" +) + +type imageConfig struct { + BootMenu *bool + CdromBus *string + DiskBus *string + NicModel *string + OperatingSystem *string + OperatingSystemDistro *string + OperatingSystemVersion *string + RescueBus *string + RescueDevice *string + SecureBoot *bool + Uefi *bool + VideoModel *string + VirtioScsi *bool +} +type inputModel struct { + *globalflags.GlobalFlagModel + + Id *string + Name string + DiskFormat string + LocalFilePath string + Labels *map[string]string + Config *imageConfig + MinDiskSize *int64 + MinRam *int64 + Protected *bool + NoProgressIndicator *bool +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates images", + Long: "Creates images.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create an image with name 'my-new-image' from a raw disk image located in '/my/raw/image'`, + `$ stackit beta image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image`, + ), + examples.NewExample( + `Create an image with name 'my-new-image' from a qcow2 image read from '/my/qcow2/image' with labels describing its contents`, + `$ stackit beta image create --name my-new-image --disk-format=qcow2 --local-file-path=/my/qcow2/image --labels os=linux,distro=alpine,version=3.12`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) (err error) { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // we open input file first to fail fast, if it is not readable + file, err := os.Open(model.LocalFilePath) + if err != nil { + return fmt.Errorf("create image: file %q is not readable: %w", model.LocalFilePath, err) + } + defer func() { + if inner := file.Close(); inner != nil { + err = fmt.Errorf("error closing input file: %w (%w)", inner, err) + } + }() + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create the image %q?", model.Name) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + result, err := request.Execute() + if err != nil { + return fmt.Errorf("create image: %w", err) + } + model.Id = result.Id + url, ok := result.GetUploadUrlOk() + if !ok { + return fmt.Errorf("create image: no upload URL has been provided") + } + if err := uploadAsync(ctx, p, model, file, *url); err != nil { + return err + } + + if err := outputResult(p, model, result); err != nil { + return err + } + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func uploadAsync(ctx context.Context, p *print.Printer, model *inputModel, file *os.File, url string) error { + stat, err := file.Stat() + if err != nil { + return fmt.Errorf("upload file: %w", err) + } + + var reader io.Reader + if model.NoProgressIndicator != nil && *model.NoProgressIndicator { + reader = file + } else { + var ch <-chan int + reader, ch = newProgressReader(file) + go func() { + ticker := time.NewTicker(2 * time.Second) + var uploaded int + done: + for { + select { + case <-ticker.C: + p.Info("uploaded %3.1f%%\r", 100.0/float64(stat.Size())*float64(uploaded)) + case n, ok := <-ch: + if !ok { + break done + } + if n >= 0 { + uploaded += n + } + } + } + }() + } + + if err = uploadFile(ctx, p, reader, stat.Size(), url); err != nil { + return fmt.Errorf("upload file: %w", err) + } + + return nil +} + +var _ io.Reader = (*progressReader)(nil) + +type progressReader struct { + delegate io.Reader + ch chan int +} + +func newProgressReader(delegate io.Reader) (reader io.Reader, result <-chan int) { + ch := make(chan int) + return &progressReader{ + delegate: delegate, + ch: ch, + }, ch +} + +// Read implements io.Reader. +func (pr *progressReader) Read(p []byte) (int, error) { + n, err := pr.delegate.Read(p) + if goerrors.Is(err, io.EOF) && n <= 0 { + close(pr.ch) + } else { + pr.ch <- n + } + return n, err +} + +func uploadFile(ctx context.Context, p *print.Printer, reader io.Reader, filesize int64, url string) error { + p.Debug(print.DebugLevel, "uploading image to %s", url) + + start := time.Now() + // pass the file contents as stream, as they can get arbitrarily large. We do + // _not_ want to load them into an internal buffer. The downside is, that we + // have to set the content-length header manually + uploadRequest, err := http.NewRequestWithContext(ctx, http.MethodPut, url, bufio.NewReader(reader)) + if err != nil { + return fmt.Errorf("create image: cannot create request: %w", err) + } + uploadRequest.Header.Add("Content-Type", "application/octet-stream") + uploadRequest.ContentLength = filesize + + uploadResponse, err := http.DefaultClient.Do(uploadRequest) + if err != nil { + return fmt.Errorf("create image: error contacting server for upload: %w", err) + } + defer func() { + if inner := uploadResponse.Body.Close(); inner != nil { + err = fmt.Errorf("error closing file: %w (%w)", inner, err) + } + }() + if uploadResponse.StatusCode != http.StatusOK { + return fmt.Errorf("create image: server rejected image upload with %s", uploadResponse.Status) + } + delay := time.Since(start) + p.Debug(print.DebugLevel, "uploaded %d bytes in %v", filesize, delay) + + return nil +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "The name of the image.") + cmd.Flags().String(diskFormatFlag, "", "The disk format of the image. ") + cmd.Flags().String(localFilePathFlag, "", "The path to the local disk image file.") + cmd.Flags().Bool(noProgressIndicatorFlag, false, "Show no progress indicator for upload.") + + cmd.Flags().Bool(bootMenuFlag, false, "Enables the BIOS bootmenu.") + cmd.Flags().String(cdromBusFlag, "", "Sets CDROM bus controller type.") + cmd.Flags().String(diskBusFlag, "", "Sets Disk bus controller type.") + cmd.Flags().String(nicModelFlag, "", "Sets virtual nic model.") + cmd.Flags().String(operatingSystemFlag, "", "Enables OS specific optimizations.") + cmd.Flags().String(operatingSystemDistroFlag, "", "Operating System Distribution.") + cmd.Flags().String(operatingSystemVersionFlag, "", "Version of the OS.") + cmd.Flags().String(rescueBusFlag, "", "Sets the device bus when the image is used as a rescue image.") + cmd.Flags().String(rescueDeviceFlag, "", "Sets the device when the image is used as a rescue image.") + cmd.Flags().Bool(secureBootFlag, false, "Enables Secure Boot.") + cmd.Flags().Bool(uefiFlag, false, "Enables UEFI boot.") + cmd.Flags().String(videoModelFlag, "", "Sets Graphic device model.") + cmd.Flags().Bool(virtioScsiFlag, false, "Enables the use of VirtIO SCSI to provide block device access. By default instances use VirtIO Block.") + + cmd.Flags().StringToString(labelsFlag, nil, "Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...'") + + cmd.Flags().Int64(minDiskSizeFlag, 0, "Size in Gigabyte.") + cmd.Flags().Int64(minRamFlag, 0, "Size in Megabyte.") + cmd.Flags().Bool(protectedFlag, false, "Protected VM.") + + if err := flags.MarkFlagsRequired(cmd, nameFlag, diskFormatFlag, localFilePathFlag); err != nil { + cobra.CheckErr(err) + } +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + name := flags.FlagToStringValue(p, cmd, nameFlag) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: name, + DiskFormat: flags.FlagToStringValue(p, cmd, diskFormatFlag), + LocalFilePath: flags.FlagToStringValue(p, cmd, localFilePathFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), + NoProgressIndicator: flags.FlagToBoolPointer(p, cmd, noProgressIndicatorFlag), + Config: &imageConfig{ + BootMenu: flags.FlagToBoolPointer(p, cmd, bootMenuFlag), + CdromBus: flags.FlagToStringPointer(p, cmd, cdromBusFlag), + DiskBus: flags.FlagToStringPointer(p, cmd, diskBusFlag), + NicModel: flags.FlagToStringPointer(p, cmd, nicModelFlag), + OperatingSystem: flags.FlagToStringPointer(p, cmd, operatingSystemFlag), + OperatingSystemDistro: flags.FlagToStringPointer(p, cmd, operatingSystemDistroFlag), + OperatingSystemVersion: flags.FlagToStringPointer(p, cmd, operatingSystemVersionFlag), + RescueBus: flags.FlagToStringPointer(p, cmd, rescueBusFlag), + RescueDevice: flags.FlagToStringPointer(p, cmd, rescueDeviceFlag), + SecureBoot: flags.FlagToBoolPointer(p, cmd, secureBootFlag), + Uefi: flags.FlagToBoolPointer(p, cmd, uefiFlag), + VideoModel: flags.FlagToStringPointer(p, cmd, videoModelFlag), + VirtioScsi: flags.FlagToBoolPointer(p, cmd, virtioScsiFlag), + }, + MinDiskSize: flags.FlagToInt64Pointer(p, cmd, minDiskSizeFlag), + MinRam: flags.FlagToInt64Pointer(p, cmd, minRamFlag), + Protected: flags.FlagToBoolPointer(p, cmd, protectedFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateImageRequest { + request := apiClient.CreateImage(ctx, model.ProjectId). + CreateImagePayload(createPayload(ctx, model)) + return request +} + +func createPayload(_ context.Context, model *inputModel) iaas.CreateImagePayload { + var labelsMap *map[string]any + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + payload := iaas.CreateImagePayload{ + DiskFormat: &model.DiskFormat, + Name: &model.Name, + Labels: labelsMap, + MinDiskSize: model.MinDiskSize, + MinRam: model.MinRam, + Protected: model.Protected, + } + if model.Config != nil { + payload.Config = &iaas.ImageConfig{ + BootMenu: model.Config.BootMenu, + CdromBus: iaas.NewNullableString(model.Config.CdromBus), + DiskBus: iaas.NewNullableString(model.Config.DiskBus), + NicModel: iaas.NewNullableString(model.Config.NicModel), + OperatingSystem: model.Config.OperatingSystem, + OperatingSystemDistro: iaas.NewNullableString(model.Config.OperatingSystemDistro), + OperatingSystemVersion: iaas.NewNullableString(model.Config.OperatingSystemVersion), + RescueBus: iaas.NewNullableString(model.Config.RescueBus), + RescueDevice: iaas.NewNullableString(model.Config.RescueDevice), + SecureBoot: model.Config.SecureBoot, + Uefi: model.Config.Uefi, + VideoModel: iaas.NewNullableString(model.Config.VideoModel), + VirtioScsi: model.Config.VirtioScsi, + } + } + + return payload +} + +func outputResult(p *print.Printer, model *inputModel, resp *iaas.ImageCreateResponse) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal image: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal image: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created image %q with id %s\n", model.Name, *model.Id) + return nil + } +} diff --git a/internal/cmd/beta/image/create/create_test.go b/internal/cmd/beta/image/create/create_test.go new file mode 100644 index 000000000..2a2902424 --- /dev/null +++ b/internal/cmd/beta/image/create/create_test.go @@ -0,0 +1,341 @@ +package create + +import ( + "context" + "strconv" + "strings" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + + testLocalImagePath = "/does/not/exist" + testDiskFormat = "raw" + testDiskSize int64 = 16 * 1024 * 1024 * 1024 + testRamSize int64 = 8 * 1024 * 1024 * 1024 + testName = "test-image" + testProtected = true + testCdRomBus = "test-cdrom" + testDiskBus = "test-diskbus" + testNicModel = "test-nic" + testOperatingSystem = "test-os" + testOperatingSystemDistro = "test-distro" + testOperatingSystemVersion = "test-distro-version" + testRescueBus = "test-rescue-bus" + testRescueDevice = "test-rescue-device" + testBootmenu = true + testSecureBoot = true + testUefi = true + testVideoModel = "test-video-model" + testVirtioScsi = true + testLabels = "foo=FOO,bar=BAR,baz=BAZ" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + + nameFlag: testName, + diskFormatFlag: testDiskFormat, + localFilePathFlag: testLocalImagePath, + bootMenuFlag: strconv.FormatBool(testBootmenu), + cdromBusFlag: testCdRomBus, + diskBusFlag: testDiskBus, + nicModelFlag: testNicModel, + operatingSystemFlag: testOperatingSystem, + operatingSystemDistroFlag: testOperatingSystemDistro, + operatingSystemVersionFlag: testOperatingSystemVersion, + rescueBusFlag: testRescueBus, + rescueDeviceFlag: testRescueDevice, + secureBootFlag: strconv.FormatBool(testSecureBoot), + uefiFlag: strconv.FormatBool(testUefi), + videoModelFlag: testVideoModel, + virtioScsiFlag: strconv.FormatBool(testVirtioScsi), + labelsFlag: testLabels, + minDiskSizeFlag: strconv.Itoa(int(testDiskSize)), + minRamFlag: strconv.Itoa(int(testRamSize)), + protectedFlag: strconv.FormatBool(testProtected), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func parseLabels(labelstring string) map[string]string { + labels := map[string]string{} + for _, part := range strings.Split(labelstring, ",") { + v := strings.Split(part, "=") + labels[v[0]] = v[1] + } + + return labels +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + Name: testName, + DiskFormat: testDiskFormat, + LocalFilePath: testLocalImagePath, + Labels: utils.Ptr(parseLabels(testLabels)), + Config: &imageConfig{ + BootMenu: &testBootmenu, + CdromBus: &testCdRomBus, + DiskBus: &testDiskBus, + NicModel: &testNicModel, + OperatingSystem: &testOperatingSystem, + OperatingSystemDistro: &testOperatingSystemDistro, + OperatingSystemVersion: &testOperatingSystemVersion, + RescueBus: &testRescueBus, + RescueDevice: &testRescueDevice, + SecureBoot: &testSecureBoot, + Uefi: &testUefi, + VideoModel: &testVideoModel, + VirtioScsi: &testVirtioScsi, + }, + MinDiskSize: &testDiskSize, + MinRam: &testRamSize, + Protected: &testProtected, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureCreatePayload(mods ...func(payload *iaas.CreateImagePayload)) (payload iaas.CreateImagePayload) { + payload = iaas.CreateImagePayload{ + Config: &iaas.ImageConfig{ + BootMenu: &testBootmenu, + CdromBus: iaas.NewNullableString(&testCdRomBus), + DiskBus: iaas.NewNullableString(&testDiskBus), + NicModel: iaas.NewNullableString(&testNicModel), + OperatingSystem: &testOperatingSystem, + OperatingSystemDistro: iaas.NewNullableString(&testOperatingSystemDistro), + OperatingSystemVersion: iaas.NewNullableString(&testOperatingSystemVersion), + RescueBus: iaas.NewNullableString(&testRescueBus), + RescueDevice: iaas.NewNullableString(&testRescueDevice), + SecureBoot: &testSecureBoot, + Uefi: &testUefi, + VideoModel: iaas.NewNullableString(&testVideoModel), + VirtioScsi: &testVirtioScsi, + }, + DiskFormat: &testDiskFormat, + Labels: &map[string]interface{}{ + "foo": "FOO", + "bar": "BAR", + "baz": "BAZ", + }, + MinDiskSize: &testDiskSize, + MinRam: &testRamSize, + Name: &testName, + Protected: &testProtected, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateImageRequest)) iaas.ApiCreateImageRequest { + request := testClient.CreateImage(testCtx, testProjectId) + + request = request.CreateImagePayload(fixtureCreatePayload()) + + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "name missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + { + description: "no labels", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelsFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + }, + { + description: "single label", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelsFlag] = "foo=bar" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = &map[string]string{ + "foo": "bar", + } + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateImageRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no labels", + model: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateImageRequest) { + *request = request.CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { + payload.Labels = nil + })) + }), + }, + { + description: "cd rom bus", + model: fixtureInputModel(func(model *inputModel) { + model.Config.CdromBus = utils.Ptr("foobar") + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateImageRequest) { + *request = request.CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { + payload.Config.CdromBus = iaas.NewNullableString(utils.Ptr("foobar")) + })) + }), + }, + { + description: "uefi flag", + model: fixtureInputModel(func(model *inputModel) { + model.Config.Uefi = utils.Ptr(false) + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateImageRequest) { + *request = request.CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { + payload.Config.Uefi = utils.Ptr(false) + })) + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(iaas.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/image/delete/delete.go b/internal/cmd/beta/image/delete/delete.go new file mode 100644 index 000000000..3e2b44260 --- /dev/null +++ b/internal/cmd/beta/image/delete/delete.go @@ -0,0 +1,110 @@ +package delete + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ImageId string +} + +const imageIdArg = "IMAGE_ID" + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", imageIdArg), + Short: "Deletes an image", + Long: "Deletes an image by its internal ID.", + Args: args.SingleArg(imageIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample(`Delete an image with ID "xxx"`, `$ stackit beta image delete xxx`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + imageName, err := iaasUtils.GetImageName(ctx, apiClient, model.ProjectId, model.ImageId) + if err != nil { + p.Debug(print.ErrorLevel, "get image name: %v", err) + imageName = model.ImageId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete the image %q for %q?", imageName, projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + if err := request.Execute(); err != nil { + return fmt.Errorf("delete image: %w", err) + } + p.Info("Deleted image %q for %q\n", imageName, projectLabel) + + return nil + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ImageId: cliArgs[0], + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteImageRequest { + request := apiClient.DeleteImage(ctx, model.ProjectId, model.ImageId) + return request +} diff --git a/internal/cmd/beta/image/delete/delete_test.go b/internal/cmd/beta/image/delete/delete_test.go new file mode 100644 index 000000000..1fa1ed5bc --- /dev/null +++ b/internal/cmd/beta/image/delete/delete_test.go @@ -0,0 +1,183 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testImageId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + ImageId: testImageId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteImageRequest)) iaas.ApiDeleteImageRequest { + request := testClient.DeleteImage(testCtx, testProjectId, testImageId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + args []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + args: []string{testImageId}, + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "no arguments", + flagValues: fixtureFlagValues(), + args: nil, + isValid: false, + }, + { + description: "multiple arguments", + flagValues: fixtureFlagValues(), + args: []string{"foo", "bar"}, + isValid: false, + }, + { + description: "invalid image id", + flagValues: fixtureFlagValues(), + args: []string{"foo"}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + cmd.SetArgs(tt.args) + + 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) + } + } + + if err := cmd.ValidateArgs(tt.args); err != nil { + if !tt.isValid { + return + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd, tt.args) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteImageRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/image/describe/describe.go b/internal/cmd/beta/image/describe/describe.go new file mode 100644 index 000000000..3a85f635c --- /dev/null +++ b/internal/cmd/beta/image/describe/describe.go @@ -0,0 +1,173 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ImageId string +} + +const imageIdArg = "IMAGE_ID" + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", imageIdArg), + Short: "Describes image", + Long: "Describes an image by its internal ID.", + Args: args.SingleArg(imageIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample(`Describe image "xxx"`, `$ stackit beta image describe xxx`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + image, err := request.Execute() + if err != nil { + return fmt.Errorf("get image: %w", err) + } + + if err := outputResult(p, model, image); err != nil { + return err + } + + return nil + }, + } + + return cmd +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetImageRequest { + request := apiClient.GetImage(ctx, model.ProjectId, model.ImageId) + return request +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ImageId: cliArgs[0], + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *iaas.Image) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal image: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal image: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + if id := resp.Id; id != nil { + table.AddRow("ID", *id) + } + table.AddSeparator() + + if name := resp.Name; name != nil { + table.AddRow("NAME", *name) + table.AddSeparator() + } + if format := resp.DiskFormat; format != nil { + table.AddRow("FORMAT", *format) + table.AddSeparator() + } + if diskSize := resp.MinDiskSize; diskSize != nil { + table.AddRow("DISK SIZE", *diskSize) + table.AddSeparator() + } + if ramSize := resp.MinRam; ramSize != nil { + table.AddRow("RAM SIZE", *ramSize) + table.AddSeparator() + } + if config := resp.Config; config != nil { + if os := config.OperatingSystem; os != nil { + table.AddRow("OPERATING SYSTEM", *os) + table.AddSeparator() + } + if distro := config.OperatingSystemDistro; distro != nil { + table.AddRow("OPERATING SYSTEM DISTRIBUTION", *distro) + table.AddSeparator() + } + if version := config.OperatingSystemVersion; version != nil { + table.AddRow("OPERATING SYSTEM VERSION", *version) + table.AddSeparator() + } + if uefi := config.Uefi; uefi != nil { + table.AddRow("UEFI BOOT", *uefi) + table.AddSeparator() + } + } + + if resp.Labels != nil && len(*resp.Labels) > 0 { + labels := []string{} + for key, value := range *resp.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } + + if err := table.Display(p); err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/image/describe/describe_test.go b/internal/cmd/beta/image/describe/describe_test.go new file mode 100644 index 000000000..4003e78d1 --- /dev/null +++ b/internal/cmd/beta/image/describe/describe_test.go @@ -0,0 +1,194 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testImageId = []string{uuid.NewString()} +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + ImageId: testImageId[0], + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetImageRequest)) iaas.ApiGetImageRequest { + request := testClient.GetImage(testCtx, testProjectId, testImageId[0]) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + isValid bool + args []string + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + args: testImageId, + isValid: true, + }, + { + description: "no values", + flagValues: map[string]string{}, + args: testImageId, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + args: testImageId, + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + args: testImageId, + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + args: testImageId, + isValid: false, + }, + { + description: "no image id passed", + flagValues: fixtureFlagValues(), + args: nil, + isValid: false, + }, + { + description: "multiple image ids passed", + flagValues: fixtureFlagValues(), + args: []string{uuid.NewString(), uuid.NewString()}, + isValid: false, + }, + { + description: "invalid image id passed", + flagValues: fixtureFlagValues(), + args: []string{"foobar"}, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + if err := cmd.ValidateArgs(tt.args); err != nil { + if !tt.isValid { + return + } + } + + model, err := parseInput(p, cmd, tt.args) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetImageRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/image/image.go b/internal/cmd/beta/image/image.go new file mode 100644 index 000000000..c84ef1430 --- /dev/null +++ b/internal/cmd/beta/image/image.go @@ -0,0 +1,37 @@ +package image + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "image", + Short: "Manage server images", + Long: "Manage the lifecycle of server images.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand( + create.NewCmd(p), + list.NewCmd(p), + delete.NewCmd(p), + describe.NewCmd(p), + update.NewCmd(p), + ) +} diff --git a/internal/cmd/beta/image/list/list.go b/internal/cmd/beta/image/list/list.go new file mode 100644 index 000000000..1447f75a7 --- /dev/null +++ b/internal/cmd/beta/image/list/list.go @@ -0,0 +1,189 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + LabelSelector *string + Limit *int64 +} + +const ( + labelSelectorFlag = "label-selector" + limitFlag = "limit" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists images", + Long: "Lists images by their internal ID.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all images`, + `$ stackit beta image list`, + ), + examples.NewExample( + `List images with label`, + `$ stackit beta image list --label-selector ARM64,dev`, + ), + examples.NewExample( + `List the first 10 images`, + `$ stackit beta image list --limit=10`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + response, err := request.Execute() + if err != nil { + return fmt.Errorf("list images: %w", err) + } + + if items := response.GetItems(); items == nil || len(*items) == 0 { + p.Info("No images found for project %q", projectLabel) + } else { + if model.Limit != nil && len(*items) > int(*model.Limit) { + *items = (*items)[:*model.Limit] + } + if err := outputResult(p, model.OutputFormat, *items); err != nil { + return fmt.Errorf("output images: %w", err) + } + } + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") + cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), + Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListImagesRequest { + request := apiClient.ListImages(ctx, model.ProjectId) + if model.LabelSelector != nil { + request = request.LabelSelector(*model.LabelSelector) + } + + return request +} +func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(items, "", " ") + if err != nil { + return fmt.Errorf("marshal image list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal image list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "OS", "DISTRIBUTION", "VERSION", "LABELS") + for _, item := range items { + var ( + os string = "n/a" + distro string = "n/a" + version string = "n/a" + ) + if cfg := item.Config; cfg != nil { + if v := cfg.OperatingSystem; v != nil { + os = *v + } + if v := cfg.OperatingSystemDistro; v != nil && v.IsSet() { + distro = *v.Get() + } + if v := cfg.OperatingSystemVersion; v != nil && v.IsSet() { + version = *v.Get() + } + } + table.AddRow(utils.PtrString(item.Id), + utils.PtrString(item.Name), + os, + distro, + version, + utils.JoinStringKeysPtr(*item.Labels, ",")) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/image/list/list_test.go b/internal/cmd/beta/image/list/list_test.go new file mode 100644 index 000000000..70c6112cb --- /dev/null +++ b/internal/cmd/beta/image/list/list_test.go @@ -0,0 +1,212 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testLabels = "fooKey=fooValue,barKey=barValue,bazKey=bazValue" + testLimit int64 = 10 +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + labelSelectorFlag: testLabels, + limitFlag: strconv.Itoa(int(testLimit)), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + LabelSelector: utils.Ptr(testLabels), + Limit: &testLimit, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListImagesRequest)) iaas.ApiListImagesRequest { + request := testClient.ListImages(testCtx, testProjectId) + request = request.LabelSelector(testLabels) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "no labels", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelSelectorFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = nil + }), + }, + { + description: "single label", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "foo=bar" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("foo=bar") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListImagesRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + + { + description: "no labels", + model: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("") + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiListImagesRequest) { + *request = request.LabelSelector("") + }), + }, + { + description: "single label", + model: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = utils.Ptr("foo=bar") + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiListImagesRequest) { + *request = request.LabelSelector("foo=bar") + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/image/update/update.go b/internal/cmd/beta/image/update/update.go new file mode 100644 index 000000000..9c672e86f --- /dev/null +++ b/internal/cmd/beta/image/update/update.go @@ -0,0 +1,283 @@ +package update + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type imageConfig struct { + BootMenu *bool + CdromBus *string + DiskBus *string + NicModel *string + OperatingSystem *string + OperatingSystemDistro *string + OperatingSystemVersion *string + RescueBus *string + RescueDevice *string + SecureBoot *bool + Uefi *bool + VideoModel *string + VirtioScsi *bool +} + +func (ic *imageConfig) isEmpty() bool { + return ic.BootMenu == nil && + ic.CdromBus == nil && + ic.DiskBus == nil && + ic.NicModel == nil && + ic.OperatingSystem == nil && + ic.OperatingSystemDistro == nil && + ic.OperatingSystemVersion == nil && + ic.RescueBus == nil && + ic.RescueDevice == nil && + ic.SecureBoot == nil && + ic.Uefi == nil && + ic.VideoModel == nil && + ic.VirtioScsi == nil +} + +type inputModel struct { + *globalflags.GlobalFlagModel + + Id string + Name *string + DiskFormat *string + LocalFilePath *string + Labels *map[string]string + Config *imageConfig + MinDiskSize *int64 + MinRam *int64 + Protected *bool +} + +func (im *inputModel) isEmpty() bool { + return im.Name == nil && + im.DiskFormat == nil && + im.LocalFilePath == nil && + im.Labels == nil && + (im.Config == nil || im.Config.isEmpty()) && + im.MinDiskSize == nil && + im.MinRam == nil && + im.Protected == nil +} + +const imageIdArg = "IMAGE_ID" + +const ( + nameFlag = "name" + diskFormatFlag = "disk-format" + localFilePathFlag = "local-file-path" + + bootMenuFlag = "boot-menu" + cdromBusFlag = "cdrom-bus" + diskBusFlag = "disk-bus" + nicModelFlag = "nic-model" + operatingSystemFlag = "os" + operatingSystemDistroFlag = "os-distro" + operatingSystemVersionFlag = "os-version" + rescueBusFlag = "rescue-bus" + rescueDeviceFlag = "rescue-device" + secureBootFlag = "secure-boot" + uefiFlag = "uefi" + videoModelFlag = "video-model" + virtioScsiFlag = "virtio-scsi" + + labelsFlag = "labels" + + minDiskSizeFlag = "min-disk-size" + minRamFlag = "min-ram" + ownerFlag = "owner" + protectedFlag = "protected" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", imageIdArg), + Short: "Updates an image", + Long: "Updates an image", + Args: args.SingleArg(imageIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample(`Update the name of an image with ID "xxx"`, `$ stackit beta image update xxx --name my-new-name`), + examples.NewExample(`Update the labels of an image with ID "xxx"`, `$ stackit beta image update xxx --labels label1=value1,label2=value2`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + imageLabel, err := iaasUtils.GetImageName(ctx, apiClient, model.ProjectId, model.Id) + if err != nil { + p.Debug(print.WarningLevel, "cannot retrieve image name: %v", err) + imageLabel = model.Id + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update the image %q?", imageLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update image: %w", err) + } + p.Info("Updated image \"%v\" for %q\n", utils.PtrString(resp.Name), projectLabel) + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "The name of the image.") + cmd.Flags().String(diskFormatFlag, "", "The disk format of the image. ") + cmd.Flags().String(localFilePathFlag, "", "The path to the local disk image file.") + + cmd.Flags().Bool(bootMenuFlag, false, "Enables the BIOS bootmenu.") + cmd.Flags().String(cdromBusFlag, "", "Sets CDROM bus controller type.") + cmd.Flags().String(diskBusFlag, "", "Sets Disk bus controller type.") + cmd.Flags().String(nicModelFlag, "", "Sets virtual nic model.") + cmd.Flags().String(operatingSystemFlag, "", "Enables OS specific optimizations.") + cmd.Flags().String(operatingSystemDistroFlag, "", "Operating System Distribution.") + cmd.Flags().String(operatingSystemVersionFlag, "", "Version of the OS.") + cmd.Flags().String(rescueBusFlag, "", "Sets the device bus when the image is used as a rescue image.") + cmd.Flags().String(rescueDeviceFlag, "", "Sets the device when the image is used as a rescue image.") + cmd.Flags().Bool(secureBootFlag, false, "Enables Secure Boot.") + cmd.Flags().Bool(uefiFlag, false, "Enables UEFI boot.") + cmd.Flags().String(videoModelFlag, "", "Sets Graphic device model.") + cmd.Flags().Bool(virtioScsiFlag, false, "Enables the use of VirtIO SCSI to provide block device access. By default instances use VirtIO Block.") + + cmd.Flags().StringToString(labelsFlag, nil, "Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...'") + + cmd.Flags().Int64(minDiskSizeFlag, 0, "Size in Gigabyte.") + cmd.Flags().Int64(minRamFlag, 0, "Size in Megabyte.") + cmd.Flags().Bool(protectedFlag, false, "Protected VM.") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Id: cliArgs[0], + Name: flags.FlagToStringPointer(p, cmd, nameFlag), + + DiskFormat: flags.FlagToStringPointer(p, cmd, diskFormatFlag), + LocalFilePath: flags.FlagToStringPointer(p, cmd, localFilePathFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), + Config: &imageConfig{ + BootMenu: flags.FlagToBoolPointer(p, cmd, bootMenuFlag), + CdromBus: flags.FlagToStringPointer(p, cmd, cdromBusFlag), + DiskBus: flags.FlagToStringPointer(p, cmd, diskBusFlag), + NicModel: flags.FlagToStringPointer(p, cmd, nicModelFlag), + OperatingSystem: flags.FlagToStringPointer(p, cmd, operatingSystemFlag), + OperatingSystemDistro: flags.FlagToStringPointer(p, cmd, operatingSystemDistroFlag), + OperatingSystemVersion: flags.FlagToStringPointer(p, cmd, operatingSystemVersionFlag), + RescueBus: flags.FlagToStringPointer(p, cmd, rescueBusFlag), + RescueDevice: flags.FlagToStringPointer(p, cmd, rescueDeviceFlag), + SecureBoot: flags.FlagToBoolPointer(p, cmd, secureBootFlag), + Uefi: flags.FlagToBoolPointer(p, cmd, uefiFlag), + VideoModel: flags.FlagToStringPointer(p, cmd, videoModelFlag), + VirtioScsi: flags.FlagToBoolPointer(p, cmd, virtioScsiFlag), + }, + MinDiskSize: flags.FlagToInt64Pointer(p, cmd, minDiskSizeFlag), + MinRam: flags.FlagToInt64Pointer(p, cmd, minRamFlag), + Protected: flags.FlagToBoolPointer(p, cmd, protectedFlag), + } + + if model.isEmpty() { + return nil, fmt.Errorf("no flags have been passed") + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateImageRequest { + request := apiClient.UpdateImage(ctx, model.ProjectId, model.Id) + payload := iaas.NewUpdateImagePayload() + var labelsMap *map[string]any + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + // Config *ImageConfig `json:"config,omitempty"` + payload.DiskFormat = model.DiskFormat + payload.Labels = labelsMap + payload.MinDiskSize = model.MinDiskSize + payload.MinRam = model.MinRam + payload.Name = model.Name + payload.Protected = model.Protected + + if model.Config != nil { + payload.Config = &iaas.ImageConfig{ + BootMenu: model.Config.BootMenu, + CdromBus: iaas.NewNullableString(model.Config.CdromBus), + DiskBus: iaas.NewNullableString(model.Config.DiskBus), + NicModel: iaas.NewNullableString(model.Config.NicModel), + OperatingSystem: model.Config.OperatingSystem, + OperatingSystemDistro: iaas.NewNullableString(model.Config.OperatingSystemDistro), + OperatingSystemVersion: iaas.NewNullableString(model.Config.OperatingSystemVersion), + RescueBus: iaas.NewNullableString(model.Config.RescueBus), + RescueDevice: iaas.NewNullableString(model.Config.RescueDevice), + SecureBoot: model.Config.SecureBoot, + Uefi: model.Config.Uefi, + VideoModel: iaas.NewNullableString(model.Config.VideoModel), + VirtioScsi: model.Config.VirtioScsi, + } + } + + request = request.UpdateImagePayload(*payload) + + return request +} diff --git a/internal/cmd/beta/image/update/update_test.go b/internal/cmd/beta/image/update/update_test.go new file mode 100644 index 000000000..ebab81e51 --- /dev/null +++ b/internal/cmd/beta/image/update/update_test.go @@ -0,0 +1,383 @@ +package update + +import ( + "context" + "strconv" + "strings" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + + testImageId = []string{uuid.NewString()} + testLocalImagePath = "/does/not/exist" + testDiskFormat = "raw" + testDiskSize int64 = 16 * 1024 * 1024 * 1024 + testRamSize int64 = 8 * 1024 * 1024 * 1024 + testName = "test-image" + testProtected = true + testCdRomBus = "test-cdrom" + testDiskBus = "test-diskbus" + testNicModel = "test-nic" + testOperatingSystem = "test-os" + testOperatingSystemDistro = "test-distro" + testOperatingSystemVersion = "test-distro-version" + testRescueBus = "test-rescue-bus" + testRescueDevice = "test-rescue-device" + testBootmenu = true + testSecureBoot = true + testUefi = true + testVideoModel = "test-video-model" + testVirtioScsi = true + testLabels = "foo=FOO,bar=BAR,baz=BAZ" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + + nameFlag: testName, + diskFormatFlag: testDiskFormat, + localFilePathFlag: testLocalImagePath, + bootMenuFlag: strconv.FormatBool(testBootmenu), + cdromBusFlag: testCdRomBus, + diskBusFlag: testDiskBus, + nicModelFlag: testNicModel, + operatingSystemFlag: testOperatingSystem, + operatingSystemDistroFlag: testOperatingSystemDistro, + operatingSystemVersionFlag: testOperatingSystemVersion, + rescueBusFlag: testRescueBus, + rescueDeviceFlag: testRescueDevice, + secureBootFlag: strconv.FormatBool(testSecureBoot), + uefiFlag: strconv.FormatBool(testUefi), + videoModelFlag: testVideoModel, + virtioScsiFlag: strconv.FormatBool(testVirtioScsi), + labelsFlag: testLabels, + minDiskSizeFlag: strconv.Itoa(int(testDiskSize)), + minRamFlag: strconv.Itoa(int(testRamSize)), + protectedFlag: strconv.FormatBool(testProtected), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func parseLabels(labelstring string) map[string]string { + labels := map[string]string{} + for _, part := range strings.Split(labelstring, ",") { + v := strings.Split(part, "=") + labels[v[0]] = v[1] + } + + return labels +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + Id: testImageId[0], + Name: &testName, + DiskFormat: &testDiskFormat, + LocalFilePath: &testLocalImagePath, + Labels: utils.Ptr(parseLabels(testLabels)), + Config: &imageConfig{ + BootMenu: &testBootmenu, + CdromBus: &testCdRomBus, + DiskBus: &testDiskBus, + NicModel: &testNicModel, + OperatingSystem: &testOperatingSystem, + OperatingSystemDistro: &testOperatingSystemDistro, + OperatingSystemVersion: &testOperatingSystemVersion, + RescueBus: &testRescueBus, + RescueDevice: &testRescueDevice, + SecureBoot: &testSecureBoot, + Uefi: &testUefi, + VideoModel: &testVideoModel, + VirtioScsi: &testVirtioScsi, + }, + MinDiskSize: &testDiskSize, + MinRam: &testRamSize, + Protected: &testProtected, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureCreatePayload(mods ...func(payload *iaas.UpdateImagePayload)) (payload iaas.UpdateImagePayload) { + payload = iaas.UpdateImagePayload{ + Config: &iaas.ImageConfig{ + BootMenu: &testBootmenu, + CdromBus: iaas.NewNullableString(&testCdRomBus), + DiskBus: iaas.NewNullableString(&testDiskBus), + NicModel: iaas.NewNullableString(&testNicModel), + OperatingSystem: &testOperatingSystem, + OperatingSystemDistro: iaas.NewNullableString(&testOperatingSystemDistro), + OperatingSystemVersion: iaas.NewNullableString(&testOperatingSystemVersion), + RescueBus: iaas.NewNullableString(&testRescueBus), + RescueDevice: iaas.NewNullableString(&testRescueDevice), + SecureBoot: &testSecureBoot, + Uefi: &testUefi, + VideoModel: iaas.NewNullableString(&testVideoModel), + VirtioScsi: &testVirtioScsi, + }, + DiskFormat: &testDiskFormat, + Labels: &map[string]interface{}{ + "foo": "FOO", + "bar": "BAR", + "baz": "BAZ", + }, + MinDiskSize: &testDiskSize, + MinRam: &testRamSize, + Name: &testName, + Protected: &testProtected, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(*iaas.ApiUpdateImageRequest)) iaas.ApiUpdateImageRequest { + request := testClient.UpdateImage(testCtx, testProjectId, testImageId[0]) + + request = request.UpdateImagePayload(fixtureCreatePayload()) + + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + args []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + args: testImageId, + expectedModel: fixtureInputModel(), + }, + { + description: "no values but valid image id", + flagValues: map[string]string{ + projectIdFlag: testProjectId, + }, + args: testImageId, + isValid: false, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + model.Name = nil + }), + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + args: testImageId, + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + args: testImageId, + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + args: testImageId, + isValid: false, + }, + { + description: "no name passed", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + args: testImageId, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = nil + }), + isValid: true, + }, + { + description: "no labels", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelsFlag) + }), + args: testImageId, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + isValid: true, + }, + { + description: "single label", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelsFlag] = "foo=bar" + }), + args: testImageId, + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = &map[string]string{ + "foo": "bar", + } + }), + }, + { + description: "no image id passed", + flagValues: fixtureFlagValues(), + args: nil, + isValid: false, + }, + { + description: "invalid image id passed", + flagValues: fixtureFlagValues(), + args: []string{"foobar"}, + isValid: false, + }, + { + description: "multiple image ids passed", + flagValues: fixtureFlagValues(), + args: []string{uuid.NewString(), uuid.NewString()}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot configure global flags: %v", err) + } + + for flag, value := range tt.flagValues { + if err := cmd.Flags().Set(flag, value); err != nil { + if !tt.isValid { + return + } + t.Fatalf("setting flag --%s=%s: %v", flag, value, err) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + if err := cmd.ValidateArgs(tt.args); err != nil { + if !tt.isValid { + return + } + } + + model, err := parseInput(p, cmd, tt.args) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateImageRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no labels", + model: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateImageRequest) { + *request = request.UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { + payload.Labels = nil + })) + }), + }, + { + description: "change name", + model: fixtureInputModel(func(model *inputModel) { + model.Name = utils.Ptr("something else") + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateImageRequest) { + *request = request.UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { + payload.Name = utils.Ptr("something else") + })) + }), + }, + { + description: "change cdrom", + model: fixtureInputModel(func(model *inputModel) { + model.Config.CdromBus = utils.Ptr("something else") + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateImageRequest) { + *request = request.UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { + payload.Config.CdromBus.Set(utils.Ptr("something else")) + })) + }), + }, + } + + 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, iaas.NullableString{}), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index e7a455688..c3102cfed 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -17,6 +17,7 @@ type IaaSClient interface { GetNetworkAreaExecute(ctx context.Context, organizationId, areaId string) (*iaas.NetworkArea, error) ListNetworkAreaProjectsExecute(ctx context.Context, organizationId, areaId string) (*iaas.ProjectListResponse, error) GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) + GetImageExecute(ctx context.Context, projectId string, imageId string) (*iaas.Image, error) } func GetSecurityGroupRuleName(ctx context.Context, apiClient IaaSClient, projectId, securityGroupRuleId, securityGroupId string) (string, error) { @@ -117,3 +118,14 @@ func GetNetworkRangeFromAPIResponse(prefix string, networkRanges *[]iaas.Network } return iaas.NetworkRange{}, fmt.Errorf("new network range not found in API response") } + +func GetImageName(ctx context.Context, apiClient IaaSClient, projectId, imageId string) (string, error) { + resp, err := apiClient.GetImageExecute(ctx, projectId, imageId) + if err != nil { + return "", fmt.Errorf("get image: %w", err) + } + if resp.Name == nil { + return "", nil + } + return *resp.Name, nil +} diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index c7e75a683..01c59aa70 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -29,6 +29,8 @@ type IaaSClientMocked struct { GetAttachedProjectsResp *iaas.ProjectListResponse GetNetworkAreaRangeFails bool GetNetworkAreaRangeResp *iaas.NetworkRange + GetImageFails bool + GetImageResp *iaas.Image } func (m *IaaSClientMocked) GetSecurityGroupRuleExecute(_ context.Context, _, _, _ string) (*iaas.SecurityGroupRule, error) { @@ -94,6 +96,13 @@ func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _ return m.GetNetworkAreaRangeResp, nil } +func (m *IaaSClientMocked) GetImageExecute(_ context.Context, _, _ string) (*iaas.Image, error) { + if m.GetImageFails { + return nil, fmt.Errorf("could not get image") + } + return m.GetImageResp, nil +} + func TestGetSecurityGroupRuleName(t *testing.T) { type args struct { getInstanceFails bool @@ -662,3 +671,47 @@ func TestGetNetworkRangeFromAPIResponse(t *testing.T) { }) } } + +func TestGetImageName(t *testing.T) { + tests := []struct { + name string + imageResp *iaas.Image + imageErr bool + want string + wantErr bool + }{ + { + name: "successful retrieval", + imageResp: &iaas.Image{Name: utils.Ptr("test-image")}, + want: "test-image", + wantErr: false, + }, + { + name: "error on retrieval", + imageErr: true, + wantErr: true, + }, + { + name: "nil name", + imageErr: false, + imageResp: &iaas.Image{}, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := &IaaSClientMocked{ + GetImageFails: tt.imageErr, + GetImageResp: tt.imageResp, + } + got, err := GetImageName(context.Background(), client, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetImageName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetImageName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/pkg/utils/strings.go b/internal/pkg/utils/strings.go new file mode 100644 index 000000000..6c33cfc82 --- /dev/null +++ b/internal/pkg/utils/strings.go @@ -0,0 +1,26 @@ +package utils + +import ( + "strings" +) + +// JoinStringKeys concatenates the string keys of a map, each separatore by the +// [sep] string. +func JoinStringKeys(m map[string]any, sep string) string { + keys := make([]string, len(m)) + i := 0 + for k := range m { + keys[i] = k + i++ + } + return strings.Join(keys, sep) +} + +// JoinStringKeysPtr concatenates the string keys of a map pointer, each separatore by the +// [sep] string. +func JoinStringKeysPtr(m map[string]any, sep string) string { + if m == nil { + return "" + } + return JoinStringKeys(m, sep) +} From 674d3878703eb9a7ce9c4d1232507ce1da065e93 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 16 Jan 2025 09:51:24 +0100 Subject: [PATCH 147/619] fix: deprecated endpoints for validating ske service state (#562) * Fix: Replace deprecated endpoint for ske service state * Remove deprecated commands (`ske credentials rotate` and `ske credentials describe`) --- internal/cmd/ske/cluster/create/create.go | 10 +- internal/cmd/ske/cluster/list/list.go | 11 +- internal/cmd/ske/credentials/credentials.go | 4 - .../cmd/ske/credentials/describe/describe.go | 146 ------------- .../ske/credentials/describe/describe_test.go | 206 ------------------ internal/cmd/ske/credentials/rotate/rotate.go | 125 ----------- .../cmd/ske/credentials/rotate/rotate_test.go | 206 ------------------ internal/cmd/ske/describe/describe.go | 15 +- internal/cmd/ske/describe/describe_test.go | 11 +- .../service-enablement/utils/utils.go | 28 +++ .../service-enablement/utils/utils_test.go | 106 +++++++++ internal/pkg/services/ske/utils/utils.go | 18 -- internal/pkg/services/ske/utils/utils_test.go | 66 ------ 13 files changed, 166 insertions(+), 786 deletions(-) delete mode 100644 internal/cmd/ske/credentials/describe/describe.go delete mode 100644 internal/cmd/ske/credentials/describe/describe_test.go delete mode 100644 internal/cmd/ske/credentials/rotate/rotate.go delete mode 100644 internal/cmd/ske/credentials/rotate/rotate_test.go create mode 100644 internal/pkg/services/service-enablement/utils/utils_test.go diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index c1309f00d..31fad09f4 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -13,6 +13,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + serviceEnablementClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/client" + serviceEnablementUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" skeUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" @@ -87,8 +89,14 @@ func NewCmd(p *print.Printer) *cobra.Command { } } + // Configure ServiceEnable API client + serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(p) + if err != nil { + return err + } + // Check if the project is enabled before trying to create - enabled, err := skeUtils.ProjectEnabled(ctx, apiClient, model.ProjectId) + enabled, err := serviceEnablementUtils.ProjectEnabled(ctx, serviceEnablementApiClient, model.ProjectId) if err != nil { return err } diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index a4fcd139c..834b2ea38 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -13,8 +13,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + serviceEnablementClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/client" + serviceEnablementUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" - skeUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/spf13/cobra" @@ -60,8 +61,14 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + // Configure ServiceEnable API client + serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(p) + if err != nil { + return err + } + // Check if SKE is enabled for this project - enabled, err := skeUtils.ProjectEnabled(ctx, apiClient, model.ProjectId) + enabled, err := serviceEnablementUtils.ProjectEnabled(ctx, serviceEnablementApiClient, model.ProjectId) if err != nil { return err } diff --git a/internal/cmd/ske/credentials/credentials.go b/internal/cmd/ske/credentials/credentials.go index 9d421ad7d..6fdfb1fc3 100644 --- a/internal/cmd/ske/credentials/credentials.go +++ b/internal/cmd/ske/credentials/credentials.go @@ -2,8 +2,6 @@ package credentials import ( completerotation "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials/complete-rotation" - "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials/rotate" startrotation "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials/start-rotation" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -25,8 +23,6 @@ func NewCmd(p *print.Printer) *cobra.Command { } func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(rotate.NewCmd(p)) cmd.AddCommand(startrotation.NewCmd(p)) cmd.AddCommand(completerotation.NewCmd(p)) } diff --git a/internal/cmd/ske/credentials/describe/describe.go b/internal/cmd/ske/credentials/describe/describe.go deleted file mode 100644 index a793628b5..000000000 --- a/internal/cmd/ske/credentials/describe/describe.go +++ /dev/null @@ -1,146 +0,0 @@ -package describe - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/goccy/go-yaml" - "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/ske/client" - skeUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/utils" - "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/ske" -) - -const ( - clusterNameArg = "CLUSTER_NAME" -) - -type inputModel struct { - *globalflags.GlobalFlagModel - ClusterName string -} - -func NewCmd(p *print.Printer) *cobra.Command { - cmd := &cobra.Command{ - Use: fmt.Sprintf("describe %s", clusterNameArg), - Short: "Shows details of the credentials associated to a SKE cluster", - Long: "Shows details of the credentials associated to a STACKIT Kubernetes Engine (SKE) cluster", - Args: args.SingleArg(clusterNameArg, nil), - Deprecated: fmt.Sprintf("%s\n%s\n%s\n%s\n", - "and will be removed in a future release.", - "Please use the following command to obtain a kubeconfig file instead:", - " $ stackit ske kubeconfig create CLUSTER_NAME", - "For more information, visit: https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html", - ), - Example: examples.Build( - examples.NewExample( - `Get details of the credentials associated to the SKE cluster with name "my-cluster"`, - "$ stackit ske credentials describe my-cluster"), - examples.NewExample( - `Get details of the credentials associated to the SKE cluster with name "my-cluster" in JSON format`, - "$ stackit ske credentials describe my-cluster --output-format json"), - ), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() - model, err := parseInput(p, cmd, args) - if err != nil { - return err - } - - // Configure API client - apiClient, err := client.ConfigureClient(p) - if err != nil { - return err - } - - // Check if SKE is enabled for this project - enabled, err := skeUtils.ProjectEnabled(ctx, apiClient, model.ProjectId) - if err != nil { - return err - } - if !enabled { - return fmt.Errorf("SKE isn't enabled for this project, please run 'stackit ske enable'") - } - - // Call API - req := buildRequest(ctx, model, apiClient) - resp, err := req.Execute() - if err != nil { - return fmt.Errorf("get SKE credentials: %w", err) - } - - return outputResult(p, model.OutputFormat, resp) - }, - } - return cmd -} - -func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { - clusterName := inputArgs[0] - - globalFlags := globalflags.Parse(p, cmd) - if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} - } - - model := inputModel{ - GlobalFlagModel: globalFlags, - ClusterName: clusterName, - } - - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - - return &model, nil -} - -func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiGetCredentialsRequest { - req := apiClient.GetCredentials(ctx, model.ProjectId, model.ClusterName) //nolint:staticcheck //command will be removed in a later update - return req -} - -func outputResult(p *print.Printer, outputFormat string, credentials *ske.Credentials) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal SKE credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) - if err != nil { - return fmt.Errorf("marshal SKE credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: - table := tables.NewTable() - table.AddRow("SERVER", *credentials.Server) - table.AddSeparator() - table.AddRow("TOKEN", *credentials.Token) - err := table.Display(p) - if err != nil { - return fmt.Errorf("render table: %w", err) - } - - return nil - } -} diff --git a/internal/cmd/ske/credentials/describe/describe_test.go b/internal/cmd/ske/credentials/describe/describe_test.go deleted file mode 100644 index c589ca77b..000000000 --- a/internal/cmd/ske/credentials/describe/describe_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package describe - -import ( - "context" - "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/ske" -) - -var projectIdFlag = globalflags.ProjectIdFlag - -type testCtxKey struct{} - -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &ske.APIClient{} -var testProjectId = uuid.NewString() -var testClusterName = "cluster" - -func fixtureArgValues(mods ...func(argValues []string)) []string { - argValues := []string{ - testClusterName, - } - for _, mod := range mods { - mod(argValues) - } - return argValues -} - -func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { - flagValues := map[string]string{ - projectIdFlag: testProjectId, - } - for _, mod := range mods { - mod(flagValues) - } - return flagValues -} - -func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { - model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ - ProjectId: testProjectId, - Verbosity: globalflags.VerbosityDefault, - }, - ClusterName: testClusterName, - } - for _, mod := range mods { - mod(model) - } - return model -} - -func fixtureRequest(mods ...func(request *ske.ApiGetCredentialsRequest)) ske.ApiGetCredentialsRequest { - request := testClient.GetCredentials(testCtx, testProjectId, testClusterName) //nolint:staticcheck //command will be removed in a later update - for _, mod := range mods { - mod(&request) - } - return request -} - -func TestParseInput(t *testing.T) { - tests := []struct { - description string - argValues []string - flagValues map[string]string - isValid bool - expectedModel *inputModel - }{ - { - description: "base", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(), - }, - { - description: "no values", - argValues: []string{}, - flagValues: map[string]string{}, - isValid: false, - }, - { - description: "no arg values", - argValues: []string{}, - flagValues: fixtureFlagValues(), - isValid: false, - }, - { - description: "no flag values", - argValues: fixtureArgValues(), - flagValues: map[string]string{}, - isValid: false, - }, - { - description: "project id missing", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) - }), - isValid: false, - }, - { - description: "project id invalid 1", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" - }), - isValid: false, - }, - { - description: "project id invalid 2", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" - }), - isValid: false, - }, - } - - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(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) - } - } - - 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) - } - }) - } -} - -func TestBuildRequest(t *testing.T) { - tests := []struct { - description string - model *inputModel - expectedRequest ske.ApiGetCredentialsRequest - }{ - { - 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), - cmpopts.EquateComparable(testCtx), - ) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } - }) - } -} diff --git a/internal/cmd/ske/credentials/rotate/rotate.go b/internal/cmd/ske/credentials/rotate/rotate.go deleted file mode 100644 index 676c712e2..000000000 --- a/internal/cmd/ske/credentials/rotate/rotate.go +++ /dev/null @@ -1,125 +0,0 @@ -package rotate - -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/ske/client" - "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" - - "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/ske" - "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" -) - -const ( - clusterNameArg = "CLUSTER_NAME" -) - -type inputModel struct { - *globalflags.GlobalFlagModel - ClusterName string -} - -func NewCmd(p *print.Printer) *cobra.Command { - cmd := &cobra.Command{ - Use: fmt.Sprintf("rotate %s", clusterNameArg), - Short: "Rotates credentials associated to a SKE cluster", - Long: "Rotates credentials associated to a STACKIT Kubernetes Engine (SKE) cluster. The old credentials will be invalid after the operation.", - Args: args.SingleArg(clusterNameArg, nil), - Deprecated: fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n", - "and will be removed in a future release.", - "Please use the 2-step credential rotation flow instead, by running the commands:", - " $ stackit ske credentials start-rotation CLUSTER_NAME", - " $ stackit ske credentials complete-rotation CLUSTER_NAME", - "For more information, visit: https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html", - ), - Example: examples.Build( - examples.NewExample( - `Rotate credentials associated to the SKE cluster with name "my-cluster"`, - "$ stackit ske credentials rotate my-cluster"), - ), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() - model, err := parseInput(p, cmd, args) - if err != nil { - return err - } - - // Configure API client - apiClient, err := client.ConfigureClient(p) - if err != nil { - return err - } - - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to rotate credentials for SKE cluster %q? (The old credentials will be invalid after this operation)", model.ClusterName) - err = p.PromptForConfirmation(prompt) - if err != nil { - return err - } - } - - // Call API - req := buildRequest(ctx, model, apiClient) - _, err = req.Execute() - if err != nil { - return fmt.Errorf("rotate SKE credentials: %w", err) - } - - // Wait for async operation, if async mode not enabled - if !model.Async { - s := spinner.New(p) - s.Start("Rotating credentials") - _, err = wait.RotateCredentialsWaitHandler(ctx, apiClient, model.ProjectId, model.ClusterName).WaitWithContext(ctx) - if err != nil { - return fmt.Errorf("wait for SKE credentials rotation: %w", err) - } - s.Stop() - } - - operationState := "Rotated" - if model.Async { - operationState = "Triggered rotation of" - } - p.Info("%s credentials for cluster %q\n", operationState, model.ClusterName) - return nil - }, - } - return cmd -} - -func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { - clusterName := inputArgs[0] - - globalFlags := globalflags.Parse(p, cmd) - if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} - } - - model := inputModel{ - GlobalFlagModel: globalFlags, - ClusterName: clusterName, - } - - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - - return &model, nil -} - -func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerRotateCredentialsRequest { - req := apiClient.TriggerRotateCredentials(ctx, model.ProjectId, model.ClusterName) //nolint:staticcheck //command will be removed in a later update - return req -} diff --git a/internal/cmd/ske/credentials/rotate/rotate_test.go b/internal/cmd/ske/credentials/rotate/rotate_test.go deleted file mode 100644 index 9156795fb..000000000 --- a/internal/cmd/ske/credentials/rotate/rotate_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package rotate - -import ( - "context" - "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/ske" -) - -var projectIdFlag = globalflags.ProjectIdFlag - -type testCtxKey struct{} - -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &ske.APIClient{} -var testProjectId = uuid.NewString() -var testClusterName = "cluster" - -func fixtureArgValues(mods ...func(argValues []string)) []string { - argValues := []string{ - testClusterName, - } - for _, mod := range mods { - mod(argValues) - } - return argValues -} - -func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { - flagValues := map[string]string{ - projectIdFlag: testProjectId, - } - for _, mod := range mods { - mod(flagValues) - } - return flagValues -} - -func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { - model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ - ProjectId: testProjectId, - Verbosity: globalflags.VerbosityDefault, - }, - ClusterName: testClusterName, - } - for _, mod := range mods { - mod(model) - } - return model -} - -func fixtureRequest(mods ...func(request *ske.ApiTriggerRotateCredentialsRequest)) ske.ApiTriggerRotateCredentialsRequest { - request := testClient.TriggerRotateCredentials(testCtx, testProjectId, testClusterName) //nolint:staticcheck //command will be removed in a later update - for _, mod := range mods { - mod(&request) - } - return request -} - -func TestParseInput(t *testing.T) { - tests := []struct { - description string - argValues []string - flagValues map[string]string - isValid bool - expectedModel *inputModel - }{ - { - description: "base", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(), - }, - { - description: "no values", - argValues: []string{}, - flagValues: map[string]string{}, - isValid: false, - }, - { - description: "no arg values", - argValues: []string{}, - flagValues: fixtureFlagValues(), - isValid: false, - }, - { - description: "no flag values", - argValues: fixtureArgValues(), - flagValues: map[string]string{}, - isValid: false, - }, - { - description: "project id missing", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) - }), - isValid: false, - }, - { - description: "project id invalid 1", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" - }), - isValid: false, - }, - { - description: "project id invalid 2", - argValues: fixtureArgValues(), - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" - }), - isValid: false, - }, - } - - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(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) - } - } - - 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) - } - }) - } -} - -func TestBuildRequest(t *testing.T) { - tests := []struct { - description string - model *inputModel - expectedRequest ske.ApiTriggerRotateCredentialsRequest - }{ - { - 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), - cmpopts.EquateComparable(testCtx), - ) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } - }) - } -} diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index f1b4cec26..3f54a607d 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -11,11 +11,12 @@ import ( "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/ske/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/ske" ) type inputModel struct { @@ -52,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read SKE project details: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, resp, model.ProjectId) }, } return cmd @@ -80,12 +81,12 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiGetServiceStatusRequest { - req := apiClient.GetServiceStatus(ctx, model.ProjectId) //nolint:staticcheck //command will be removed in a later update +func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiGetServiceStatusRequest { + req := apiClient.GetServiceStatus(ctx, model.ProjectId, utils.SKEServiceId) return req } -func outputResult(p *print.Printer, outputFormat string, project *ske.ProjectResponse) error { +func outputResult(p *print.Printer, outputFormat string, project *serviceenablement.ServiceStatus, projectId string) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(project, "", " ") @@ -105,7 +106,7 @@ func outputResult(p *print.Printer, outputFormat string, project *ske.ProjectRes return nil default: table := tables.NewTable() - table.AddRow("ID", *project.ProjectId) + table.AddRow("ID", projectId) table.AddSeparator() table.AddRow("STATE", *project.State) err := table.Display(p) diff --git a/internal/cmd/ske/describe/describe_test.go b/internal/cmd/ske/describe/describe_test.go index 5805585aa..fe8e39e71 100644 --- a/internal/cmd/ske/describe/describe_test.go +++ b/internal/cmd/ske/describe/describe_test.go @@ -6,12 +6,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + serviceEnablementUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/ske" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -19,7 +20,7 @@ var projectIdFlag = globalflags.ProjectIdFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &ske.APIClient{} +var testClient = &serviceenablement.APIClient{} var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { @@ -45,8 +46,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *ske.ApiGetServiceStatusRequest)) ske.ApiGetServiceStatusRequest { - request := testClient.GetServiceStatus(testCtx, testProjectId) //nolint:staticcheck //command will be removed in a later update +func fixtureRequest(mods ...func(request *serviceenablement.ApiGetServiceStatusRequest)) serviceenablement.ApiGetServiceStatusRequest { + request := testClient.GetServiceStatus(testCtx, testProjectId, serviceEnablementUtils.SKEServiceId) //nolint:staticcheck //command will be removed in a later update for _, mod := range mods { mod(&request) } @@ -145,7 +146,7 @@ func TestBuildRequest(t *testing.T) { description string model *inputModel isValid bool - expectedRequest ske.ApiGetServiceStatusRequest + expectedRequest serviceenablement.ApiGetServiceStatusRequest }{ { description: "base", diff --git a/internal/pkg/services/service-enablement/utils/utils.go b/internal/pkg/services/service-enablement/utils/utils.go index 27952a763..45e3f819b 100644 --- a/internal/pkg/services/service-enablement/utils/utils.go +++ b/internal/pkg/services/service-enablement/utils/utils.go @@ -1,5 +1,33 @@ package utils +import ( + "context" + "net/http" + + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/wait" +) + const ( SKEServiceId = "cloud.stackit.ske" ) + +type ServiceEnablementClient interface { + GetServiceStatusExecute(ctx context.Context, projectId string, serviceId string) (*serviceenablement.ServiceStatus, error) +} + +func ProjectEnabled(ctx context.Context, apiClient ServiceEnablementClient, projectId string) (bool, error) { + project, err := apiClient.GetServiceStatusExecute(ctx, projectId, SKEServiceId) + if err != nil { + oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped + if !ok { + return false, err + } + if oapiErr.StatusCode == http.StatusNotFound { + return false, nil + } + return false, err + } + return *project.State == wait.ServiceStateEnabled, nil +} diff --git a/internal/pkg/services/service-enablement/utils/utils_test.go b/internal/pkg/services/service-enablement/utils/utils_test.go new file mode 100644 index 000000000..4ade8fa58 --- /dev/null +++ b/internal/pkg/services/service-enablement/utils/utils_test.go @@ -0,0 +1,106 @@ +package utils + +import ( + "context" + "fmt" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/wait" +) + +var ( + testProjectId = uuid.NewString() +) + +type serviceEnableClientMocked struct { + serviceDisabled bool + getServiceStatusFails bool + getServiceStatusResp *serviceenablement.ServiceStatus +} + +func (m *serviceEnableClientMocked) GetServiceStatusExecute(_ context.Context, _, _ string) (*serviceenablement.ServiceStatus, error) { + if m.getServiceStatusFails { + return nil, fmt.Errorf("could not get service status") + } + if m.serviceDisabled { + return nil, &oapierror.GenericOpenAPIError{StatusCode: 404} + } + return m.getServiceStatusResp, nil +} + +func TestProjectEnabled(t *testing.T) { + tests := []struct { + description string + serviceDisabled bool + getProjectFails bool + getProjectResp *serviceenablement.ServiceStatus + isValid bool + expectedOutput bool + }{ + { + description: "project enabled", + getProjectResp: &serviceenablement.ServiceStatus{State: utils.Ptr(wait.ServiceStateEnabled)}, + isValid: true, + expectedOutput: true, + }, + { + description: "project disabled (404)", + serviceDisabled: true, + isValid: true, + expectedOutput: false, + }, + { + description: "project disabled 1", + getProjectResp: &serviceenablement.ServiceStatus{State: utils.Ptr(wait.ServiceStateEnabling)}, + isValid: true, + expectedOutput: false, + }, + { + description: "project disabled 2", + getProjectResp: &serviceenablement.ServiceStatus{State: utils.Ptr(wait.ServiceStateDisabled)}, + isValid: true, + expectedOutput: false, + }, + { + description: "project disabled 3", + getProjectResp: &serviceenablement.ServiceStatus{State: utils.Ptr(wait.ServiceStateDisabling)}, + isValid: true, + expectedOutput: false, + }, + { + description: "get clusters fails", + getProjectFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &serviceEnableClientMocked{ + serviceDisabled: tt.serviceDisabled, + getServiceStatusFails: tt.getProjectFails, + getServiceStatusResp: tt.getProjectResp, + } + + output, err := ProjectEnabled(context.Background(), client, testProjectId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %t, got %t", tt.expectedOutput, output) + } + }) + } +} diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 1ce6c8974..366467643 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -3,14 +3,11 @@ package utils import ( "context" "fmt" - "net/http" "os" "path/filepath" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/services/ske" "golang.org/x/mod/semver" ) @@ -37,21 +34,6 @@ type SKEClient interface { ListProviderOptionsExecute(ctx context.Context) (*ske.ProviderOptions, error) } -func ProjectEnabled(ctx context.Context, apiClient SKEClient, projectId string) (bool, error) { - project, err := apiClient.GetServiceStatusExecute(ctx, projectId) - if err != nil { - oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped - if !ok { - return false, err - } - if oapiErr.StatusCode == http.StatusNotFound { - return false, nil - } - return false, err - } - return *project.State == ske.PROJECTSTATE_CREATED, nil -} - func ClusterExists(ctx context.Context, apiClient SKEClient, projectId, clusterName string) (bool, error) { clusters, err := apiClient.ListClustersExecute(ctx, projectId) if err != nil { diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index 55331155a..c3efcfe88 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -57,72 +57,6 @@ func (m *skeClientMocked) ListProviderOptionsExecute(_ context.Context) (*ske.Pr return m.listProviderOptionsResp, nil } -func TestProjectEnabled(t *testing.T) { - tests := []struct { - description string - serviceDisabled bool - getProjectFails bool - getProjectResp *ske.ProjectResponse - isValid bool - expectedOutput bool - }{ - { - description: "project enabled", - getProjectResp: &ske.ProjectResponse{State: ske.PROJECTSTATE_CREATED.Ptr()}, - isValid: true, - expectedOutput: true, - }, - { - description: "project disabled (404)", - serviceDisabled: true, - isValid: true, - expectedOutput: false, - }, - { - description: "project disabled 1", - getProjectResp: &ske.ProjectResponse{State: ske.PROJECTSTATE_CREATING.Ptr()}, - isValid: true, - expectedOutput: false, - }, - { - description: "project disabled 2", - getProjectResp: &ske.ProjectResponse{State: ske.PROJECTSTATE_DELETING.Ptr()}, - isValid: true, - expectedOutput: false, - }, - { - description: "get clusters fails", - getProjectFails: true, - isValid: false, - }, - } - - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - client := &skeClientMocked{ - serviceDisabled: tt.serviceDisabled, - getServiceStatusFails: tt.getProjectFails, - getServiceStatusResp: tt.getProjectResp, - } - - output, err := ProjectEnabled(context.Background(), client, testProjectId) - - if tt.isValid && err != nil { - t.Errorf("failed on valid input") - } - if !tt.isValid && err == nil { - t.Errorf("did not fail on invalid input") - } - if !tt.isValid { - return - } - if output != tt.expectedOutput { - t.Errorf("expected output to be %t, got %t", tt.expectedOutput, output) - } - }) - } -} - func TestClusterExists(t *testing.T) { tests := []struct { description string From 3d5a916b0c23b0fcbce27a7ca10a35c551f45ed0 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 17 Jan 2025 11:41:46 +0100 Subject: [PATCH 148/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/authorization to v0.5.1 (#565) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4b6553eb8..ed319d055 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/stackitcloud/stackit-sdk-go/core v0.15.1 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1 diff --git a/go.sum b/go.sum index e2800bb6d..1e400ad63 100644 --- a/go.sum +++ b/go.sum @@ -119,8 +119,8 @@ github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stackitcloud/stackit-sdk-go/core v0.15.1 h1:hIj/k/JXEuYmud3VWo3lr7Cfj2hfl4gG9nUIzcaZ9pM= github.com/stackitcloud/stackit-sdk-go/core v0.15.1/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.0 h1:Phqfx//JkBSFc1cq31d6EDzLDZU5JukaODMlaWpnFQw= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.0/go.mod h1:wP0L4+HKCKei7r26u7w4+tIOOsRwtkz/2RAsLGPXDMU= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.1 h1:MAB7z8Hr6nCNdPCiLy5uNOJB+1R/eYFseFNEQUYK7qc= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.1/go.mod h1:8xSVF4KRo4GbkGBmmiOYP/CzIIivppvGIafUpdctnZc= github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 h1:nzOZQ2X6joM2iStePoACZeYvXFBQIBjkYE9sLanOGvE= github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 h1:o9OAGh4mdYY5LZYZiJio0KYUhqPSpBY4vT08piGx0pI= From c5b3de6821297d257516d9a0c37985ae37a9de0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Fri, 17 Jan 2025 11:47:30 +0100 Subject: [PATCH 149/619] Fixes for image sub commands (#564) * fix: output of describe command * fix: require rescue bus and device as pair, remove unsupported local-image-path from update command, fix describe for undefined fields * fix: added testcases for flag groups --- internal/cmd/beta/image/create/create.go | 1 + internal/cmd/beta/image/create/create_test.go | 33 ++++++++++++++++ internal/cmd/beta/image/describe/describe.go | 10 ++--- internal/cmd/beta/image/update/update.go | 31 +++++++-------- internal/cmd/beta/image/update/update_test.go | 39 +++++++++++++++++-- 5 files changed, 89 insertions(+), 25 deletions(-) diff --git a/internal/cmd/beta/image/create/create.go b/internal/cmd/beta/image/create/create.go index fee5907c5..e02518b01 100644 --- a/internal/cmd/beta/image/create/create.go +++ b/internal/cmd/beta/image/create/create.go @@ -283,6 +283,7 @@ func configureFlags(cmd *cobra.Command) { if err := flags.MarkFlagsRequired(cmd, nameFlag, diskFormatFlag, localFilePathFlag); err != nil { cobra.CheckErr(err) } + cmd.MarkFlagsRequiredTogether(rescueBusFlag, rescueDeviceFlag) } func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { diff --git a/internal/cmd/beta/image/create/create_test.go b/internal/cmd/beta/image/create/create_test.go index 2a2902424..5777a9cf8 100644 --- a/internal/cmd/beta/image/create/create_test.go +++ b/internal/cmd/beta/image/create/create_test.go @@ -233,6 +233,32 @@ func TestParseInput(t *testing.T) { } }), }, + { + description: "only rescue bus is invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, rescueDeviceFlag) + }), + isValid: false, + }, + { + description: "only rescue device is invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, rescueBusFlag) + }), + isValid: false, + }, + { + description: "no rescue device and no bus is valid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, rescueBusFlag) + delete(flagValues, rescueDeviceFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Config.RescueBus = nil + model.Config.RescueDevice = nil + }), + }, } for _, tt := range tests { @@ -253,6 +279,13 @@ func TestParseInput(t *testing.T) { } } + if err := cmd.ValidateFlagGroups(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flag groups: %v", err) + } + if err := cmd.ValidateRequiredFlags(); err != nil { if !tt.isValid { return diff --git a/internal/cmd/beta/image/describe/describe.go b/internal/cmd/beta/image/describe/describe.go index 3a85f635c..6da572ad4 100644 --- a/internal/cmd/beta/image/describe/describe.go +++ b/internal/cmd/beta/image/describe/describe.go @@ -106,7 +106,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.Image) error { return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal image: %w", err) } @@ -141,12 +141,12 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.Image) error { table.AddRow("OPERATING SYSTEM", *os) table.AddSeparator() } - if distro := config.OperatingSystemDistro; distro != nil { - table.AddRow("OPERATING SYSTEM DISTRIBUTION", *distro) + if distro := config.OperatingSystemDistro; distro != nil && distro.IsSet() { + table.AddRow("OPERATING SYSTEM DISTRIBUTION", *distro.Get()) table.AddSeparator() } - if version := config.OperatingSystemVersion; version != nil { - table.AddRow("OPERATING SYSTEM VERSION", *version) + if version := config.OperatingSystemVersion; version != nil && version.IsSet() { + table.AddRow("OPERATING SYSTEM VERSION", *version.Get()) table.AddSeparator() } if uefi := config.Uefi; uefi != nil { diff --git a/internal/cmd/beta/image/update/update.go b/internal/cmd/beta/image/update/update.go index 9c672e86f..8e8becebd 100644 --- a/internal/cmd/beta/image/update/update.go +++ b/internal/cmd/beta/image/update/update.go @@ -53,21 +53,19 @@ func (ic *imageConfig) isEmpty() bool { type inputModel struct { *globalflags.GlobalFlagModel - Id string - Name *string - DiskFormat *string - LocalFilePath *string - Labels *map[string]string - Config *imageConfig - MinDiskSize *int64 - MinRam *int64 - Protected *bool + Id string + Name *string + DiskFormat *string + Labels *map[string]string + Config *imageConfig + MinDiskSize *int64 + MinRam *int64 + Protected *bool } func (im *inputModel) isEmpty() bool { return im.Name == nil && im.DiskFormat == nil && - im.LocalFilePath == nil && im.Labels == nil && (im.Config == nil || im.Config.isEmpty()) && im.MinDiskSize == nil && @@ -78,9 +76,8 @@ func (im *inputModel) isEmpty() bool { const imageIdArg = "IMAGE_ID" const ( - nameFlag = "name" - diskFormatFlag = "disk-format" - localFilePathFlag = "local-file-path" + nameFlag = "name" + diskFormatFlag = "disk-format" bootMenuFlag = "boot-menu" cdromBusFlag = "cdrom-bus" @@ -167,7 +164,6 @@ func NewCmd(p *print.Printer) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().String(nameFlag, "", "The name of the image.") cmd.Flags().String(diskFormatFlag, "", "The disk format of the image. ") - cmd.Flags().String(localFilePathFlag, "", "The path to the local disk image file.") cmd.Flags().Bool(bootMenuFlag, false, "Enables the BIOS bootmenu.") cmd.Flags().String(cdromBusFlag, "", "Sets CDROM bus controller type.") @@ -188,6 +184,8 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(minDiskSizeFlag, 0, "Size in Gigabyte.") cmd.Flags().Int64(minRamFlag, 0, "Size in Megabyte.") cmd.Flags().Bool(protectedFlag, false, "Protected VM.") + + cmd.MarkFlagsRequiredTogether(rescueBusFlag, rescueDeviceFlag) } func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { @@ -201,9 +199,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM Id: cliArgs[0], Name: flags.FlagToStringPointer(p, cmd, nameFlag), - DiskFormat: flags.FlagToStringPointer(p, cmd, diskFormatFlag), - LocalFilePath: flags.FlagToStringPointer(p, cmd, localFilePathFlag), - Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), + DiskFormat: flags.FlagToStringPointer(p, cmd, diskFormatFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), Config: &imageConfig{ BootMenu: flags.FlagToBoolPointer(p, cmd, bootMenuFlag), CdromBus: flags.FlagToStringPointer(p, cmd, cdromBusFlag), diff --git a/internal/cmd/beta/image/update/update_test.go b/internal/cmd/beta/image/update/update_test.go index ebab81e51..b08d3ceca 100644 --- a/internal/cmd/beta/image/update/update_test.go +++ b/internal/cmd/beta/image/update/update_test.go @@ -26,7 +26,6 @@ var ( testProjectId = uuid.NewString() testImageId = []string{uuid.NewString()} - testLocalImagePath = "/does/not/exist" testDiskFormat = "raw" testDiskSize int64 = 16 * 1024 * 1024 * 1024 testRamSize int64 = 8 * 1024 * 1024 * 1024 @@ -54,7 +53,6 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st nameFlag: testName, diskFormatFlag: testDiskFormat, - localFilePathFlag: testLocalImagePath, bootMenuFlag: strconv.FormatBool(testBootmenu), cdromBusFlag: testCdRomBus, diskBusFlag: testDiskBus, @@ -95,7 +93,6 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Id: testImageId[0], Name: &testName, DiskFormat: &testDiskFormat, - LocalFilePath: &testLocalImagePath, Labels: utils.Ptr(parseLabels(testLabels)), Config: &imageConfig{ BootMenu: &testBootmenu, @@ -271,6 +268,35 @@ func TestParseInput(t *testing.T) { args: []string{uuid.NewString(), uuid.NewString()}, isValid: false, }, + { + description: "only rescue bus is invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, rescueDeviceFlag) + }), + args: []string{testImageId[0]}, + isValid: false, + }, + { + description: "only rescue device is invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, rescueBusFlag) + }), + args: []string{testImageId[0]}, + isValid: false, + }, + { + description: "no rescue device and no bus is valid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, rescueBusFlag) + delete(flagValues, rescueDeviceFlag) + }), + isValid: true, + args: []string{testImageId[0]}, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Config.RescueBus = nil + model.Config.RescueDevice = nil + }), + }, } for _, tt := range tests { @@ -297,6 +323,13 @@ func TestParseInput(t *testing.T) { t.Fatalf("error validating flags: %v", err) } + if err := cmd.ValidateFlagGroups(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flag groups: %v", err) + } + if err := cmd.ValidateArgs(tt.args); err != nil { if !tt.isValid { return From f649139eaaa7864e65be44f05bc8ce35ee178d3c Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 17 Jan 2025 15:33:59 +0100 Subject: [PATCH 150/619] Use working aptly version 1.5.0 (#566) aptly version 1.6.0 results in an segmentation fault. Therefore we fall back to version 1.5.0. Since it is not possible to specify a version via brew command a formula was added for aptly 1.5.0 (source: https://github.com/Homebrew/homebrew-core/pull/202415/files) Signed-off-by: Alexander Dahmen --- .github/workflows/release.yaml | 7 ++++-- aptly.rb | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 aptly.rb diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0344e3995..b672b5150 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -57,8 +57,11 @@ jobs: APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} SIGNING_CERTIFICATE_BASE64: ${{ secrets.APPLICATION_ID_CERT }} AUTHKEY_BASE64: ${{ secrets.APPLE_API_KEY }} - - name: Install Aptly - run: brew install aptly + # aptly version 1.6.0 results in an segmentation fault. Therefore we fall back to version 1.5.0. + # Since it is not possible to specify a version via brew command a formula was added for aptly 1.5.0 + # (source: https://github.com/Homebrew/homebrew-core/pull/202415/files) + - name: Install Aptly version 1.5.0 + run: brew install aptly.rb - name: Install Snapcraft uses: samuelmeuli/action-snapcraft@v2 - name: Run GoReleaser diff --git a/aptly.rb b/aptly.rb new file mode 100644 index 000000000..8b1f49727 --- /dev/null +++ b/aptly.rb @@ -0,0 +1,40 @@ +class Aptly < Formula + desc "Swiss army knife for Debian repository management" + homepage "https://www.aptly.info/" + url "https://github.com/aptly-dev/aptly/archive/refs/tags/v1.5.0.tar.gz" + sha256 "07e18ce606feb8c86a1f79f7f5dd724079ac27196faa61a2cefa5b599bbb5bb1" + license "MIT" + head "https://github.com/aptly-dev/aptly.git", branch: "master" + + bottle do + rebuild 2 + sha256 cellar: :any_skip_relocation, arm64_sequoia: "f689184731329b1c22f23af361e31cd8aa6992084434d49281227654281a8f45" + sha256 cellar: :any_skip_relocation, arm64_sonoma: "0d022b595e520ea53e23b1dfceb4a45139e7e2ba735994196135c1f9c1a36d4c" + sha256 cellar: :any_skip_relocation, arm64_ventura: "c6fa91fb368a63d5558b8c287b330845e04f90bd4fe7223e161493b01747c869" + sha256 cellar: :any_skip_relocation, arm64_monterey: "19c0c8c0b35c1c5faa2a71fc0bd088725f5623f465369dcca5b2cea59322714c" + sha256 cellar: :any_skip_relocation, arm64_big_sur: "2314abe4aae7ea53660920d311cacccd168045994e1a9eddf12a381b215c1908" + sha256 cellar: :any_skip_relocation, sonoma: "0f077e265538e235ad867b39edc756180c8a0fba7ac5385ab59b18e827519f4c" + sha256 cellar: :any_skip_relocation, ventura: "d132d06243b93952309f3fbe1970d87cde272ea103cf1829c880c1b8a85a12cb" + sha256 cellar: :any_skip_relocation, monterey: "86111a102d0782a77bab0d48015bd275f120a36964d86f8f613f1a8f73d94664" + sha256 cellar: :any_skip_relocation, big_sur: "d622cfe1d925f0058f583b8bf48b0bdcee36a441f1bcf145040e5f93879f8765" + sha256 cellar: :any_skip_relocation, catalina: "5d9d495ec8215cfade3e856528dfa233496849517813b19a9ba8d60cb72c4751" + sha256 cellar: :any_skip_relocation, x86_64_linux: "bbff5503f74ef5dcaae33846e285ecf1a23c23de1c858760ae1789ef6fc99524" + end + + depends_on "go" => :build + + def install + system "go", "generate" if build.head? + system "go", "build", *std_go_args(ldflags: "-s -w -X main.Version=#{version}") + + bash_completion.install "completion.d/aptly" + end + + test do + assert_match "aptly version:", shell_output("#{bin}/aptly version") + + (testpath/".aptly.conf").write("{}") + result = shell_output("#{bin}/aptly -config='#{testpath}/.aptly.conf' mirror list") + assert_match "No mirrors found, create one with", result + end +end \ No newline at end of file From 4cdc840d2e5d1f9ef4f802e94fd2d7f7c2363975 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:08:51 +0100 Subject: [PATCH 151/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.15 (#563) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ed319d055..a1c8cab13 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.13 + github.com/goccy/go-yaml v1.15.15 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 1e400ad63..a0be4b760 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.13 h1:Xd87Yddmr2rC1SLLTm2MNDcTjeO/GYo0JGiww6gSTDg= -github.com/goccy/go-yaml v1.15.13/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.15 h1:5turdzAlutS2Q7/QR/9R99Z1K0J00qDb4T0pHJcZ5ew= +github.com/goccy/go-yaml v1.15.15/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 83bbf0af1f8d2a4f15369c82890078e4db21107c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Tue, 21 Jan 2025 11:15:55 +0100 Subject: [PATCH 152/619] Support for listing of quotas (#567) * feat: support for quota listing * feat: integrated review hints --- README.md | 2 +- docs/stackit_beta.md | 1 + docs/stackit_beta_quota.md | 34 ++++ docs/stackit_beta_quota_list.md | 40 +++++ internal/cmd/beta/beta.go | 2 + internal/cmd/beta/quota/list/list.go | 190 ++++++++++++++++++++++ internal/cmd/beta/quota/list/list_test.go | 164 +++++++++++++++++++ internal/cmd/beta/quota/quota.go | 29 ++++ 8 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 docs/stackit_beta_quota.md create mode 100644 docs/stackit_beta_quota_list.md create mode 100644 internal/cmd/beta/quota/list/list.go create mode 100644 internal/cmd/beta/quota/list/list_test.go create mode 100644 internal/cmd/beta/quota/quota.go diff --git a/README.md b/README.md index b00887fd9..d7f76ff26 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Service | CLI Commands | Status | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | | Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta security-group`
`beta key-pair`
`beta image` | :white_check_mark: (beta)| +| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta security-group`
`beta key-pair`
`beta image`
`beta quota` | :white_check_mark: (beta)| | Authorization | `project`, `organization` | :white_check_mark: | | DNS | `dns` | :white_check_mark: | | Kubernetes Engine (SKE) | `ske` | :white_check_mark: | diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index d5ed983dc..fde3ac259 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -47,6 +47,7 @@ stackit beta [flags] * [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) * [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces * [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit beta quota](./stackit_beta_quota.md) - Manage server quotas * [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups * [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_quota.md b/docs/stackit_beta_quota.md new file mode 100644 index 000000000..3fa8e4a33 --- /dev/null +++ b/docs/stackit_beta_quota.md @@ -0,0 +1,34 @@ +## stackit beta quota + +Manage server quotas + +### Synopsis + +Manage the lifecycle of server quotas. + +``` +stackit beta quota [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta quota" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta quota list](./stackit_beta_quota_list.md) - Lists quotas + diff --git a/docs/stackit_beta_quota_list.md b/docs/stackit_beta_quota_list.md new file mode 100644 index 000000000..f9a6fa62c --- /dev/null +++ b/docs/stackit_beta_quota_list.md @@ -0,0 +1,40 @@ +## stackit beta quota list + +Lists quotas + +### Synopsis + +Lists server quotas. + +``` +stackit beta quota list [flags] +``` + +### Examples + +``` + List available quotas + $ stackit beta quota list +``` + +### Options + +``` + -h, --help Help for "stackit beta quota list" +``` + +### 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 beta quota](./stackit_beta_quota.md) - Manage server quotas + diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 966e5f414..72ed0c5f2 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -9,6 +9,7 @@ import ( networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/quota" securitygroup "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" @@ -54,4 +55,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(securitygroup.NewCmd(p)) cmd.AddCommand(keypair.NewCmd(p)) cmd.AddCommand(image.NewCmd(p)) + cmd.AddCommand(quota.NewCmd(p)) } diff --git a/internal/cmd/beta/quota/list/list.go b/internal/cmd/beta/quota/list/list.go new file mode 100644 index 000000000..32a2be9d4 --- /dev/null +++ b/internal/cmd/beta/quota/list/list.go @@ -0,0 +1,190 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists quotas", + Long: "Lists project quotas.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List available quotas`, + `$ stackit beta quota list`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + response, err := request.Execute() + if err != nil { + return fmt.Errorf("list quotas: %w", err) + } + + if items := response.Quotas; items == nil { + p.Info("No quotas found for project %q", projectLabel) + } else { + if err := outputResult(p, model.OutputFormat, items); err != nil { + return fmt.Errorf("output quotas: %w", err) + } + } + + return nil + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListQuotasRequest { + request := apiClient.ListQuotas(ctx, model.ProjectId) + + return request +} + +func outputResult(p *print.Printer, outputFormat string, quotas *iaas.QuotaList) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(quotas, "", " ") + if err != nil { + return fmt.Errorf("marshal quota list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(quotas, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal quota list: %w", err) + } + p.Outputln(string(details)) + + return nil + + default: + table := tables.NewTable() + table.SetHeader("NAME", "LIMIT", "CURRENT USAGE", "PERCENT") + if val := quotas.BackupGigabytes; val != nil { + table.AddRow("Total size in GiB of backups [GiB]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.Backups; val != nil { + table.AddRow("Number of backups [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.Gigabytes; val != nil { + table.AddRow("Total size in GiB of volumes and snapshots [GiB]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.Networks; val != nil { + table.AddRow("Number of networks [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.Nics; val != nil { + table.AddRow("Number of network interfaces (nics) [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.PublicIps; val != nil { + table.AddRow("Number of public IP addresses [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.Ram; val != nil { + table.AddRow("Amount of server RAM in MiB [MiB]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.SecurityGroupRules; val != nil { + table.AddRow("Number of security group rules [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.SecurityGroups; val != nil { + table.AddRow("Number of security groups [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.Snapshots; val != nil { + table.AddRow("Number of snapshots [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.Vcpu; val != nil { + table.AddRow("Number of server cores (vcpu) [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + if val := quotas.Volumes; val != nil { + table.AddRow("Number of volumes [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} + +func conv(n *int64) string { + if n != nil { + return strconv.FormatInt(*n, 10) + } + return "n/a" +} + +func percentage(val interface { + GetLimit() *int64 + GetUsage() *int64 +}) string { + if a, b := val.GetLimit(), val.GetUsage(); a != nil && b != nil { + return fmt.Sprintf("%3.1f%%", 100.0/float64(*a)*float64(*b)) + } + return "n/a" +} diff --git a/internal/cmd/beta/quota/list/list_test.go b/internal/cmd/beta/quota/list/list_test.go new file mode 100644 index 000000000..b8fa5319c --- /dev/null +++ b/internal/cmd/beta/quota/list/list_test.go @@ -0,0 +1,164 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListQuotasRequest)) iaas.ApiListQuotasRequest { + request := testClient.ListQuotas(testCtx, testProjectId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListQuotasRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/quota/quota.go b/internal/cmd/beta/quota/quota.go new file mode 100644 index 000000000..e4eaf4bd8 --- /dev/null +++ b/internal/cmd/beta/quota/quota.go @@ -0,0 +1,29 @@ +package quota + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/quota/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "quota", + Short: "Manage server quotas", + Long: "Manage the lifecycle of server quotas.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand( + list.NewCmd(p), + ) +} From 5b1782e096a5e0791c021916348f5e6c2f6f476b Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:48:31 +0100 Subject: [PATCH 153/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/postgresflex to v0.16.1 (#568) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a1c8cab13..067d26c2b 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.1 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 diff --git a/go.sum b/go.sum index a0be4b760..e1ce1b7b8 100644 --- a/go.sum +++ b/go.sum @@ -139,8 +139,8 @@ github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 h1:sIz4wJIz github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1/go.mod h1:okcRTrNDTI3d7MQcYJMliK0qoXeLq0b1wvZuEqgJIWE= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 h1:hwRkCCUSWMhKTc7fLakL89V6+9xkxsFQlRthVmrvi1U= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1/go.mod h1:U45gFwIAAdXWL/Wlp9rY3iPVWFHLGILz1C3Qc62o8KM= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0 h1:aRVPIaTtM2zyep3k22lu6ARG0j0P1N/7fjH7TS6ucio= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.0/go.mod h1:JnhCZzXprN/em1Uxpvl1ITMf6Hl/8N/4y5zNsRqEGlA= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.1 h1:c4pocENxdDycScEpt0s81v+uEtLhfj+8Gwwih7iCVFI= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.1/go.mod h1:JnhCZzXprN/em1Uxpvl1ITMf6Hl/8N/4y5zNsRqEGlA= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1 h1:6XfGxsPFqci/geSDd1gCtiaRJun85X5JepXn4edobXQ= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1/go.mod h1:42oYZOqin+rIUrUqgtCIE4wzCWWY30H4UFhzvo1Wg2w= github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1 h1:/EVm0bD9a3KCk9aj/v2ivJIURlGsTr4O2OwMQ4ey3e4= From 388f37f8ec38ecda02e99e0a1c45b54bce78e5e1 Mon Sep 17 00:00:00 2001 From: Javier Vela <5806680+fjvela@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:43:29 +0100 Subject: [PATCH 154/619] feat: ske kubeconfig create. merge kubeconfig into the default kubeconfig file #556 (#557) * feat: ske kubeconfig create merge kubeconfig into the default kubeconfig file * feat: ske kubeconfig merge add flag overwrite --------- Signed-off-by: Javier Vela --- docs/stackit_ske_kubeconfig.md | 2 +- docs/stackit_ske_kubeconfig_create.md | 20 ++- internal/cmd/ske/kubeconfig/create/create.go | 60 ++++--- .../cmd/ske/kubeconfig/create/create_test.go | 29 +++- internal/pkg/services/ske/utils/utils.go | 36 ++++ internal/pkg/services/ske/utils/utils_test.go | 161 ++++++++++++++++-- 6 files changed, 256 insertions(+), 52 deletions(-) diff --git a/docs/stackit_ske_kubeconfig.md b/docs/stackit_ske_kubeconfig.md index 79d8f0381..5c7d3adf0 100644 --- a/docs/stackit_ske_kubeconfig.md +++ b/docs/stackit_ske_kubeconfig.md @@ -30,6 +30,6 @@ stackit ske kubeconfig [flags] ### SEE ALSO * [stackit ske](./stackit_ske.md) - Provides functionality for SKE -* [stackit ske kubeconfig create](./stackit_ske_kubeconfig_create.md) - Creates a kubeconfig for an SKE cluster +* [stackit ske kubeconfig create](./stackit_ske_kubeconfig_create.md) - Creates or update a kubeconfig for an SKE cluster * [stackit ske kubeconfig login](./stackit_ske_kubeconfig_login.md) - Login plugin for kubernetes clients diff --git a/docs/stackit_ske_kubeconfig_create.md b/docs/stackit_ske_kubeconfig_create.md index b63225e7e..d3d0e5622 100644 --- a/docs/stackit_ske_kubeconfig_create.md +++ b/docs/stackit_ske_kubeconfig_create.md @@ -1,14 +1,16 @@ ## stackit ske kubeconfig create -Creates a kubeconfig for an SKE cluster +Creates or update a kubeconfig for an SKE cluster ### Synopsis -Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster. +Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exits in the kubeconfig file the information will be updated. -By default the kubeconfig is created in the .kube folder, in the user's home directory. The kubeconfig file will be overwritten if it already exists. +By default, the kubeconfig information of the SKE cluster is merged into the default kubeconfig file of the current user. If the kubeconfig file doesn't exist, a new one will be created. You can override this behavior by specifying a custom filepath with the --filepath flag. + An expiration time can be set for the kubeconfig. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 1h. + Note that the format is , e.g. 30d for 30 days and you can't combine units. ``` @@ -18,23 +20,26 @@ stackit ske kubeconfig create CLUSTER_NAME [flags] ### Examples ``` - Create a kubeconfig for the SKE cluster with name "my-cluster" + Create or update a kubeconfig for the SKE cluster with name "my-cluster. If the config exits in the kubeconfig file the information will be updated." $ stackit ske kubeconfig create my-cluster Get a login kubeconfig for the SKE cluster with name "my-cluster". This kubeconfig does not contain any credentials and instead obtains valid credentials via the `stackit ske kubeconfig login` command. $ stackit ske kubeconfig create my-cluster --login - Create a kubeconfig for the SKE cluster with name "my-cluster" and set the expiration time to 30 days + Create a kubeconfig for the SKE cluster with name "my-cluster" and set the expiration time to 30 days. If the config exits in the kubeconfig file the information will be updated. $ stackit ske kubeconfig create my-cluster --expiration 30d - Create a kubeconfig for the SKE cluster with name "my-cluster" and set the expiration time to 2 months + Create or update a kubeconfig for the SKE cluster with name "my-cluster" and set the expiration time to 2 months. If the config exits in the kubeconfig file the information will be updated. $ stackit ske kubeconfig create my-cluster --expiration 2M - Create a kubeconfig for the SKE cluster with name "my-cluster" in a custom filepath + Create or update a kubeconfig for the SKE cluster with name "my-cluster" in a custom filepath. If the config exits in the kubeconfig file the information will be updated. $ stackit ske kubeconfig create my-cluster --filepath /path/to/config Get a kubeconfig for the SKE cluster with name "my-cluster" without writing it to a file and format the output as json $ stackit ske kubeconfig create my-cluster --disable-writing --output-format json + + Create a kubeconfig for the SKE cluster with name "my-cluster. It will OVERWRITE your current kubeconfig file." + $ stackit ske kubeconfig create my-cluster --overwrite true ``` ### Options @@ -45,6 +50,7 @@ stackit ske kubeconfig create CLUSTER_NAME [flags] --filepath string Path to create the kubeconfig file. By default, the kubeconfig is created as 'config' in the .kube folder, in the user's home directory. -h, --help Help for "stackit ske kubeconfig create" -l, --login Create a login kubeconfig that obtains valid credentials via the STACKIT CLI. This flag is mutually exclusive with the expiration flag. + --overwrite Overwrite the kubeconfig file. ``` ### Options inherited from parent commands diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index be86251ab..4d2549e04 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -22,52 +22,57 @@ import ( const ( clusterNameArg = "CLUSTER_NAME" - loginFlag = "login" + disableWritingFlag = "disable-writing" expirationFlag = "expiration" filepathFlag = "filepath" - disableWritingFlag = "disable-writing" + loginFlag = "login" + overwriteFlag = "overwrite" ) type inputModel struct { *globalflags.GlobalFlagModel ClusterName string - Filepath *string + DisableWriting bool ExpirationTime *string + Filepath *string Login bool - DisableWriting bool + Overwrite bool } func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", clusterNameArg), - Short: "Creates a kubeconfig for an SKE cluster", + Short: "Creates or update a kubeconfig for an SKE cluster", Long: fmt.Sprintf("%s\n\n%s\n%s\n%s\n%s", - "Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster.", - "By default the kubeconfig is created in the .kube folder, in the user's home directory. The kubeconfig file will be overwritten if it already exists.", - "You can override this behavior by specifying a custom filepath with the --filepath flag.", - "An expiration time can be set for the kubeconfig. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 1h.", + "Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exits in the kubeconfig file the information will be updated.", + "By default, the kubeconfig information of the SKE cluster is merged into the default kubeconfig file of the current user. If the kubeconfig file doesn't exist, a new one will be created.", + "You can override this behavior by specifying a custom filepath with the --filepath flag.\n", + "An expiration time can be set for the kubeconfig. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 1h.\n", "Note that the format is , e.g. 30d for 30 days and you can't combine units."), Args: args.SingleArg(clusterNameArg, nil), Example: examples.Build( examples.NewExample( - `Create a kubeconfig for the SKE cluster with name "my-cluster"`, + `Create or update a kubeconfig for the SKE cluster with name "my-cluster. If the config exits in the kubeconfig file the information will be updated."`, "$ stackit ske kubeconfig create my-cluster"), examples.NewExample( `Get a login kubeconfig for the SKE cluster with name "my-cluster". `+ "This kubeconfig does not contain any credentials and instead obtains valid credentials via the `stackit ske kubeconfig login` command.", "$ stackit ske kubeconfig create my-cluster --login"), examples.NewExample( - `Create a kubeconfig for the SKE cluster with name "my-cluster" and set the expiration time to 30 days`, + `Create a kubeconfig for the SKE cluster with name "my-cluster" and set the expiration time to 30 days. If the config exits in the kubeconfig file the information will be updated.`, "$ stackit ske kubeconfig create my-cluster --expiration 30d"), examples.NewExample( - `Create a kubeconfig for the SKE cluster with name "my-cluster" and set the expiration time to 2 months`, + `Create or update a kubeconfig for the SKE cluster with name "my-cluster" and set the expiration time to 2 months. If the config exits in the kubeconfig file the information will be updated.`, "$ stackit ske kubeconfig create my-cluster --expiration 2M"), examples.NewExample( - `Create a kubeconfig for the SKE cluster with name "my-cluster" in a custom filepath`, + `Create or update a kubeconfig for the SKE cluster with name "my-cluster" in a custom filepath. If the config exits in the kubeconfig file the information will be updated.`, "$ stackit ske kubeconfig create my-cluster --filepath /path/to/config"), examples.NewExample( `Get a kubeconfig for the SKE cluster with name "my-cluster" without writing it to a file and format the output as json`, "$ stackit ske kubeconfig create my-cluster --disable-writing --output-format json"), + examples.NewExample( + `Create a kubeconfig for the SKE cluster with name "my-cluster. It will OVERWRITE your current kubeconfig file."`, + "$ stackit ske kubeconfig create my-cluster --overwrite true"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -83,7 +88,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.AssumeYes && !model.DisableWriting { - prompt := fmt.Sprintf("Are you sure you want to create a kubeconfig for SKE cluster %q? This will OVERWRITE your current kubeconfig file, if it exists.", model.ClusterName) + var prompt string + if model.Overwrite { + prompt = fmt.Sprintf("Are you sure you want to create a kubeconfig for SKE cluster %q? This will OVERWRITE your current kubeconfig file, if it exists.", model.ClusterName) + } else { + prompt = fmt.Sprintf("Are you sure you want to update your kubeconfig for SKE cluster %q? This will update your kubeconfig file. \nIf it the kubeconfig file doesn't exists, it will create a new one.", model.ClusterName) + } err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -137,10 +147,15 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.DisableWriting { - err = skeUtils.WriteConfigFile(kubeconfigPath, kubeconfig) + if model.Overwrite { + err = skeUtils.WriteConfigFile(kubeconfigPath, kubeconfig) + } else { + err = skeUtils.MergeKubeConfig(kubeconfigPath, kubeconfig) + } if err != nil { return fmt.Errorf("write kubeconfig file: %w", err) } + p.Outputf("\nSet kubectl context to %s with: kubectl config use-context %s\n", model.ClusterName, model.ClusterName) } return outputResult(p, model, kubeconfigPath, respKubeconfig, respLogin) @@ -151,11 +166,11 @@ func NewCmd(p *print.Printer) *cobra.Command { } func configureFlags(cmd *cobra.Command) { + cmd.Flags().Bool(disableWritingFlag, false, fmt.Sprintf("Disable the writing of kubeconfig. Set the output format to json or yaml using the --%s flag to display the kubeconfig.", globalflags.OutputFormatFlag)) cmd.Flags().BoolP(loginFlag, "l", false, "Create a login kubeconfig that obtains valid credentials via the STACKIT CLI. This flag is mutually exclusive with the expiration flag.") - cmd.Flags().StringP(expirationFlag, "e", "", "Expiration time for the kubeconfig in seconds(s), minutes(m), hours(h), days(d) or months(M). Example: 30d. By default, expiration time is 1h") cmd.Flags().String(filepathFlag, "", "Path to create the kubeconfig file. By default, the kubeconfig is created as 'config' in the .kube folder, in the user's home directory.") - cmd.Flags().Bool(disableWritingFlag, false, fmt.Sprintf("Disable the writing of kubeconfig. Set the output format to json or yaml using the --%s flag to display the kubeconfig.", globalflags.OutputFormatFlag)) - + cmd.Flags().StringP(expirationFlag, "e", "", "Expiration time for the kubeconfig in seconds(s), minutes(m), hours(h), days(d) or months(M). Example: 30d. By default, expiration time is 1h") + cmd.Flags().Bool(overwriteFlag, false, "Overwrite the kubeconfig file.") cmd.MarkFlagsMutuallyExclusive(loginFlag, expirationFlag) } @@ -189,12 +204,13 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } model := inputModel{ - GlobalFlagModel: globalFlags, ClusterName: clusterName, - Filepath: flags.FlagToStringPointer(p, cmd, filepathFlag), + DisableWriting: disableWriting, ExpirationTime: expTime, + Filepath: flags.FlagToStringPointer(p, cmd, filepathFlag), + GlobalFlagModel: globalFlags, Login: flags.FlagToBoolValue(p, cmd, loginFlag), - DisableWriting: disableWriting, + Overwrite: flags.FlagToBoolValue(p, cmd, overwriteFlag), } if p.IsVerbosityDebug() { @@ -260,7 +276,7 @@ func outputResult(p *print.Printer, model *inputModel, kubeconfigPath string, re if respKubeconfig != nil { expiration = fmt.Sprintf(", with expiration date %v (UTC)", *respKubeconfig.ExpirationTimestamp) } - p.Outputf("Created kubeconfig file for cluster %s in %q%s\n", model.ClusterName, kubeconfigPath, expiration) + p.Outputf("Updated kubeconfig file for cluster %s in %q%s\n", model.ClusterName, kubeconfigPath, expiration) return nil } diff --git a/internal/cmd/ske/kubeconfig/create/create_test.go b/internal/cmd/ske/kubeconfig/create/create_test.go index bae59d3bb..85cfe1560 100644 --- a/internal/cmd/ske/kubeconfig/create/create_test.go +++ b/internal/cmd/ske/kubeconfig/create/create_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) @@ -177,6 +176,28 @@ func TestParseInput(t *testing.T) { }), isValid: true, }, + { + description: "enable overwrite", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[overwriteFlag] = "true" + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Overwrite = true + }), + isValid: true, + }, + { + description: "disable overwrite", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[overwriteFlag] = "false" + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Overwrite = false + }), + isValid: true, + }, } for _, tt := range tests { diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 366467643..8834a54a3 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -3,11 +3,14 @@ package utils import ( "context" "fmt" + "maps" "os" "path/filepath" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "k8s.io/client-go/tools/clientcmd" + "github.com/stackitcloud/stackit-sdk-go/services/ske" "golang.org/x/mod/semver" ) @@ -228,6 +231,39 @@ func ConvertToSeconds(timeStr string) (*string, error) { return utils.Ptr(strconv.FormatUint(result, 10)), nil } +// Merge new Kubeconfig into existing Kubeconfig. If it doesn´t exits, creates a new one +func MergeKubeConfig(pathDestionationKubeConfig, contentNewKubeConfig string) error { + if contentNewKubeConfig == "" { + return fmt.Errorf("no data to merge. the new kubeconfig is empty") + } + + newConfig, err := clientcmd.Load([]byte(contentNewKubeConfig)) + if err != nil { + return fmt.Errorf("error loading new kubeconfig: %w", err) + } + + // if the destionation kubeconfig does not exist, create a new one + if _, err := os.Stat(pathDestionationKubeConfig); os.IsNotExist(err) { + return WriteConfigFile(pathDestionationKubeConfig, contentNewKubeConfig) + } + + existingConfig, err := clientcmd.LoadFromFile(pathDestionationKubeConfig) + if err != nil { + return fmt.Errorf("error loading existing kubeconfig: %w", err) + } + + maps.Copy(existingConfig.AuthInfos, newConfig.AuthInfos) + maps.Copy(existingConfig.Contexts, newConfig.Contexts) + maps.Copy(existingConfig.Clusters, newConfig.Clusters) + + err = clientcmd.WriteToFile(*existingConfig, pathDestionationKubeConfig) + if err != nil { + return fmt.Errorf("error writing merged kubeconfig: %w", err) + } + + return nil +} + // WriteConfigFile writes the given data to the given path. // The directory is created if it does not exist. func WriteConfigFile(configPath, data string) error { diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index c3efcfe88..d07207663 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "k8s.io/client-go/tools/clientcmd" "github.com/google/go-cmp/cmp" "github.com/google/uuid" @@ -20,7 +21,47 @@ var ( ) const ( - testClusterName = "test-cluster" + testClusterName = "test-cluster" + existingKubeConfig = ` +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJSjFTZ1NWTjhnMmt3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBeE1UQXhNakkxTlRSYUZ3MHpOVEF4TURneE1qTXdOVFJhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUM4ZXIwam1aS05STlR6Z2dCV3Q1cXMvaW94NXkxY2xBMHBGRHYwOWNmMGtmVGRVQWE3bmpqU0F2WlYKVFpsQlFFaW40Um9PTm1TZzdVMzVWN3FMSW56UVNmZXFuYi9wK05pODhDbkZvMThleUVnb3pHQklTTFpHK0EybQpuNFFEV3k3bVV1UUxFRnpjNjFpazdBQ0F5akZwRDlVdkdSdkxxVGJTQWcwYitYbktqbUUyWVgzTnRLbnJWOUN0CktrTG83K2JSa0MyemNkVnlraExhODhaR1BORUhjdVp2Uk0zQW5NclVGdGVvc0Fjb09xVW4xK09mYlhwUUlsTC8KKzBvRjcwN09Vc2tOUit0WEp4Z1VXL1R4Q0lONTYwU2E4eDVlWjB2VTZNR3ZOSTYwZ3h2S1lGL0pKa0pxU0NwNQovWWhpVmZ2QnNOSG5tVUZsNEdpOGFVMFNVTjRiQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJTUlkxVVhOamlMbFJLWktuSHJWRU55djA4aUp6QVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQVFaOVcwVFdvMQp4UFhPZU9xWHV6aFgzSkRoY0JVRkZyUVlOcHBMSmtqOWdUVm5Eck16b1dmeW9FQXRtT1ZQWURuTnEyTFhOSnpmClltd3RiUGxPemhGYkpWZVBWR0tLZktrUXZ1K3BhZGRtUHRhTzdUcnZqblRHeDhXczJadE5xK20wbkRGRUN4SDkKc1o2K1IycWhBUWNnSGdQWFZQdTdxSXFmbkNWRDkyeGprTE40c2JLZjRMb2x0R3hZbTBTWVZuY09rTFlBL3BvawpqTCsvODRJQXRrRXlEL21VdVF4MEsyVzFvVUM4dDRyMUlPZ3Y3OHZQMkRDRlBuZDVvbTJBM1dCNHY2dUFNZWc0Cnk3Y3FTcjBlSzJhNFQvMUtpTEdzYXI1V01ONTNwMjFiOGJMSTlISGNJMkh6c0tOdEdpNGFOT0hsWWkwUFgrUW0KT3U4NW4ycVdwSUxmCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:61274 + name: existing-cluster +contexts: +- context: + cluster: existing-cluster + user: existing-cluster + name: existing-cluster +current-context: existing-cluster +kind: Config +preferences: {} +users: +- name: existing-cluster + user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJYWFEL3lTemlKM1F3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBeE1UQXhNakkxTlRSYUZ3MHlOakF4TVRBeE1qTXdOVFJhTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEQSs2WjkKWU02RC9DK2VNWnJQRHZoR0VIRk4zeDVXdFMrVWlsb1F3QkJBSXdUNXFQczVnSERWK1cyWjdjT3VGNVFEYlpyUQo3dktWSUtlWXQ0Mk9SZytYQktibHhDV1VpdFZDdmZZbHJYKzlaY0JGL2dFaVBjOE9aK2h0Q1pPNlgyZ3d0WVNOCkgwZ1lLOTlhOFRWUWxlWm9Eem93WlE0Um5aSjhkRGo1STA2blRjdkk3bDBlMWt3VnM5aXFLRHpyekRhYnhqb0EKamZkcUpiZTVkOFc0ZTloTTRBdVRUbFRkWmFVTWFnUHhyaWxEOU9mUXhaUmlReFIzNkhSOHZabm9TcndXeWh5ZApqall0TFQvcE00UXAybUU5NFJqVWE2ekNUVlJKeWduY3RHVnpDRi84RDc1TVU4OVhmVjltQVV5L3BoR1M5MDdjCjlXbzE4Um42TytHNHYwdFRBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkpGalZSYzJPSXVWRXBrcQpjZXRVUTNLL1R5SW5NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUMySVRwUlM1SlU3bGpkeDVRMlkwQzBkZG8yCm9PSmp5TUhVQXJ5ZTIyM2xOd1R1OTNHZXkvUjNIOHNpYWxDRURXdFR0cCsrY3BucW1ON05ia3UvWFI5SUlFdlIKYTNZS3VvbGdOTGtLaEtqMWQ0NVAxeEs0VE5CV1hSV2FMbksxcTdLVWxWWHp2bjdSN3RDY0NtNk90S3d4OUl2WgorRGhUU0pobFEzTVNmNXhjMUdOMm9qb0pPWmVlOXFNc3R1RzdPUVl1M08yUitYVUIwRHgzNnlPeFR2S0NBZ24xCm55Yk5FS0Nia1BmTXdvSU5aTm9iSWE3Y2VHcTdOMzRHaCs3Vi9iazUrQmhoTzVJRTRPeDYvUUxQc1B2ZGtOZHcKSkFyclQ3QytHSkF1UzNXQ2dYUXRyRWFyT3drWHhqajFPc3NuNjdMNlpONG01SkYzWHViSmdQUGZ3L2NECi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBd1B1bWZXRE9nL3d2bmpHYXp3NzRSaEJ4VGQ4ZVZyVXZsSXBhRU1BUVFDTUUrYWo3Ck9ZQncxZmx0bWUzRHJoZVVBMjJhME83eWxTQ25tTGVOamtZUGx3U201Y1FsbElyVlFyMzJKYTEvdldYQVJmNEIKSWozUERtZm9iUW1UdWw5b01MV0VqUjlJR0N2Zld2RTFVSlhtYUE4Nk1HVU9FWjJTZkhRNCtTTk9wMDNMeU81ZApIdFpNRmJQWXFpZzg2OHcybThZNkFJMzNhaVczdVhmRnVIdllUT0FMazA1VTNXV2xER29EOGE0cFEvVG4wTVdVCllrTVVkK2gwZkwyWjZFcThGc29jblk0MkxTMC82VE9FS2RwaFBlRVkxR3Vzd2sxVVNjb0ozTFJsY3doZi9BKysKVEZQUFYzMWZaZ0ZNdjZZUmt2ZE8zUFZxTmZFWitqdmh1TDlMVXdJREFRQUJBb0lCQVFDS0lWWFk5anE3VS8zTgpjRm9MalA1K1AvU3B0V01rMHdsY2UrN2RnR3ZoVEcrYU42NmlTT0g2OWs3UjE5S3hRS1VzRXY2MlArSVloY2dRClVvbWE1V0R4U2w0ZnBkYjBUSzg2MTNkaEhwK0pORlI4aE1QUSs0YkNHL1BNWUFlQ1poblFpNHgxNm9jUzdnd3cKTHVoblp2UUZWYWpqek9GV0VJQXlYb29OSVkyQng3bjlzRlBGYmZSK1NOVVhuWHNHemFkMlArVmIyTkFCUjRFLwp4K2dYWlhFKzFnU0RhK25ZVHBiaG1hd3hreStEQnZBQlRWTzlWY2J2ZWoybDZ2WjAwK2lMTm9rYjF1UmJmbzNECkdEN2RZTjRYdCtwWXRMdFJYRGNqb2Q3OXpFcmJ4UkE4ZWoxblllOFpXQUNZa0ZOT3lpRHlJY3dFbWtDNXhlcHAKS1ByRGVCeEpBb0dCQU5XYzI4cFY4SDhRWm1Hb25QQkNZUUNrY2NLYnpEaXpwa0ZKMlZNVXZ5TG1Ia0w5bWlWUApQb1RsdXF4T2htMHhyRlNRaEFTQUlUaG0rWHN0c0pYdjNSd2dIZVdadTluUEVPeWpRcG02bTNEa1ZVK29kdTRGCnYwa25qdlduUTRPZnVQeDlCV3UyN1I3d1VBNHBqNUk0MGtlMVovdDZwdzZjeWFBckZ5L01HODZmQW9HQkFPZEcKMXRocFNUT3dZbEltWWoxNDdTSVJyb0VaSTNSaUNBVUh1ME54VEJObk5WL1JNVDdaNGVpZkRMMndXc0s1Q1Y0aQpFR2hBODRxYVB0dTFCaVhwTmdpMDBBdllWUGN6d0VDa3hocFdBeTJVRGZSc2FENnNYQ04ycVdtcGdjQzBTOWpICkdqUkdnSVFselhWNFVVcHFTYzVEUDZBYUFzRkhxVU1aT3dRZTgyck5Bb0dCQU5FN2FLbml6Y09ZQzhDQ2lONXAKRmx5cnRtWVpkc3JmWk95MGFqT1BzYng4VEkzdm04b0p1Y0l3eDAwNVNVQ3hsQXZzMWZNV2tmT09JYlkreGFYSApvZnVIbGVFc1dTejZQcWliTFlRb25WTFJ4S0pXNzg4clAvZG0wUWZiZ3l6dENTUC9UWXo1UzMrdmdhcXRtTnh2CjNjQ3hkcDJEd1JoMkNLUmpNTDMzbmhFZkFvR0FDNmNRRUJ0TjZ1TEtNV1Zwc2JzMEIzRm9uMnlLMHNSVnJ4c3kKbmpWSkpma2ZRVktpN28yL3loNnBYNjFSQlZxWlZEclhKTW1RKzd6RnlnQVc3VFlRMk9OelVBVjRVblF6RFk2Lwp4SGZzOVJEdW14QVRPSVVxcDBiRlJtT1ovQUdaaUxTUFoyN2Q3c3FRelloZ1lDVjJ6b09vNHdJc2ZWeUU5TEtDCnZMUnFnMGtDZ1lFQXlJRUdjeHQxcTIwdUhYUTFLTU92V2xWUUJCQklPUUJjeXoyR0djcWFGOHhSKzJCOGc3R2YKbEh4dHBvaTNNQUxTVXlhOTQzZEpMUHA4Q0xSOTBkQWtqZ1JROURPN2wyYWlWYWVncTA0NURCMnBwN05YVlc4NgptUXFPZUJRYzcyY0ZYdk9YZmRKUUQwME5HZThlS0VjTWN2QlhxTVIrSUtEdGozcGlKVjlsSHpBPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=` + newKubeConfig = `apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJTjAvdmZkM3RCeGd3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBeE1URXhOekV4TVRkYUZ3MHpOVEF4TURreE56RTJNVGRhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUURJS25lRWZrM0F0WWlhanZyYWcwdU1zZUd1Q3BuZW80OXl3T0NFSmF0ZnVncVZXVXJ3cVd1WEdjUVgKTWp5MTZEVGxlR2YxeS83NXJuRUY1cld0Vm5wMDlNc0w1NW5YM0ZnT21SY3ozNmxtYTBOMmdMQU5RR0VmZU50NQpsa0Y5R2t6VFZMVy84alNWcXRkaTBCTm8xejEya0FCUm5yM1M0bWU0cExma0xFeWZKQTFQcnlpVUp0NnFBbldrCkUwV2RxbmJJMGRHQWZpZ3hTVFRZK09PMExWbjdJaG1QTGpPVEhHb0JRaW1DL091ZEZFK01FZG1kQkNOTHgzeE4KRDlSbk1taUxjVkVlSDlvVTFjYUdRamRIbXhnRUpJbStTOVdmWDZuRSsxOUpDZ0dkTS9KaFVtT0xRQWg4NzhMcQptc085WlNYdXFweW9ROTBhRDBDaFNNdzJyOXBQQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJRMXRjTE5rMmVjRkFJRDl5citZMnUyaHI4OWJEQVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQWdUZGJkTzZQNQo2M2hiZVRsS1E2UkpzRlkrdUdIeXcyMXNGU205Ni9vblZhOS91SjNQZ3BsMndKaFhpanZmZnNQamg2ekpkdTJXCll4WWkxcHdEWGZtMHpsNHJQMEcwQmkzL2Y1VkU0dkRnSmUwcDRKdkx2MWVmclZBcGhpakJiRkFHVTh6WVVPdEUKM2pGNy92ZDkvVUwxRWwzNVNRZjdEWWJhQ2NndzByS0tiNkQwaUZJcjJCRFZqbE01VDhqRzdETEk0a3pXTzFaTQpmNHh4ay9MQjBpY1R0a1RVRGQzcjBtZmFzNUdqR0lDR2QzbUpHbWY3bzFScXVyYlZ3dmVPWE5oL2tud2hnNGZqCitsTjJvaHpuaWdkTVNNQ1FnbDQ2NlowQTZvVDUrNUV6a2JwYS8yRDQ1cVN0ZGZBbTNtQ0RhdHdUelc1RlBudFMKMm0weVo2ZWVydkE4Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:55209 + name: my-new-super-ske-cluster +contexts: + - context: + cluster: my-new-super-ske-cluster + user: my-new-super-ske-cluster + name: my-new-super-ske-cluster +current-context: my-new-super-ske-cluster +kind: Config +preferences: {} +users: + - name: my-new-super-ske-cluster + user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJUmpoS0w0dlJWSFV3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBeE1URXhOekV4TVRkYUZ3MHlOakF4TVRFeE56RTJNVGRhTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEVE5WSmEKekJHZWU4OXVRNjVZWEdhT1pwTWJTZE9tcWFyNUlVbkRTUEpMbHdJKzkyWVRrcFBKcXFncWEwa2FZYVdZUmFlTQpCNVlDeTRpNjNXSTBYYlgvMW9LNUFPZ2xXL1FwcGczWnc5K3ZPYXdtdEpqUHQ1T2xEVWRONGdmYm40TjV1OWpoCmltQ09wak5VL285NzNZZy9nM3pqNi9nUm9EYldhaW5wSDltTk1nOHFTS0xaNkNpUlp2VjZuYkgyVDVSa3ZVVWgKUDNWN09CZE1oUlp3MW1rVVRQVXY5T056VVBubFFaS3hwWXphYjBiZm92eFd6UDhxQkVIdk9xaXZoWFhaaGp1bApaTU1OMjYrN2RyS3lCWS8rRnBmeGpqb3AyZytUSlMxNHhhOTh0dCtqT3dUUkI5aWh1WUQzTnlVbEZXVjhiUG51CnJqSW52ckxVcjkvQzB2cmhBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkRXMXdzMlRaNXdVQWdQMwpLdjVqYTdhR3Z6MXNNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUFZQkpld0ZwMTJnbkxQM1hGQ09JaXRZZWVnCkVmMjQwLysvaVFUUXQreHNjTU1ITGF4VjNFNEgxZ3JyNDdXUjE0bDdlbE1ING5qWnZzU3djSUZsa1RieVR6eW0KeW9XamhQQ0M2WWpzZHFEM2Vlc1ZpV2xhZkthczFrNmtmWHhVR2EvSUtQNzJoQ2tub2pia2o3amlSdjgrMTd5NgpKa2JIaXNYLzFqM2R1VHVIdDNORXJnNmNud0M5MGlldjZFZVFaV0oxaG5NSHhDMkRYMEdvOW14ZDlPYWFVODdBCkhBNDMzRnVJQWpoZjRWN2Vma3dGQU1ZMEhZSjZQaFZqTXdNWmdKczhLSHhVdjl3Y0xYMlFPUC9TSmhRZUtMV1UKYTFHTWlzTFBNc2NmL2JjU051SVpxMTR5S0xSelEwL1FIUW1PVVdSZDIva002MmxhbFl5Rlk2V0J4cCt3Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMHpWU1dzd1JubnZQYmtPdVdGeG1qbWFURzBuVHBxbXErU0ZKdzBqeVM1Y0NQdmRtCkU1S1R5YXFvS210SkdtR2xtRVduakFlV0FzdUl1dDFpTkYyMS85YUN1UURvSlZ2MEthWU4yY1Bmcnptc0pyU1kKejdlVHBRMUhUZUlIMjUrRGVidlk0WXBnanFZelZQNlBlOTJJUDROODQrdjRFYUEyMW1vcDZSL1pqVElQS2tpaQoyZWdva1diMWVwMng5aytVWkwxRklUOTFlemdYVElVV2NOWnBGRXoxTC9UamMxRDU1VUdTc2FXTTJtOUczNkw4ClZzei9LZ1JCN3pxb3I0VjEyWVk3cFdURERkdXZ1M2F5c2dXUC9oYVg4WTQ2S2RvUGt5VXRlTVd2ZkxiZm96c0UKMFFmWW9ibUE5emNsSlJWbGZHejU3cTR5Sjc2eTFLL2Z3dEw2NFFJREFRQUJBb0lCQVFDRDBQV1RJV1dscWRQdQpGMk9LVmpEVGt3VWd0TlRaWVc4SmlWTUdCRkxrQmwwcWV6RkQ2ZWsrcGJuS3I2YXlSbHNaUysram4yQnFZaWoxCnB4R1JhU01iaHYrVEF4UGZyU0lYbEVGMHRhQzNOYUZSanNrSWFxUkZFS0o5NHlIUVdoK3VMQ1RScnBGUXRqMjMKUUNEQXg2UXZMNXNVak1NSURSdnNlZG1xVzJ4bGg4UkF5RUdYVi9sUmJ5ZTdEOTIrWVpwd21kV3dsa2tiZy8yTQowdHF1R1k0Qk1XTFY0K09DVlNmVWVEWU1nZkZIL0RVWThUdUIvNitzVm9rUnhLalhYbjYzN1c4Q2dJWUVaQngrCkE5TG8vYk1YN0RaSDRmS0RyRCsycVQ1SDNUTDFIc3BtSXJ1Mi84RllCZ08ySjNzZVdHdHdtelVXalVzL2ExSGoKdXZMamNCTjVBb0dCQU83YitESTBsdFRGT29MSERISGNZdXZqMTYydU96bk51ejNXa1R0Sng3QzZJSVpVd2YwSQpuM2pJWXhKRi9yVVZUZzZPbU5XNXpGdDA2QTVWQitwZ2RNblFhOHMybVNldFlKVW51eE42emRsOGJoblZ6dXUzCi8walM3cU1pWGg5aU8vRlZ6VDNxcnNqU1VnMmNCRTA3WlZweU0ycVNMUlkrVmdiRDg4aUdUbXhiQW9HQkFPSmQKWWVNc1JpVVZ5Wk5sZU1ra3puS2pjYXoyOE9Vb0NyZjd0dVhaYUpqRDdWZncyWmNBd0cvZG5lZ3M2YmEvck54bgplMXU3Rm05VlNTR2pNejJEaC9QdlNuQlZReGtQeHo1ZFRja2V0RUJSQk1XaVV1enI2UUFXdmZudEZXcWNZTkpvClBCVWY3c2k4Wk1rMjJpanR1OWxEVnRRUFpJdDZUMzJrb0Z3eHNrcHpBb0dBYjQ0c2pNWWk2NXh4aDBLUGZWNEEKbFVzRUlBbVBmNSttSTJ0aXlOM2NkWjE0TTBUQ2xQckNBQmNXcmlJaW8xQWY5SXlFdE16aHRKVVZEQnlLWmR4RwpyenE0SFdDU2h3Vmlaa2I0Q0ZFQ2N1QzZTemFnUFZiaDA1RXdBdUM2Tk00Y1VNcFI0T2tLV0tCaDBobGJxUFprCmo2bG1lZzlySDBoZHhTc2ZZRGZaeUtFQ2dZQnZZMVk4ekZlRC9qR2YxMG5WYU1neC94MTc2RlBuMzRsT3VZMXAKazA3MkJVdHdmN01DckRzRmtQOFg5YW5YNUgveVFQV2gwUEVjUGRKcnUvd0Y1QWh0VDYzSWt4d2VZL1krU1BseQo0eW45a0NDU0ErdGNiRVhPWm1KN2JsK2dnMnpkZks4OEVlZVZYYWNXb0dnL3hhUXZLQVM4K3dvVjNFenJYYXdQClVlRVM0d0tCZ1FEUm9QbXkvNloySUdERkRReWt3YmFMRDlvQlZqN3BJSTI0NmlLM1hwQmRtRGFVR0hLYnRiNmUKYXNYRWNQQmp0enYvTzVOM2dlZWFYREduaW5XcXJJZm1FTzIyMDhmQ0VCc0RWc3RQMDhxRnorekFSMnJEQm9xbQpFVkwxN0o0Q2J6Tlh4bStOT1R6aVhCN2tLVWhNQUFBbmkwcXQ1QXN0QlJpcENuMER4Y2JpekE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= +` ) type skeClientMocked struct { @@ -482,33 +523,34 @@ func TestConvertToSeconds(t *testing.T) { } } -func TestWriteConfigFile(t *testing.T) { +func TestMergeKubeConfig(t *testing.T) { tests := []struct { - description string - location string - kubeconfig string - isValid bool - isLocationDir bool - isLocationEmpty bool - expectedErr string + description string + location string + kubeconfig string + existingKubeconfig string + isValid bool + isLocationDir bool + isLocationEmpty bool + expectedErr string }{ { description: "base", location: filepath.Join("base", "config"), - kubeconfig: "kubeconfig", + kubeconfig: newKubeConfig, isValid: true, }, { description: "empty location", location: "", - kubeconfig: "kubeconfig", + kubeconfig: newKubeConfig, isValid: false, isLocationEmpty: true, }, { description: "path is only dir", location: "only_dir", - kubeconfig: "kubeconfig", + kubeconfig: newKubeConfig, isValid: false, isLocationDir: true, }, @@ -518,6 +560,20 @@ func TestWriteConfigFile(t *testing.T) { kubeconfig: "", isValid: false, }, + { + description: "kubeconfig bad content", + location: filepath.Join("empty", "config"), + existingKubeconfig: "hola", + kubeconfig: "kubeconfig", + isValid: false, + }, + { + description: "kubeconfig content", + location: filepath.Join("content", "config"), + kubeconfig: newKubeConfig, + existingKubeconfig: existingKubeConfig, + isValid: true, + }, } baseTestDir := "test_data/" @@ -527,27 +583,96 @@ func TestWriteConfigFile(t *testing.T) { // make sure empty case still works if tt.isLocationEmpty { testLocation = "" + } else if tt.existingKubeconfig != "" { + dir := filepath.Dir(testLocation) + + err := os.MkdirAll(dir, 0o700) + if err != nil { + t.Errorf("error create config directory: %s (%s)", dir, err.Error()) + } + + err = os.WriteFile(testLocation, []byte(tt.existingKubeconfig), 0o600) + if err != nil { + t.Errorf("could not write file: %s", tt.location) + } + defer func() { + err := os.Remove(testLocation) + if err != nil { + t.Errorf("could not deleete file: %s", tt.location) + } + }() } // filepath Join cleans trailing separators if tt.isLocationDir { testLocation += string(filepath.Separator) } - err := WriteConfigFile(testLocation, tt.kubeconfig) + + err := MergeKubeConfig(testLocation, tt.kubeconfig) if tt.isValid && err != nil { - t.Errorf("failed on valid input") + t.Errorf("failed on valid input %s", err) } + if !tt.isValid && err == nil { t.Errorf("did not fail on invalid input") } if tt.isValid { - data, err := os.ReadFile(testLocation) + kubeConfigFinal, err := clientcmd.LoadFromFile(testLocation) + if err != nil { + t.Errorf("error loading final kubeconfig: %s", err) + } + + kubeConfigNew, err := clientcmd.Load([]byte(tt.kubeconfig)) if err != nil { - t.Errorf("could not read file: %s", tt.location) + t.Errorf("error loading new kubeconfig: %s", err) } - if string(data) != tt.kubeconfig { - t.Errorf("expected file content to be %s, got %s", tt.kubeconfig, string(data)) + + // check new kubeconfig is still there + for name := range kubeConfigNew.AuthInfos { + _, exits := kubeConfigFinal.AuthInfos[name] + if !exits { + t.Errorf("the user %s does not exist in the final kubeconfig", name) + } + } + for name := range kubeConfigNew.Contexts { + _, exits := kubeConfigFinal.Contexts[name] + if !exits { + t.Errorf("the context %s does not exist in the final kubeconfig", name) + } + } + for name := range kubeConfigNew.Clusters { + _, exits := kubeConfigFinal.Clusters[name] + if !exits { + t.Errorf("the cluster %s does not exist in the final kubeconfig", name) + } + } + + if tt.existingKubeconfig != "" { + kubeConfigExisting, err := clientcmd.Load([]byte(tt.existingKubeconfig)) + if err != nil { + t.Errorf("error loading existing kubeconfig: %s", err) + } + + // check exiting kubeconfig is still there + for name := range kubeConfigExisting.AuthInfos { + _, exits := kubeConfigFinal.AuthInfos[name] + if !exits { + t.Errorf("the user %s does not exist in the final kubeconfig", name) + } + } + for name := range kubeConfigExisting.Contexts { + _, exits := kubeConfigFinal.Contexts[name] + if !exits { + t.Errorf("the context %s does not exist in the final kubeconfig", name) + } + } + for name := range kubeConfigExisting.Clusters { + _, exits := kubeConfigFinal.Clusters[name] + if !exits { + t.Errorf("the cluster %s does not exist in the final kubeconfig", name) + } + } } } }) From eae49a05d044acb7a327903ae45cca0c0756b020 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:01:14 +0100 Subject: [PATCH 155/619] Extend output of IaaS commands (#569) * Extend output of IaaS commands - `beta network list` - add value: prefixes - `beta security-groups describe` - add values - stateful - createdAt - updatedAt - add rules table with values: - ID - description - protocol - direction - etherType - portRange - ipRange - icmpParameters - remoteSecurityGroupId - `beta security-groups list` - add values: - description - labels - `beta security-group rule list` - add value: remoteSecurityGroupId - `beta server describe` - add value: ip address - add table MaintenanceWindow with values: - status - details - startsAt - endsAt - `beta server list` - add values: - machineType - nicIPv4 - publicIPs --- internal/cmd/beta/network/list/list.go | 9 ++- .../beta/security-group/describe/describe.go | 77 ++++++++++++++++++- internal/cmd/beta/security-group/list/list.go | 20 ++++- .../cmd/beta/security-group/rule/list/list.go | 15 +++- internal/cmd/beta/server/describe/describe.go | 55 ++++++++++--- internal/cmd/beta/server/list/list.go | 35 ++++++++- internal/cmd/beta/server/list/list_test.go | 1 + internal/pkg/utils/utils.go | 10 +++ 8 files changed, 195 insertions(+), 27 deletions(-) diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index 889f9e307..ee388765c 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -151,7 +152,7 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network return nil default: table := tables.NewTable() - table.SetHeader("ID", "NAME", "STATUS", "PUBLIC IP", "ROUTED") + table.SetHeader("ID", "NAME", "STATUS", "PUBLIC IP", "PREFIXES", "ROUTED") for _, network := range networks { publicIp := "" @@ -163,8 +164,12 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network if network.Routed != nil { routed = *network.Routed } + prefixes := "" + if network.Prefixes != nil && len(*network.Prefixes) > 0 { + prefixes = strings.Join(*network.Prefixes, ", ") + } - table.AddRow(*network.NetworkId, *network.Name, *network.State, publicIp, routed) + table.AddRow(*network.NetworkId, *network.Name, *network.State, publicIp, prefixes, routed) table.AddSeparator() } diff --git a/internal/cmd/beta/security-group/describe/describe.go b/internal/cmd/beta/security-group/describe/describe.go index 10533c1da..2a01e8515 100644 --- a/internal/cmd/beta/security-group/describe/describe.go +++ b/internal/cmd/beta/security-group/describe/describe.go @@ -6,8 +6,6 @@ import ( "fmt" "strings" - "github.com/goccy/go-yaml" - "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" @@ -16,6 +14,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -114,7 +115,11 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) return nil default: + var content []tables.Table + table := tables.NewTable() + table.SetTitle("SECURITY GROUP") + if id := resp.Id; id != nil { table.AddRow("ID", *id) } @@ -130,8 +135,13 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) table.AddSeparator() } + if stateful := resp.Stateful; stateful != nil { + table.AddRow("STATEFUL", *stateful) + table.AddSeparator() + } + if resp.Labels != nil && len(*resp.Labels) > 0 { - labels := []string{} + var labels []string for key, value := range *resp.Labels { labels = append(labels, fmt.Sprintf("%s: %s", key, value)) } @@ -139,7 +149,66 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) table.AddSeparator() } - if err := table.Display(p); err != nil { + if resp.CreatedAt != nil { + table.AddRow("CREATED AT", utils.ConvertTimePToDateTimeString(resp.CreatedAt)) + table.AddSeparator() + } + + if resp.UpdatedAt != nil { + table.AddRow("UPDATED AT", utils.ConvertTimePToDateTimeString(resp.UpdatedAt)) + table.AddSeparator() + } + + content = append(content, table) + + if resp.Rules != nil && len(*resp.Rules) > 0 { + rulesTable := tables.NewTable() + rulesTable.SetTitle("RULES") + rulesTable.SetHeader( + "ID", + "DESCRIPTION", + "PROTOCOL", + "DIRECTION", + "ETHER TYPE", + "PORT RANGE", + "IP RANGE", + "ICMP PARAMETERS", + "REMOTE SECURITY GROUP ID", + ) + + for _, rule := range *resp.Rules { + var portRange string + if rule.PortRange != nil { + portRange = fmt.Sprintf("%s-%s", utils.PtrString(rule.PortRange.Min), utils.PtrString(rule.PortRange.Max)) + } + + var protocol string + if rule.Protocol != nil { + protocol = utils.PtrString(rule.Protocol.Name) + } + + var icmpParameter string + if rule.IcmpParameters != nil { + icmpParameter = fmt.Sprintf("type: %s, code: %s", utils.PtrString(rule.IcmpParameters.Type), utils.PtrString(rule.IcmpParameters.Code)) + } + + rulesTable.AddRow( + utils.PtrString(rule.Id), + utils.PtrString(rule.Description), + protocol, + utils.PtrString(rule.Direction), + utils.PtrString(rule.Ethertype), + portRange, + utils.PtrString(rule.IpRange), + icmpParameter, + utils.PtrString(rule.RemoteSecurityGroupId), + ) + } + + content = append(content, rulesTable) + } + + if err := tables.DisplayTables(p, content); err != nil { return fmt.Errorf("render table: %w", err) } diff --git a/internal/cmd/beta/security-group/list/list.go b/internal/cmd/beta/security-group/list/list.go index 6c2bf6fcf..9ecb4a360 100644 --- a/internal/cmd/beta/security-group/list/list.go +++ b/internal/cmd/beta/security-group/list/list.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/goccy/go-yaml" "github.com/spf13/cobra" @@ -137,9 +138,24 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.SecurityGr return nil default: table := tables.NewTable() - table.SetHeader("ID", "NAME", "STATEFUL") + table.SetHeader("ID", "NAME", "STATEFUL", "DESCRIPTION", "LABELS") for _, item := range items { - table.AddRow(utils.PtrString(item.Id), utils.PtrString(item.Name), utils.PtrString(item.Stateful)) + var labelsString string + if item.Labels != nil { + var labels []string + for key, value := range *item.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + labelsString = strings.Join(labels, ", ") + } + + table.AddRow( + utils.PtrString(item.Id), + utils.PtrString(item.Name), + utils.PtrString(item.Stateful), + utils.PtrString(item.Description), + labelsString, + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/security-group/rule/list/list.go b/internal/cmd/beta/security-group/rule/list/list.go index 3675dec91..55b75e8c2 100644 --- a/internal/cmd/beta/security-group/rule/list/list.go +++ b/internal/cmd/beta/security-group/rule/list/list.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -16,9 +15,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) const ( @@ -166,7 +167,7 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRules []ia return nil default: table := tables.NewTable() - table.SetHeader("ID", "ETHER TYPE", "DIRECTION", "PROTOCOL") + table.SetHeader("ID", "ETHER TYPE", "DIRECTION", "PROTOCOL", "REMOTE SECURITY GROUP ID") for _, securityGroupRule := range securityGroupRules { etherType := "" @@ -181,7 +182,13 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRules []ia } } - table.AddRow(*securityGroupRule.Id, etherType, *securityGroupRule.Direction, protocolName) + table.AddRow( + utils.PtrString(securityGroupRule.Id), + etherType, + utils.PtrString(securityGroupRule.Direction), + protocolName, + utils.PtrString(securityGroupRule.RemoteSecurityGroupId), + ) table.AddSeparator() } diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/beta/server/describe/describe.go index 639b0a320..abfe5a99b 100644 --- a/internal/cmd/beta/server/describe/describe.go +++ b/internal/cmd/beta/server/describe/describe.go @@ -6,8 +6,6 @@ import ( "fmt" "strings" - "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -16,9 +14,10 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) const ( @@ -138,8 +137,10 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro table.AddSeparator() table.AddRow("AVAILABILITY ZONE", *server.AvailabilityZone) table.AddSeparator() - table.AddRow("BOOT VOLUME", *server.BootVolume.Id) - table.AddSeparator() + if server.BootVolume != nil && server.BootVolume.Id != nil { + table.AddRow("BOOT VOLUME", *server.BootVolume.Id) + table.AddSeparator() + } table.AddRow("POWER STATUS", *server.PowerStatus) table.AddSeparator() @@ -189,20 +190,52 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro if server.Nics != nil && len(*server.Nics) > 0 { nicsTable := tables.NewTable() nicsTable.SetTitle("Attached Network Interfaces") - nicsTable.SetHeader("ID", "NETWORK ID", "NETWORK NAME", "PUBLIC IP") + nicsTable.SetHeader("ID", "NETWORK ID", "NETWORK NAME", "IPv4", "PUBLIC IP") for _, nic := range *server.Nics { - publicIp := "" - if nic.PublicIp != nil { - publicIp = *nic.PublicIp - } - nicsTable.AddRow(*nic.NicId, *nic.NetworkId, *nic.NetworkName, publicIp) + nicsTable.AddRow( + utils.PtrString(nic.NicId), + utils.PtrString(nic.NetworkId), + utils.PtrString(nic.NetworkName), + utils.PtrString(nic.Ipv4), + utils.PtrString(nic.PublicIp), + ) nicsTable.AddSeparator() } content = append(content, nicsTable) } + if server.MaintenanceWindow != nil { + maintenanceWindow := tables.NewTable() + maintenanceWindow.SetTitle("Maintenance Window") + + if server.MaintenanceWindow.Status != nil { + maintenanceWindow.AddRow("STATUS", *server.MaintenanceWindow.Status) + maintenanceWindow.AddSeparator() + } + if server.MaintenanceWindow.Details != nil { + maintenanceWindow.AddRow("DETAILS", *server.MaintenanceWindow.Details) + maintenanceWindow.AddSeparator() + } + if server.MaintenanceWindow.StartsAt != nil { + maintenanceWindow.AddRow( + "STARTS AT", + utils.ConvertTimePToDateTimeString(server.MaintenanceWindow.StartsAt), + ) + maintenanceWindow.AddSeparator() + } + if server.MaintenanceWindow.EndsAt != nil { + maintenanceWindow.AddRow( + "ENDS AT", + utils.ConvertTimePToDateTimeString(server.MaintenanceWindow.EndsAt), + ) + maintenanceWindow.AddSeparator() + } + + content = append(content, maintenanceWindow) + } + err := tables.DisplayTables(p, content) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/beta/server/list/list.go b/internal/cmd/beta/server/list/list.go index af2e59655..366d31e8f 100644 --- a/internal/cmd/beta/server/list/list.go +++ b/internal/cmd/beta/server/list/list.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -15,9 +14,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) const ( @@ -140,6 +141,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) } + req = req.Details(true) return req } @@ -164,11 +166,36 @@ func outputResult(p *print.Printer, outputFormat string, servers []iaas.Server) return nil default: table := tables.NewTable() - table.SetHeader("ID", "Name", "Status", "Availability Zones") + table.SetHeader("ID", "Name", "Status", "Machine Type", "Availability Zones", "Nic IPv4", "Public IPs") for i := range servers { server := servers[i] - table.AddRow(*server.Id, *server.Name, *server.Status, *server.AvailabilityZone) + + nicIPv4 := "" + publicIPs := "" + if server.Nics != nil && len(*server.Nics) > 0 { + for i, nic := range *server.Nics { + if nic.Ipv4 != nil || nic.PublicIp != nil { + nicIPv4 += utils.PtrString(nic.Ipv4) + publicIPs += utils.PtrString(nic.PublicIp) + + if i != len(*server.Nics)-1 { + publicIPs += "\n" + nicIPv4 += "\n" + } + } + } + } + + table.AddRow( + utils.PtrString(server.Id), + utils.PtrString(server.Name), + utils.PtrString(server.Status), + utils.PtrString(server.MachineType), + utils.PtrString(server.AvailabilityZone), + nicIPv4, + publicIPs, + ) } p.Outputln(table.Render()) diff --git a/internal/cmd/beta/server/list/list_test.go b/internal/cmd/beta/server/list/list_test.go index 47ed2e4f1..8cc72571b 100644 --- a/internal/cmd/beta/server/list/list_test.go +++ b/internal/cmd/beta/server/list/list_test.go @@ -53,6 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func fixtureRequest(mods ...func(request *iaas.ApiListServersRequest)) iaas.ApiListServersRequest { request := testClient.ListServers(testCtx, testProjectId) request = request.LabelSelector(testLabelSelector) + request = request.Details(true) for _, mod := range mods { mod(&request) } diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index dc1cfeffb..1b4a4ad5e 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -4,6 +4,7 @@ import ( "fmt" "net/url" "strings" + "time" "github.com/google/uuid" "github.com/spf13/cobra" @@ -79,3 +80,12 @@ func ValidateURLDomain(value string) error { } return nil } + +// ConvertTimePToDateTimeString converts a time.Time pointer to a string represented as "2006-01-02 15:04:05" +// This function will return an empty string if the input is nil +func ConvertTimePToDateTimeString(t *time.Time) string { + if t == nil { + return "" + } + return t.Format(time.DateTime) +} From ec2aa5ebb6621836e1f8f6626f0d966ae4fc90a7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:00:47 +0100 Subject: [PATCH 156/619] fix(deps): update stackit sdk modules (#571) Co-authored-by: Renovate Bot --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 067d26c2b..307f9bd8a 100644 --- a/go.mod +++ b/go.mod @@ -19,17 +19,17 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.1 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.1 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.1 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.22.0 golang.org/x/oauth2 v0.25.0 @@ -79,7 +79,7 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.1 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.2 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 diff --git a/go.sum b/go.sum index e1ce1b7b8..b079e7bc4 100644 --- a/go.sum +++ b/go.sum @@ -127,20 +127,20 @@ github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 h1:o9OAGh4mdYY5LZYZ github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.1 h1:ogo7Ce4wA9ln/Z0VwvckH0FT5/i7d9/34bG85aayHn8= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.1/go.mod h1:+NlUMcid2dEFSmqtbXJrcT57iP0oTdnIXHOQku0E04A= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.2 h1:K921/2U8dJh1SAOClhPqmZtid+/kP+BPrGZjXWOABkQ= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.2/go.mod h1:mwKowXJhwB9/PQdvdmOyyqOzLF0AmkzpcwrQbDYxllo= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1 h1:J+GLgfDIDnNpq/z6ev1whfLbOwUn5XgSKh3aE2auHIs= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1/go.mod h1:nuZK6OXyZ4zlGsC1gZDj9+ajJzzFi9vVgSSRQlEJAqA= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1 h1:BCzShNI9TX6vZ8Q5vLzdG32gOdgcAwMWjEpy2AGHdnI= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.16.1/go.mod h1:CvGSm9Goma2O1xkA0LEJbHfZpGlhy0AXJnMPpMmRdMM= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0 h1:SXNkKaAsGOkr9C6bv2i7q3kucxL3kril+z2wnshlXK0= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0/go.mod h1:5hMtm08NrL+QcgKl94zUDrY7VEzKRcvCJOEOvENBxqc= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1 h1:Df3fTAHaVgyiiyp9LyTTQI8jXSVeGo49eW5ya4AATCY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1/go.mod h1:V2LEHKyTaaiEBi9L3v62mNQ7xyJSred4OK+himLJOZQ= github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 h1:sIz4wJIz6/9Eh6nSoi2sQ+Ef53iOrFsqLKIp2oRkmgo= github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1/go.mod h1:okcRTrNDTI3d7MQcYJMliK0qoXeLq0b1wvZuEqgJIWE= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 h1:hwRkCCUSWMhKTc7fLakL89V6+9xkxsFQlRthVmrvi1U= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1/go.mod h1:U45gFwIAAdXWL/Wlp9rY3iPVWFHLGILz1C3Qc62o8KM= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.1 h1:c4pocENxdDycScEpt0s81v+uEtLhfj+8Gwwih7iCVFI= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.16.1/go.mod h1:JnhCZzXprN/em1Uxpvl1ITMf6Hl/8N/4y5zNsRqEGlA= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.17.0 h1:2mxf7vAaQuEM28D78uSIdUyqHKqNLM+pZnYC0LqbDpc= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.17.0/go.mod h1:gPOT3o+b0mx2Z4r/ZXhSqt5MRHbZplGoUafxeClSSng= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1 h1:6XfGxsPFqci/geSDd1gCtiaRJun85X5JepXn4edobXQ= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1/go.mod h1:42oYZOqin+rIUrUqgtCIE4wzCWWY30H4UFhzvo1Wg2w= github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1 h1:/EVm0bD9a3KCk9aj/v2ivJIURlGsTr4O2OwMQ4ey3e4= @@ -157,10 +157,10 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0/go.mod h1:zyg0hpiNdZLRbelkJb2KDf9OHQKLqqcTpePQ1qHL5dE= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.1 h1:Gw68D2U+cAh20sRX2GvhLCSvRVvbKF52Ew7FQ/AoCXc= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.20.1/go.mod h1:A4+9KslxCA31JvxnT+O/GC67eAOdw+iqhBzewZZaCD0= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.1 h1:26MyaOGc3Sn4yuR3zoOOOFfb4MTbDV9PJwzU8yulWNc= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.8.1/go.mod h1:ui+yRLddE9mknzjZa45boyaU1ZomQuZy3p7wuwOufCY= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.0 h1:Pew85wQJe2e9K8ZRzxeFSimI29aqUZwOT/Ty0N1K+c0= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.0/go.mod h1:iZyh3DMi2fUZxAIseykjKfDo2wf2FIDwpF43I22b8uk= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0 h1:OYWT7B63isBPyVuPxd3yobvky7/nhcXQxaBgPki5nR4= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0/go.mod h1:vrl+OVJkjjupkvfkqY2T3HAB6x2x0S6zDhdFB5BWEnU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= From deb510395a1e4ec3df94f47a30f46c8df9404c8e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 23 Jan 2025 16:34:37 +0100 Subject: [PATCH 157/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/ske to v0.21.1 (#573) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove GetServiceStatusExecute for ske service Function was deprecated on 2024-04-16 and was now removed. Signed-off-by: Alexander Dahmen * Adjust ske datatypes Signed-off-by: Alexander Dahmen * chore: fix testcase setup * fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/ske to v0.21.1 --------- Signed-off-by: Alexander Dahmen Co-authored-by: Alexander Dahmen Co-authored-by: Rüdiger Schmitz <152157960+bahkauv70@users.noreply.github.com> Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- internal/cmd/ske/cluster/create/create_test.go | 5 +++-- internal/cmd/ske/cluster/update/update_test.go | 5 +++-- internal/cmd/ske/options/options.go | 5 +++-- internal/pkg/services/ske/utils/utils.go | 1 - internal/pkg/services/ske/utils/utils_test.go | 14 -------------- 7 files changed, 12 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 307f9bd8a..5f512f130 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.22.0 diff --git a/go.sum b/go.sum index b079e7bc4..781c3b93c 100644 --- a/go.sum +++ b/go.sum @@ -157,8 +157,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0/go.mod h1:zyg0hpiNdZLRbelkJb2KDf9OHQKLqqcTpePQ1qHL5dE= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.0 h1:Pew85wQJe2e9K8ZRzxeFSimI29aqUZwOT/Ty0N1K+c0= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.0/go.mod h1:iZyh3DMi2fUZxAIseykjKfDo2wf2FIDwpF43I22b8uk= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1 h1:oO+wCobC4OfH+vpfJQEnCUQuKVILRj5mQojBbzWgzDA= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1/go.mod h1:iZyh3DMi2fUZxAIseykjKfDo2wf2FIDwpF43I22b8uk= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0 h1:OYWT7B63isBPyVuPxd3yobvky7/nhcXQxaBgPki5nR4= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0/go.mod h1:vrl+OVJkjjupkvfkqY2T3HAB6x2x0S6zDhdFB5BWEnU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/internal/cmd/ske/cluster/create/create_test.go b/internal/cmd/ske/cluster/create/create_test.go index cc2c6bd58..7e2496c84 100644 --- a/internal/cmd/ske/cluster/create/create_test.go +++ b/internal/cmd/ske/cluster/create/create_test.go @@ -3,6 +3,7 @@ package create import ( "context" "testing" + "time" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -60,8 +61,8 @@ var testPayload = &ske.CreateOrUpdateClusterPayload{ MachineImageVersion: utils.Ptr(true), }, TimeWindow: &ske.TimeWindow{ - End: utils.Ptr("0000-01-01T05:00:00+02:00"), - Start: utils.Ptr("0000-01-01T03:00:00+02:00"), + End: utils.Ptr(time.Date(0, 1, 1, 5, 0, 0, 0, time.FixedZone("test-zone", 2*60*60))), + Start: utils.Ptr(time.Date(0, 1, 1, 3, 0, 0, 0, time.FixedZone("test-zone", 2*60*60))), }, }, } diff --git a/internal/cmd/ske/cluster/update/update_test.go b/internal/cmd/ske/cluster/update/update_test.go index 4bcab1e72..32a1cfed5 100644 --- a/internal/cmd/ske/cluster/update/update_test.go +++ b/internal/cmd/ske/cluster/update/update_test.go @@ -3,6 +3,7 @@ package update import ( "context" "testing" + "time" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -60,8 +61,8 @@ var testPayload = ske.CreateOrUpdateClusterPayload{ MachineImageVersion: utils.Ptr(true), }, TimeWindow: &ske.TimeWindow{ - End: utils.Ptr("0000-01-01T05:00:00+02:00"), - Start: utils.Ptr("0000-01-01T03:00:00+02:00"), + End: utils.Ptr(time.Date(0, 1, 1, 5, 0, 0, 0, time.FixedZone("test-zone", 2*60*60))), + Start: utils.Ptr(time.Date(0, 1, 1, 3, 0, 0, 0, time.FixedZone("test-zone", 2*60*60))), }, }, } diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index fd0976997..51a8abb93 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -238,7 +239,7 @@ func buildKubernetesVersionsTable(resp *ske.ProviderOptions) (tables.Table, erro } expirationDate := "" if v.ExpirationDate != nil { - expirationDate = *v.ExpirationDate + expirationDate = v.ExpirationDate.Format(time.RFC3339) } table.AddRow(*v.Version, *v.State, expirationDate, string(featureGate)) } @@ -265,7 +266,7 @@ func buildMachineImagesTable(resp *ske.ProviderOptions) tables.Table { expirationDate := "-" if version.ExpirationDate != nil { - expirationDate = *version.ExpirationDate + expirationDate = version.ExpirationDate.Format(time.RFC3339) } table.AddRow(*image.Name, *version.Version, *version.State, expirationDate, criNamesString) } diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 8834a54a3..452d4b584 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -32,7 +32,6 @@ const ( ) type SKEClient interface { - GetServiceStatusExecute(ctx context.Context, projectId string) (*ske.ProjectResponse, error) ListClustersExecute(ctx context.Context, projectId string) (*ske.ListClustersResponse, error) ListProviderOptionsExecute(ctx context.Context) (*ske.ProviderOptions, error) } diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index d07207663..e19c16116 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -12,7 +12,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) @@ -65,25 +64,12 @@ users: ) type skeClientMocked struct { - serviceDisabled bool - getServiceStatusFails bool - getServiceStatusResp *ske.ProjectResponse listClustersFails bool listClustersResp *ske.ListClustersResponse listProviderOptionsFails bool listProviderOptionsResp *ske.ProviderOptions } -func (m *skeClientMocked) GetServiceStatusExecute(_ context.Context, _ string) (*ske.ProjectResponse, error) { - if m.getServiceStatusFails { - return nil, fmt.Errorf("could not get service status") - } - if m.serviceDisabled { - return nil, &oapierror.GenericOpenAPIError{StatusCode: 404} - } - return m.getServiceStatusResp, nil -} - func (m *skeClientMocked) ListClustersExecute(_ context.Context, _ string) (*ske.ListClustersResponse, error) { if m.listClustersFails { return nil, fmt.Errorf("could not list clusters") From 6bdfff17fdfe19e9da1f3e3a9202de1a4a21d143 Mon Sep 17 00:00:00 2001 From: a_nackov Date: Tue, 28 Jan 2025 14:55:42 +0200 Subject: [PATCH 158/619] ref 700848 - server os-update (#561) Signed-off-by: Adrian Nackov --- docs/stackit_beta_server.md | 1 + docs/stackit_beta_server_os-update.md | 39 +++ docs/stackit_beta_server_os-update_create.md | 45 +++ .../stackit_beta_server_os-update_describe.md | 44 +++ docs/stackit_beta_server_os-update_disable.md | 41 +++ docs/stackit_beta_server_os-update_enable.md | 41 +++ docs/stackit_beta_server_os-update_list.md | 45 +++ .../stackit_beta_server_os-update_schedule.md | 38 +++ ...t_beta_server_os-update_schedule_create.md | 48 ++++ ...t_beta_server_os-update_schedule_delete.md | 41 +++ ...beta_server_os-update_schedule_describe.md | 44 +++ ...kit_beta_server_os-update_schedule_list.md | 45 +++ ...t_beta_server_os-update_schedule_update.md | 45 +++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 2 + .../beta/server/os-update/create/create.go | 147 ++++++++++ .../server/os-update/create/create_test.go | 205 ++++++++++++++ .../server/os-update/describe/describe.go | 162 +++++++++++ .../os-update/describe/describe_test.go | 211 ++++++++++++++ .../beta/server/os-update/disable/disable.go | 108 +++++++ .../server/os-update/disable/disable_test.go | 173 ++++++++++++ .../beta/server/os-update/enable/enable.go | 112 ++++++++ .../server/os-update/enable/enable_test.go | 173 ++++++++++++ .../cmd/beta/server/os-update/list/list.go | 177 ++++++++++++ .../beta/server/os-update/list/list_test.go | 188 +++++++++++++ .../cmd/beta/server/os-update/os-update.go | 36 +++ .../os-update/schedule/create/create.go | 167 +++++++++++ .../os-update/schedule/create/create_test.go | 212 ++++++++++++++ .../os-update/schedule/delete/delete.go | 113 ++++++++ .../os-update/schedule/delete/delete_test.go | 209 ++++++++++++++ .../os-update/schedule/describe/describe.go | 149 ++++++++++ .../schedule/describe/describe_test.go | 211 ++++++++++++++ .../server/os-update/schedule/list/list.go | 160 +++++++++++ .../os-update/schedule/list/list_test.go | 188 +++++++++++++ .../server/os-update/schedule/schedule.go | 34 +++ .../os-update/schedule/update/update.go | 191 +++++++++++++ .../os-update/schedule/update/update_test.go | 265 ++++++++++++++++++ internal/cmd/beta/server/server.go | 2 + internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 13 + internal/pkg/config/config.go | 3 + .../services/serverosupdate/client/client.go | 46 +++ 45 files changed, 4188 insertions(+) create mode 100644 docs/stackit_beta_server_os-update.md create mode 100644 docs/stackit_beta_server_os-update_create.md create mode 100644 docs/stackit_beta_server_os-update_describe.md create mode 100644 docs/stackit_beta_server_os-update_disable.md create mode 100644 docs/stackit_beta_server_os-update_enable.md create mode 100644 docs/stackit_beta_server_os-update_list.md create mode 100644 docs/stackit_beta_server_os-update_schedule.md create mode 100644 docs/stackit_beta_server_os-update_schedule_create.md create mode 100644 docs/stackit_beta_server_os-update_schedule_delete.md create mode 100644 docs/stackit_beta_server_os-update_schedule_describe.md create mode 100644 docs/stackit_beta_server_os-update_schedule_list.md create mode 100644 docs/stackit_beta_server_os-update_schedule_update.md create mode 100644 internal/cmd/beta/server/os-update/create/create.go create mode 100644 internal/cmd/beta/server/os-update/create/create_test.go create mode 100644 internal/cmd/beta/server/os-update/describe/describe.go create mode 100644 internal/cmd/beta/server/os-update/describe/describe_test.go create mode 100644 internal/cmd/beta/server/os-update/disable/disable.go create mode 100644 internal/cmd/beta/server/os-update/disable/disable_test.go create mode 100644 internal/cmd/beta/server/os-update/enable/enable.go create mode 100644 internal/cmd/beta/server/os-update/enable/enable_test.go create mode 100644 internal/cmd/beta/server/os-update/list/list.go create mode 100644 internal/cmd/beta/server/os-update/list/list_test.go create mode 100644 internal/cmd/beta/server/os-update/os-update.go create mode 100644 internal/cmd/beta/server/os-update/schedule/create/create.go create mode 100644 internal/cmd/beta/server/os-update/schedule/create/create_test.go create mode 100644 internal/cmd/beta/server/os-update/schedule/delete/delete.go create mode 100644 internal/cmd/beta/server/os-update/schedule/delete/delete_test.go create mode 100644 internal/cmd/beta/server/os-update/schedule/describe/describe.go create mode 100644 internal/cmd/beta/server/os-update/schedule/describe/describe_test.go create mode 100644 internal/cmd/beta/server/os-update/schedule/list/list.go create mode 100644 internal/cmd/beta/server/os-update/schedule/list/list_test.go create mode 100644 internal/cmd/beta/server/os-update/schedule/schedule.go create mode 100644 internal/cmd/beta/server/os-update/schedule/update/update.go create mode 100644 internal/cmd/beta/server/os-update/schedule/update/update_test.go create mode 100644 internal/pkg/services/serverosupdate/client/client.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index d3abb34f4..a56612e08 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -40,6 +40,7 @@ stackit beta server [flags] * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project * [stackit beta server log](./stackit_beta_server_log.md) - Gets server console log * [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers +* [stackit beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates * [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers * [stackit beta server reboot](./stackit_beta_server_reboot.md) - Reboots a server * [stackit beta server rescue](./stackit_beta_server_rescue.md) - Rescues an existing server diff --git a/docs/stackit_beta_server_os-update.md b/docs/stackit_beta_server_os-update.md new file mode 100644 index 000000000..0cf8358b9 --- /dev/null +++ b/docs/stackit_beta_server_os-update.md @@ -0,0 +1,39 @@ +## stackit beta server os-update + +Provides functionality for managed server updates + +### Synopsis + +Provides functionality for managed server updates. + +``` +stackit beta server os-update [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update" +``` + +### 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 beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit beta server os-update create](./stackit_beta_server_os-update_create.md) - Creates a Server os-update. +* [stackit beta server os-update describe](./stackit_beta_server_os-update_describe.md) - Shows details of a Server os-update +* [stackit beta server os-update disable](./stackit_beta_server_os-update_disable.md) - Disables server os-update service +* [stackit beta server os-update enable](./stackit_beta_server_os-update_enable.md) - Enables Server os-update service +* [stackit beta server os-update list](./stackit_beta_server_os-update_list.md) - Lists all server os-updates +* [stackit beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule + diff --git a/docs/stackit_beta_server_os-update_create.md b/docs/stackit_beta_server_os-update_create.md new file mode 100644 index 000000000..fcfa3efb6 --- /dev/null +++ b/docs/stackit_beta_server_os-update_create.md @@ -0,0 +1,45 @@ +## stackit beta server os-update create + +Creates a Server os-update. + +### Synopsis + +Creates a Server os-update. Operation always is async. + +``` +stackit beta server os-update create [flags] +``` + +### Examples + +``` + Create a Server os-update with name "myupdate" + $ stackit beta server os-update create --server-id xxx --name=myupdate + + Create a Server os-update with name "myupdate" and maintenance window for 13 o'clock. + $ stackit beta server os-update create --server-id xxx --name=mybupdate --maintenance-window=13 +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update create" + -m, --maintenance-window int Maintenance window (in hours, 1-24) (default 23) + -s, --server-id string Server ID +``` + +### 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 beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates + diff --git a/docs/stackit_beta_server_os-update_describe.md b/docs/stackit_beta_server_os-update_describe.md new file mode 100644 index 000000000..a73f04dd7 --- /dev/null +++ b/docs/stackit_beta_server_os-update_describe.md @@ -0,0 +1,44 @@ +## stackit beta server os-update describe + +Shows details of a Server os-update + +### Synopsis + +Shows details of a Server os-update. + +``` +stackit beta server os-update describe UPDATE_ID [flags] +``` + +### Examples + +``` + Get details of a Server os-update with id "my-os-update-id" + $ stackit beta server os-update describe my-os-update-id + + Get details of a Server os-update with id "my-os-update-id" in JSON format + $ stackit beta server os-update describe my-os-update-id --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update describe" + -s, --server-id string Server ID +``` + +### 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 beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates + diff --git a/docs/stackit_beta_server_os-update_disable.md b/docs/stackit_beta_server_os-update_disable.md new file mode 100644 index 000000000..477d42214 --- /dev/null +++ b/docs/stackit_beta_server_os-update_disable.md @@ -0,0 +1,41 @@ +## stackit beta server os-update disable + +Disables server os-update service + +### Synopsis + +Disables server os-update service. + +``` +stackit beta server os-update disable [flags] +``` + +### Examples + +``` + Disable os-update functionality for your server. + $ stackit beta server os-update disable --server-id=zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update disable" + -s, --server-id string Server ID +``` + +### 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 beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates + diff --git a/docs/stackit_beta_server_os-update_enable.md b/docs/stackit_beta_server_os-update_enable.md new file mode 100644 index 000000000..661ddaf47 --- /dev/null +++ b/docs/stackit_beta_server_os-update_enable.md @@ -0,0 +1,41 @@ +## stackit beta server os-update enable + +Enables Server os-update service + +### Synopsis + +Enables Server os-update service. + +``` +stackit beta server os-update enable [flags] +``` + +### Examples + +``` + Enable os-update functionality for your server + $ stackit beta server os-update enable --server-id=zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update enable" + -s, --server-id string Server ID +``` + +### 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 beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates + diff --git a/docs/stackit_beta_server_os-update_list.md b/docs/stackit_beta_server_os-update_list.md new file mode 100644 index 000000000..57c46d3df --- /dev/null +++ b/docs/stackit_beta_server_os-update_list.md @@ -0,0 +1,45 @@ +## stackit beta server os-update list + +Lists all server os-updates + +### Synopsis + +Lists all server os-updates. + +``` +stackit beta server os-update list [flags] +``` + +### Examples + +``` + List all os-updates for a server with ID "xxx" + $ stackit beta server os-update list --server-id xxx + + List all os-updates for a server with ID "xxx" in JSON format + $ stackit beta server os-update list --server-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update list" + --limit int Maximum number of entries to list + -s, --server-id string Server ID +``` + +### 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 beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates + diff --git a/docs/stackit_beta_server_os-update_schedule.md b/docs/stackit_beta_server_os-update_schedule.md new file mode 100644 index 000000000..9579ba4b9 --- /dev/null +++ b/docs/stackit_beta_server_os-update_schedule.md @@ -0,0 +1,38 @@ +## stackit beta server os-update schedule + +Provides functionality for Server os-update Schedule + +### Synopsis + +Provides functionality for Server os-update Schedule. + +``` +stackit beta server os-update schedule [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update schedule" +``` + +### 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 beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates +* [stackit beta server os-update schedule create](./stackit_beta_server_os-update_schedule_create.md) - Creates a Server os-update Schedule +* [stackit beta server os-update schedule delete](./stackit_beta_server_os-update_schedule_delete.md) - Deletes a Server os-update Schedule +* [stackit beta server os-update schedule describe](./stackit_beta_server_os-update_schedule_describe.md) - Shows details of a Server os-update Schedule +* [stackit beta server os-update schedule list](./stackit_beta_server_os-update_schedule_list.md) - Lists all server os-update schedules +* [stackit beta server os-update schedule update](./stackit_beta_server_os-update_schedule_update.md) - Updates a Server os-update Schedule + diff --git a/docs/stackit_beta_server_os-update_schedule_create.md b/docs/stackit_beta_server_os-update_schedule_create.md new file mode 100644 index 000000000..529fe2b87 --- /dev/null +++ b/docs/stackit_beta_server_os-update_schedule_create.md @@ -0,0 +1,48 @@ +## stackit beta server os-update schedule create + +Creates a Server os-update Schedule + +### Synopsis + +Creates a Server os-update Schedule. + +``` +stackit beta server os-update schedule create [flags] +``` + +### Examples + +``` + Create a Server os-update Schedule with name "myschedule" + $ stackit beta server os-update schedule create --server-id xxx --name=myschedule + + Create a Server os-update Schedule with name "myschedule" and maintenance window for 14 o'clock + $ stackit beta server os-update schedule create --server-id xxx --name=myschedule --maintenance-window=14 +``` + +### Options + +``` + -e, --enabled Is the server os-update schedule enabled (default true) + -h, --help Help for "stackit beta server os-update schedule create" + -d, --maintenance-window int os-update maintenance window (in hours, 1-24) (default 23) + -n, --name string os-update schedule name + -r, --rrule string os-update RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") + -s, --server-id string Server ID +``` + +### 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 beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule + diff --git a/docs/stackit_beta_server_os-update_schedule_delete.md b/docs/stackit_beta_server_os-update_schedule_delete.md new file mode 100644 index 000000000..d2e5e2bc9 --- /dev/null +++ b/docs/stackit_beta_server_os-update_schedule_delete.md @@ -0,0 +1,41 @@ +## stackit beta server os-update schedule delete + +Deletes a Server os-update Schedule + +### Synopsis + +Deletes a Server os-update Schedule. + +``` +stackit beta server os-update schedule delete SCHEDULE_ID [flags] +``` + +### Examples + +``` + Delete a Server os-update Schedule with ID "xxx" for server "zzz" + $ stackit beta server os-update schedule delete xxx --server-id=zzz +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update schedule delete" + -s, --server-id string Server ID +``` + +### 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 beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule + diff --git a/docs/stackit_beta_server_os-update_schedule_describe.md b/docs/stackit_beta_server_os-update_schedule_describe.md new file mode 100644 index 000000000..fc6542fd2 --- /dev/null +++ b/docs/stackit_beta_server_os-update_schedule_describe.md @@ -0,0 +1,44 @@ +## stackit beta server os-update schedule describe + +Shows details of a Server os-update Schedule + +### Synopsis + +Shows details of a Server os-update Schedule. + +``` +stackit beta server os-update schedule describe SCHEDULE_ID [flags] +``` + +### Examples + +``` + Get details of a Server os-update Schedule with id "my-schedule-id" + $ stackit beta server os-update schedule describe my-schedule-id + + Get details of a Server os-update Schedule with id "my-schedule-id" in JSON format + $ stackit beta server os-update schedule describe my-schedule-id --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update schedule describe" + -s, --server-id string Server ID +``` + +### 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 beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule + diff --git a/docs/stackit_beta_server_os-update_schedule_list.md b/docs/stackit_beta_server_os-update_schedule_list.md new file mode 100644 index 000000000..5352184bb --- /dev/null +++ b/docs/stackit_beta_server_os-update_schedule_list.md @@ -0,0 +1,45 @@ +## stackit beta server os-update schedule list + +Lists all server os-update schedules + +### Synopsis + +Lists all server os-update schedules. + +``` +stackit beta server os-update schedule list [flags] +``` + +### Examples + +``` + List all os-update schedules for a server with ID "xxx" + $ stackit beta server os-update schedule list --server-id xxx + + List all os-update schedules for a server with ID "xxx" in JSON format + $ stackit beta server os-update schedule list --server-id xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server os-update schedule list" + --limit int Maximum number of entries to list + -s, --server-id string Server ID +``` + +### 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 beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule + diff --git a/docs/stackit_beta_server_os-update_schedule_update.md b/docs/stackit_beta_server_os-update_schedule_update.md new file mode 100644 index 000000000..4b901269f --- /dev/null +++ b/docs/stackit_beta_server_os-update_schedule_update.md @@ -0,0 +1,45 @@ +## stackit beta server os-update schedule update + +Updates a Server os-update Schedule + +### Synopsis + +Updates a Server os-update Schedule. + +``` +stackit beta server os-update schedule update SCHEDULE_ID [flags] +``` + +### Examples + +``` + Update the name of the os-update schedule "zzz" of server "xxx" + $ stackit beta server os-update schedule update zzz --server-id=xxx --name=newname +``` + +### Options + +``` + -e, --enabled Is the server os-update schedule enabled (default true) + -h, --help Help for "stackit beta server os-update schedule update" + -d, --maintenance-window int Maintenance window (in hours, 1-24) (default 23) + -n, --name string os-update schedule name + -r, --rrule string os-update RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") + -s, --server-id string Server ID +``` + +### 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 beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index d8e1f20a5..b1abf5662 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -49,6 +49,7 @@ stackit config set [flags] --resource-manager-custom-endpoint string Resource Manager API base URL, used in calls to this API --runcommand-custom-endpoint string Run Command API base URL, used in calls to this API --secrets-manager-custom-endpoint string Secrets Manager API base URL, used in calls to this API + --server-osupdate-custom-endpoint string Server Update Management API base URL, used in calls to this API --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API --service-account-custom-endpoint string Service Account API base URL, used in calls to this API --service-enablement-custom-endpoint string Service Enablement API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 933bacc3d..4a48b759e 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -50,6 +50,7 @@ stackit config unset [flags] --resource-manager-custom-endpoint Resource Manager API base URL. If unset, uses the default base URL --runcommand-custom-endpoint Server Command base URL. If unset, uses the default base URL --secrets-manager-custom-endpoint Secrets Manager API base URL. If unset, uses the default base URL + --server-osupdate-custom-endpoint Server Update Management base URL. If unset, uses the default base URL --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL --service-account-custom-endpoint Service Account API base URL. If unset, uses the default base URL --service-enablement-custom-endpoint Service Enablement API base URL. If unset, uses the default base URL diff --git a/go.mod b/go.mod index 5f512f130..cd2cec4dc 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( al.essio.dev/pkg/shellescape v1.5.1 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.2.3 // indirect github.com/x448/float16 v0.8.4 // indirect ) diff --git a/go.sum b/go.sum index 781c3b93c..a1f298913 100644 --- a/go.sum +++ b/go.sum @@ -153,6 +153,8 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 h1:qShB0O github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 h1:33zKhcNS1bZ2usGnYZ6YE6Vxm7c9U0aC8lDg96UN+e4= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0/go.mod h1:thrCIDBjEHAcihjWUOMJ5mbYVhOWfS/bLTBJ+yl5W4g= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.2.3 h1:+D7NWWP/FF1asAZhntwzaFaSnHExgwta7/k+mRGmzrQ= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.2.3/go.mod h1:etidTptNDvvCPA1FGC7T9DXHxXA4bYW3qIUzWG8wVcc= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= diff --git a/internal/cmd/beta/server/os-update/create/create.go b/internal/cmd/beta/server/os-update/create/create.go new file mode 100644 index 000000000..bf0bf664d --- /dev/null +++ b/internal/cmd/beta/server/os-update/create/create.go @@ -0,0 +1,147 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + serverIdFlag = "server-id" + maintenanceWindowFlag = "maintenance-window" + defaultMaintenanceWindow = 23 +) + +type inputModel struct { + *globalflags.GlobalFlagModel + + ServerId string + MaintenanceWindow int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a Server os-update.", + Long: "Creates a Server os-update. Operation always is async.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a Server os-update with name "myupdate"`, + `$ stackit beta server os-update create --server-id xxx --name=myupdate`), + examples.NewExample( + `Create a Server os-update with name "myupdate" and maintenance window for 13 o'clock.`, + `$ stackit beta server os-update create --server-id xxx --name=mybupdate --maintenance-window=13`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a os-update for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create Server os-update: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().Int64P(maintenanceWindowFlag, "m", defaultMaintenanceWindow, "Maintenance window (in hours, 1-24)") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + MaintenanceWindow: flags.FlagWithDefaultToInt64Value(p, cmd, maintenanceWindowFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) (serverupdate.ApiCreateUpdateRequest, error) { + req := apiClient.CreateUpdate(ctx, model.ProjectId, model.ServerId) + payload := serverupdate.CreateUpdatePayload{ + MaintenanceWindow: &model.MaintenanceWindow, + } + req = req.CreateUpdatePayload(payload) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal server os-update: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server os-update: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Triggered creation of server os-update for server %s. Update ID: %d\n", model.ServerId, *resp.Id) + return nil + } +} diff --git a/internal/cmd/beta/server/os-update/create/create_test.go b/internal/cmd/beta/server/os-update/create/create_test.go new file mode 100644 index 000000000..2402f81a8 --- /dev/null +++ b/internal/cmd/beta/server/os-update/create/create_test.go @@ -0,0 +1,205 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} + +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + maintenanceWindowFlag: "13", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + MaintenanceWindow: int64(13), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiCreateUpdateRequest)) serverupdate.ApiCreateUpdateRequest { + request := testClient.CreateUpdate(testCtx, testProjectId, testServerId) + request = request.CreateUpdatePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *serverupdate.CreateUpdatePayload)) serverupdate.CreateUpdatePayload { + payload := serverupdate.CreateUpdatePayload{ + MaintenanceWindow: utils.Ptr(int64(13)), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "with defaults", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, maintenanceWindowFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.MaintenanceWindow = 23 + }), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverupdate.ApiCreateUpdateRequest + isValid bool + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/describe/describe.go b/internal/cmd/beta/server/os-update/describe/describe.go new file mode 100644 index 000000000..3a92dd3dc --- /dev/null +++ b/internal/cmd/beta/server/os-update/describe/describe.go @@ -0,0 +1,162 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + updateIdArg = "UPDATE_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + UpdateId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", updateIdArg), + Short: "Shows details of a Server os-update", + Long: "Shows details of a Server os-update.", + Args: args.SingleArg(updateIdArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details of a Server os-update with id "my-os-update-id"`, + "$ stackit beta server os-update describe my-os-update-id"), + examples.NewExample( + `Get details of a Server os-update with id "my-os-update-id" in JSON format`, + "$ stackit beta server os-update describe my-os-update-id --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read server os-update: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + updateId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + UpdateId: updateId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiGetUpdateRequest { + req := apiClient.GetUpdate(ctx, model.ProjectId, model.ServerId, model.UpdateId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, update *serverupdate.Update) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(update, "", " ") + if err != nil { + return fmt.Errorf("marshal server update: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(update, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server update: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("ID", *update.Id) + table.AddSeparator() + table.AddRow("STATUS", *update.Status) + table.AddSeparator() + if update.InstalledUpdates != nil { + table.AddRow("INSTALLED UPDATES", *update.InstalledUpdates) + } else { + table.AddRow("INSTALLED UPDATES", "...") + } + table.AddSeparator() + if update.FailedUpdates != nil { + table.AddRow("FAILED UPDATES", *update.FailedUpdates) + } else { + table.AddRow("FAILED UPDATES", "...") + } + table.AddRow("START DATE", *update.StartDate) + table.AddSeparator() + if update.EndDate != nil { + table.AddRow("END DATE", *update.EndDate) + } else { + table.AddRow("END DATE", "...") + } + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/server/os-update/describe/describe_test.go b/internal/cmd/beta/server/os-update/describe/describe_test.go new file mode 100644 index 000000000..e02f0298f --- /dev/null +++ b/internal/cmd/beta/server/os-update/describe/describe_test.go @@ -0,0 +1,211 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testUpdateId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testUpdateId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + UpdateId: testUpdateId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiGetUpdateRequest)) serverupdate.ApiGetUpdateRequest { + request := testClient.GetUpdate(testCtx, testProjectId, testServerId, testUpdateId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + isValid bool + expectedRequest serverupdate.ApiGetUpdateRequest + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/disable/disable.go b/internal/cmd/beta/server/os-update/disable/disable.go new file mode 100644 index 000000000..1fbc89823 --- /dev/null +++ b/internal/cmd/beta/server/os-update/disable/disable.go @@ -0,0 +1,108 @@ +package disable + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "disable", + Short: "Disables server os-update service", + Long: "Disables server os-update service.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Disable os-update functionality for your server.`, + "$ stackit beta server os-update disable --server-id=zzz"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to disable the os-update service for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("disable server os-update service: %w", err) + } + + p.Info("Disabled Server os-update service for server %s\n", model.ServerId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiDisableServiceRequest { + req := apiClient.DisableService(ctx, model.ProjectId, model.ServerId) + return req +} diff --git a/internal/cmd/beta/server/os-update/disable/disable_test.go b/internal/cmd/beta/server/os-update/disable/disable_test.go new file mode 100644 index 000000000..6560a7fae --- /dev/null +++ b/internal/cmd/beta/server/os-update/disable/disable_test.go @@ -0,0 +1,173 @@ +package disable + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiDisableServiceRequest)) serverupdate.ApiDisableServiceRequest { + request := testClient.DisableService(testCtx, testProjectId, testServerId) + 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(func(model *inputModel) { + model.ServerId = "" + }), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverupdate.ApiDisableServiceRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/enable/enable.go b/internal/cmd/beta/server/os-update/enable/enable.go new file mode 100644 index 000000000..c16d19318 --- /dev/null +++ b/internal/cmd/beta/server/os-update/enable/enable.go @@ -0,0 +1,112 @@ +package enable + +import ( + "context" + "fmt" + "strings" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "enable", + Short: "Enables Server os-update service", + Long: "Enables Server os-update service.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Enable os-update functionality for your server`, + "$ stackit beta server os-update enable --server-id=zzz"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to enable the server os-update service for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + if !strings.Contains(err.Error(), "Tried to activate already active service") { + return fmt.Errorf("enable server os-update: %w", err) + } + } + + p.Info("Enabled os-update service for server %s\n", model.ServerId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiEnableServiceRequest { + payload := serverupdate.EnableServicePayload{} + req := apiClient.EnableService(ctx, model.ProjectId, model.ServerId).EnableServicePayload(payload) + return req +} diff --git a/internal/cmd/beta/server/os-update/enable/enable_test.go b/internal/cmd/beta/server/os-update/enable/enable_test.go new file mode 100644 index 000000000..6e55c1c77 --- /dev/null +++ b/internal/cmd/beta/server/os-update/enable/enable_test.go @@ -0,0 +1,173 @@ +package enable + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiEnableServiceRequest)) serverupdate.ApiEnableServiceRequest { + request := testClient.EnableService(testCtx, testProjectId, testServerId).EnableServicePayload(serverupdate.EnableServicePayload{}) + 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(func(model *inputModel) { + model.ServerId = "" + }), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverupdate.ApiEnableServiceRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/list/list.go b/internal/cmd/beta/server/os-update/list/list.go new file mode 100644 index 000000000..2f41b0ab1 --- /dev/null +++ b/internal/cmd/beta/server/os-update/list/list.go @@ -0,0 +1,177 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + + "github.com/goccy/go-yaml" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + limitFlag = "limit" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all server os-updates", + Long: "Lists all server os-updates.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all os-updates for a server with ID "xxx"`, + "$ stackit beta server os-update list --server-id xxx"), + examples.NewExample( + `List all os-updates for a server with ID "xxx" in JSON format`, + "$ stackit beta server os-update list --server-id xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list server os-update: %w", err) + } + updates := *resp.Items + if len(updates) == 0 { + p.Info("No os-updates found for server %s\n", model.ServerId) + return nil + } + + // Truncate output + if model.Limit != nil && len(updates) > int(*model.Limit) { + updates = updates[:*model.Limit] + } + return outputResult(p, model.OutputFormat, updates) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiListUpdatesRequest { + req := apiClient.ListUpdates(ctx, model.ProjectId, model.ServerId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, updates []serverupdate.Update) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(updates, "", " ") + if err != nil { + return fmt.Errorf("marshal server os-update list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(updates, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server os-update list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "STATUS", "INSTALLED UPDATES", "FAILED UPDATES", "START DATE", "END DATE") + for i := range updates { + s := updates[i] + + endDate := "..." + if s.EndDate != nil { + endDate = *s.EndDate + } + + installed := "..." + if s.InstalledUpdates != nil { + installed = strconv.FormatInt(*s.InstalledUpdates, 10) + } + + failed := "..." + if s.FailedUpdates != nil { + failed = strconv.FormatInt(*s.FailedUpdates, 10) + } + + table.AddRow(*s.Id, *s.Status, installed, failed, *s.StartDate, endDate) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/os-update/list/list_test.go b/internal/cmd/beta/server/os-update/list/list_test.go new file mode 100644 index 000000000..32f75311c --- /dev/null +++ b/internal/cmd/beta/server/os-update/list/list_test.go @@ -0,0 +1,188 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(int64(10)), + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiListUpdatesRequest)) serverupdate.ApiListUpdatesRequest { + request := testClient.ListUpdates(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverupdate.ApiListUpdatesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/os-update.go b/internal/cmd/beta/server/os-update/os-update.go new file mode 100644 index 000000000..b4100b3d6 --- /dev/null +++ b/internal/cmd/beta/server/os-update/os-update.go @@ -0,0 +1,36 @@ +package osupdate + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/disable" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "os-update", + Short: "Provides functionality for managed server updates", + Long: "Provides functionality for managed server updates.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(enable.NewCmd(p)) + cmd.AddCommand(disable.NewCmd(p)) + cmd.AddCommand(schedule.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/os-update/schedule/create/create.go b/internal/cmd/beta/server/os-update/schedule/create/create.go new file mode 100644 index 000000000..5a4d7ce93 --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/create/create.go @@ -0,0 +1,167 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + nameFlag = "name" + enabledFlag = "enabled" + rruleFlag = "rrule" + maintenanceWindowFlag = "maintenance-window" + serverIdFlag = "server-id" + + defaultRrule = "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1" + defaultMaintenanceWindow = 23 + defaultEnabled = true +) + +type inputModel struct { + *globalflags.GlobalFlagModel + + ServerId string + ScheduleName string + Enabled bool + Rrule string + MaintenanceWindow int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a Server os-update Schedule", + Long: "Creates a Server os-update Schedule.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a Server os-update Schedule with name "myschedule"`, + `$ stackit beta server os-update schedule create --server-id xxx --name=myschedule`), + examples.NewExample( + `Create a Server os-update Schedule with name "myschedule" and maintenance window for 14 o'clock`, + `$ stackit beta server os-update schedule create --server-id xxx --name=myschedule --maintenance-window=14`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a os-update Schedule for server %s?", model.ServerId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create Server os-update Schedule: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + cmd.Flags().StringP(nameFlag, "n", "", "os-update schedule name") + cmd.Flags().Int64P(maintenanceWindowFlag, "d", defaultMaintenanceWindow, "os-update maintenance window (in hours, 1-24)") + cmd.Flags().BoolP(enabledFlag, "e", defaultEnabled, "Is the server os-update schedule enabled") + cmd.Flags().StringP(rruleFlag, "r", defaultRrule, "os-update RRULE (recurrence rule)") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag, nameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + MaintenanceWindow: flags.FlagWithDefaultToInt64Value(p, cmd, maintenanceWindowFlag), + ScheduleName: flags.FlagToStringValue(p, cmd, nameFlag), + Rrule: flags.FlagWithDefaultToStringValue(p, cmd, rruleFlag), + Enabled: flags.FlagToBoolValue(p, cmd, enabledFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) (serverupdate.ApiCreateUpdateScheduleRequest, error) { + req := apiClient.CreateUpdateSchedule(ctx, model.ProjectId, model.ServerId) + req = req.CreateUpdateSchedulePayload(serverupdate.CreateUpdateSchedulePayload{ + Enabled: &model.Enabled, + Name: &model.ScheduleName, + Rrule: &model.Rrule, + MaintenanceWindow: &model.MaintenanceWindow, + }) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.UpdateSchedule) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal server os-update schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server os-update schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created server os-update schedule for server %s. os-update Schedule ID: %d\n", model.ServerId, *resp.Id) + return nil + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/create/create_test.go b/internal/cmd/beta/server/os-update/schedule/create/create_test.go new file mode 100644 index 000000000..31e6f781b --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/create/create_test.go @@ -0,0 +1,212 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} + +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + nameFlag: "example-schedule-name", + enabledFlag: "true", + rruleFlag: defaultRrule, + maintenanceWindowFlag: "23", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + ScheduleName: "example-schedule-name", + Enabled: defaultEnabled, + Rrule: defaultRrule, + MaintenanceWindow: int64(23), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiCreateUpdateScheduleRequest)) serverupdate.ApiCreateUpdateScheduleRequest { + request := testClient.CreateUpdateSchedule(testCtx, testProjectId, testServerId) + request = request.CreateUpdateSchedulePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *serverupdate.CreateUpdateSchedulePayload)) serverupdate.CreateUpdateSchedulePayload { + payload := serverupdate.CreateUpdateSchedulePayload{ + Name: utils.Ptr("example-schedule-name"), + Enabled: utils.Ptr(defaultEnabled), + Rrule: utils.Ptr("DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1"), + MaintenanceWindow: utils.Ptr(int64(23)), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + aclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "with defaults", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, maintenanceWindowFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverupdate.ApiCreateUpdateScheduleRequest + isValid bool + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/delete/delete.go b/internal/cmd/beta/server/os-update/schedule/delete/delete.go new file mode 100644 index 000000000..d19482752 --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/delete/delete.go @@ -0,0 +1,113 @@ +package delete + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + scheduleIdArg = "SCHEDULE_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ScheduleId string + ServerId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", scheduleIdArg), + Short: "Deletes a Server os-update Schedule", + Long: "Deletes a Server os-update Schedule.", + Args: args.SingleArg(scheduleIdArg, nil), + Example: examples.Build( + examples.NewExample( + `Delete a Server os-update Schedule with ID "xxx" for server "zzz"`, + "$ stackit beta server os-update schedule delete xxx --server-id=zzz"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete server os-update schedule %q? (This cannot be undone)", model.ScheduleId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete Server os-update Schedule: %w", err) + } + + p.Info("Deleted server os-update schedule %q\n", model.ScheduleId) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + scheduleId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ScheduleId: scheduleId, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiDeleteUpdateScheduleRequest { + req := apiClient.DeleteUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + return req +} diff --git a/internal/cmd/beta/server/os-update/schedule/delete/delete_test.go b/internal/cmd/beta/server/os-update/schedule/delete/delete_test.go new file mode 100644 index 000000000..60b00b97c --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/delete/delete_test.go @@ -0,0 +1,209 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testUpdateScheduleId = "5" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testUpdateScheduleId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + ScheduleId: testUpdateScheduleId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiDeleteUpdateScheduleRequest)) serverupdate.ApiDeleteUpdateScheduleRequest { + request := testClient.DeleteUpdateSchedule(testCtx, testProjectId, testServerId, testUpdateScheduleId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverupdate.ApiDeleteUpdateScheduleRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/describe/describe.go b/internal/cmd/beta/server/os-update/schedule/describe/describe.go new file mode 100644 index 000000000..d46bf0a1e --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/describe/describe.go @@ -0,0 +1,149 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + scheduleIdArg = "SCHEDULE_ID" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + ScheduleId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", scheduleIdArg), + Short: "Shows details of a Server os-update Schedule", + Long: "Shows details of a Server os-update Schedule.", + Args: args.SingleArg(scheduleIdArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details of a Server os-update Schedule with id "my-schedule-id"`, + "$ stackit beta server os-update schedule describe my-schedule-id"), + examples.NewExample( + `Get details of a Server os-update Schedule with id "my-schedule-id" in JSON format`, + "$ stackit beta server os-update schedule describe my-schedule-id --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read server os-update schedule: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + scheduleId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + ScheduleId: scheduleId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiGetUpdateScheduleRequest { + req := apiClient.GetUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, schedule *serverupdate.UpdateSchedule) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(schedule, "", " ") + if err != nil { + return fmt.Errorf("marshal server os-update schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(schedule, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server os-update schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("SCHEDULE ID", *schedule.Id) + table.AddSeparator() + table.AddRow("SCHEDULE NAME", *schedule.Name) + table.AddSeparator() + table.AddRow("ENABLED", *schedule.Enabled) + table.AddSeparator() + table.AddRow("RRULE", *schedule.Rrule) + table.AddSeparator() + table.AddRow("MAINTENANCE WINDOW", *schedule.MaintenanceWindow) + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/describe/describe_test.go b/internal/cmd/beta/server/os-update/schedule/describe/describe_test.go new file mode 100644 index 000000000..f1165bb00 --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/describe/describe_test.go @@ -0,0 +1,211 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testScheduleId = "5" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testScheduleId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ServerId: testServerId, + ScheduleId: testScheduleId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiGetUpdateScheduleRequest)) serverupdate.ApiGetUpdateScheduleRequest { + request := testClient.GetUpdateSchedule(testCtx, testProjectId, testServerId, testScheduleId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + isValid bool + expectedRequest serverupdate.ApiGetUpdateScheduleRequest + }{ + { + description: "base", + model: fixtureInputModel(), + isValid: true, + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/list/list.go b/internal/cmd/beta/server/os-update/schedule/list/list.go new file mode 100644 index 000000000..f24d8becf --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/list/list.go @@ -0,0 +1,160 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + limitFlag = "limit" + serverIdFlag = "server-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ServerId string + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all server os-update schedules", + Long: "Lists all server os-update schedules.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all os-update schedules for a server with ID "xxx"`, + "$ stackit beta server os-update schedule list --server-id xxx"), + examples.NewExample( + `List all os-update schedules for a server with ID "xxx" in JSON format`, + "$ stackit beta server os-update schedule list --server-id xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list server os-update schedules: %w", err) + } + schedules := *resp.Items + if len(schedules) == 0 { + p.Info("No os-update schedules found for server %s\n", model.ServerId) + return nil + } + + // Truncate output + if model.Limit != nil && len(schedules) > int(*model.Limit) { + schedules = schedules[:*model.Limit] + } + return outputResult(p, model.OutputFormat, schedules) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiListUpdateSchedulesRequest { + req := apiClient.ListUpdateSchedules(ctx, model.ProjectId, model.ServerId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, schedules []serverupdate.UpdateSchedule) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(schedules, "", " ") + if err != nil { + return fmt.Errorf("marshal Server os-update Schedules list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(schedules, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal Server os-update Schedules list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("SCHEDULE ID", "SCHEDULE NAME", "ENABLED", "RRULE", "MAINTENANCE WINDOW") + for i := range schedules { + s := schedules[i] + table.AddRow(*s.Id, *s.Name, *s.Enabled, *s.Rrule, *s.MaintenanceWindow) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/list/list_test.go b/internal/cmd/beta/server/os-update/schedule/list/list_test.go new file mode 100644 index 000000000..6c0ce72f7 --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/list/list_test.go @@ -0,0 +1,188 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + serverIdFlag: testServerId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(int64(10)), + ServerId: testServerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiListUpdateSchedulesRequest)) serverupdate.ApiListUpdateSchedulesRequest { + request := testClient.ListUpdateSchedules(testCtx, testProjectId, testServerId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverupdate.ApiListUpdateSchedulesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/schedule.go b/internal/cmd/beta/server/os-update/schedule/schedule.go new file mode 100644 index 000000000..60c9e503c --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/schedule.go @@ -0,0 +1,34 @@ +package schedule + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/create" + del "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "schedule", + Short: "Provides functionality for Server os-update Schedule", + Long: "Provides functionality for Server os-update Schedule.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(del.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/os-update/schedule/update/update.go b/internal/cmd/beta/server/os-update/schedule/update/update.go new file mode 100644 index 000000000..c85a429f2 --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/update/update.go @@ -0,0 +1,191 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +const ( + scheduleIdArg = "SCHEDULE_ID" + + nameFlag = "name" + enabledFlag = "enabled" + rruleFlag = "rrule" + maintenanceWindowFlag = "maintenance-window" + serverIdFlag = "server-id" + + defaultRrule = "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1" + defaultMaintenanceWindow = 23 + defaultEnabled = true +) + +type inputModel struct { + *globalflags.GlobalFlagModel + + ServerId string + ScheduleId string + ScheduleName *string + Enabled *bool + Rrule *string + MaintenanceWindow *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", scheduleIdArg), + Short: "Updates a Server os-update Schedule", + Long: "Updates a Server os-update Schedule.", + Example: examples.Build( + examples.NewExample( + `Update the name of the os-update schedule "zzz" of server "xxx"`, + "$ stackit beta server os-update schedule update zzz --server-id=xxx --name=newname"), + ), + Args: args.SingleArg(scheduleIdArg, nil), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + currentSchedule, err := apiClient.GetUpdateScheduleExecute(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + if err != nil { + p.Debug(print.ErrorLevel, "get current server os-update schedule: %v", err) + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update Server os-update Schedule %q?", model.ScheduleId) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient, *currentSchedule) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update Server os-update Schedule: %w", err) + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") + + cmd.Flags().StringP(nameFlag, "n", "", "os-update schedule name") + cmd.Flags().Int64P(maintenanceWindowFlag, "d", defaultMaintenanceWindow, "Maintenance window (in hours, 1-24)") + cmd.Flags().BoolP(enabledFlag, "e", defaultEnabled, "Is the server os-update schedule enabled") + cmd.Flags().StringP(rruleFlag, "r", defaultRrule, "os-update RRULE (recurrence rule)") + + err := flags.MarkFlagsRequired(cmd, serverIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + scheduleId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ScheduleId: scheduleId, + ScheduleName: flags.FlagToStringPointer(p, cmd, nameFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), + MaintenanceWindow: flags.FlagToInt64Pointer(p, cmd, maintenanceWindowFlag), + Rrule: flags.FlagToStringPointer(p, cmd, rruleFlag), + Enabled: flags.FlagToBoolPointer(p, cmd, enabledFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient, old serverupdate.UpdateSchedule) (serverupdate.ApiUpdateUpdateScheduleRequest, error) { + req := apiClient.UpdateUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + + if model.MaintenanceWindow != nil { + old.MaintenanceWindow = model.MaintenanceWindow + } + if model.Enabled != nil { + old.Enabled = model.Enabled + } + if model.ScheduleName != nil { + old.Name = model.ScheduleName + } + if model.Rrule != nil { + old.Rrule = model.Rrule + } + + req = req.UpdateUpdateSchedulePayload(serverupdate.UpdateUpdateSchedulePayload{ + Enabled: old.Enabled, + Name: old.Name, + Rrule: old.Rrule, + MaintenanceWindow: old.MaintenanceWindow, + }) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.UpdateSchedule) error { + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal update server os-update schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal update server os-update schedule: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Info("Updated server os-update schedule %d\n", *resp.Id) + return nil + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/update/update_test.go b/internal/cmd/beta/server/os-update/schedule/update/update_test.go new file mode 100644 index 000000000..20d8afe36 --- /dev/null +++ b/internal/cmd/beta/server/os-update/schedule/update/update_test.go @@ -0,0 +1,265 @@ +package update + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &serverupdate.APIClient{} +var testProjectId = uuid.NewString() +var testServerId = uuid.NewString() +var testScheduleId = "5" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testScheduleId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + serverIdFlag: testServerId, + nameFlag: "example-schedule-name", + enabledFlag: "true", + rruleFlag: defaultRrule, + maintenanceWindowFlag: "23", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + ScheduleId: testScheduleId, + ServerId: testServerId, + ScheduleName: utils.Ptr("example-schedule-name"), + Enabled: utils.Ptr(defaultEnabled), + Rrule: utils.Ptr(defaultRrule), + MaintenanceWindow: utils.Ptr(int64(23)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureUpdateSchedule(mods ...func(schedule *serverupdate.UpdateSchedule)) *serverupdate.UpdateSchedule { + id, _ := strconv.ParseInt(testScheduleId, 10, 64) + schedule := &serverupdate.UpdateSchedule{ + Name: utils.Ptr("example-schedule-name"), + Id: utils.Ptr(id), + Enabled: utils.Ptr(defaultEnabled), + Rrule: utils.Ptr(defaultRrule), + MaintenanceWindow: utils.Ptr(int64(23)), + } + for _, mod := range mods { + mod(schedule) + } + return schedule +} + +func fixturePayload(mods ...func(payload *serverupdate.UpdateUpdateSchedulePayload)) serverupdate.UpdateUpdateSchedulePayload { + payload := serverupdate.UpdateUpdateSchedulePayload{ + Name: utils.Ptr("example-schedule-name"), + Enabled: utils.Ptr(defaultEnabled), + Rrule: utils.Ptr("DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1"), + MaintenanceWindow: utils.Ptr(int64(23)), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *serverupdate.ApiUpdateUpdateScheduleRequest)) serverupdate.ApiUpdateUpdateScheduleRequest { + request := testClient.UpdateUpdateSchedule(testCtx, testProjectId, testServerId, testScheduleId) + request = request.UpdateUpdateSchedulePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "schedule id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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) + } + + err = cmd.ValidateFlagGroups() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flag groups: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest serverupdate.ApiUpdateUpdateScheduleRequest + isValid bool + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + isValid: true, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient, *fixtureUpdateSchedule()) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index 6d75b27d5..ef8922220 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/log" networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface" + osUpdate "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/reboot" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/rescue" @@ -62,4 +63,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(resize.NewCmd(p)) cmd.AddCommand(rescue.NewCmd(p)) cmd.AddCommand(unrescue.NewCmd(p)) + cmd.AddCommand(osUpdate.NewCmd(p)) } diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 5f983cd88..b8defa692 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -37,6 +37,7 @@ const ( resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" + serverOsUpdateCustomEndpointFlag = "server-osupdate-custom-endpoint" runCommandCustomEndpointFlag = "runcommand-custom-endpoint" serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" serviceEnablementCustomEndpointFlag = "service-enablement-custom-endpoint" @@ -151,6 +152,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(serviceAccountCustomEndpointFlag, "", "Service Account API base URL, used in calls to this API") cmd.Flags().String(serviceEnablementCustomEndpointFlag, "", "Service Enablement API base URL, used in calls to this API") cmd.Flags().String(serverBackupCustomEndpointFlag, "", "Server Backup API base URL, used in calls to this API") + cmd.Flags().String(serverOsUpdateCustomEndpointFlag, "", "Server Update Management API base URL, used in calls to this API") cmd.Flags().String(runCommandCustomEndpointFlag, "", "Run Command API base URL, used in calls to this API") cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") @@ -196,6 +198,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.ServerBackupCustomEndpointKey, cmd.Flags().Lookup(serverBackupCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.ServerOsUpdateCustomEndpointKey, cmd.Flags().Lookup(serverOsUpdateCustomEndpointFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.RunCommandCustomEndpointKey, cmd.Flags().Lookup(runCommandCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.ServiceAccountCustomEndpointKey, cmd.Flags().Lookup(serviceAccountCustomEndpointFlag)) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 0890dbc8a..72d79aeb3 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -43,6 +43,7 @@ const ( serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" serviceEnablementCustomEndpointFlag = "service-enablement-custom-endpoint" serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" + serverOsUpdateCustomEndpointFlag = "server-osupdate-custom-endpoint" runCommandCustomEndpointFlag = "runcommand-custom-endpoint" skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" @@ -77,6 +78,7 @@ type inputModel struct { ResourceManagerCustomEndpoint bool SecretsManagerCustomEndpoint bool ServerBackupCustomEndpoint bool + ServerOsUpdateCustomEndpoint bool RunCommandCustomEndpoint bool ServiceAccountCustomEndpoint bool ServiceEnablementCustomEndpoint bool @@ -186,6 +188,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.ServerBackupCustomEndpoint { viper.Set(config.ServerBackupCustomEndpointKey, "") } + if model.ServerOsUpdateCustomEndpoint { + viper.Set(config.ServerOsUpdateCustomEndpointKey, "") + } if model.RunCommandCustomEndpoint { viper.Set(config.RunCommandCustomEndpointKey, "") } @@ -242,6 +247,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(serviceAccountCustomEndpointFlag, false, "Service Account API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serviceEnablementCustomEndpointFlag, false, "Service Enablement API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serverBackupCustomEndpointFlag, false, "Server Backup base URL. If unset, uses the default base URL") + cmd.Flags().Bool(serverOsUpdateCustomEndpointFlag, false, "Server Update Management base URL. If unset, uses the default base URL") cmd.Flags().Bool(runCommandCustomEndpointFlag, false, "Server Command base URL. If unset, uses the default base URL") cmd.Flags().Bool(skeCustomEndpointFlag, false, "SKE API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") @@ -279,6 +285,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { ServiceAccountCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceAccountCustomEndpointFlag), ServiceEnablementCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceEnablementCustomEndpointFlag), ServerBackupCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverBackupCustomEndpointFlag), + ServerOsUpdateCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverOsUpdateCustomEndpointFlag), RunCommandCustomEndpoint: flags.FlagToBoolValue(p, cmd, runCommandCustomEndpointFlag), SKECustomEndpoint: flags.FlagToBoolValue(p, cmd, skeCustomEndpointFlag), SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 2bf703677..bc262c002 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -35,6 +35,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool secretsManagerCustomEndpointFlag: true, serviceAccountCustomEndpointFlag: true, serverBackupCustomEndpointFlag: true, + serverOsUpdateCustomEndpointFlag: true, runCommandCustomEndpointFlag: true, skeCustomEndpointFlag: true, sqlServerFlexCustomEndpointFlag: true, @@ -73,6 +74,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { SecretsManagerCustomEndpoint: true, ServiceAccountCustomEndpoint: true, ServerBackupCustomEndpoint: true, + ServerOsUpdateCustomEndpoint: true, RunCommandCustomEndpoint: true, SKECustomEndpoint: true, SQLServerFlexCustomEndpoint: true, @@ -127,6 +129,7 @@ func TestParseInput(t *testing.T) { model.SecretsManagerCustomEndpoint = false model.ServiceAccountCustomEndpoint = false model.ServerBackupCustomEndpoint = false + model.ServerOsUpdateCustomEndpoint = false model.RunCommandCustomEndpoint = false model.SKECustomEndpoint = false model.SQLServerFlexCustomEndpoint = false @@ -254,6 +257,16 @@ func TestParseInput(t *testing.T) { model.ServerBackupCustomEndpoint = false }), }, + { + description: "serverosupdate custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[serverOsUpdateCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.ServerOsUpdateCustomEndpoint = false + }), + }, { description: "runcommand custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index f72154d92..8de467877 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -39,6 +39,7 @@ const ( ServiceAccountCustomEndpointKey = "service_account_custom_endpoint" ServiceEnablementCustomEndpointKey = "service_enablement_custom_endpoint" ServerBackupCustomEndpointKey = "serverbackup_custom_endpoint" + ServerOsUpdateCustomEndpointKey = "serverosupdate_custom_endpoint" RunCommandCustomEndpointKey = "runcommand_custom_endpoint" SKECustomEndpointKey = "ske_custom_endpoint" SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" @@ -96,6 +97,7 @@ var ConfigKeys = []string{ ServiceAccountCustomEndpointKey, ServiceEnablementCustomEndpointKey, ServerBackupCustomEndpointKey, + ServerOsUpdateCustomEndpointKey, RunCommandCustomEndpointKey, SKECustomEndpointKey, SQLServerFlexCustomEndpointKey, @@ -178,6 +180,7 @@ func setConfigDefaults() { viper.SetDefault(ServiceAccountCustomEndpointKey, "") viper.SetDefault(ServiceEnablementCustomEndpointKey, "") viper.SetDefault(ServerBackupCustomEndpointKey, "") + viper.SetDefault(ServerOsUpdateCustomEndpointKey, "") viper.SetDefault(RunCommandCustomEndpointKey, "") viper.SetDefault(SKECustomEndpointKey, "") viper.SetDefault(SQLServerFlexCustomEndpointKey, "") diff --git a/internal/pkg/services/serverosupdate/client/client.go b/internal/pkg/services/serverosupdate/client/client.go new file mode 100644 index 000000000..8b46d6f1d --- /dev/null +++ b/internal/pkg/services/serverosupdate/client/client.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/spf13/viper" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" +) + +func ConfigureClient(p *print.Printer) (*serverupdate.APIClient, error) { + var err error + var apiClient *serverupdate.APIClient + var cfgOptions []sdkConfig.ConfigurationOption + + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return nil, &errors.AuthError{} + } + cfgOptions = append(cfgOptions, authCfgOption) + + customEndpoint := viper.GetString(config.ServerOsUpdateCustomEndpointKey) + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } else { + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err = serverupdate.NewAPIClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return nil, &errors.AuthError{} + } + + return apiClient, nil +} From 7f18fd6fb90cb7d2b6b74216d873c0f2961fc0d8 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 29 Jan 2025 09:09:11 +0100 Subject: [PATCH 159/619] fix(deps): update module github.com/lmittmann/tint to v1.0.7 (#575) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index cd2cec4dc..168a64f5a 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jedib0t/go-pretty/v6 v6.6.5 - github.com/lmittmann/tint v1.0.6 + github.com/lmittmann/tint v1.0.7 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 @@ -26,6 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.2.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1 @@ -49,7 +50,6 @@ require ( al.essio.dev/pkg/shellescape v1.5.1 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.2.3 // indirect github.com/x448/float16 v0.8.4 // indirect ) diff --git a/go.sum b/go.sum index a1f298913..3c60531f7 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lmittmann/tint v1.0.6 h1:vkkuDAZXc0EFGNzYjWcV0h7eEX+uujH48f/ifSkJWgc= -github.com/lmittmann/tint v1.0.6/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y= +github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= From d11ed2febf70d3b84bf26e27559cf757b7972ea9 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 30 Jan 2025 09:06:48 +0100 Subject: [PATCH 160/619] fix(deps): update module github.com/spf13/pflag to v1.0.6 (#577) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 168a64f5a..70babcc0c 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/lmittmann/tint v1.0.7 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.8.1 - github.com/spf13/pflag v1.0.5 + github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.19.0 github.com/stackitcloud/stackit-sdk-go/core v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.1 diff --git a/go.sum b/go.sum index 3c60531f7..c77019d09 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,9 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stackitcloud/stackit-sdk-go/core v0.15.1 h1:hIj/k/JXEuYmud3VWo3lr7Cfj2hfl4gG9nUIzcaZ9pM= From 6a42ca3afeeed0f981151118f4240f174c959650 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 30 Jan 2025 09:11:38 +0100 Subject: [PATCH 161/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/serverupdate to v0.3.0 (#578) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 70babcc0c..c663ea284 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.2.3 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1 diff --git a/go.sum b/go.sum index c77019d09..e294cc22a 100644 --- a/go.sum +++ b/go.sum @@ -154,8 +154,8 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 h1:qShB0O github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 h1:33zKhcNS1bZ2usGnYZ6YE6Vxm7c9U0aC8lDg96UN+e4= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0/go.mod h1:thrCIDBjEHAcihjWUOMJ5mbYVhOWfS/bLTBJ+yl5W4g= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.2.3 h1:+D7NWWP/FF1asAZhntwzaFaSnHExgwta7/k+mRGmzrQ= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.2.3/go.mod h1:etidTptNDvvCPA1FGC7T9DXHxXA4bYW3qIUzWG8wVcc= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.3.0 h1:x39lier26DANhGoo3Ko9Ta7ZeXwhW97fD6zPFX6xvNc= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.3.0/go.mod h1:m/lZ3XH3wdKkkFb6vHxi0MhhMdRL2uAuCATeYChh+s0= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= From 0a0e07d86cac588a60a49d18593391413acbf26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Thu, 30 Jan 2025 11:37:20 +0100 Subject: [PATCH 162/619] chore: add script to replace dependencies in a dummy go.work file (#576) * chore: add script to replace dependencies in a dummy go.work file * chore: use option to defined sdk directory --- .gitignore | 4 ++++ scripts/replace.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100755 scripts/replace.sh diff --git a/.gitignore b/.gitignore index 428e142ad..47aabc929 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ dist/ # OS generated files .DS_Store + +# Go workspace file +go.work +go.work.sum \ No newline at end of file diff --git a/scripts/replace.sh b/scripts/replace.sh new file mode 100755 index 000000000..0c37f4b85 --- /dev/null +++ b/scripts/replace.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Add replace directives to local files to go.work +set -eo pipefail + +while getopts "s:" option; do + case "${option}" in + s) + SDK_DIR=${OPTARG} + ;; + + *) + echo "call: $0 [-s sdk-dir] " + exit 0 + ;; + esac +done +shift $((OPTIND-1)) + +if [ -z "$SDK_DIR" ]; then + SDK_DIR=../stackit-sdk-generator/sdk-repo-updated + echo "No SDK_DIR set, using $SDK_DIR" +fi + + +if [ ! -f go.work ]; then + go work init + go work use . +else + echo "go.work already exists" +fi + +if [ $# -gt 0 ];then + # modules passed via commandline + for service in $*; do + if [ ! -d $SDK_DIR/services/$service ]; then + echo "service directory $SDK_DIR/services/$service does not exist" + exit 1 + fi + echo "replacing selected service $service" + if [ "$service" = "core" ]; then + go work edit -replace github.com/stackitcloud/stackit-sdk-go/core=$SDK_DIR/core + else + go work edit -replace github.com/stackitcloud/stackit-sdk-go/services/$service=$SDK_DIR/services/$service + fi + done +else + # replace all modules + echo "replacing all services" + go work edit -replace github.com/stackitcloud/stackit-sdk-go/core=$SDK_DIR/core + for n in $(find ${SDK_DIR}/services -name go.mod);do + service=$(dirname $n) + service=${service#${SDK_DIR}/services/} + go work edit -replace github.com/stackitcloud/stackit-sdk-go/services/$service=$(dirname $n) + done +fi +go work edit -fmt +go work sync From f663e9d8197d69396770766e83d69692459a782e Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 31 Jan 2025 10:03:38 +0100 Subject: [PATCH 163/619] Onboard server machine-types command (#579) Signed-off-by: Alexander Dahmen --- docs/stackit_beta_server.md | 1 + docs/stackit_beta_server_machine-type.md | 35 +++ ...ackit_beta_server_machine-type_describe.md | 43 ++++ docs/stackit_beta_server_machine-type_list.md | 47 ++++ .../server/machine-type/describe/describe.go | 140 ++++++++++++ .../machine-type/describe/describe_test.go | 206 ++++++++++++++++++ .../cmd/beta/server/machine-type/list/list.go | 171 +++++++++++++++ .../server/machine-type/list/list_test.go | 190 ++++++++++++++++ .../beta/server/machine-type/machine-type.go | 28 +++ internal/cmd/beta/server/server.go | 2 + .../performance-class/describe/describe.go | 17 +- 11 files changed, 877 insertions(+), 3 deletions(-) create mode 100644 docs/stackit_beta_server_machine-type.md create mode 100644 docs/stackit_beta_server_machine-type_describe.md create mode 100644 docs/stackit_beta_server_machine-type_list.md create mode 100644 internal/cmd/beta/server/machine-type/describe/describe.go create mode 100644 internal/cmd/beta/server/machine-type/describe/describe_test.go create mode 100644 internal/cmd/beta/server/machine-type/list/list.go create mode 100644 internal/cmd/beta/server/machine-type/list/list_test.go create mode 100644 internal/cmd/beta/server/machine-type/machine-type.go diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md index a56612e08..8846ca99c 100644 --- a/docs/stackit_beta_server.md +++ b/docs/stackit_beta_server.md @@ -39,6 +39,7 @@ stackit beta server [flags] * [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server * [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project * [stackit beta server log](./stackit_beta_server_log.md) - Gets server console log +* [stackit beta server machine-type](./stackit_beta_server_machine-type.md) - Provides functionality for server machine types available inside a project * [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers * [stackit beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates * [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers diff --git a/docs/stackit_beta_server_machine-type.md b/docs/stackit_beta_server_machine-type.md new file mode 100644 index 000000000..406ff1176 --- /dev/null +++ b/docs/stackit_beta_server_machine-type.md @@ -0,0 +1,35 @@ +## stackit beta server machine-type + +Provides functionality for server machine types available inside a project + +### Synopsis + +Provides functionality for server machine types available inside a project. + +``` +stackit beta server machine-type [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta server machine-type" +``` + +### 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 beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit beta server machine-type describe](./stackit_beta_server_machine-type_describe.md) - Shows details of a server machine type +* [stackit beta server machine-type list](./stackit_beta_server_machine-type_list.md) - Get list of all machine types available in a project + diff --git a/docs/stackit_beta_server_machine-type_describe.md b/docs/stackit_beta_server_machine-type_describe.md new file mode 100644 index 000000000..81519354a --- /dev/null +++ b/docs/stackit_beta_server_machine-type_describe.md @@ -0,0 +1,43 @@ +## stackit beta server machine-type describe + +Shows details of a server machine type + +### Synopsis + +Shows details of a server machine type. + +``` +stackit beta server machine-type describe MACHINE_TYPE [flags] +``` + +### Examples + +``` + Show details of a server machine type with name "xxx" + $ stackit beta server machine-type describe xxx + + Show details of a server machine type with name "xxx" in JSON format + $ stackit beta server machine-type describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta server machine-type 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 beta server machine-type](./stackit_beta_server_machine-type.md) - Provides functionality for server machine types available inside a project + diff --git a/docs/stackit_beta_server_machine-type_list.md b/docs/stackit_beta_server_machine-type_list.md new file mode 100644 index 000000000..3a10a8be5 --- /dev/null +++ b/docs/stackit_beta_server_machine-type_list.md @@ -0,0 +1,47 @@ +## stackit beta server machine-type list + +Get list of all machine types available in a project + +### Synopsis + +Get list of all machine types available in a project. + +``` +stackit beta server machine-type list [flags] +``` + +### Examples + +``` + Get list of all machine types + $ stackit beta server machine-type list + + Get list of all machine types in JSON format + $ stackit beta server machine-type list --output-format json + + List the first 10 machine types + $ stackit beta server machine-type list --limit=10 +``` + +### Options + +``` + -h, --help Help for "stackit beta server machine-type list" + --limit int Limit the output to the first n elements +``` + +### 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 beta server machine-type](./stackit_beta_server_machine-type.md) - Provides functionality for server machine types available inside a project + diff --git a/internal/cmd/beta/server/machine-type/describe/describe.go b/internal/cmd/beta/server/machine-type/describe/describe.go new file mode 100644 index 000000000..4caf15d8b --- /dev/null +++ b/internal/cmd/beta/server/machine-type/describe/describe.go @@ -0,0 +1,140 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + + "github.com/spf13/cobra" +) + +const ( + machineTypeArg = "MACHINE_TYPE" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + MachineType string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", machineTypeArg), + Short: "Shows details of a server machine type", + Long: "Shows details of a server machine type.", + Args: args.SingleArg(machineTypeArg, nil), + Example: examples.Build( + examples.NewExample( + `Show details of a server machine type with name "xxx"`, + "$ stackit beta server machine-type describe xxx", + ), + examples.NewExample( + `Show details of a server machine type with name "xxx" in JSON format`, + "$ stackit beta server machine-type describe xxx --output-format json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read server machine type: %w", err) + } + + return outputResult(p, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + machineType := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + MachineType: machineType, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetMachineTypeRequest { + return apiClient.GetMachineType(ctx, model.ProjectId, model.MachineType) +} + +func outputResult(p *print.Printer, outputFormat string, machineType *iaas.MachineType) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(machineType, "", " ") + if err != nil { + return fmt.Errorf("marshal server machine type: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(machineType, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal server machine type: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("NAME", utils.PtrString(machineType.Name)) + table.AddSeparator() + table.AddRow("VCPUS", utils.PtrString(machineType.Vcpus)) + table.AddSeparator() + table.AddRow("RAM (in MB)", utils.PtrString(machineType.Ram)) + table.AddSeparator() + table.AddRow("DISK SIZE (in GB)", utils.PtrString(machineType.Disk)) + table.AddSeparator() + table.AddRow("DESCRIPTION", utils.PtrString(machineType.Description)) + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/internal/cmd/beta/server/machine-type/describe/describe_test.go b/internal/cmd/beta/server/machine-type/describe/describe_test.go new file mode 100644 index 000000000..44c5bcb78 --- /dev/null +++ b/internal/cmd/beta/server/machine-type/describe/describe_test.go @@ -0,0 +1,206 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() +var testMachineType = "t1.1" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testMachineType, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + MachineType: testMachineType, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetMachineTypeRequest)) iaas.ApiGetMachineTypeRequest { + request := testClient.GetMachineType(testCtx, testProjectId, testMachineType) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "missing machine type arg", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetMachineTypeRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/machine-type/list/list.go b/internal/cmd/beta/server/machine-type/list/list.go new file mode 100644 index 000000000..db378a1e7 --- /dev/null +++ b/internal/cmd/beta/server/machine-type/list/list.go @@ -0,0 +1,171 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +const ( + limitFlag = "limit" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Get list of all machine types available in a project", + Long: "Get list of all machine types available in a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Get list of all machine types`, + "$ stackit beta server machine-type list", + ), + examples.NewExample( + `Get list of all machine types in JSON format`, + "$ stackit beta server machine-type list --output-format json", + ), + examples.NewExample( + `List the first 10 machine types`, + `$ stackit beta server machine-type list --limit=10`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read machine-types: %w", err) + } + + if resp.Items == nil || len(*resp.Items) == 0 { + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + p.Info("No machine-types found for project %q\n", projectLabel) + return nil + } + + // limit output + if model.Limit != nil && len(*resp.Items) > int(*model.Limit) { + *resp.Items = (*resp.Items)[:*model.Limit] + } + + return outputResult(p, model, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListMachineTypesRequest { + return apiClient.ListMachineTypes(ctx, model.ProjectId) +} + +func outputResult(p *print.Printer, model *inputModel, machineTypes *iaas.MachineTypeListResponse) error { + outputFormat := model.OutputFormat + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(machineTypes, "", " ") + if err != nil { + return fmt.Errorf("marshal machineTypes: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(machineTypes, yaml.IndentSequence(true)) + if err != nil { + return fmt.Errorf("marshal machineTypes: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetTitle("Machine-Types") + + table.SetHeader("NAME", "DESCRIPTION") + for _, machineType := range *machineTypes.GetItems() { + table.AddRow(*machineType.Name, utils.PtrString(machineType.Description)) + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/server/machine-type/list/list_test.go b/internal/cmd/beta/server/machine-type/list/list_test.go new file mode 100644 index 000000000..a76fcf00b --- /dev/null +++ b/internal/cmd/beta/server/machine-type/list/list_test.go @@ -0,0 +1,190 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} +var testProjectId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + limitFlag: "10", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListMachineTypesRequest)) iaas.ApiListMachineTypesRequest { + request := testClient.ListMachineTypes(testCtx, testProjectId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListMachineTypesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/server/machine-type/machine-type.go b/internal/cmd/beta/server/machine-type/machine-type.go new file mode 100644 index 000000000..8878cc29f --- /dev/null +++ b/internal/cmd/beta/server/machine-type/machine-type.go @@ -0,0 +1,28 @@ +package machinetype + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/machine-type/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/machine-type/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "machine-type", + Short: "Provides functionality for server machine types available inside a project", + Long: "Provides functionality for server machine types available inside a project.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go index ef8922220..888ed703a 100644 --- a/internal/cmd/beta/server/server.go +++ b/internal/cmd/beta/server/server.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/log" + machinetype "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/machine-type" networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface" osUpdate "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" @@ -64,4 +65,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(rescue.NewCmd(p)) cmd.AddCommand(unrescue.NewCmd(p)) cmd.AddCommand(osUpdate.NewCmd(p)) + cmd.AddCommand(machinetype.NewCmd(p)) } diff --git a/internal/cmd/beta/volume/performance-class/describe/describe.go b/internal/cmd/beta/volume/performance-class/describe/describe.go index fa9625853..4864f25c5 100644 --- a/internal/cmd/beta/volume/performance-class/describe/describe.go +++ b/internal/cmd/beta/volume/performance-class/describe/describe.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/goccy/go-yaml" @@ -14,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/cobra" @@ -121,13 +123,22 @@ func outputResult(p *print.Printer, outputFormat string, performanceClass *iaas. table := tables.NewTable() table.AddRow("NAME", *performanceClass.Name) table.AddSeparator() - table.AddRow("DESCRIPTION", *performanceClass.Description) + table.AddRow("DESCRIPTION", utils.PtrString(performanceClass.Description)) table.AddSeparator() - table.AddRow("IOPS", *performanceClass.Iops) + table.AddRow("IOPS", utils.PtrString(performanceClass.Iops)) table.AddSeparator() - table.AddRow("THROUGHPUT", *performanceClass.Throughput) + table.AddRow("THROUGHPUT", utils.PtrString(performanceClass.Throughput)) table.AddSeparator() + if performanceClass.Labels != nil && len(*performanceClass.Labels) > 0 { + labels := []string{} + for key, value := range *performanceClass.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } + err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) From 5c5f3b843dac8e1591584fdbaffd7b71fb2d06f2 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 3 Feb 2025 08:04:38 +0100 Subject: [PATCH 164/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.16 (#581) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c663ea284..3b692a723 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.15 + github.com/goccy/go-yaml v1.15.16 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index e294cc22a..947c7a15a 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.15 h1:5turdzAlutS2Q7/QR/9R99Z1K0J00qDb4T0pHJcZ5ew= -github.com/goccy/go-yaml v1.15.15/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.16 h1:PMTVcGI9uNPIn7KLs0H7KC1rE+51yPl5YNh4i8rGuRA= +github.com/goccy/go-yaml v1.15.16/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From fd12918c6bf2b1d018953a3745ef93ae5faaa432 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 3 Feb 2025 08:05:38 +0100 Subject: [PATCH 165/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/resourcemanager to v0.12.0 (#582) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3b692a723..a814f668f 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 diff --git a/go.sum b/go.sum index 947c7a15a..8b0f2e101 100644 --- a/go.sum +++ b/go.sum @@ -146,8 +146,8 @@ github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1 h1:6XfGxsPFqci/ github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1/go.mod h1:42oYZOqin+rIUrUqgtCIE4wzCWWY30H4UFhzvo1Wg2w= github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1 h1:/EVm0bD9a3KCk9aj/v2ivJIURlGsTr4O2OwMQ4ey3e4= github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1/go.mod h1:YJdkyuY7aK/clfE3lQDz7O369JLPcg0FO4yfCIPNUNE= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1 h1:bICGCqRsGEzqidVCgQIH3hxB+SX1vJapZgrSP5nhvBo= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.11.1/go.mod h1:9Om4A5FI/wXZE/8zu5wF8eRBb70VddyPfnj/nlYXHX0= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.12.0 h1:uYWg/wovldLquCsHsdJUWyUF3Z1Yz4rR64WPfcfudmg= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.12.0/go.mod h1:hLc1YDjcwnkkQntTMQ5pk1ZQyX6cuBZoaEe4lr8sppI= github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 h1:qAKT20siGhkIIg4gY0JBPD7TU+I/6UieYcivGU7hVKc= github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1/go.mod h1:LgCIIj7jA2lWX4DI3bxUYD+m0TbWCr1VgAyBYNJeghc= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 h1:qShB0OuNR8EOffY36/DfJs/Yk12syy38xkE88Z15f4k= From 28f7db3905d18f18bcfbb498ec6a045a2437000a Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:03:25 +0100 Subject: [PATCH 166/619] feat: Support dns TXT records with more than 255 characters (#580) * add support for updating DNS TXT records with values > 255 characters * fix: review feedback - create new function which formats the dns records - add test cases - moved the formatting of txt records - in create command to parseInput - in update to separate function --- internal/cmd/dns/record-set/create/create.go | 18 ++- .../cmd/dns/record-set/create/create_test.go | 31 ++++- internal/cmd/dns/record-set/update/update.go | 36 +++++ .../cmd/dns/record-set/update/update_test.go | 77 ++++++++++- internal/pkg/services/dns/utils/utils.go | 36 +++++ internal/pkg/services/dns/utils/utils_test.go | 124 +++++++++++++++++- 6 files changed, 314 insertions(+), 8 deletions(-) diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 36c065d1c..ed77e5735 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -16,8 +17,6 @@ import ( dnsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/dns/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/dns" "github.com/stackitcloud/stackit-sdk-go/services/dns/wait" ) @@ -31,6 +30,7 @@ const ( typeFlag = "type" defaultType = "A" + txtType = "TXT" ) type inputModel struct { @@ -137,6 +137,20 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Type: flags.FlagWithDefaultToStringValue(p, cmd, typeFlag), } + if model.Type == txtType { + for idx := range model.Records { + // Based on RFC 1035 section 2.3.4, TXT Records are limited to 255 Characters + // Longer strings need to be split into multiple records + if len(model.Records[idx]) > 255 { + var err error + model.Records[idx], err = dnsUtils.FormatTxtRecord(model.Records[idx]) + if err != nil { + return nil, err + } + } + } + } + if p.IsVerbosityDebug() { modelStr, err := print.BuildDebugStrFromInputModel(model) if err != nil { diff --git a/internal/cmd/dns/record-set/create/create_test.go b/internal/cmd/dns/record-set/create/create_test.go index 79044ecde..f1841d7bb 100644 --- a/internal/cmd/dns/record-set/create/create_test.go +++ b/internal/cmd/dns/record-set/create/create_test.go @@ -2,6 +2,8 @@ package create import ( "context" + "fmt" + "strings" "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -23,6 +25,12 @@ var testClient = &dns.APIClient{} var testProjectId = uuid.NewString() var testZoneId = uuid.NewString() +var recordTxtOver255Char = []string{ + "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo", + "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo", + "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar", +} + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, @@ -76,7 +84,7 @@ func fixtureRequest(mods ...func(request *dns.ApiCreateRecordSetRequest)) dns.Ap } func TestParseInput(t *testing.T) { - tests := []struct { + var tests = []struct { description string flagValues map[string]string recordFlagValues []string @@ -236,8 +244,27 @@ func TestParseInput(t *testing.T) { model.Records = append(model.Records, "1.2.3.4", "5.6.7.8") }), }, - } + { + description: "TXT record with > 255 characters", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[typeFlag] = txtType + flagValues[recordFlag] = strings.Join(recordTxtOver255Char, "") + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + var content string + for idx, val := range recordTxtOver255Char { + content += fmt.Sprintf("%q", val) + if idx != len(recordTxtOver255Char)-1 { + content += " " + } + } + model.Records = []string{content} + model.Type = txtType + }), + }, + } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() diff --git a/internal/cmd/dns/record-set/update/update.go b/internal/cmd/dns/record-set/update/update.go index 77a054a14..2b3d258aa 100644 --- a/internal/cmd/dns/record-set/update/update.go +++ b/internal/cmd/dns/record-set/update/update.go @@ -28,6 +28,7 @@ const ( nameFlag = "name" recordFlag = "record" ttlFlag = "ttl" + txtType = "TXT" ) type inputModel struct { @@ -38,6 +39,7 @@ type inputModel struct { Name *string Records *[]string TTL *int64 + Type *string } func NewCmd(p *print.Printer) *cobra.Command { @@ -76,6 +78,19 @@ func NewCmd(p *print.Printer) *cobra.Command { recordSetLabel = model.RecordSetId } + typeLabel, err := dnsUtils.GetRecordSetType(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId) + if err != nil { + p.Debug(print.ErrorLevel, "get record set type: %v", err) + } + model.Type = typeLabel + + if utils.PtrString(model.Type) == txtType { + err = parseTxtRecord(model.Records) + if err != nil { + return err + } + } + if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update record set %s of zone %s?", recordSetLabel, zoneLabel) err = p.PromptForConfirmation(prompt) @@ -165,6 +180,27 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } +func parseTxtRecord(records *[]string) error { + if records == nil { + return nil + } + if len(*records) == 0 { + return nil + } + + for idx := range *records { + var err error + // Based on RFC 1035 section 2.3.4, TXT Records are limited to 255 Characters. + // Longer strings need to be split into multiple records + (*records)[idx], err = dnsUtils.FormatTxtRecord((*records)[idx]) + if err != nil { + return err + } + } + + return nil +} + func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClient) dns.ApiPartialUpdateRecordSetRequest { var records *[]dns.RecordPayload = nil if model.Records != nil { diff --git a/internal/cmd/dns/record-set/update/update_test.go b/internal/cmd/dns/record-set/update/update_test.go index 19e544a76..9b07ffabb 100644 --- a/internal/cmd/dns/record-set/update/update_test.go +++ b/internal/cmd/dns/record-set/update/update_test.go @@ -24,6 +24,13 @@ var testProjectId = uuid.NewString() var testZoneId = uuid.NewString() var testRecordSetId = uuid.NewString() +var ( + text255Characters = "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo" + text256Characters = "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoob" + result256Characters = "\"foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo\" \"b\"" + text4050Characters = "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo" +) + func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testRecordSetId, @@ -78,10 +85,11 @@ func fixtureRequest(mods ...func(request *dns.ApiPartialUpdateRecordSetRequest)) }, Ttl: utils.Ptr(int64(3600)), }) + req := &request for _, mod := range mods { - mod(&request) + mod(req) } - return request + return *req } func TestParseInput(t *testing.T) { @@ -306,6 +314,71 @@ func TestParseInput(t *testing.T) { } } +func TestParseTxtRecord(t *testing.T) { + tests := []struct { + description string + records *[]string + expectedResult *[]string + isValid bool + shouldErr bool + }{ + { + description: "empty", + records: nil, + expectedResult: nil, + isValid: true, + }, + { + description: "base", + records: &[]string{"foobar"}, + expectedResult: &[]string{"foobar"}, + isValid: true, + }, + { + description: "input has length of 255 characters and should not split", + records: &[]string{text255Characters}, + expectedResult: &[]string{text255Characters}, + isValid: true, + }, + { + description: "input has length 256 characters and should split", + records: &[]string{text256Characters}, + expectedResult: &[]string{result256Characters}, + isValid: true, + }, + { + description: "input has length 4050 characters and should fail", + records: &[]string{text4050Characters}, + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := parseTxtRecord(tt.records) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("should not fail but got error: %v", err) + return + } + if err == nil && !tt.isValid { + t.Fatalf("should fail but got none") + return + } + + if !tt.isValid { + t.Fatalf("should fail but got none") + return + } + diff := cmp.Diff(tt.expectedResult, tt.records) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + func TestBuildRequest(t *testing.T) { tests := []struct { description string diff --git a/internal/pkg/services/dns/utils/utils.go b/internal/pkg/services/dns/utils/utils.go index da57eb96c..351cf2e47 100644 --- a/internal/pkg/services/dns/utils/utils.go +++ b/internal/pkg/services/dns/utils/utils.go @@ -3,7 +3,9 @@ package utils import ( "context" "fmt" + "math" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -27,3 +29,37 @@ func GetRecordSetName(ctx context.Context, apiClient DNSClient, projectId, zoneI } return *resp.Rrset.Name, nil } + +func GetRecordSetType(ctx context.Context, apiClient DNSClient, projectId, zoneId, recordSetId string) (*string, error) { + resp, err := apiClient.GetRecordSetExecute(ctx, projectId, zoneId, recordSetId) + if err != nil { + return utils.Ptr(""), fmt.Errorf("get DNS recordset: %w", err) + } + return resp.Rrset.Type, nil +} + +func FormatTxtRecord(input string) (string, error) { + length := float64(len(input)) + if length <= 255 { + return input, nil + } + // Max length with quotes and white spaces is 4096. Without the quotes and white spaces the max length is 4049 + if length > 4049 { + return "", fmt.Errorf("max input length is 4049. The length of the input is %v", length) + } + + result := "" + chunks := int(math.Ceil(length / 255)) + for i := range chunks { + skip := 255 * i + if i == chunks-1 { + // Append the left record content + result += fmt.Sprintf("%q", input[0+skip:]) + } else { + // Add 255 characters of the record data quoted to the result + result += fmt.Sprintf("%q ", input[0+skip:255+skip]) + } + } + + return result, nil +} diff --git a/internal/pkg/services/dns/utils/utils_test.go b/internal/pkg/services/dns/utils/utils_test.go index 2c972218c..12cae8fdc 100644 --- a/internal/pkg/services/dns/utils/utils_test.go +++ b/internal/pkg/services/dns/utils/utils_test.go @@ -5,9 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -15,11 +14,17 @@ var ( testProjectId = uuid.NewString() testZoneId = uuid.NewString() testRecordSetId = uuid.NewString() + + text255Characters = "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo" + text256Characters = "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoob" + result256Characters = "\"foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo\" \"b\"" + text4050Characters = "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoofoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo" ) const ( testZoneName = "zone" testRecordSetName = "record-set" + testRecordSetType = "A" ) type dnsClientMocked struct { @@ -142,3 +147,118 @@ func TestGetRecordSetName(t *testing.T) { }) } } + +func TestGetRecordSetType(t *testing.T) { + tests := []struct { + description string + getRecordSetFails bool + getRecordSetResp *dns.RecordSetResponse + isValid bool + expectedOutput string + }{ + { + description: "base", + getRecordSetResp: &dns.RecordSetResponse{ + Rrset: &dns.RecordSet{ + Name: utils.Ptr(testRecordSetType), + }, + }, + isValid: true, + expectedOutput: testRecordSetType, + }, + { + description: "get record set fails", + getRecordSetFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &dnsClientMocked{ + getRecordSetFails: tt.getRecordSetFails, + getRecordSetResp: tt.getRecordSetResp, + } + + output, err := GetRecordSetName(context.Background(), client, testProjectId, testZoneId, testRecordSetId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %s, got %s", tt.expectedOutput, output) + } + }) + } +} + +func TestFormatTxtRecord(t *testing.T) { + tests := []struct { + description string + input string + expected string + isValid bool + }{ + { + description: "base", + input: "foobar", + expected: "foobar", + isValid: true, + }, + { + description: "empty", + input: "", + expected: "", + isValid: true, + }, + { + description: "255 characters", + input: text255Characters, + expected: text255Characters, + isValid: true, + }, + { + description: "256 characters", + input: text256Characters, + expected: result256Characters, + isValid: true, + }, + { + description: "> 4049 characters should throw error", + input: text4050Characters, + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + result, err := FormatTxtRecord(tt.input) + + if err != nil { + if !tt.isValid { + return + } + t.Errorf("failed on valid input, got %v", err) + return + } + + if err == nil && !tt.isValid { + t.Errorf("did not fail on invalid input") + return + } + + if !tt.isValid { + t.Errorf("did not fail on invalid input") + return + } + if result != tt.expected { + t.Errorf("expected result to be %s, got %s", tt.expected, result) + } + }) + } +} From a2ccc0c72d4c4d6dc63c059a0dd43761e257201f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 4 Feb 2025 08:01:27 +0100 Subject: [PATCH 167/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.17 (#584) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a814f668f..9eb395224 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.16 + github.com/goccy/go-yaml v1.15.17 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 8b0f2e101..ee4a6662c 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.16 h1:PMTVcGI9uNPIn7KLs0H7KC1rE+51yPl5YNh4i8rGuRA= -github.com/goccy/go-yaml v1.15.16/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.17 h1:dK4FbbTTEOZTLH/NW3/xBqg0JdC14YKVmYwS9GT3H60= +github.com/goccy/go-yaml v1.15.17/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 84bed8699e6efc20eea7389acdfa38eceab67f9d Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Tue, 4 Feb 2025 14:22:32 +0100 Subject: [PATCH 168/619] Fix network-interface output (#585) If no interfaces are attached to the network display the name in the message Signed-off-by: Alexander Dahmen --- internal/cmd/beta/network-interface/list/list.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/cmd/beta/network-interface/list/list.go b/internal/cmd/beta/network-interface/list/list.go index fc8b4a8c5..4fe9005ef 100644 --- a/internal/cmd/beta/network-interface/list/list.go +++ b/internal/cmd/beta/network-interface/list/list.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -77,7 +78,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - p.Info("No network interfaces found for network %d\n", model.NetworkId) + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) + if err != nil { + p.Debug(print.ErrorLevel, "get network name: %v", err) + networkLabel = *model.NetworkId + } + p.Info("No network interfaces found for network %q\n", networkLabel) return nil } From 7308df8df859e90bedffc00cdd2f2568af25ffc3 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 5 Feb 2025 08:53:21 +0100 Subject: [PATCH 169/619] fix(deps): update module golang.org/x/mod to v0.23.0 (#586) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9eb395224..5f63f57ae 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.22.0 + golang.org/x/mod v0.23.0 golang.org/x/oauth2 v0.25.0 golang.org/x/term v0.28.0 golang.org/x/text v0.21.0 diff --git a/go.sum b/go.sum index ee4a6662c..902ee2ba7 100644 --- a/go.sum +++ b/go.sum @@ -192,8 +192,8 @@ golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRj golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From b7a1f394e63aea6107bec36c80b112efdf5b8ed7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 5 Feb 2025 09:12:37 +0100 Subject: [PATCH 170/619] fix(deps): update module golang.org/x/oauth2 to v0.26.0 (#587) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5f63f57ae..ef92a179b 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.23.0 - golang.org/x/oauth2 v0.25.0 + golang.org/x/oauth2 v0.26.0 golang.org/x/term v0.28.0 golang.org/x/text v0.21.0 k8s.io/apimachinery v0.31.3 diff --git a/go.sum b/go.sum index 902ee2ba7..5e1f82534 100644 --- a/go.sum +++ b/go.sum @@ -200,8 +200,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= +golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 7aabd4d60978310777226b76411dbaf7db1746d6 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 5 Feb 2025 09:24:59 +0100 Subject: [PATCH 171/619] fix(deps): update module golang.org/x/term to v0.29.0 (#588) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ef92a179b..434e2eaaa 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.23.0 golang.org/x/oauth2 v0.26.0 - golang.org/x/term v0.28.0 + golang.org/x/term v0.29.0 golang.org/x/text v0.21.0 k8s.io/apimachinery v0.31.3 k8s.io/client-go v0.31.3 @@ -89,7 +89,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/sys v0.29.0 // indirect + golang.org/x/sys v0.30.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 5e1f82534..90cfbd1c1 100644 --- a/go.sum +++ b/go.sum @@ -209,10 +209,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= From d64356ae6d6d271db10436cf8b65af0f667933d5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 5 Feb 2025 09:33:26 +0100 Subject: [PATCH 172/619] fix(deps): update module golang.org/x/text to v0.22.0 (#589) Co-authored-by: Renovate Bot Co-authored-by: Marcel Jacek <72880145+marceljk@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 434e2eaaa..f8cb222d3 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( golang.org/x/mod v0.23.0 golang.org/x/oauth2 v0.26.0 golang.org/x/term v0.29.0 - golang.org/x/text v0.21.0 + golang.org/x/text v0.22.0 k8s.io/apimachinery v0.31.3 k8s.io/client-go v0.31.3 ) diff --git a/go.sum b/go.sum index 90cfbd1c1..0e0165794 100644 --- a/go.sum +++ b/go.sum @@ -215,8 +215,8 @@ golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 3a4bf87c5113e9b56eb111496a7736268e89e6d7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 6 Feb 2025 07:23:22 +0100 Subject: [PATCH 173/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/serverupdate to v0.4.0 (#590) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f8cb222d3..c00bae78b 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1 diff --git a/go.sum b/go.sum index 0e0165794..75b404731 100644 --- a/go.sum +++ b/go.sum @@ -154,8 +154,8 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 h1:qShB0O github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 h1:33zKhcNS1bZ2usGnYZ6YE6Vxm7c9U0aC8lDg96UN+e4= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0/go.mod h1:thrCIDBjEHAcihjWUOMJ5mbYVhOWfS/bLTBJ+yl5W4g= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.3.0 h1:x39lier26DANhGoo3Ko9Ta7ZeXwhW97fD6zPFX6xvNc= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.3.0/go.mod h1:m/lZ3XH3wdKkkFb6vHxi0MhhMdRL2uAuCATeYChh+s0= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.4.0 h1:kHzmcwSs1vgwSHIjgRlDoavKyzByOxSEUJ1XfYZvqn4= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.4.0/go.mod h1:m/lZ3XH3wdKkkFb6vHxi0MhhMdRL2uAuCATeYChh+s0= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= From 1d85aa43269839974c357aedc99672eb312c7fb1 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:32:26 +0100 Subject: [PATCH 174/619] fix: Add nil checks for values which are printed to the console (#583) * add nil checks and wrap output of pointers with utils.PtrString() * fix: linter issues * Add tests cases for outputResult * implement review feedback --- internal/cmd/beta/image/create/create.go | 2 +- internal/cmd/beta/key-pair/create/create.go | 15 ++++-- .../cmd/beta/key-pair/create/create_test.go | 39 +++++++++++++++ .../cmd/beta/key-pair/describe/describe.go | 26 ++++++---- .../beta/key-pair/describe/describe_test.go | 32 +++++++++++++ internal/cmd/beta/key-pair/list/list.go | 16 +++++-- internal/cmd/beta/key-pair/list/list_test.go | 34 +++++++++++++ internal/cmd/beta/key-pair/update/update.go | 26 +++++----- .../cmd/beta/key-pair/update/update_test.go | 45 +++++++++++++---- .../cmd/beta/network-area/create/create.go | 2 +- .../beta/network-area/describe/describe.go | 48 ++++++++++--------- internal/cmd/beta/network-area/list/list.go | 19 ++++++-- .../network-range/create/create.go | 9 ++-- .../network-range/describe/describe.go | 4 +- .../beta/network-area/route/create/create.go | 2 +- .../network-area/route/describe/describe.go | 6 +-- .../cmd/beta/network-area/route/list/list.go | 10 ++-- .../beta/network-area/route/update/update.go | 2 +- .../beta/network-interface/create/create.go | 2 +- .../network-interface/describe/describe.go | 8 ++-- .../cmd/beta/network-interface/list/list.go | 16 ++++--- .../cmd/beta/network/describe/describe.go | 6 +-- internal/cmd/beta/network/list/list.go | 18 ++++--- .../cmd/beta/public-ip/associate/associate.go | 2 +- internal/cmd/beta/public-ip/create/create.go | 2 +- .../cmd/beta/public-ip/describe/describe.go | 4 +- internal/cmd/beta/public-ip/list/list.go | 12 +++-- .../beta/security-group/rule/create/create.go | 3 +- .../security-group/rule/describe/describe.go | 4 +- .../cmd/beta/security-group/rule/list/list.go | 5 +- .../cmd/beta/server/backup/create/create.go | 3 +- .../beta/server/backup/describe/describe.go | 17 +++---- internal/cmd/beta/server/backup/list/list.go | 21 ++++---- .../server/backup/schedule/create/create.go | 3 +- .../backup/schedule/describe/describe.go | 16 +++---- .../beta/server/backup/schedule/list/list.go | 25 +++++++--- .../server/backup/schedule/update/update.go | 3 +- .../cmd/beta/server/command/create/create.go | 6 +-- .../beta/server/command/describe/describe.go | 22 ++++----- internal/cmd/beta/server/command/list/list.go | 14 ++++-- .../command/template/describe/describe.go | 16 ++++--- .../beta/server/command/template/list/list.go | 18 +++++-- internal/cmd/beta/server/console/console.go | 3 ++ internal/cmd/beta/server/create/create.go | 2 +- internal/cmd/beta/server/describe/describe.go | 10 ++-- .../server/network-interface/attach/attach.go | 3 +- .../server/network-interface/detach/detach.go | 3 +- .../server/network-interface/list/list.go | 6 +-- .../beta/server/os-update/create/create.go | 3 +- .../server/os-update/describe/describe.go | 31 +++++------- .../cmd/beta/server/os-update/list/list.go | 22 +++++---- .../os-update/schedule/create/create.go | 3 +- .../os-update/schedule/describe/describe.go | 14 +++--- .../server/os-update/schedule/list/list.go | 13 +++-- .../os-update/schedule/update/update.go | 6 +-- internal/cmd/beta/server/rescue/rescue.go | 2 +- .../beta/server/volume/describe/describe.go | 4 +- internal/cmd/beta/server/volume/list/list.go | 7 ++- .../database/describe/describe.go | 8 ++-- .../beta/sqlserverflex/database/list/list.go | 6 +-- .../sqlserverflex/instance/create/create.go | 2 +- .../instance/describe/describe.go | 25 +++++----- .../beta/sqlserverflex/instance/list/list.go | 10 ++-- .../beta/sqlserverflex/user/create/create.go | 7 +-- .../sqlserverflex/user/describe/describe.go | 5 +- .../cmd/beta/sqlserverflex/user/list/list.go | 9 ++-- .../user/reset-password/reset_password.go | 5 +- internal/cmd/beta/volume/create/create.go | 2 +- internal/cmd/beta/volume/describe/describe.go | 12 ++--- internal/cmd/beta/volume/list/list.go | 17 ++++--- .../performance-class/describe/describe.go | 2 +- .../volume/performance-class/list/list.go | 3 +- internal/cmd/dns/record-set/create/create.go | 2 +- .../cmd/dns/record-set/describe/describe.go | 10 ++-- internal/cmd/dns/record-set/list/list.go | 13 +++-- internal/cmd/dns/zone/clone/clone.go | 2 +- internal/cmd/dns/zone/create/create.go | 3 +- internal/cmd/dns/zone/describe/describe.go | 30 ++++++------ internal/cmd/dns/zone/list/list.go | 9 +++- internal/cmd/load-balancer/create/create.go | 12 ++--- .../cmd/load-balancer/describe/describe.go | 21 ++++---- internal/cmd/load-balancer/list/list.go | 14 ++++-- .../observability-credentials/add/add.go | 2 +- .../describe/describe.go | 12 +++-- .../observability-credentials/list/list.go | 16 +++---- .../target-pool/describe/describe.go | 16 ++++--- .../cmd/logme/credentials/create/create.go | 25 +++++----- .../logme/credentials/describe/describe.go | 19 ++++---- internal/cmd/logme/credentials/list/list.go | 3 +- internal/cmd/logme/instance/create/create.go | 2 +- .../cmd/logme/instance/describe/describe.go | 10 ++-- internal/cmd/logme/instance/list/list.go | 11 +++-- internal/cmd/logme/plans/plans.go | 12 +++-- .../cmd/mariadb/credentials/create/create.go | 25 +++++----- .../mariadb/credentials/describe/describe.go | 13 ++--- internal/cmd/mariadb/credentials/list/list.go | 6 +-- .../cmd/mariadb/instance/create/create.go | 2 +- .../cmd/mariadb/instance/describe/describe.go | 10 ++-- internal/cmd/mariadb/instance/list/list.go | 11 +++-- internal/cmd/mariadb/plans/plans.go | 12 +++-- .../mongodbflex/backup/describe/describe.go | 17 +++---- internal/cmd/mongodbflex/backup/list/list.go | 10 +++- .../backup/restore-jobs/restore_jobs.go | 12 +++-- .../mongodbflex/backup/schedule/schedule.go | 28 ++++++----- .../cmd/mongodbflex/instance/create/create.go | 2 +- .../mongodbflex/instance/describe/describe.go | 24 ++++++---- .../cmd/mongodbflex/instance/list/list.go | 7 ++- internal/cmd/mongodbflex/options/options.go | 18 +++++-- .../cmd/mongodbflex/user/create/create.go | 17 +++---- .../cmd/mongodbflex/user/describe/describe.go | 12 ++--- internal/cmd/mongodbflex/user/list/list.go | 6 ++- .../user/reset-password/reset_password.go | 6 +-- .../bucket/describe/describe.go | 9 ++-- .../cmd/object-storage/bucket/list/list.go | 11 +++-- .../credentials-group/create/create.go | 7 ++- .../credentials-group/list/list.go | 10 ++-- .../credentials/create/create.go | 10 ++-- .../object-storage/credentials/list/list.go | 14 ++---- .../credentials/create/create.go | 5 +- .../observability/credentials/list/list.go | 3 +- .../grafana/describe/describe.go | 8 ++-- .../observability/instance/create/create.go | 3 +- .../instance/describe/describe.go | 36 +++++++------- .../cmd/observability/instance/list/list.go | 11 +++-- internal/cmd/observability/plans/plans.go | 9 +++- .../scrape-config/create/create.go | 3 +- .../scrape-config/describe/describe.go | 18 +++---- .../observability/scrape-config/list/list.go | 7 ++- .../opensearch/credentials/create/create.go | 24 +++++----- .../credentials/describe/describe.go | 15 +++--- .../cmd/opensearch/credentials/list/list.go | 5 +- .../opensearch/instance/describe/describe.go | 10 ++-- internal/cmd/opensearch/instance/list/list.go | 11 +++-- internal/cmd/opensearch/plans/plans.go | 9 +++- internal/cmd/organization/member/list/list.go | 3 +- internal/cmd/organization/role/list/list.go | 8 +++- .../postgresflex/backup/describe/describe.go | 11 +++-- internal/cmd/postgresflex/backup/list/list.go | 10 +++- .../instance/describe/describe.go | 27 ++++++----- .../cmd/postgresflex/instance/list/list.go | 10 ++-- internal/cmd/postgresflex/options/options.go | 19 ++++++-- .../cmd/postgresflex/user/create/create.go | 18 +++---- .../postgresflex/user/describe/describe.go | 14 +++--- internal/cmd/postgresflex/user/list/list.go | 9 ++-- .../user/reset-password/reset_password.go | 10 ++-- internal/cmd/project/create/create.go | 2 +- internal/cmd/project/describe/describe.go | 10 ++-- internal/cmd/project/list/list.go | 11 +++-- internal/cmd/project/member/add/add.go | 2 +- internal/cmd/project/member/list/list.go | 6 +-- internal/cmd/project/member/remove/remove.go | 2 +- internal/cmd/project/role/list/list.go | 11 +++-- .../cmd/rabbitmq/credentials/create/create.go | 25 +++++----- .../rabbitmq/credentials/describe/describe.go | 13 ++--- .../cmd/rabbitmq/credentials/list/list.go | 6 +-- .../rabbitmq/instance/describe/describe.go | 10 ++-- internal/cmd/rabbitmq/instance/list/list.go | 11 +++-- internal/cmd/rabbitmq/plans/plans.go | 9 +++- .../cmd/redis/credentials/create/create.go | 23 ++++----- .../redis/credentials/describe/describe.go | 13 ++--- internal/cmd/redis/credentials/list/list.go | 6 +-- .../cmd/redis/instance/describe/describe.go | 10 ++-- internal/cmd/redis/instance/list/list.go | 11 +++-- internal/cmd/redis/plans/plans.go | 12 +++-- .../instance/describe/describe.go | 12 ++--- .../cmd/secrets-manager/instance/list/list.go | 11 +++-- .../cmd/secrets-manager/user/create/create.go | 10 ++-- .../secrets-manager/user/describe/describe.go | 6 +-- .../cmd/secrets-manager/user/list/list.go | 11 +++-- internal/cmd/service-account/create/create.go | 3 +- internal/cmd/service-account/key/list/list.go | 11 +++-- internal/cmd/service-account/list/list.go | 9 ++-- .../service-account/token/create/create.go | 10 ++-- .../cmd/service-account/token/list/list.go | 8 +++- internal/cmd/ske/cluster/create/create.go | 6 +-- internal/cmd/ske/cluster/describe/describe.go | 10 ++-- internal/cmd/ske/cluster/list/list.go | 9 +++- internal/cmd/ske/describe/describe.go | 10 ++-- internal/cmd/ske/kubeconfig/create/create.go | 3 +- internal/cmd/ske/options/options.go | 26 +++++++--- internal/pkg/utils/strings.go | 9 ++++ internal/pkg/utils/utils.go | 18 +++++++ 182 files changed, 1299 insertions(+), 763 deletions(-) diff --git a/internal/cmd/beta/image/create/create.go b/internal/cmd/beta/image/create/create.go index e02518b01..7b259010e 100644 --- a/internal/cmd/beta/image/create/create.go +++ b/internal/cmd/beta/image/create/create.go @@ -395,7 +395,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.ImageCreateRes return nil default: - p.Outputf("Created image %q with id %s\n", model.Name, *model.Id) + p.Outputf("Created image %q with id %s\n", model.Name, utils.PtrString(model.Id)) return nil } } diff --git a/internal/cmd/beta/key-pair/create/create.go b/internal/cmd/beta/key-pair/create/create.go index 4626946b2..b4bd759bb 100644 --- a/internal/cmd/beta/key-pair/create/create.go +++ b/internal/cmd/beta/key-pair/create/create.go @@ -82,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create key pair: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.GlobalFlagModel.OutputFormat, resp) }, } configureFlags(cmd) @@ -141,8 +141,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateKeyPairPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, item *iaas.Keypair) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, item *iaas.Keypair) error { + if item == nil { + return fmt.Errorf("no key pair found") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(item, "", " ") if err != nil { @@ -156,7 +160,10 @@ func outputResult(p *print.Printer, model *inputModel, item *iaas.Keypair) error } p.Outputln(string(details)) default: - p.Outputf("Created key pair %q.\nkey pair Fingerprint: %q\n", *item.Name, *item.Fingerprint) + p.Outputf("Created key pair %q.\nkey pair Fingerprint: %q\n", + utils.PtrString(item.Name), + utils.PtrString(item.Fingerprint), + ) } return nil } diff --git a/internal/cmd/beta/key-pair/create/create_test.go b/internal/cmd/beta/key-pair/create/create_test.go index adb0f90b7..f912892d5 100644 --- a/internal/cmd/beta/key-pair/create/create_test.go +++ b/internal/cmd/beta/key-pair/create/create_test.go @@ -194,3 +194,42 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + item *iaas.Keypair + outputFormat string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + item: nil, + outputFormat: "", + }, + wantErr: true, + }, + { + name: "base", + args: args{ + item: &iaas.Keypair{}, + outputFormat: "", + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.item); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/key-pair/describe/describe.go b/internal/cmd/beta/key-pair/describe/describe.go index 7f7a8e7b6..85981bde3 100644 --- a/internal/cmd/beta/key-pair/describe/describe.go +++ b/internal/cmd/beta/key-pair/describe/describe.go @@ -6,6 +6,8 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -69,7 +71,11 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read key pair: %w", err) } - return outputResult(p, model.OutputFormat, model.PublicKey, resp) + if keypair := resp; keypair != nil { + return outputResult(p, model.OutputFormat, model.PublicKey, *keypair) + } + p.Outputln("No keypair found.") + return nil }, } configureFlags(cmd) @@ -107,7 +113,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return apiClient.GetKeyPair(ctx, model.KeyPairName) } -func outputResult(p *print.Printer, outputFormat string, showOnlyPublicKey bool, keyPair *iaas.Keypair) error { +func outputResult(p *print.Printer, outputFormat string, showOnlyPublicKey bool, keyPair iaas.Keypair) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(keyPair, "", " ") @@ -145,10 +151,10 @@ func outputResult(p *print.Printer, outputFormat string, showOnlyPublicKey bool, return nil } table := tables.NewTable() - table.AddRow("KEY PAIR NAME", *keyPair.Name) + table.AddRow("KEY PAIR NAME", utils.PtrString(keyPair.Name)) table.AddSeparator() - if *keyPair.Labels != nil && len(*keyPair.Labels) > 0 { + if keyPair.Labels != nil && len(*keyPair.Labels) > 0 { var labels []string for key, value := range *keyPair.Labels { labels = append(labels, fmt.Sprintf("%s: %s", key, value)) @@ -157,17 +163,21 @@ func outputResult(p *print.Printer, outputFormat string, showOnlyPublicKey bool, table.AddSeparator() } - table.AddRow("FINGERPRINT", *keyPair.Fingerprint) + table.AddRow("FINGERPRINT", utils.PtrString(keyPair.Fingerprint)) table.AddSeparator() - truncatedPublicKey := (*keyPair.PublicKey)[:maxLengthPublicKey] + "..." + truncatedPublicKey := "" + if keyPair.PublicKey != nil { + truncatedPublicKey = (*keyPair.PublicKey)[:maxLengthPublicKey] + "..." + } + table.AddRow("PUBLIC KEY", truncatedPublicKey) table.AddSeparator() - table.AddRow("CREATED AT", *keyPair.CreatedAt) + table.AddRow("CREATED AT", utils.PtrString(keyPair.CreatedAt)) table.AddSeparator() - table.AddRow("UPDATED AT", *keyPair.UpdatedAt) + table.AddRow("UPDATED AT", utils.PtrString(keyPair.UpdatedAt)) table.AddSeparator() p.Outputln(table.Render()) diff --git a/internal/cmd/beta/key-pair/describe/describe_test.go b/internal/cmd/beta/key-pair/describe/describe_test.go index 69add5828..46374b3c8 100644 --- a/internal/cmd/beta/key-pair/describe/describe_test.go +++ b/internal/cmd/beta/key-pair/describe/describe_test.go @@ -186,3 +186,35 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + showOnlyPublicKey bool + keyPair iaas.Keypair + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "base", + args: args{ + outputFormat: "", + showOnlyPublicKey: false, + keyPair: iaas.Keypair{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.showOnlyPublicKey, tt.args.keyPair); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/key-pair/list/list.go b/internal/cmd/beta/key-pair/list/list.go index 469a332fe..b25e6d6f6 100644 --- a/internal/cmd/beta/key-pair/list/list.go +++ b/internal/cmd/beta/key-pair/list/list.go @@ -6,6 +6,8 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -158,11 +160,19 @@ func outputResult(p *print.Printer, outputFormat string, keyPairs []iaas.Keypair keyPair := keyPairs[idx] var labels []string - for key, value := range *keyPair.Labels { - labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + if keyPair.Labels != nil { + for key, value := range *keyPair.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } } - table.AddRow(*keyPair.Name, strings.Join(labels, ", "), *keyPair.Fingerprint, *keyPair.CreatedAt, *keyPair.UpdatedAt) + table.AddRow( + utils.PtrString(keyPair.Name), + strings.Join(labels, ", "), + utils.PtrString(keyPair.Fingerprint), + utils.PtrString(keyPair.CreatedAt), + utils.PtrString(keyPair.UpdatedAt), + ) } p.Outputln(table.Render()) diff --git a/internal/cmd/beta/key-pair/list/list_test.go b/internal/cmd/beta/key-pair/list/list_test.go index 99bedd4ba..8fa0a948f 100644 --- a/internal/cmd/beta/key-pair/list/list_test.go +++ b/internal/cmd/beta/key-pair/list/list_test.go @@ -186,3 +186,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + keyPairs []iaas.Keypair + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + outputFormat: "", + keyPairs: []iaas.Keypair{ + {}, + }, + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + if err := outputResult(p, tt.args.outputFormat, tt.args.keyPairs); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/key-pair/update/update.go b/internal/cmd/beta/key-pair/update/update.go index 39b6abacf..de9b9f5d4 100644 --- a/internal/cmd/beta/key-pair/update/update.go +++ b/internal/cmd/beta/key-pair/update/update.go @@ -43,10 +43,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) - if err != nil { - return err - } + model := parseInput(p, cmd, args) // Configure API client apiClient, err := client.ConfigureClient(p) @@ -63,13 +60,16 @@ func NewCmd(p *print.Printer) *cobra.Command { } // Call API - req := buildRequest(ctx, model, apiClient) + req := buildRequest(ctx, &model, apiClient) resp, err := req.Execute() if err != nil { return fmt.Errorf("update key pair: %w", err) } + if resp == nil { + return fmt.Errorf("response is nil") + } - return outputResult(p, model, resp) + return outputResult(p, model, *resp) }, } configureFlags(cmd) @@ -100,7 +100,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.UpdateKeyPairPayload(payload) } -func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) inputModel { keyPairName := inputArgs[0] globalFlags := globalflags.Parse(p, cmd) @@ -119,11 +119,15 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } } - return &model, nil + return model } -func outputResult(p *print.Printer, model *inputModel, keyPair *iaas.Keypair) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, model inputModel, keyPair iaas.Keypair) error { + var outputFormat string + if model.GlobalFlagModel != nil { + outputFormat = model.GlobalFlagModel.OutputFormat + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(keyPair, "", " ") if err != nil { @@ -137,7 +141,7 @@ func outputResult(p *print.Printer, model *inputModel, keyPair *iaas.Keypair) er } p.Outputln(string(details)) default: - p.Outputf("Updated labels of key pair %q\n", *model.KeyPairName) + p.Outputf("Updated labels of key pair %q\n", utils.PtrString(model.KeyPairName)) } return nil } diff --git a/internal/cmd/beta/key-pair/update/update_test.go b/internal/cmd/beta/key-pair/update/update_test.go index 49d6aeabb..5743e2d60 100644 --- a/internal/cmd/beta/key-pair/update/update_test.go +++ b/internal/cmd/beta/key-pair/update/update_test.go @@ -141,18 +141,12 @@ func TestParseInput(t *testing.T) { t.Fatalf("error validating args: %v", err) } - model, err := parseInput(p, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing flags: %v", err) - } + model := parseInput(p, cmd, tt.argValues) if !tt.isValid { t.Fatalf("did not fail on invalid input") } - diff := cmp.Diff(model, tt.expectedModel) + diff := cmp.Diff(&model, tt.expectedModel) if diff != "" { t.Fatalf("Data does not match: %s", diff) } @@ -188,3 +182,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + keyPair iaas.Keypair + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "base", + args: args{ + model: inputModel{}, + keyPair: iaas.Keypair{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.keyPair); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/create/create.go b/internal/cmd/beta/network-area/create/create.go index 83322226b..576fd8904 100644 --- a/internal/cmd/beta/network-area/create/create.go +++ b/internal/cmd/beta/network-area/create/create.go @@ -197,7 +197,7 @@ func outputResult(p *print.Printer, model *inputModel, orgLabel string, networkA return nil default: - p.Outputf("Created STACKIT Network Area for organization %q.\nNetwork area ID: %s\n", orgLabel, *networkArea.AreaId) + p.Outputf("Created STACKIT Network Area for organization %q.\nNetwork area ID: %s\n", orgLabel, utils.PtrString(networkArea.AreaId)) return nil } } diff --git a/internal/cmd/beta/network-area/describe/describe.go b/internal/cmd/beta/network-area/describe/describe.go index 1332572a6..61c329af9 100644 --- a/internal/cmd/beta/network-area/describe/describe.go +++ b/internal/cmd/beta/network-area/describe/describe.go @@ -160,11 +160,11 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo } table := tables.NewTable() - table.AddRow("ID", *networkArea.AreaId) + table.AddRow("ID", utils.PtrString(networkArea.AreaId)) table.AddSeparator() - table.AddRow("NAME", *networkArea.Name) + table.AddRow("NAME", utils.PtrString(networkArea.Name)) table.AddSeparator() - table.AddRow("STATE", *networkArea.State) + table.AddRow("STATE", utils.PtrString(networkArea.State)) table.AddSeparator() if len(networkRanges) > 0 { table.AddRow("NETWORK RANGES", strings.Join(networkRanges, ",")) @@ -174,31 +174,33 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo table.AddRow(fmt.Sprintf("STATIC ROUTE %d", i+1), route) table.AddSeparator() } - if networkArea.Ipv4.TransferNetwork != nil { - table.AddRow("TRANSFER RANGE", *networkArea.Ipv4.TransferNetwork) - table.AddSeparator() - } - if networkArea.Ipv4.DefaultNameservers != nil { - table.AddRow("DNS NAME SERVERS", strings.Join(*networkArea.Ipv4.DefaultNameservers, ",")) - table.AddSeparator() - } - if networkArea.Ipv4.DefaultPrefixLen != nil { - table.AddRow("DEFAULT PREFIX LENGTH", *networkArea.Ipv4.DefaultPrefixLen) - table.AddSeparator() - } - if networkArea.Ipv4.MaxPrefixLen != nil { - table.AddRow("MAX PREFIX LENGTH", *networkArea.Ipv4.MaxPrefixLen) - table.AddSeparator() - } - if networkArea.Ipv4.MinPrefixLen != nil { - table.AddRow("MIN PREFIX LENGTH", *networkArea.Ipv4.MinPrefixLen) - table.AddSeparator() + if networkArea.Ipv4 != nil { + if networkArea.Ipv4.TransferNetwork != nil { + table.AddRow("TRANSFER RANGE", *networkArea.Ipv4.TransferNetwork) + table.AddSeparator() + } + if networkArea.Ipv4.DefaultNameservers != nil && len(*networkArea.Ipv4.DefaultNameservers) > 0 { + table.AddRow("DNS NAME SERVERS", strings.Join(*networkArea.Ipv4.DefaultNameservers, ",")) + table.AddSeparator() + } + if networkArea.Ipv4.DefaultPrefixLen != nil { + table.AddRow("DEFAULT PREFIX LENGTH", *networkArea.Ipv4.DefaultPrefixLen) + table.AddSeparator() + } + if networkArea.Ipv4.MaxPrefixLen != nil { + table.AddRow("MAX PREFIX LENGTH", *networkArea.Ipv4.MaxPrefixLen) + table.AddSeparator() + } + if networkArea.Ipv4.MinPrefixLen != nil { + table.AddRow("MIN PREFIX LENGTH", *networkArea.Ipv4.MinPrefixLen) + table.AddSeparator() + } } if len(attachedProjects) > 0 { table.AddRow("ATTACHED PROJECTS IDS", strings.Join(attachedProjects, "\n")) table.AddSeparator() } else { - table.AddRow("# ATTACHED PROJECTS", *networkArea.ProjectCount) + table.AddRow("# ATTACHED PROJECTS", utils.PtrString(networkArea.ProjectCount)) table.AddSeparator() } diff --git a/internal/cmd/beta/network-area/list/list.go b/internal/cmd/beta/network-area/list/list.go index 08b619851..984ebb4df 100644 --- a/internal/cmd/beta/network-area/list/list.go +++ b/internal/cmd/beta/network-area/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -16,9 +17,8 @@ import ( rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" rmUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" - - "github.com/spf13/cobra" ) const ( @@ -164,7 +164,20 @@ func outputResult(p *print.Printer, outputFormat string, networkAreas []iaas.Net table.SetHeader("ID", "Name", "Status", "Network Ranges", "# Attached Projects") for _, networkArea := range networkAreas { - table.AddRow(*networkArea.AreaId, *networkArea.Name, *networkArea.State, len(*networkArea.Ipv4.NetworkRanges), *networkArea.ProjectCount) + networkRanges := "n/a" + if ipv4 := networkArea.Ipv4; ipv4 != nil { + if netRange := ipv4.NetworkRanges; netRange != nil { + networkRanges = fmt.Sprint(len(*netRange)) + } + } + + table.AddRow( + utils.PtrString(networkArea.AreaId), + utils.PtrString(networkArea.Name), + utils.PtrString(networkArea.State), + networkRanges, + utils.PtrString(networkArea.ProjectCount), + ) table.AddSeparator() } diff --git a/internal/cmd/beta/network-area/network-range/create/create.go b/internal/cmd/beta/network-area/network-range/create/create.go index e66870dd4..4efb43d49 100644 --- a/internal/cmd/beta/network-area/network-range/create/create.go +++ b/internal/cmd/beta/network-area/network-range/create/create.go @@ -12,7 +12,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/cobra" @@ -57,7 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // Get network area label - networkAreaLabel, err := utils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { p.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("empty response from API") } - networkRange, err := utils.GetNetworkRangeFromAPIResponse(*model.NetworkRange, resp.Items) + networkRange, err := iaasUtils.GetNetworkRangeFromAPIResponse(*model.NetworkRange, resp.Items) if err != nil { return err } @@ -156,7 +157,7 @@ func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, return nil default: - p.Outputf("Created network range for SNA %q.\nNetwork range ID: %s\n", networkAreaLabel, *networkRange.NetworkRangeId) + p.Outputf("Created network range for SNA %q.\nNetwork range ID: %s\n", networkAreaLabel, utils.PtrString(networkRange.NetworkRangeId)) return nil } } diff --git a/internal/cmd/beta/network-area/network-range/describe/describe.go b/internal/cmd/beta/network-area/network-range/describe/describe.go index ed75127f9..8ca934686 100644 --- a/internal/cmd/beta/network-area/network-range/describe/describe.go +++ b/internal/cmd/beta/network-area/network-range/describe/describe.go @@ -128,9 +128,9 @@ func outputResult(p *print.Printer, outputFormat string, networkRange *iaas.Netw return nil default: table := tables.NewTable() - table.AddRow("ID", *networkRange.NetworkRangeId) + table.AddRow("ID", utils.PtrString(networkRange.NetworkRangeId)) table.AddSeparator() - table.AddRow("Network range", *networkRange.Prefix) + table.AddRow("Network range", utils.PtrString(networkRange.Prefix)) err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/network-area/route/create/create.go b/internal/cmd/beta/network-area/route/create/create.go index 24608f14f..a6f14b1c8 100644 --- a/internal/cmd/beta/network-area/route/create/create.go +++ b/internal/cmd/beta/network-area/route/create/create.go @@ -184,7 +184,7 @@ func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, return nil default: - p.Outputf("Created static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, *route.RouteId) + p.Outputf("Created static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, utils.PtrString(route.RouteId)) return nil } } diff --git a/internal/cmd/beta/network-area/route/describe/describe.go b/internal/cmd/beta/network-area/route/describe/describe.go index aa9dbb7c5..9a4c91300 100644 --- a/internal/cmd/beta/network-area/route/describe/describe.go +++ b/internal/cmd/beta/network-area/route/describe/describe.go @@ -133,11 +133,11 @@ func outputResult(p *print.Printer, outputFormat string, route *iaas.Route) erro return nil default: table := tables.NewTable() - table.AddRow("ID", *route.RouteId) + table.AddRow("ID", utils.PtrString(route.RouteId)) table.AddSeparator() - table.AddRow("PREFIX", *route.Prefix) + table.AddRow("PREFIX", utils.PtrString(route.Prefix)) table.AddSeparator() - table.AddRow("NEXTHOP", *route.Nexthop) + table.AddRow("NEXTHOP", utils.PtrString(route.Nexthop)) if route.Labels != nil && len(*route.Labels) > 0 { labels := []string{} for key, value := range *route.Labels { diff --git a/internal/cmd/beta/network-area/route/list/list.go b/internal/cmd/beta/network-area/route/list/list.go index 6a33d5e2f..6d5baa093 100644 --- a/internal/cmd/beta/network-area/route/list/list.go +++ b/internal/cmd/beta/network-area/route/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,9 +16,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" - - "github.com/spf13/cobra" ) const ( @@ -162,7 +162,11 @@ func outputResult(p *print.Printer, outputFormat string, routes []iaas.Route) er table.SetHeader("Static Route ID", "Next Hop", "Prefix") for _, route := range routes { - table.AddRow(*route.RouteId, *route.Nexthop, *route.Prefix) + table.AddRow( + utils.PtrString(route.RouteId), + utils.PtrString(route.Nexthop), + utils.PtrString(route.Prefix), + ) } p.Outputln(table.Render()) diff --git a/internal/cmd/beta/network-area/route/update/update.go b/internal/cmd/beta/network-area/route/update/update.go index bf11fc1a6..f022e0d2d 100644 --- a/internal/cmd/beta/network-area/route/update/update.go +++ b/internal/cmd/beta/network-area/route/update/update.go @@ -160,7 +160,7 @@ func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, return nil default: - p.Outputf("Updated static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, *route.RouteId) + p.Outputf("Updated static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, utils.PtrString(route.RouteId)) return nil } } diff --git a/internal/cmd/beta/network-interface/create/create.go b/internal/cmd/beta/network-interface/create/create.go index 0a1345f47..ac3686652 100644 --- a/internal/cmd/beta/network-interface/create/create.go +++ b/internal/cmd/beta/network-interface/create/create.go @@ -245,7 +245,7 @@ func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { return nil default: - p.Outputf("Created network interface for project %q.\nNIC ID: %s\n", model.ProjectId, *nic.Id) + p.Outputf("Created network interface for project %q.\nNIC ID: %s\n", model.ProjectId, utils.PtrString(nic.Id)) return nil } } diff --git a/internal/cmd/beta/network-interface/describe/describe.go b/internal/cmd/beta/network-interface/describe/describe.go index 92da8a62d..02332642f 100644 --- a/internal/cmd/beta/network-interface/describe/describe.go +++ b/internal/cmd/beta/network-interface/describe/describe.go @@ -152,9 +152,9 @@ func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { table.AddRow("IPV6", *nic.Ipv6) table.AddSeparator() } - table.AddRow("MAC", *nic.Mac) + table.AddRow("MAC", utils.PtrString(nic.Mac)) table.AddSeparator() - table.AddRow("NIC SECURITY", *nic.NicSecurity) + table.AddRow("NIC SECURITY", utils.PtrString(nic.NicSecurity)) if nic.AllowedAddresses != nil && len(*nic.AllowedAddresses) > 0 { allowedAddresses := []string{} for _, value := range *nic.AllowedAddresses { @@ -172,9 +172,9 @@ func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { table.AddRow("LABELS", strings.Join(labels, "\n")) } table.AddSeparator() - table.AddRow("STATUS", *nic.Status) + table.AddRow("STATUS", utils.PtrString(nic.Status)) table.AddSeparator() - table.AddRow("TYPE", *nic.Type) + table.AddRow("TYPE", utils.PtrString(nic.Type)) if nic.SecurityGroups != nil && len(*nic.SecurityGroups) > 0 { table.AddSeparator() table.AddRow("SECURITY GROUPS", strings.Join(*nic.SecurityGroups, "\n")) diff --git a/internal/cmd/beta/network-interface/list/list.go b/internal/cmd/beta/network-interface/list/list.go index 4fe9005ef..994cdf096 100644 --- a/internal/cmd/beta/network-interface/list/list.go +++ b/internal/cmd/beta/network-interface/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,9 +16,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" - - "github.com/spf13/cobra" ) const ( @@ -174,11 +174,13 @@ func outputResult(p *print.Printer, outputFormat string, nics []iaas.NIC) error table.SetHeader("ID", "NAME", "NIC SECURITY", "STATUS", "TYPE") for _, nic := range nics { - name := "" - if nic.Name != nil { - name = *nic.Name - } - table.AddRow(*nic.Id, name, *nic.NicSecurity, *nic.Status, *nic.Type) + table.AddRow( + utils.PtrString(nic.Id), + utils.PtrString(nic.Name), + utils.PtrString(nic.NicSecurity), + utils.PtrString(nic.Status), + utils.PtrString(nic.Type), + ) table.AddSeparator() } diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/beta/network/describe/describe.go index 31982a366..26efcc3dc 100644 --- a/internal/cmd/beta/network/describe/describe.go +++ b/internal/cmd/beta/network/describe/describe.go @@ -140,11 +140,11 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) } table := tables.NewTable() - table.AddRow("ID", *network.NetworkId) + table.AddRow("ID", utils.PtrString(network.NetworkId)) table.AddSeparator() - table.AddRow("NAME", *network.Name) + table.AddRow("NAME", utils.PtrString(network.Name)) table.AddSeparator() - table.AddRow("STATE", *network.State) + table.AddRow("STATE", utils.PtrString(network.State)) table.AddSeparator() if network.PublicIp != nil { diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index ee388765c..62ca68e6f 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -16,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/cobra" @@ -164,12 +164,16 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network if network.Routed != nil { routed = *network.Routed } - prefixes := "" - if network.Prefixes != nil && len(*network.Prefixes) > 0 { - prefixes = strings.Join(*network.Prefixes, ", ") - } - - table.AddRow(*network.NetworkId, *network.Name, *network.State, publicIp, prefixes, routed) + prefixes := utils.JoinStringPtr(network.Prefixes, ", ") + + table.AddRow( + utils.PtrString(network.NetworkId), + utils.PtrString(network.Name), + utils.PtrString(network.State), + publicIp, + prefixes, + routed, + ) table.AddSeparator() } diff --git a/internal/cmd/beta/public-ip/associate/associate.go b/internal/cmd/beta/public-ip/associate/associate.go index 7233b827c..1c33b2b8d 100644 --- a/internal/cmd/beta/public-ip/associate/associate.go +++ b/internal/cmd/beta/public-ip/associate/associate.go @@ -76,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("associate public IP: %w", err) } - p.Outputf("Associated public IP %q with resource %v.\n", publicIpLabel, *resp.GetNetworkInterface()) + p.Outputf("Associated public IP %q with resource %v.\n", publicIpLabel, utils.PtrString(resp.GetNetworkInterface())) return nil }, } diff --git a/internal/cmd/beta/public-ip/create/create.go b/internal/cmd/beta/public-ip/create/create.go index 1f2bbe18c..dd1db3e5f 100644 --- a/internal/cmd/beta/public-ip/create/create.go +++ b/internal/cmd/beta/public-ip/create/create.go @@ -159,7 +159,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, publ return nil default: - p.Outputf("Created public IP for project %q.\nPublic IP ID: %s\n", projectLabel, *publicIp.Id) + p.Outputf("Created public IP for project %q.\nPublic IP ID: %s\n", projectLabel, utils.PtrString(publicIp.Id)) return nil } } diff --git a/internal/cmd/beta/public-ip/describe/describe.go b/internal/cmd/beta/public-ip/describe/describe.go index fe85c6902..19d03a4c9 100644 --- a/internal/cmd/beta/public-ip/describe/describe.go +++ b/internal/cmd/beta/public-ip/describe/describe.go @@ -121,9 +121,9 @@ func outputResult(p *print.Printer, outputFormat string, publicIp *iaas.PublicIp return nil default: table := tables.NewTable() - table.AddRow("ID", *publicIp.Id) + table.AddRow("ID", utils.PtrString(publicIp.Id)) table.AddSeparator() - table.AddRow("IP ADDRESS", *publicIp.Ip) + table.AddRow("IP ADDRESS", utils.PtrString(publicIp.Ip)) table.AddSeparator() if publicIp.NetworkInterface != nil { diff --git a/internal/cmd/beta/public-ip/list/list.go b/internal/cmd/beta/public-ip/list/list.go index 4ab82d197..2ac5b56ba 100644 --- a/internal/cmd/beta/public-ip/list/list.go +++ b/internal/cmd/beta/public-ip/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/cobra" @@ -167,11 +168,12 @@ func outputResult(p *print.Printer, outputFormat string, publicIps []iaas.Public table.SetHeader("ID", "IP ADDRESS", "USED BY") for _, publicIp := range publicIps { - networkInterfaceId := "" - if publicIp.NetworkInterface != nil { - networkInterfaceId = *publicIp.GetNetworkInterface() - } - table.AddRow(*publicIp.Id, *publicIp.Ip, networkInterfaceId) + networkInterfaceId := utils.PtrStringDefault(publicIp.GetNetworkInterface(), "") + table.AddRow( + utils.PtrString(publicIp.Id), + utils.PtrString(publicIp.Ip), + networkInterfaceId, + ) table.AddSeparator() } diff --git a/internal/cmd/beta/security-group/rule/create/create.go b/internal/cmd/beta/security-group/rule/create/create.go index 04b49745e..2dcd875b6 100644 --- a/internal/cmd/beta/security-group/rule/create/create.go +++ b/internal/cmd/beta/security-group/rule/create/create.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/cobra" @@ -240,7 +241,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, securityGro if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s security group rule for security group %q in project %q.\nSecurity group rule ID: %s\n", operationState, securityGroupName, projectLabel, *securityGroupRule.Id) + p.Outputf("%s security group rule for security group %q in project %q.\nSecurity group rule ID: %s\n", operationState, securityGroupName, projectLabel, utils.PtrString(securityGroupRule.Id)) return nil } } diff --git a/internal/cmd/beta/security-group/rule/describe/describe.go b/internal/cmd/beta/security-group/rule/describe/describe.go index bc1b7abd3..64ff2834d 100644 --- a/internal/cmd/beta/security-group/rule/describe/describe.go +++ b/internal/cmd/beta/security-group/rule/describe/describe.go @@ -132,7 +132,7 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRule *iaas return nil default: table := tables.NewTable() - table.AddRow("ID", *securityGroupRule.Id) + table.AddRow("ID", utils.PtrString(securityGroupRule.Id)) table.AddSeparator() if securityGroupRule.Protocol != nil { @@ -147,7 +147,7 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRule *iaas } } - table.AddRow("DIRECTION", *securityGroupRule.Direction) + table.AddRow("DIRECTION", utils.PtrString(securityGroupRule.Direction)) table.AddSeparator() if securityGroupRule.PortRange != nil { diff --git a/internal/cmd/beta/security-group/rule/list/list.go b/internal/cmd/beta/security-group/rule/list/list.go index 55b75e8c2..385b98dd8 100644 --- a/internal/cmd/beta/security-group/rule/list/list.go +++ b/internal/cmd/beta/security-group/rule/list/list.go @@ -170,10 +170,7 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRules []ia table.SetHeader("ID", "ETHER TYPE", "DIRECTION", "PROTOCOL", "REMOTE SECURITY GROUP ID") for _, securityGroupRule := range securityGroupRules { - etherType := "" - if securityGroupRule.Ethertype != nil { - etherType = *securityGroupRule.Ethertype - } + etherType := utils.PtrStringDefault(securityGroupRule.Ethertype, "") protocolName := "" if securityGroupRule.Protocol != nil { diff --git a/internal/cmd/beta/server/backup/create/create.go b/internal/cmd/beta/server/backup/create/create.go index 90b3109c4..2ae95c259 100644 --- a/internal/cmd/beta/server/backup/create/create.go +++ b/internal/cmd/beta/server/backup/create/create.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" @@ -158,7 +159,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.Backup return nil default: - p.Outputf("Triggered creation of server backup for server %s. Backup ID: %s\n", model.ServerId, *resp.Id) + p.Outputf("Triggered creation of server backup for server %s. Backup ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/backup/describe/describe.go b/internal/cmd/beta/server/backup/describe/describe.go index 38509fb97..a14f7a64d 100644 --- a/internal/cmd/beta/server/backup/describe/describe.go +++ b/internal/cmd/beta/server/backup/describe/describe.go @@ -129,23 +129,20 @@ func outputResult(p *print.Printer, outputFormat string, backup *serverbackup.Ba return nil default: table := tables.NewTable() - table.AddRow("ID", *backup.Id) + table.AddRow("ID", utils.PtrString(backup.Id)) table.AddSeparator() - table.AddRow("NAME", *backup.Name) + table.AddRow("NAME", utils.PtrString(backup.Name)) table.AddSeparator() - table.AddRow("SIZE (GB)", *backup.Size) + table.AddRow("SIZE (GB)", utils.PtrString(backup.Size)) table.AddSeparator() - table.AddRow("STATUS", *backup.Status) + table.AddRow("STATUS", utils.PtrString(backup.Status)) table.AddSeparator() - table.AddRow("CREATED AT", *backup.CreatedAt) + table.AddRow("CREATED AT", utils.PtrString(backup.CreatedAt)) table.AddSeparator() - table.AddRow("EXPIRES AT", *backup.ExpireAt) + table.AddRow("EXPIRES AT", utils.PtrString(backup.ExpireAt)) table.AddSeparator() - lastRestored := "" - if backup.LastRestoredAt != nil { - lastRestored = *backup.LastRestoredAt - } + lastRestored := utils.PtrStringDefault(backup.LastRestoredAt, "") table.AddRow("LAST RESTORED AT", lastRestored) table.AddSeparator() table.AddRow("VOLUME BACKUPS", len(*backup.VolumeBackups)) diff --git a/internal/cmd/beta/server/backup/list/list.go b/internal/cmd/beta/server/backup/list/list.go index 6588cd96e..f5c2dbf0e 100644 --- a/internal/cmd/beta/server/backup/list/list.go +++ b/internal/cmd/beta/server/backup/list/list.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" - + "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" @@ -15,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) @@ -150,11 +149,17 @@ func outputResult(p *print.Printer, outputFormat string, backups []serverbackup. for i := range backups { s := backups[i] - lastRestored := "" - if s.LastRestoredAt != nil { - lastRestored = *s.LastRestoredAt - } - table.AddRow(*s.Id, *s.Name, *s.Size, *s.Status, *s.CreatedAt, *s.ExpireAt, lastRestored, len(*s.VolumeBackups)) + lastRestored := utils.PtrStringDefault(s.LastRestoredAt, "") + table.AddRow( + utils.PtrString(s.Id), + utils.PtrString(s.Name), + utils.PtrString(s.Size), + utils.PtrString(s.Status), + utils.PtrString(s.CreatedAt), + utils.PtrString(s.ExpireAt), + lastRestored, + len(*s.VolumeBackups), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/backup/schedule/create/create.go b/internal/cmd/beta/server/backup/schedule/create/create.go index d59a50df3..e35755d8e 100644 --- a/internal/cmd/beta/server/backup/schedule/create/create.go +++ b/internal/cmd/beta/server/backup/schedule/create/create.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" @@ -177,7 +178,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.Backup return nil default: - p.Outputf("Created server backup schedule for server %s. Backup Schedule ID: %d\n", model.ServerId, *resp.Id) + p.Outputf("Created server backup schedule for server %s. Backup Schedule ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/backup/schedule/describe/describe.go b/internal/cmd/beta/server/backup/schedule/describe/describe.go index 27557b2c6..c94144658 100644 --- a/internal/cmd/beta/server/backup/schedule/describe/describe.go +++ b/internal/cmd/beta/server/backup/schedule/describe/describe.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -15,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" @@ -129,13 +129,13 @@ func outputResult(p *print.Printer, outputFormat string, schedule *serverbackup. return nil default: table := tables.NewTable() - table.AddRow("SCHEDULE ID", *schedule.Id) + table.AddRow("SCHEDULE ID", utils.PtrString(schedule.Id)) table.AddSeparator() - table.AddRow("SCHEDULE NAME", *schedule.Name) + table.AddRow("SCHEDULE NAME", utils.PtrString(schedule.Name)) table.AddSeparator() - table.AddRow("ENABLED", *schedule.Enabled) + table.AddRow("ENABLED", utils.PtrString(schedule.Enabled)) table.AddSeparator() - table.AddRow("RRULE", *schedule.Rrule) + table.AddRow("RRULE", utils.PtrString(schedule.Rrule)) table.AddSeparator() if schedule.BackupProperties != nil { table.AddRow("BACKUP NAME", *schedule.BackupProperties.Name) @@ -143,11 +143,7 @@ func outputResult(p *print.Printer, outputFormat string, schedule *serverbackup. table.AddRow("BACKUP RETENTION DAYS", *schedule.BackupProperties.RetentionPeriod) table.AddSeparator() ids := schedule.BackupProperties.VolumeIds - if ids == nil || len(*ids) == 0 { - table.AddRow("BACKUP VOLUME IDS", "") - } else { - table.AddRow("BACKUP VOLUME IDS", strings.Join(*ids, "\n")) - } + table.AddRow("BACKUP VOLUME IDS", utils.JoinStringPtr(ids, "\n")) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/backup/schedule/list/list.go b/internal/cmd/beta/server/backup/schedule/list/list.go index 0a5cd7f95..0709f81bd 100644 --- a/internal/cmd/beta/server/backup/schedule/list/list.go +++ b/internal/cmd/beta/server/backup/schedule/list/list.go @@ -4,10 +4,9 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/goccy/go-yaml" - + "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" @@ -16,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) @@ -151,11 +149,24 @@ func outputResult(p *print.Printer, outputFormat string, schedules []serverbacku for i := range schedules { s := schedules[i] + backupName := "" + retentionPeriod := "" ids := "" - if s.BackupProperties.VolumeIds != nil && len(*s.BackupProperties.VolumeIds) != 0 { - ids = strings.Join(*s.BackupProperties.VolumeIds, ",") + if s.BackupProperties != nil { + backupName = utils.PtrString(s.BackupProperties.Name) + retentionPeriod = utils.PtrString(s.BackupProperties.RetentionPeriod) + + ids = utils.JoinStringPtr(s.BackupProperties.VolumeIds, ",") } - table.AddRow(*s.Id, *s.Name, *s.Enabled, *s.Rrule, *s.BackupProperties.Name, *s.BackupProperties.RetentionPeriod, ids) + table.AddRow( + utils.PtrString(s.Id), + utils.PtrString(s.Name), + utils.PtrString(s.Enabled), + utils.PtrString(s.Rrule), + backupName, + retentionPeriod, + ids, + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/backup/schedule/update/update.go b/internal/cmd/beta/server/backup/schedule/update/update.go index 0d69981ea..88691fc82 100644 --- a/internal/cmd/beta/server/backup/schedule/update/update.go +++ b/internal/cmd/beta/server/backup/schedule/update/update.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" @@ -202,7 +203,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.Backup return nil default: - p.Info("Updated server backup schedule %d\n", *resp.Id) + p.Info("Updated server backup schedule %s\n", utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/command/create/create.go b/internal/cmd/beta/server/command/create/create.go index 6aeb808ec..15d3a0d40 100644 --- a/internal/cmd/beta/server/command/create/create.go +++ b/internal/cmd/beta/server/command/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" runcommandUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/utils" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) @@ -156,7 +156,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *runcommand.NewComma return nil default: - p.Outputf("Created server command for server %s. Command ID: %d\n", model.ServerId, *resp.Id) + p.Outputf("Created server command for server %s. Command ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/command/describe/describe.go b/internal/cmd/beta/server/command/describe/describe.go index 70db7e791..e7964c189 100644 --- a/internal/cmd/beta/server/command/describe/describe.go +++ b/internal/cmd/beta/server/command/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) @@ -128,23 +128,23 @@ func outputResult(p *print.Printer, outputFormat string, command *runcommand.Com return nil default: table := tables.NewTable() - table.AddRow("ID", *command.Id) + table.AddRow("ID", utils.PtrString(command.Id)) table.AddSeparator() - table.AddRow("COMMAND TEMPLATE NAME", *command.CommandTemplateName) + table.AddRow("COMMAND TEMPLATE NAME", utils.PtrString(command.CommandTemplateName)) table.AddSeparator() - table.AddRow("COMMAND TEMPLATE TITLE", *command.CommandTemplateTitle) + table.AddRow("COMMAND TEMPLATE TITLE", utils.PtrString(command.CommandTemplateTitle)) table.AddSeparator() - table.AddRow("STATUS", *command.Status) + table.AddRow("STATUS", utils.PtrString(command.Status)) table.AddSeparator() - table.AddRow("STARTED AT", *command.StartedAt) + table.AddRow("STARTED AT", utils.PtrString(command.StartedAt)) table.AddSeparator() - table.AddRow("FINISHED AT", *command.FinishedAt) + table.AddRow("FINISHED AT", utils.PtrString(command.FinishedAt)) table.AddSeparator() - table.AddRow("EXIT CODE", *command.ExitCode) + table.AddRow("EXIT CODE", utils.PtrString(command.ExitCode)) table.AddSeparator() - table.AddRow("COMMAND SCRIPT", *command.Script) + table.AddRow("COMMAND SCRIPT", utils.PtrString(command.Script)) table.AddSeparator() - table.AddRow("COMMAND OUTPUT", *command.Output) + table.AddRow("COMMAND OUTPUT", utils.PtrString(command.Output)) table.AddSeparator() err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/command/list/list.go b/internal/cmd/beta/server/command/list/list.go index b13a53319..5cdedac7d 100644 --- a/internal/cmd/beta/server/command/list/list.go +++ b/internal/cmd/beta/server/command/list/list.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" - + "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" @@ -15,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) @@ -149,7 +148,14 @@ func outputResult(p *print.Printer, outputFormat string, commands []runcommand.C table.SetHeader("ID", "TEMPLATE NAME", "TEMPLATE TITLE", "STATUS", "STARTED_AT", "FINISHED_AT") for i := range commands { s := commands[i] - table.AddRow(*s.Id, *s.CommandTemplateName, *s.CommandTemplateTitle, *s.Status, *s.StartedAt, *s.FinishedAt) + table.AddRow( + utils.PtrString(s.Id), + utils.PtrString(s.CommandTemplateName), + utils.PtrString(s.CommandTemplateTitle), + utils.PtrString(s.Status), + utils.PtrString(s.StartedAt), + utils.PtrString(s.FinishedAt), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/command/template/describe/describe.go b/internal/cmd/beta/server/command/template/describe/describe.go index c393b1892..054e81940 100644 --- a/internal/cmd/beta/server/command/template/describe/describe.go +++ b/internal/cmd/beta/server/command/template/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) @@ -129,14 +129,16 @@ func outputResult(p *print.Printer, outputFormat string, commandTemplate *runcom return nil default: table := tables.NewTable() - table.AddRow("NAME", *commandTemplate.Name) + table.AddRow("NAME", utils.PtrString(commandTemplate.Name)) table.AddSeparator() - table.AddRow("TITLE", *commandTemplate.Title) + table.AddRow("TITLE", utils.PtrString(commandTemplate.Title)) table.AddSeparator() - table.AddRow("DESCRIPTION", *commandTemplate.Description) - table.AddSeparator() - table.AddRow("OS TYPE", strings.Join(*commandTemplate.OsType, "\n")) + table.AddRow("DESCRIPTION", utils.PtrString(commandTemplate.Description)) table.AddSeparator() + if commandTemplate.OsType != nil { + table.AddRow("OS TYPE", strings.Join(*commandTemplate.OsType, "\n")) + table.AddSeparator() + } if commandTemplate.ParameterSchema != nil { table.AddRow("PARAMS", *commandTemplate.ParameterSchema) } else { diff --git a/internal/cmd/beta/server/command/template/list/list.go b/internal/cmd/beta/server/command/template/list/list.go index a544b2fc6..03485da5a 100644 --- a/internal/cmd/beta/server/command/template/list/list.go +++ b/internal/cmd/beta/server/command/template/list/list.go @@ -4,10 +4,9 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/goccy/go-yaml" - + "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" @@ -16,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) @@ -143,7 +141,17 @@ func outputResult(p *print.Printer, outputFormat string, templates []runcommand. table.SetHeader("NAME", "OS TYPE", "TITLE") for i := range templates { s := templates[i] - table.AddRow(*s.Name, strings.Join(*s.OsType, ","), *s.Title) + + var osType string + if s.OsType != nil && len(*s.OsType) > 0 { + osType = utils.JoinStringPtr(s.OsType, ",") + } + + table.AddRow( + utils.PtrString(s.Name), + osType, + utils.PtrString(s.Title), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/console/console.go b/internal/cmd/beta/server/console/console.go index 1e9bf05e3..006936dcf 100644 --- a/internal/cmd/beta/server/console/console.go +++ b/internal/cmd/beta/server/console/console.go @@ -127,6 +127,9 @@ func outputResult(p *print.Printer, model *inputModel, serverLabel string, serve return nil default: + if serverUrl.GetUrl() == nil { + return fmt.Errorf("server url is nil") + } // unescape url in order to get rid of e.g. %40 unescapedURL, err := url.PathUnescape(*serverUrl.GetUrl()) if err != nil { diff --git a/internal/cmd/beta/server/create/create.go b/internal/cmd/beta/server/create/create.go index 106956633..f1c4bf0cf 100644 --- a/internal/cmd/beta/server/create/create.go +++ b/internal/cmd/beta/server/create/create.go @@ -353,7 +353,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, serv return nil default: - p.Outputf("Created server for project %q.\nServer ID: %s\n", projectLabel, *server.Id) + p.Outputf("Created server for project %q.\nServer ID: %s\n", projectLabel, utils.PtrString(server.Id)) return nil } } diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/beta/server/describe/describe.go index abfe5a99b..0f69c92d6 100644 --- a/internal/cmd/beta/server/describe/describe.go +++ b/internal/cmd/beta/server/describe/describe.go @@ -129,19 +129,19 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro table := tables.NewTable() table.SetTitle("Server") - table.AddRow("ID", *server.Id) + table.AddRow("ID", utils.PtrString(server.Id)) table.AddSeparator() - table.AddRow("NAME", *server.Name) + table.AddRow("NAME", utils.PtrString(server.Name)) table.AddSeparator() - table.AddRow("STATE", *server.Status) + table.AddRow("STATE", utils.PtrString(server.Status)) table.AddSeparator() - table.AddRow("AVAILABILITY ZONE", *server.AvailabilityZone) + table.AddRow("AVAILABILITY ZONE", utils.PtrString(server.AvailabilityZone)) table.AddSeparator() if server.BootVolume != nil && server.BootVolume.Id != nil { table.AddRow("BOOT VOLUME", *server.BootVolume.Id) table.AddSeparator() } - table.AddRow("POWER STATUS", *server.PowerStatus) + table.AddRow("POWER STATUS", utils.PtrString(server.PowerStatus)) table.AddSeparator() if server.AffinityGroup != nil { diff --git a/internal/cmd/beta/server/network-interface/attach/attach.go b/internal/cmd/beta/server/network-interface/attach/attach.go index 1a2b45d45..ecbf6bd41 100644 --- a/internal/cmd/beta/server/network-interface/attach/attach.go +++ b/internal/cmd/beta/server/network-interface/attach/attach.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -106,7 +107,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("attach network interface: %w", err) } - p.Info("Attached network interface %q to server %q\n", *model.NicId, serverLabel) + p.Info("Attached network interface %q to server %q\n", utils.PtrString(model.NicId), serverLabel) return nil }, diff --git a/internal/cmd/beta/server/network-interface/detach/detach.go b/internal/cmd/beta/server/network-interface/detach/detach.go index fb11d12d9..57e9c1f7a 100644 --- a/internal/cmd/beta/server/network-interface/detach/detach.go +++ b/internal/cmd/beta/server/network-interface/detach/detach.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -106,7 +107,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("detach network interface: %w", err) } - p.Info("Detached network interface %q from server %q\n", *model.NicId, serverLabel) + p.Info("Detached network interface %q from server %q\n", utils.PtrString(model.NicId), serverLabel) return nil }, diff --git a/internal/cmd/beta/server/network-interface/list/list.go b/internal/cmd/beta/server/network-interface/list/list.go index 307afdbcd..b715527f4 100644 --- a/internal/cmd/beta/server/network-interface/list/list.go +++ b/internal/cmd/beta/server/network-interface/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,9 +16,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" - - "github.com/spf13/cobra" ) const ( @@ -162,7 +162,7 @@ func outputResult(p *print.Printer, outputFormat, serverId string, serverNics [] for i := range serverNics { nic := serverNics[i] - table.AddRow(*nic.Id, serverId) + table.AddRow(utils.PtrString(nic.Id), serverId) } table.EnableAutoMergeOnColumns(2) diff --git a/internal/cmd/beta/server/os-update/create/create.go b/internal/cmd/beta/server/os-update/create/create.go index bf0bf664d..076a4d204 100644 --- a/internal/cmd/beta/server/os-update/create/create.go +++ b/internal/cmd/beta/server/os-update/create/create.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" @@ -141,7 +142,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update return nil default: - p.Outputf("Triggered creation of server os-update for server %s. Update ID: %d\n", model.ServerId, *resp.Id) + p.Outputf("Triggered creation of server os-update for server %s. Update ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/os-update/describe/describe.go b/internal/cmd/beta/server/os-update/describe/describe.go index 3a92dd3dc..2a3c1fbed 100644 --- a/internal/cmd/beta/server/os-update/describe/describe.go +++ b/internal/cmd/beta/server/os-update/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) @@ -128,28 +128,19 @@ func outputResult(p *print.Printer, outputFormat string, update *serverupdate.Up return nil default: table := tables.NewTable() - table.AddRow("ID", *update.Id) + table.AddRow("ID", utils.PtrString(update.Id)) table.AddSeparator() - table.AddRow("STATUS", *update.Status) + table.AddRow("STATUS", utils.PtrString(update.Status)) table.AddSeparator() - if update.InstalledUpdates != nil { - table.AddRow("INSTALLED UPDATES", *update.InstalledUpdates) - } else { - table.AddRow("INSTALLED UPDATES", "...") - } + installedUpdates := utils.PtrStringDefault(update.InstalledUpdates, "n/a") + table.AddRow("INSTALLED UPDATES", installedUpdates) table.AddSeparator() - if update.FailedUpdates != nil { - table.AddRow("FAILED UPDATES", *update.FailedUpdates) - } else { - table.AddRow("FAILED UPDATES", "...") - } - table.AddRow("START DATE", *update.StartDate) + failedUpdates := utils.PtrStringDefault(update.FailedUpdates, "n/a") + table.AddRow("FAILED UPDATES", failedUpdates) + + table.AddRow("START DATE", utils.PtrString(update.StartDate)) table.AddSeparator() - if update.EndDate != nil { - table.AddRow("END DATE", *update.EndDate) - } else { - table.AddRow("END DATE", "...") - } + table.AddRow("END DATE", utils.PtrString(update.EndDate)) table.AddSeparator() err := table.Display(p) diff --git a/internal/cmd/beta/server/os-update/list/list.go b/internal/cmd/beta/server/os-update/list/list.go index 2f41b0ab1..5a25607dd 100644 --- a/internal/cmd/beta/server/os-update/list/list.go +++ b/internal/cmd/beta/server/os-update/list/list.go @@ -6,8 +6,6 @@ import ( "fmt" "strconv" - "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -16,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) @@ -151,22 +151,26 @@ func outputResult(p *print.Printer, outputFormat string, updates []serverupdate. for i := range updates { s := updates[i] - endDate := "..." - if s.EndDate != nil { - endDate = *s.EndDate - } + endDate := utils.PtrStringDefault(s.EndDate, "n/a") - installed := "..." + installed := "n/a" if s.InstalledUpdates != nil { installed = strconv.FormatInt(*s.InstalledUpdates, 10) } - failed := "..." + failed := "n/a" if s.FailedUpdates != nil { failed = strconv.FormatInt(*s.FailedUpdates, 10) } - table.AddRow(*s.Id, *s.Status, installed, failed, *s.StartDate, endDate) + table.AddRow( + utils.PtrString(s.Id), + utils.PtrString(s.Status), + installed, + failed, + utils.PtrString(s.StartDate), + endDate, + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/os-update/schedule/create/create.go b/internal/cmd/beta/server/os-update/schedule/create/create.go index 5a4d7ce93..fb767e690 100644 --- a/internal/cmd/beta/server/os-update/schedule/create/create.go +++ b/internal/cmd/beta/server/os-update/schedule/create/create.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" @@ -161,7 +162,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update return nil default: - p.Outputf("Created server os-update schedule for server %s. os-update Schedule ID: %d\n", model.ServerId, *resp.Id) + p.Outputf("Created server os-update schedule for server %s. os-update Schedule ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/os-update/schedule/describe/describe.go b/internal/cmd/beta/server/os-update/schedule/describe/describe.go index d46bf0a1e..33a5caefa 100644 --- a/internal/cmd/beta/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/beta/server/os-update/schedule/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) @@ -128,15 +128,15 @@ func outputResult(p *print.Printer, outputFormat string, schedule *serverupdate. return nil default: table := tables.NewTable() - table.AddRow("SCHEDULE ID", *schedule.Id) + table.AddRow("SCHEDULE ID", utils.PtrString(schedule.Id)) table.AddSeparator() - table.AddRow("SCHEDULE NAME", *schedule.Name) + table.AddRow("SCHEDULE NAME", utils.PtrString(schedule.Name)) table.AddSeparator() - table.AddRow("ENABLED", *schedule.Enabled) + table.AddRow("ENABLED", utils.PtrString(schedule.Enabled)) table.AddSeparator() - table.AddRow("RRULE", *schedule.Rrule) + table.AddRow("RRULE", utils.PtrString(schedule.Rrule)) table.AddSeparator() - table.AddRow("MAINTENANCE WINDOW", *schedule.MaintenanceWindow) + table.AddRow("MAINTENANCE WINDOW", utils.PtrString(schedule.MaintenanceWindow)) table.AddSeparator() err := table.Display(p) diff --git a/internal/cmd/beta/server/os-update/schedule/list/list.go b/internal/cmd/beta/server/os-update/schedule/list/list.go index f24d8becf..b9d1f0cff 100644 --- a/internal/cmd/beta/server/os-update/schedule/list/list.go +++ b/internal/cmd/beta/server/os-update/schedule/list/list.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" - + "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" @@ -15,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) @@ -149,7 +148,13 @@ func outputResult(p *print.Printer, outputFormat string, schedules []serverupdat table.SetHeader("SCHEDULE ID", "SCHEDULE NAME", "ENABLED", "RRULE", "MAINTENANCE WINDOW") for i := range schedules { s := schedules[i] - table.AddRow(*s.Id, *s.Name, *s.Enabled, *s.Rrule, *s.MaintenanceWindow) + table.AddRow( + utils.PtrString(s.Id), + utils.PtrString(s.Name), + utils.PtrString(s.Enabled), + utils.PtrString(s.Rrule), + utils.PtrString(s.MaintenanceWindow), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/os-update/schedule/update/update.go b/internal/cmd/beta/server/os-update/schedule/update/update.go index c85a429f2..5b8251d70 100644 --- a/internal/cmd/beta/server/os-update/schedule/update/update.go +++ b/internal/cmd/beta/server/os-update/schedule/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -13,8 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) @@ -185,7 +185,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update return nil default: - p.Info("Updated server os-update schedule %d\n", *resp.Id) + p.Info("Updated server os-update schedule %s\n", utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/rescue/rescue.go b/internal/cmd/beta/server/rescue/rescue.go index b634587fe..ef6474220 100644 --- a/internal/cmd/beta/server/rescue/rescue.go +++ b/internal/cmd/beta/server/rescue/rescue.go @@ -93,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered rescue of" } - p.Info("%s server %q. Image %q is used as temporary boot image\n", operationState, serverLabel, *model.ImageId) + p.Info("%s server %q. Image %q is used as temporary boot image\n", operationState, serverLabel, utils.PtrString(model.ImageId)) return nil }, diff --git a/internal/cmd/beta/server/volume/describe/describe.go b/internal/cmd/beta/server/volume/describe/describe.go index d5e4a3146..cc77e843d 100644 --- a/internal/cmd/beta/server/volume/describe/describe.go +++ b/internal/cmd/beta/server/volume/describe/describe.go @@ -147,11 +147,11 @@ func outputResult(p *print.Printer, outputFormat, serverLabel, volumeLabel strin return nil default: table := tables.NewTable() - table.AddRow("SERVER ID", *volume.ServerId) + table.AddRow("SERVER ID", utils.PtrString(volume.ServerId)) table.AddSeparator() table.AddRow("SERVER NAME", serverLabel) table.AddSeparator() - table.AddRow("VOLUME ID", *volume.VolumeId) + table.AddRow("VOLUME ID", utils.PtrString(volume.VolumeId)) table.AddSeparator() // check if name is set if volumeLabel != "" { diff --git a/internal/cmd/beta/server/volume/list/list.go b/internal/cmd/beta/server/volume/list/list.go index f09ddf5dc..eefc47f94 100644 --- a/internal/cmd/beta/server/volume/list/list.go +++ b/internal/cmd/beta/server/volume/list/list.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" - + "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" @@ -16,9 +16,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" - - "github.com/spf13/cobra" ) const ( @@ -150,7 +149,7 @@ func outputResult(p *print.Printer, outputFormat, serverLabel string, volumeName table.SetHeader("SERVER ID", "SERVER NAME", "VOLUME ID", "VOLUME NAME") for i := range volumes { s := volumes[i] - table.AddRow(*s.ServerId, serverLabel, *s.VolumeId, volumeNames[i]) + table.AddRow(utils.PtrString(s.ServerId), serverLabel, utils.PtrString(s.VolumeId), volumeNames[i]) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index 26f5babc4..009ebfc0c 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,9 +15,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" - - "github.com/spf13/cobra" ) const ( @@ -130,9 +130,9 @@ func outputResult(p *print.Printer, outputFormat string, database *sqlserverflex default: database := database.Database table := tables.NewTable() - table.AddRow("ID", *database.Id) + table.AddRow("ID", utils.PtrString(database.Id)) table.AddSeparator() - table.AddRow("NAME", *database.Name) + table.AddRow("NAME", utils.PtrString(database.Name)) table.AddSeparator() if database.Options != nil { if database.Options.CompatibilityLevel != nil { diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index 990884253..aac09fc65 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,9 +16,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" - - "github.com/spf13/cobra" ) const ( @@ -159,7 +159,7 @@ func outputResult(p *print.Printer, outputFormat string, databases []sqlserverfl table.SetHeader("ID", "NAME") for i := range databases { database := databases[i] - table.AddRow(*database.Id, *database.Name) + table.AddRow(utils.PtrString(database.Id), utils.PtrString(database.Name)) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 8e0b87819..82ec72f8b 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -284,7 +284,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.Id) + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index a9e868292..59525c85d 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -117,29 +117,32 @@ func outputResult(p *print.Printer, outputFormat string, instance *sqlserverflex return nil default: - aclsArray := *instance.Acl.Items - acls := strings.Join(aclsArray, ",") + var acls string + if instance.Acl != nil && instance.Acl.HasItems() { + aclsArray := *instance.Acl.Items + acls = strings.Join(aclsArray, ",") + } table := tables.NewTable() - table.AddRow("ID", *instance.Id) + table.AddRow("ID", utils.PtrString(instance.Id)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("STATUS", *instance.Status) + table.AddRow("STATUS", utils.PtrString(instance.Status)) table.AddSeparator() - table.AddRow("STORAGE SIZE (GB)", *instance.Storage.Size) + table.AddRow("STORAGE SIZE (GB)", utils.PtrString(instance.Storage.Size)) table.AddSeparator() - table.AddRow("VERSION", *instance.Version) + table.AddRow("VERSION", utils.PtrString(instance.Version)) table.AddSeparator() - table.AddRow("BACKUP SCHEDULE (UTC)", *instance.BackupSchedule) + table.AddRow("BACKUP SCHEDULE (UTC)", utils.PtrString(instance.BackupSchedule)) table.AddSeparator() table.AddRow("ACL", acls) table.AddSeparator() - table.AddRow("FLAVOR DESCRIPTION", *instance.Flavor.Description) + table.AddRow("FLAVOR DESCRIPTION", utils.PtrString(instance.Flavor.Description)) table.AddSeparator() - table.AddRow("CPU", *instance.Flavor.Cpu) + table.AddRow("CPU", utils.PtrString(instance.Flavor.Cpu)) table.AddSeparator() - table.AddRow("RAM (GB)", *instance.Flavor.Memory) + table.AddRow("RAM (GB)", utils.PtrString(instance.Flavor.Memory)) table.AddSeparator() err := table.Display(p) diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 92814d3e4..b524c088a 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -152,7 +152,11 @@ func outputResult(p *print.Printer, outputFormat string, instances []sqlserverfl table.SetHeader("ID", "NAME", "STATUS") for i := range instances { instance := instances[i] - table.AddRow(*instance.Id, *instance.Name, *instance.Status) + table.AddRow( + utils.PtrString(instance.Id), + utils.PtrString(instance.Name), + utils.PtrString(instance.Status), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 7fc9b05e0..7153f4dca 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -16,6 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" sqlserverflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -161,9 +162,9 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, use 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("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) + p.Outputf("Username: %s\n", utils.PtrString(user.Username)) + p.Outputf("Password: %s\n", utils.PtrString(user.Password)) if user.Roles != nil && len(*user.Roles) != 0 { p.Outputf("Roles: [%v]\n", strings.Join(*user.Roles, ", ")) } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index 0f0e28ae5..a679a3e05 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" @@ -137,9 +138,9 @@ func outputResult(p *print.Printer, outputFormat string, user sqlserverflex.User return nil default: table := tables.NewTable() - table.AddRow("ID", *user.Id) + table.AddRow("ID", utils.PtrString(user.Id)) table.AddSeparator() - table.AddRow("USERNAME", *user.Username) + table.AddRow("USERNAME", utils.PtrString(user.Username)) if user.Roles != nil && len(*user.Roles) != 0 { table.AddSeparator() table.AddRow("ROLES", strings.Join(*user.Roles, "\n")) diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index 005f437f9..32f9d1557 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" sqlserverflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -160,7 +160,10 @@ func outputResult(p *print.Printer, outputFormat string, users []sqlserverflex.I table.SetHeader("ID", "USERNAME") for i := range users { user := users[i] - table.AddRow(*user.Id, *user.Username) + table.AddRow( + utils.PtrString(user.Id), + utils.PtrString(user.Username), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index d8cd47ad4..6218406a6 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client" sqlserverflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" @@ -152,8 +153,8 @@ func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel 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("Username: %s\n", utils.PtrString(user.Username)) + p.Outputf("New password: %s\n", utils.PtrString(user.Password)) if user.Uri != nil && *user.Uri != "" { p.Outputf("New URI: %s\n", *user.Uri) } diff --git a/internal/cmd/beta/volume/create/create.go b/internal/cmd/beta/volume/create/create.go index 943ee7d85..0374c5f46 100644 --- a/internal/cmd/beta/volume/create/create.go +++ b/internal/cmd/beta/volume/create/create.go @@ -217,7 +217,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, volu return nil default: - p.Outputf("Created volume for project %q.\nVolume ID: %s\n", projectLabel, *volume.Id) + p.Outputf("Created volume for project %q.\nVolume ID: %s\n", projectLabel, utils.PtrString(volume.Id)) return nil } } diff --git a/internal/cmd/beta/volume/describe/describe.go b/internal/cmd/beta/volume/describe/describe.go index 3f70f6fea..c62a0cedf 100644 --- a/internal/cmd/beta/volume/describe/describe.go +++ b/internal/cmd/beta/volume/describe/describe.go @@ -121,17 +121,17 @@ func outputResult(p *print.Printer, outputFormat string, volume *iaas.Volume) er return nil default: table := tables.NewTable() - table.AddRow("ID", *volume.Id) + table.AddRow("ID", utils.PtrString(volume.Id)) table.AddSeparator() - table.AddRow("NAME", *volume.Name) + table.AddRow("NAME", utils.PtrString(volume.Name)) table.AddSeparator() - table.AddRow("STATE", *volume.Status) + table.AddRow("STATE", utils.PtrString(volume.Status)) table.AddSeparator() - table.AddRow("VOLUME SIZE (GB)", *volume.Size) + table.AddRow("VOLUME SIZE (GB)", utils.PtrString(volume.Size)) table.AddSeparator() - table.AddRow("PERFORMANCE CLASS", *volume.PerformanceClass) + table.AddRow("PERFORMANCE CLASS", utils.PtrString(volume.PerformanceClass)) table.AddSeparator() - table.AddRow("AVAILABILITY ZONE", *volume.AvailabilityZone) + table.AddRow("AVAILABILITY ZONE", utils.PtrString(volume.AvailabilityZone)) table.AddSeparator() if volume.Source != nil { diff --git a/internal/cmd/beta/volume/list/list.go b/internal/cmd/beta/volume/list/list.go index 47b73170b..a9920f438 100644 --- a/internal/cmd/beta/volume/list/list.go +++ b/internal/cmd/beta/volume/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,9 +16,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" - - "github.com/spf13/cobra" ) const ( @@ -167,11 +167,14 @@ func outputResult(p *print.Printer, outputFormat string, volumes []iaas.Volume) table.SetHeader("ID", "Name", "Status", "Server", "Availability Zone", "Size (GB)") for _, volume := range volumes { - serverId := "" - if volume.ServerId != nil { - serverId = *volume.ServerId - } - table.AddRow(*volume.Id, *volume.Name, *volume.Status, serverId, *volume.AvailabilityZone, *volume.Size) + table.AddRow( + utils.PtrString(volume.Id), + utils.PtrString(volume.Name), + utils.PtrString(volume.Status), + utils.PtrString(volume.ServerId), + utils.PtrString(volume.AvailabilityZone), + utils.PtrString(volume.Size), + ) table.AddSeparator() } diff --git a/internal/cmd/beta/volume/performance-class/describe/describe.go b/internal/cmd/beta/volume/performance-class/describe/describe.go index 4864f25c5..b867f2e70 100644 --- a/internal/cmd/beta/volume/performance-class/describe/describe.go +++ b/internal/cmd/beta/volume/performance-class/describe/describe.go @@ -121,7 +121,7 @@ func outputResult(p *print.Printer, outputFormat string, performanceClass *iaas. return nil default: table := tables.NewTable() - table.AddRow("NAME", *performanceClass.Name) + table.AddRow("NAME", utils.PtrString(performanceClass.Name)) table.AddSeparator() table.AddRow("DESCRIPTION", utils.PtrString(performanceClass.Description)) table.AddSeparator() diff --git a/internal/cmd/beta/volume/performance-class/list/list.go b/internal/cmd/beta/volume/performance-class/list/list.go index 7c37b7284..3bc6ed37f 100644 --- a/internal/cmd/beta/volume/performance-class/list/list.go +++ b/internal/cmd/beta/volume/performance-class/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/cobra" @@ -167,7 +168,7 @@ func outputResult(p *print.Printer, outputFormat string, performanceClasses []ia table.SetHeader("Name", "Description") for _, performanceClass := range performanceClasses { - table.AddRow(*performanceClass.Name, *performanceClass.Description) + table.AddRow(utils.PtrString(performanceClass.Name), utils.PtrString(performanceClass.Description)) table.AddSeparator() } diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index ed77e5735..3ed23f57d 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -203,7 +203,7 @@ func outputResult(p *print.Printer, model *inputModel, zoneLabel string, resp *d 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) + p.Outputf("%s record set for zone %s. Record set ID: %s\n", operationState, zoneLabel, utils.PtrString(resp.Rrset.Id)) return nil } } diff --git a/internal/cmd/dns/record-set/describe/describe.go b/internal/cmd/dns/record-set/describe/describe.go index 221729d91..536ff5c64 100644 --- a/internal/cmd/dns/record-set/describe/describe.go +++ b/internal/cmd/dns/record-set/describe/describe.go @@ -139,15 +139,15 @@ func outputResult(p *print.Printer, outputFormat string, recordSet *dns.RecordSe recordsDataJoin := strings.Join(recordsData, ", ") table := tables.NewTable() - table.AddRow("ID", *recordSet.Id) + table.AddRow("ID", utils.PtrString(recordSet.Id)) table.AddSeparator() - table.AddRow("NAME", *recordSet.Name) + table.AddRow("NAME", utils.PtrString(recordSet.Name)) table.AddSeparator() - table.AddRow("STATE", *recordSet.State) + table.AddRow("STATE", utils.PtrString(recordSet.State)) table.AddSeparator() - table.AddRow("TTL", *recordSet.Ttl) + table.AddRow("TTL", utils.PtrString(recordSet.Ttl)) table.AddSeparator() - table.AddRow("TYPE", *recordSet.Type) + table.AddRow("TYPE", utils.PtrString(recordSet.Type)) table.AddSeparator() table.AddRow("RECORDS DATA", recordsDataJoin) err := table.Display(p) diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index caca06264..3e2bf0f81 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "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" @@ -17,8 +18,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/dns/client" dnsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/dns/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -276,7 +276,14 @@ func outputResult(p *print.Printer, outputFormat string, recordSets []dns.Record recordData = append(recordData, *r.Content) } recordDataJoin := strings.Join(recordData, ", ") - table.AddRow(*rs.Id, *rs.Name, *rs.State, *rs.Ttl, *rs.Type, recordDataJoin) + table.AddRow( + utils.PtrString(rs.Id), + utils.PtrString(rs.Name), + utils.PtrString(rs.State), + utils.PtrString(rs.Ttl), + utils.PtrString(rs.Type), + recordDataJoin, + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index e1af7022a..e950cdcce 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -182,7 +182,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if model.Async { operationState = "Triggered cloning of" } - p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, *resp.Zone.Id) + p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Zone.Id)) return nil } } diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 32e6ab636..2ad572f5a 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/dns/client" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/dns" @@ -218,7 +219,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, *resp.Zone.Id) + p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Zone.Id)) return nil } } diff --git a/internal/cmd/dns/zone/describe/describe.go b/internal/cmd/dns/zone/describe/describe.go index 578dee03c..56308972f 100644 --- a/internal/cmd/dns/zone/describe/describe.go +++ b/internal/cmd/dns/zone/describe/describe.go @@ -118,35 +118,35 @@ func outputResult(p *print.Printer, outputFormat string, zone *dns.Zone) error { return nil default: table := tables.NewTable() - table.AddRow("ID", *zone.Id) + table.AddRow("ID", utils.PtrString(zone.Id)) table.AddSeparator() - table.AddRow("NAME", *zone.Name) + table.AddRow("NAME", utils.PtrString(zone.Name)) table.AddSeparator() - table.AddRow("DESCRIPTION", *zone.Description) + table.AddRow("DESCRIPTION", utils.PtrString(zone.Description)) table.AddSeparator() - table.AddRow("STATE", *zone.State) + table.AddRow("STATE", utils.PtrString(zone.State)) table.AddSeparator() - table.AddRow("TYPE", *zone.Type) + table.AddRow("TYPE", utils.PtrString(zone.Type)) table.AddSeparator() - table.AddRow("DNS NAME", *zone.DnsName) + table.AddRow("DNS NAME", utils.PtrString(zone.DnsName)) table.AddSeparator() - table.AddRow("REVERSE ZONE", *zone.IsReverseZone) + table.AddRow("REVERSE ZONE", utils.PtrString(zone.IsReverseZone)) table.AddSeparator() - table.AddRow("RECORD COUNT", *zone.RecordCount) + table.AddRow("RECORD COUNT", utils.PtrString(zone.RecordCount)) table.AddSeparator() - table.AddRow("CONTACT EMAIL", *zone.ContactEmail) + table.AddRow("CONTACT EMAIL", utils.PtrString(zone.ContactEmail)) table.AddSeparator() - table.AddRow("DEFAULT TTL", *zone.DefaultTTL) + table.AddRow("DEFAULT TTL", utils.PtrString(zone.DefaultTTL)) table.AddSeparator() - table.AddRow("SERIAL NUMBER", *zone.SerialNumber) + table.AddRow("SERIAL NUMBER", utils.PtrString(zone.SerialNumber)) table.AddSeparator() - table.AddRow("REFRESH TIME", *zone.RefreshTime) + table.AddRow("REFRESH TIME", utils.PtrString(zone.RefreshTime)) table.AddSeparator() - table.AddRow("RETRY TIME", *zone.RetryTime) + table.AddRow("RETRY TIME", utils.PtrString(zone.RetryTime)) table.AddSeparator() - table.AddRow("EXPIRE TIME", *zone.ExpireTime) + table.AddRow("EXPIRE TIME", utils.PtrString(zone.ExpireTime)) table.AddSeparator() - table.AddRow("NEGATIVE CACHE", *zone.NegativeCache) + table.AddRow("NEGATIVE CACHE", utils.PtrString(zone.NegativeCache)) err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index a318ef381..7f1bd2a34 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -17,6 +17,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/dns/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/dns" @@ -260,7 +261,13 @@ func outputResult(p *print.Printer, outputFormat string, zones []dns.Zone) error table.SetHeader("ID", "NAME", "STATE", "TYPE", "DNS NAME", "RECORD COUNT") for i := range zones { z := zones[i] - table.AddRow(*z.Id, *z.Name, *z.State, *z.Type, *z.DnsName, *z.RecordCount) + table.AddRow(utils.PtrString(z.Id), + utils.PtrString(z.Name), + utils.PtrString(z.State), + utils.PtrString(z.Type), + utils.PtrString(z.DnsName), + utils.PtrString(z.RecordCount), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index c6364ef2e..e106d4aa9 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -6,20 +6,18 @@ import ( "fmt" "github.com/google/uuid" - - "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" - "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" - + "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" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/client" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer/wait" ) @@ -108,7 +106,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s load balancer with name %q \n", operationState, *model.Payload.Name) + p.Outputf("%s load balancer with name %q \n", operationState, utils.PtrString(model.Payload.Name)) return nil }, } diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index d08e5a99e..bd98be64c 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -160,10 +161,7 @@ func buildLoadBalancerTable(loadBalancer *loadbalancer.LoadBalancer) tables.Tabl networkId = *networks[0].NetworkId } - externalAdress := "-" - if loadBalancer.ExternalAddress != nil { - externalAdress = *loadBalancer.ExternalAddress - } + externalAddress := utils.PtrStringDefault(loadBalancer.ExternalAddress, "-") errorDescriptions := []string{} if loadBalancer.Errors != nil && len((*loadBalancer.Errors)) > 0 { @@ -174,9 +172,9 @@ func buildLoadBalancerTable(loadBalancer *loadbalancer.LoadBalancer) tables.Tabl table := tables.NewTable() table.SetTitle("Load Balancer") - table.AddRow("NAME", *loadBalancer.Name) + table.AddRow("NAME", utils.PtrString(loadBalancer.Name)) table.AddSeparator() - table.AddRow("STATE", *loadBalancer.Status) + table.AddRow("STATE", utils.PtrString(loadBalancer.Status)) table.AddSeparator() if len(errorDescriptions) > 0 { table.AddRow("ERROR DESCRIPTIONS", strings.Join(errorDescriptions, "\n")) @@ -184,7 +182,7 @@ func buildLoadBalancerTable(loadBalancer *loadbalancer.LoadBalancer) tables.Tabl } table.AddRow("PRIVATE ACCESS ONLY", privateAccessOnly) table.AddSeparator() - table.AddRow("ATTACHED PUBLIC IP", externalAdress) + table.AddRow("ATTACHED PUBLIC IP", externalAddress) table.AddSeparator() table.AddRow("ATTACHED NETWORK ID", networkId) table.AddSeparator() @@ -198,7 +196,12 @@ func buildListenersTable(listeners []loadbalancer.Listener) tables.Table { table.SetHeader("NAME", "PORT", "PROTOCOL", "TARGET POOL") for i := range listeners { listener := listeners[i] - table.AddRow(*listener.Name, *listener.Port, *listener.Protocol, *listener.TargetPool) + table.AddRow( + utils.PtrString(listener.Name), + utils.PtrString(listener.Port), + utils.PtrString(listener.Protocol), + utils.PtrString(listener.TargetPool), + ) } return table } @@ -208,7 +211,7 @@ func buildTargetPoolsTable(targetPools []loadbalancer.TargetPool) tables.Table { table.SetTitle("Target Pools") table.SetHeader("NAME", "PORT", "TARGETS") for _, targetPool := range targetPools { - table.AddRow(*targetPool.Name, *targetPool.TargetPort, len(*targetPool.Targets)) + table.AddRow(utils.PtrString(targetPool.Name), utils.PtrString(targetPool.TargetPort), len(*targetPool.Targets)) } return table } diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index 512f984db..dde4f20ec 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -153,11 +154,14 @@ func outputResult(p *print.Printer, outputFormat string, loadBalancers []loadbal table.SetHeader("NAME", "STATE", "IP ADDRESS", "LISTENERS", "TARGET POOLS") for i := range loadBalancers { l := loadBalancers[i] - externalAdress := "-" - if l.ExternalAddress != nil { - externalAdress = *l.ExternalAddress - } - table.AddRow(*l.Name, *l.Status, externalAdress, len(*l.Listeners), len(*l.TargetPools)) + externalAdress := utils.PtrStringDefault(l.ExternalAddress, "-") + table.AddRow( + utils.PtrString(l.Name), + utils.PtrString(l.Status), + externalAdress, + len(*l.Listeners), + len(*l.TargetPools), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index b6421195a..26c09bb90 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -167,7 +167,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil default: - p.Outputf("Added Load Balancer observability credentials on project %q. Credentials reference: %q\n", projectLabel, *resp.Credential.CredentialsRef) + p.Outputf("Added Load Balancer observability credentials on project %q. Credentials reference: %q\n", projectLabel, utils.PtrString(resp.Credential.CredentialsRef)) return nil } } diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index 27d27caf8..2fd1bc6e3 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -113,12 +114,17 @@ func outputResult(p *print.Printer, outputFormat string, credentials *loadbalanc return nil default: + if credentials == nil || credentials.Credential == nil { + p.Info("No credentials found") + return nil + } + table := tables.NewTable() - table.AddRow("REFERENCE", *credentials.Credential.CredentialsRef) + table.AddRow("REFERENCE", utils.PtrString(credentials.Credential.CredentialsRef)) table.AddSeparator() - table.AddRow("DISPLAY NAME", *credentials.Credential.DisplayName) + table.AddRow("DISPLAY NAME", utils.PtrString(credentials.Credential.DisplayName)) table.AddSeparator() - table.AddRow("USERNAME", *credentials.Credential.Username) + table.AddRow("USERNAME", utils.PtrString(credentials.Credential.Username)) table.AddSeparator() err := table.Display(p) if err != nil { diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 11c1a0161..8ed74da16 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,10 +15,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/client" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils" + lbUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -92,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return err } - credentials, err = utils.FilterCredentials(ctx, apiClient, credentials, model.ProjectId, filterOp) + credentials, err = lbUtils.FilterCredentials(ctx, apiClient, credentials, model.ProjectId, filterOp) if err != nil { return fmt.Errorf("filter credentials: %w", err) } @@ -189,7 +189,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []loadbalan table.SetHeader("REFERENCE", "DISPLAY NAME", "USERNAME") for i := range credentials { c := credentials[i] - table.AddRow(*c.CredentialsRef, *c.DisplayName, *c.Username) + table.AddRow(utils.PtrString(c.CredentialsRef), utils.PtrString(c.DisplayName), utils.PtrString(c.Username)) } err := table.Display(p) if err != nil { @@ -207,12 +207,12 @@ func getFilterOp(used, unused bool) (int, error) { } if !used && !unused { - return utils.OP_FILTER_NOP, nil + return lbUtils.OP_FILTER_NOP, nil } if used { - return utils.OP_FILTER_USED, nil + return lbUtils.OP_FILTER_USED, nil } - return utils.OP_FILTER_UNUSED, nil + return lbUtils.OP_FILTER_UNUSED, nil } diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index e3e5921fc..8eeceef88 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "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" @@ -15,10 +16,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/client" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils" + lbUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -67,12 +67,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read load balancer: %w", err) } - targetPool := utils.FindLoadBalancerTargetPoolByName(*resp.TargetPools, model.TargetPoolName) + targetPool := lbUtils.FindLoadBalancerTargetPoolByName(*resp.TargetPools, model.TargetPoolName) if targetPool == nil { return fmt.Errorf("target pool not found") } - listener := utils.FindLoadBalancerListenerByTargetPool(*resp.Listeners, *targetPool.Name) + listener := lbUtils.FindLoadBalancerListenerByTargetPool(*resp.Listeners, *targetPool.Name) return outputResult(p, model.OutputFormat, *targetPool, listener) }, @@ -183,7 +183,11 @@ func outputResultAsTable(p *print.Printer, targetPool loadbalancer.TargetPool, l listenerStr := "-" if listener != nil { - listenerStr = fmt.Sprintf("%s (Port:%d, Protocol: %s)", *listener.Name, *listener.Port, *listener.Protocol) + listenerStr = fmt.Sprintf("%s (Port:%s, Protocol: %s)", + utils.PtrString(listener.Name), + utils.PtrString(listener.Port), + utils.PtrString(listener.Protocol), + ) } table := tables.NewTable() diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 5d67574a2..b21bed0f0 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -144,20 +144,21 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(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.ShowPassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + if resp.HasRaw() && resp.Raw.Credentials != nil { + if username := resp.Raw.Credentials.Username; username != nil && *username != "" { + p.Outputf("Username: %s\n", utils.PtrString(username)) + } + if !model.ShowPassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) + } + p.Outputf("Host: %s\n", utils.PtrString(resp.Raw.Credentials.Host)) + p.Outputf("Port: %s\n", utils.PtrString(resp.Raw.Credentials.Port)) } - 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) + p.Outputf("URI: %s\n", utils.PtrString(resp.Uri)) return nil } } diff --git a/internal/cmd/logme/credentials/describe/describe.go b/internal/cmd/logme/credentials/describe/describe.go index e2b7551a9..2d51fe40b 100644 --- a/internal/cmd/logme/credentials/describe/describe.go +++ b/internal/cmd/logme/credentials/describe/describe.go @@ -131,17 +131,20 @@ func outputResult(p *print.Printer, outputFormat string, credentials *logme.Cred return nil default: table := tables.NewTable() - table.AddRow("ID", *credentials.Id) + table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty - username := *credentials.Raw.Credentials.Username - if username != "" { - table.AddRow("USERNAME", *credentials.Raw.Credentials.Username) - table.AddSeparator() + if raw := credentials.Raw; raw != nil { + if cred := raw.Credentials; cred != nil { + if username := cred.Username; username != nil && *username != "" { + table.AddRow("USERNAME", *username) + table.AddSeparator() + } + table.AddRow("PASSWORD", utils.PtrString(cred.Password)) + table.AddSeparator() + table.AddRow("URI", utils.PtrString(cred.Uri)) + } } - table.AddRow("PASSWORD", *credentials.Raw.Credentials.Password) - table.AddSeparator() - table.AddRow("URI", *credentials.Raw.Credentials.Uri) err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index e53a61174..cac18139b 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/logme/client" logmeUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/logme/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/logme" @@ -157,7 +158,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []logme.Cre table.SetHeader("ID") for i := range credentials { c := credentials[i] - table.AddRow(*c.Id) + table.AddRow(utils.PtrString(c.Id)) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index c6b34b62c..d77f9f64e 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -274,7 +274,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.InstanceId) + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) return nil } } diff --git a/internal/cmd/logme/instance/describe/describe.go b/internal/cmd/logme/instance/describe/describe.go index 9e477f16a..896f42982 100644 --- a/internal/cmd/logme/instance/describe/describe.go +++ b/internal/cmd/logme/instance/describe/describe.go @@ -119,15 +119,15 @@ func outputResult(p *print.Printer, outputFormat string, instance *logme.Instanc return nil default: table := tables.NewTable() - table.AddRow("ID", *instance.InstanceId) + table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", *instance.LastOperation.Type) + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) table.AddSeparator() - table.AddRow("LAST OPERATION STATE", *instance.LastOperation.State) + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) table.AddSeparator() - table.AddRow("PLAN ID", *instance.PlanId) + table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty acl := (*instance.Parameters)[aclParameterKey] aclStr, ok := acl.(string) diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index dba438103..e8784d054 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/logme/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/logme" ) @@ -152,7 +152,12 @@ func outputResult(p *print.Printer, outputFormat string, instances []logme.Insta table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] - table.AddRow(*instance.InstanceId, *instance.Name, *instance.LastOperation.Type, *instance.LastOperation.State) + table.AddRow( + utils.PtrString(instance.InstanceId), + utils.PtrString(instance.Name), + utils.PtrString(instance.LastOperation.Type), + utils.PtrString(instance.LastOperation.State), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index b1500eccd..6177a4143 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/logme/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/logme" ) @@ -154,7 +154,13 @@ func outputResult(p *print.Printer, outputFormat string, plans []logme.Offering) o := plans[i] for j := range *o.Plans { p := (*o.Plans)[j] - table.AddRow(*o.Name, *o.Version, *p.Id, *p.Name, *p.Description) + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(p.Id), + utils.PtrString(p.Name), + utils.PtrString(p.Description), + ) } table.AddSeparator() } diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 602286821..404d5e8a9 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -145,20 +145,21 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(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.ShowPassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + if resp.HasRaw() && resp.Raw.Credentials != nil { + if username := resp.Raw.Credentials.Username; username != nil && *username != "" { + p.Outputf("Username: %s\n", *username) + } + if !model.ShowPassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) + } + p.Outputf("Host: %s\n", utils.PtrString(resp.Raw.Credentials.Host)) + p.Outputf("Port: %s\n", utils.PtrString(resp.Raw.Credentials.Port)) } - 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) + p.Outputf("URI: %s\n", utils.PtrString(resp.Uri)) return nil } } diff --git a/internal/cmd/mariadb/credentials/describe/describe.go b/internal/cmd/mariadb/credentials/describe/describe.go index ae5eeece0..31a09a17e 100644 --- a/internal/cmd/mariadb/credentials/describe/describe.go +++ b/internal/cmd/mariadb/credentials/describe/describe.go @@ -134,14 +134,15 @@ func outputResult(p *print.Printer, outputFormat string, credentials *mariadb.Cr table.AddRow("ID", *credentials.Id) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty - username := *credentials.Raw.Credentials.Username - if username != "" { - table.AddRow("USERNAME", *credentials.Raw.Credentials.Username) + if credentials.HasRaw() && credentials.Raw.Credentials != nil { + if username := credentials.Raw.Credentials.Username; username != nil && *username != "" { + table.AddRow("USERNAME", *username) + table.AddSeparator() + } + table.AddRow("PASSWORD", utils.PtrString(credentials.Raw.Credentials.Password)) table.AddSeparator() + table.AddRow("URI", utils.PtrString(credentials.Raw.Credentials.Uri)) } - table.AddRow("PASSWORD", *credentials.Raw.Credentials.Password) - table.AddSeparator() - table.AddRow("URI", *credentials.Raw.Credentials.Uri) err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index dde2678a1..47e15f379 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/mariadb/client" mariadbUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/mariadb/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) @@ -157,7 +157,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []mariadb.C table.SetHeader("ID") for i := range credentials { c := credentials[i] - table.AddRow(*c.Id) + table.AddRow(utils.PtrString(c.Id)) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index 097588efd..031ef8930 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -274,7 +274,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.InstanceId) + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) return nil } } diff --git a/internal/cmd/mariadb/instance/describe/describe.go b/internal/cmd/mariadb/instance/describe/describe.go index 94323bc5e..49788795c 100644 --- a/internal/cmd/mariadb/instance/describe/describe.go +++ b/internal/cmd/mariadb/instance/describe/describe.go @@ -119,15 +119,15 @@ func outputResult(p *print.Printer, outputFormat string, instance *mariadb.Insta return nil default: table := tables.NewTable() - table.AddRow("ID", *instance.InstanceId) + table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", *instance.LastOperation.Type) + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) table.AddSeparator() - table.AddRow("LAST OPERATION STATE", *instance.LastOperation.State) + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) table.AddSeparator() - table.AddRow("PLAN ID", *instance.PlanId) + table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty acl := (*instance.Parameters)[aclParameterKey] aclStr, ok := acl.(string) diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index e550b01f4..f360462d3 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/mariadb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) @@ -152,7 +152,12 @@ func outputResult(p *print.Printer, outputFormat string, instances []mariadb.Ins table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] - table.AddRow(*instance.InstanceId, *instance.Name, *instance.LastOperation.Type, *instance.LastOperation.State) + table.AddRow( + utils.PtrString(instance.InstanceId), + utils.PtrString(instance.Name), + utils.PtrString(instance.LastOperation.Type), + utils.PtrString(instance.LastOperation.State), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index fff09aaba..6d6053c21 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/mariadb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) @@ -154,7 +154,13 @@ func outputResult(p *print.Printer, outputFormat string, plans []mariadb.Offerin o := plans[i] for j := range *o.Plans { plan := (*o.Plans)[j] - table.AddRow(*o.Name, *o.Version, *plan.Id, *plan.Name, *plan.Description) + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + ) } table.AddSeparator() } diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index 6488c6ee7..4d2d9d108 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/goccy/go-yaml" - "github.com/inhies/go-bytesize" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -15,8 +14,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/client" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/utils" + mongoUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -60,7 +60,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := utils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongoUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -79,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get restore jobs for MongoDB Flex instance %q: %w", instanceLabel, err) } - restoreJobState := utils.GetRestoreStatus(model.BackupId, restoreJobs) + restoreJobState := mongoUtils.GetRestoreStatus(model.BackupId, restoreJobs) return outputResult(p, cmd, model.OutputFormat, restoreJobState, *resp.Item) }, } @@ -145,13 +145,14 @@ func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat, restoreSta return nil default: table := tables.NewTable() - table.AddRow("ID", *backup.Id) + table.AddRow("ID", utils.PtrString(backup.Id)) table.AddSeparator() - table.AddRow("CREATED AT", *backup.StartTime) + table.AddRow("CREATED AT", utils.PtrString(backup.StartTime)) table.AddSeparator() - table.AddRow("EXPIRES AT", *backup.EndTime) + table.AddRow("EXPIRES AT", utils.PtrString(backup.EndTime)) table.AddSeparator() - table.AddRow("BACKUP SIZE", bytesize.New(float64(*backup.Size))) + backupSize := utils.PtrByteSizeDefault(backup.Size, "n/a") + table.AddRow("BACKUP SIZE", backupSize) table.AddSeparator() table.AddRow("RESTORE STATUS", restoreStatus) diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index 13002dc49..9f19d9c3c 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/goccy/go-yaml" - "github.com/inhies/go-bytesize" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -16,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/client" mongodbflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" @@ -168,7 +168,13 @@ func outputResult(p *print.Printer, outputFormat string, backups []mongodbflex.B for i := range backups { backup := backups[i] restoreStatus := mongodbflexUtils.GetRestoreStatus(*backup.Id, restoreJobs) - table.AddRow(*backup.Id, *backup.StartTime, *backup.EndTime, bytesize.New(float64(*backup.Size)), restoreStatus) + backupSize := utils.PtrByteSizeDefault(backup.Size, "n/a") + table.AddRow( + utils.PtrString(backup.Id), + utils.PtrString(backup.StartTime), + utils.PtrString(backup.EndTime), + backupSize, + restoreStatus) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index 6b289d2f8..e77538fd3 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/client" mongodbflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -162,7 +162,13 @@ func outputResult(p *print.Printer, outputFormat string, restoreJobs []mongodbfl for i := range restoreJobs { restoreJob := restoreJobs[i] - table.AddRow(*restoreJob.Id, *restoreJob.BackupID, *restoreJob.InstanceId, *restoreJob.Date, *restoreJob.Status) + table.AddRow( + utils.PtrString(restoreJob.Id), + utils.PtrString(restoreJob.BackupID), + utils.PtrString(restoreJob.InstanceId), + utils.PtrString(restoreJob.Date), + utils.PtrString(restoreJob.Status), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index c8a5a316d..e4b0cbb75 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -139,18 +139,20 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I return nil default: table := tables.NewTable() - table.AddRow("BACKUP SCHEDULE (UTC)", *instance.BackupSchedule) - table.AddSeparator() - table.AddRow("DAILY SNAPSHOT RETENTION (DAYS)", (*instance.Options)["dailySnapshotRetentionDays"]) - table.AddSeparator() - table.AddRow("MONTHLY SNAPSHOT RETENTION (MONTHS)", (*instance.Options)["monthlySnapshotRetentionMonths"]) - table.AddSeparator() - table.AddRow("POINT IN TIME WINDOW (HOURS)", (*instance.Options)["pointInTimeWindowHours"]) - table.AddSeparator() - table.AddRow("SNAPSHOT RETENTION (DAYS)", (*instance.Options)["snapshotRetentionDays"]) - table.AddSeparator() - table.AddRow("WEEKLY SNAPSHOT RETENTION (WEEKS)", (*instance.Options)["weeklySnapshotRetentionWeeks"]) + table.AddRow("BACKUP SCHEDULE (UTC)", utils.PtrString(instance.BackupSchedule)) table.AddSeparator() + if instance.Options != nil { + table.AddRow("DAILY SNAPSHOT RETENTION (DAYS)", (*instance.Options)["dailySnapshotRetentionDays"]) + table.AddSeparator() + table.AddRow("MONTHLY SNAPSHOT RETENTION (MONTHS)", (*instance.Options)["monthlySnapshotRetentionMonths"]) + table.AddSeparator() + table.AddRow("POINT IN TIME WINDOW (HOURS)", (*instance.Options)["pointInTimeWindowHours"]) + table.AddSeparator() + table.AddRow("SNAPSHOT RETENTION (DAYS)", (*instance.Options)["snapshotRetentionDays"]) + table.AddSeparator() + table.AddRow("WEEKLY SNAPSHOT RETENTION (WEEKS)", (*instance.Options)["weeklySnapshotRetentionWeeks"]) + table.AddSeparator() + } err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 5962804a1..f4882ab95 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -296,7 +296,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.Id) + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index 810ae1a87..bac7b7205 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -140,17 +140,23 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I table.AddSeparator() table.AddRow("ACL", acls) table.AddSeparator() - table.AddRow("FLAVOR DESCRIPTION", *instance.Flavor.Description) - table.AddSeparator() + if instance.HasFlavor() && instance.Flavor.HasDescription() { + table.AddRow("FLAVOR DESCRIPTION", *instance.Flavor.Description) + table.AddSeparator() + } table.AddRow("TYPE", instanceType) table.AddSeparator() - table.AddRow("REPLICAS", *instance.Replicas) - table.AddSeparator() - table.AddRow("CPU", *instance.Flavor.Cpu) - table.AddSeparator() - table.AddRow("RAM (GB)", *instance.Flavor.Memory) - table.AddSeparator() - table.AddRow("BACKUP SCHEDULE (UTC)", *instance.BackupSchedule) + if instance.HasReplicas() { + table.AddRow("REPLICAS", *instance.Replicas) + table.AddSeparator() + } + if instance.HasFlavor() { + table.AddRow("CPU", utils.PtrString(instance.Flavor.Cpu)) + table.AddSeparator() + table.AddRow("RAM (GB)", utils.PtrString(instance.Flavor.Memory)) + table.AddSeparator() + } + table.AddRow("BACKUP SCHEDULE (UTC)", utils.PtrString(instance.BackupSchedule)) table.AddSeparator() err = table.Display(p) if err != nil { diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index d76c3d667..40ac2ef8d 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" @@ -152,7 +153,11 @@ func outputResult(p *print.Printer, outputFormat string, instances []mongodbflex table.SetHeader("ID", "NAME", "STATUS") for i := range instances { instance := instances[i] - table.AddRow(*instance.Id, *instance.Name, *instance.Status) + table.AddRow( + utils.PtrString(instance.Id), + utils.PtrString(instance.Name), + utils.PtrString(instance.Status), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index e58a5e311..abe1cca69 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -13,8 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -231,7 +231,13 @@ func buildFlavorsTable(flavors []mongodbflex.HandlersInfraFlavor) tables.Table { table.SetHeader("ID", "CPU", "MEMORY", "DESCRIPTION", "VALID INSTANCE TYPES") for i := range flavors { f := flavors[i] - table.AddRow(*f.Id, *f.Cpu, *f.Memory, *f.Description, *f.Categories) + table.AddRow( + utils.PtrString(f.Id), + utils.PtrString(f.Cpu), + utils.PtrString(f.Memory), + utils.PtrString(f.Description), + utils.PtrString(f.Categories), + ) } return table } @@ -254,7 +260,11 @@ func buildStoragesTable(storagesResp mongodbflex.ListStoragesResponse) tables.Ta table.SetHeader("MINIMUM", "MAXIMUM", "STORAGE CLASS") for i := range storages { sc := storages[i] - table.AddRow(*storagesResp.StorageRange.Min, *storagesResp.StorageRange.Max, sc) + table.AddRow( + utils.PtrString(storagesResp.StorageRange.Min), + utils.PtrString(storagesResp.StorageRange.Max), + sc, + ) } table.EnableAutoMergeOnColumns(1, 2, 3) return table diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index 350142390..f3744c3cb 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -15,6 +15,7 @@ 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/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -167,14 +168,14 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, use 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) + p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) + p.Outputf("Username: %s\n", utils.PtrString(user.Username)) + p.Outputf("Password: %s\n", utils.PtrString(user.Password)) + p.Outputf("Roles: %v\n", utils.PtrString(user.Roles)) + p.Outputf("Database: %s\n", utils.PtrString(user.Database)) + p.Outputf("Host: %s\n", utils.PtrString(user.Host)) + p.Outputf("Port: %s\n", utils.PtrString(user.Port)) + p.Outputf("URI: %s\n", utils.PtrString(user.Uri)) return nil } diff --git a/internal/cmd/mongodbflex/user/describe/describe.go b/internal/cmd/mongodbflex/user/describe/describe.go index c3eb9d5cc..5f95804a3 100644 --- a/internal/cmd/mongodbflex/user/describe/describe.go +++ b/internal/cmd/mongodbflex/user/describe/describe.go @@ -137,17 +137,17 @@ func outputResult(p *print.Printer, outputFormat string, user mongodbflex.Instan return nil default: table := tables.NewTable() - table.AddRow("ID", *user.Id) + table.AddRow("ID", utils.PtrString(user.Id)) table.AddSeparator() - table.AddRow("USERNAME", *user.Username) + table.AddRow("USERNAME", utils.PtrString(user.Username)) table.AddSeparator() - table.AddRow("ROLES", *user.Roles) + table.AddRow("ROLES", utils.PtrString(user.Roles)) table.AddSeparator() - table.AddRow("DATABASE", *user.Database) + table.AddRow("DATABASE", utils.PtrString(user.Database)) table.AddSeparator() - table.AddRow("HOST", *user.Host) + table.AddRow("HOST", utils.PtrString(user.Host)) table.AddSeparator() - table.AddRow("PORT", *user.Port) + table.AddRow("PORT", utils.PtrString(user.Port)) err := table.Display(p) if err != nil { diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index 8ba1f3908..365f5ee36 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/client" mongodbflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" @@ -160,7 +161,10 @@ func outputResult(p *print.Printer, outputFormat string, users []mongodbflex.Lis table.SetHeader("ID", "USERNAME") for i := range users { user := users[i] - table.AddRow(*user.Id, *user.Username) + table.AddRow( + utils.PtrString(user.Id), + utils.PtrString(user.Username), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index 665ad9b8b..e04fa7b90 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -153,9 +153,9 @@ func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel 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) + p.Outputf("Username: %s\n", utils.PtrString(user.Username)) + p.Outputf("New password: %s\n", utils.PtrString(user.Password)) + p.Outputf("New URI: %s\n", utils.PtrString(user.Uri)) return nil } } diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index 4196de7bc..f23a2fc85 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -13,6 +13,7 @@ import ( "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/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" @@ -116,13 +117,13 @@ func outputResult(p *print.Printer, outputFormat string, bucket *objectstorage.B return nil default: table := tables.NewTable() - table.AddRow("Name", *bucket.Name) + table.AddRow("Name", utils.PtrString(bucket.Name)) table.AddSeparator() - table.AddRow("Region", *bucket.Region) + table.AddRow("Region", utils.PtrString(bucket.Region)) table.AddSeparator() - table.AddRow("URL (Path Style)", *bucket.UrlPathStyle) + table.AddRow("URL (Path Style)", utils.PtrString(bucket.UrlPathStyle)) table.AddSeparator() - table.AddRow("URL (Virtual Hosted Style)", *bucket.UrlVirtualHostedStyle) + table.AddRow("URL (Virtual Hosted Style)", utils.PtrString(bucket.UrlVirtualHostedStyle)) table.AddSeparator() err := table.Display(p) if err != nil { diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index 554e6b6c4..d9409ff45 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) @@ -152,7 +152,12 @@ func outputResult(p *print.Printer, outputFormat string, buckets []objectstorage table.SetHeader("NAME", "REGION", "URL (PATH STYLE)", "URL (VIRTUAL HOSTED STYLE)") for i := range buckets { bucket := buckets[i] - table.AddRow(*bucket.Name, *bucket.Region, *bucket.UrlPathStyle, *bucket.UrlVirtualHostedStyle) + table.AddRow( + utils.PtrString(bucket.Name), + utils.PtrString(bucket.Region), + utils.PtrString(bucket.UrlPathStyle), + utils.PtrString(bucket.UrlVirtualHostedStyle), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index c75a145ef..9a611b5b3 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -131,8 +131,11 @@ func outputResult(p *print.Printer, model *inputModel, resp *objectstorage.Creat 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) + p.Outputf("Created credentials group %q. Credentials group ID: %s\n\n", + utils.PtrString(resp.CredentialsGroup.DisplayName), + utils.PtrString(resp.CredentialsGroup.CredentialsGroupId), + ) + p.Outputf("URN: %s\n", utils.PtrString(resp.CredentialsGroup.Urn)) return nil } } diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index 416eef811..7f2962c23 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "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/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) @@ -144,7 +144,11 @@ func outputResult(p *print.Printer, outputFormat string, credentialsGroups []obj table.SetHeader("ID", "NAME", "URN") for i := range credentialsGroups { c := credentialsGroups[i] - table.AddRow(*c.CredentialsGroupId, *c.DisplayName, *c.Urn) + table.AddRow( + utils.PtrString(c.CredentialsGroupId), + utils.PtrString(c.DisplayName), + utils.PtrString(c.Urn), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index a4cdab240..1e659cdb7 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -7,8 +7,6 @@ import ( "time" "github.com/goccy/go-yaml" - objectStorageUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/utils" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -17,6 +15,8 @@ import ( "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/utils" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) @@ -161,9 +161,9 @@ func outputResult(p *print.Printer, model *inputModel, credentialsGroupLabel str 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("Created credentials in group %q. Credentials ID: %s\n\n", credentialsGroupLabel, utils.PtrString(resp.KeyId)) + p.Outputf("Access Key ID: %s\n", utils.PtrString(resp.AccessKey)) + p.Outputf("Secret Access Key: %s\n", utils.PtrString(resp.SecretAccessKey)) p.Outputf("Expire Date: %s\n", expireDate) return nil diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index da2643610..237d74c61 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -6,8 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" - objectStorageUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/object-storage/utils" - + "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" @@ -15,9 +14,9 @@ import ( "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/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) @@ -161,11 +160,8 @@ func outputResult(p *print.Printer, outputFormat string, credentials []objectsto for i := range credentials { c := credentials[i] - expiresAt := "Never" - if c.Expires != nil { - expiresAt = *c.Expires - } - table.AddRow(*c.KeyId, *c.DisplayName, expiresAt) + expiresAt := utils.PtrStringDefault(c.Expires, "Never") + table.AddRow(utils.PtrString(c.KeyId), utils.PtrString(c.DisplayName), expiresAt) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index d74983441..6ee744588 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/observability" ) @@ -135,7 +136,9 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res p.Outputf("Username: %s\n", username) } - p.Outputf("Password: %s\n", *resp.Credentials.Password) + if resp.Credentials != nil { + p.Outputf("Password: %s\n", utils.PtrString(resp.Credentials.Password)) + } return nil } } diff --git a/internal/cmd/observability/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go index 29096de24..397f1c6a9 100644 --- a/internal/cmd/observability/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/observability" @@ -146,7 +147,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []observabi table.SetHeader("USERNAME") for i := range credentials { c := credentials[i] - table.AddRow(*c.Name) + table.AddRow(utils.PtrString(c.Name)) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index d21258329..9c50a7c6a 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -149,13 +149,13 @@ func outputResult(p *print.Printer, inputModel *inputModel, grafanaConfigs *obse } table := tables.NewTable() - table.AddRow("GRAFANA DASHBOARD", *instance.Instance.GrafanaUrl) + table.AddRow("GRAFANA DASHBOARD", utils.PtrString(instance.Instance.GrafanaUrl)) table.AddSeparator() - table.AddRow("PUBLIC READ ACCESS", *grafanaConfigs.PublicReadAccess) + table.AddRow("PUBLIC READ ACCESS", utils.PtrString(grafanaConfigs.PublicReadAccess)) table.AddSeparator() - table.AddRow("SINGLE SIGN-ON", *grafanaConfigs.UseStackitSso) + table.AddRow("SINGLE SIGN-ON", utils.PtrString(grafanaConfigs.UseStackitSso)) table.AddSeparator() - table.AddRow("INITIAL ADMIN USER (DEFAULT)", *instance.Instance.GrafanaAdminUser) + table.AddRow("INITIAL ADMIN USER (DEFAULT)", utils.PtrString(instance.Instance.GrafanaAdminUser)) table.AddSeparator() table.AddRow("INITIAL ADMIN PASSWORD (DEFAULT)", initialAdminPassword) err := table.Display(p) diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 02057ddbe..134b8388e 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -16,6 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" @@ -222,7 +223,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, *resp.InstanceId) + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) return nil } } diff --git a/internal/cmd/observability/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go index 9f3764e00..dfd0717c7 100644 --- a/internal/cmd/observability/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -117,26 +117,30 @@ func outputResult(p *print.Printer, outputFormat string, instance *observability return nil default: table := tables.NewTable() - table.AddRow("ID", *instance.Id) + table.AddRow("ID", utils.PtrString(instance.Id)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("STATUS", *instance.Status) + table.AddRow("STATUS", utils.PtrString(instance.Status)) table.AddSeparator() - table.AddRow("PLAN NAME", *instance.PlanName) - table.AddSeparator() - table.AddRow("METRIC SAMPLES (PER MIN)", *instance.Instance.Plan.TotalMetricSamples) - table.AddSeparator() - table.AddRow("LOGS (GB)", *instance.Instance.Plan.LogsStorage) - table.AddSeparator() - table.AddRow("TRACES (GB)", *instance.Instance.Plan.TracesStorage) - table.AddSeparator() - table.AddRow("NOTIFICATION RULES", *instance.Instance.Plan.AlertRules) - table.AddSeparator() - table.AddRow("GRAFANA USERS", *instance.Instance.Plan.GrafanaGlobalUsers) - table.AddSeparator() - table.AddRow("GRAFANA URL", *instance.Instance.GrafanaUrl) + table.AddRow("PLAN NAME", utils.PtrString(instance.PlanName)) table.AddSeparator() + if inst := instance.Instance; inst != nil { + if plan := inst.Plan; plan != nil { + table.AddRow("METRIC SAMPLES (PER MIN)", utils.PtrString(plan.TotalMetricSamples)) + table.AddSeparator() + table.AddRow("LOGS (GB)", utils.PtrString(plan.LogsStorage)) + table.AddSeparator() + table.AddRow("TRACES (GB)", utils.PtrString(plan.TracesStorage)) + table.AddSeparator() + table.AddRow("NOTIFICATION RULES", utils.PtrString(plan.AlertRules)) + table.AddSeparator() + table.AddRow("GRAFANA USERS", utils.PtrString(plan.GrafanaGlobalUsers)) + table.AddSeparator() + } + table.AddRow("GRAFANA URL", utils.PtrString(inst.GrafanaUrl)) + table.AddSeparator() + } err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index 1db4743c3..db212da21 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/observability" ) @@ -152,7 +152,12 @@ func outputResult(p *print.Printer, outputFormat string, instances []observabili table.SetHeader("ID", "NAME", "PLAN", "STATUS") for i := range instances { instance := instances[i] - table.AddRow(*instance.Id, *instance.Name, *instance.PlanName, *instance.Status) + table.AddRow( + utils.PtrString(instance.Id), + utils.PtrString(instance.Name), + utils.PtrString(instance.PlanName), + utils.PtrString(instance.Status), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index 2a62612e2..872d5efea 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -15,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/observability" ) @@ -152,7 +153,11 @@ func outputResult(p *print.Printer, outputFormat string, plans []observability.P table.SetHeader("ID", "PLAN NAME", "DESCRIPTION") for i := range plans { o := plans[i] - table.AddRow(*o.Id, *o.Name, *o.Description) + table.AddRow( + utils.PtrString(o.Id), + utils.PtrString(o.Name), + utils.PtrString(o.Description), + ) table.AddSeparator() } table.EnableAutoMergeOnColumns(1) diff --git a/internal/cmd/observability/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go index 545a706c2..0856e6b19 100644 --- a/internal/cmd/observability/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/observability" @@ -118,7 +119,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s scrape configuration with name %q for Observability instance %q\n", operationState, *jobName, instanceLabel) + p.Outputf("%s scrape configuration with name %q for Observability instance %q\n", operationState, utils.PtrString(jobName), instanceLabel) return nil }, } diff --git a/internal/cmd/observability/scrape-config/describe/describe.go b/internal/cmd/observability/scrape-config/describe/describe.go index 9a94c8fd6..37dd359e7 100644 --- a/internal/cmd/observability/scrape-config/describe/describe.go +++ b/internal/cmd/observability/scrape-config/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "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" @@ -15,9 +16,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/observability" - - "github.com/spf13/cobra" ) const ( @@ -147,15 +147,15 @@ func outputResult(p *print.Printer, outputFormat string, config *observability.J } table := tables.NewTable() - table.AddRow("NAME", *config.JobName) + table.AddRow("NAME", utils.PtrString(config.JobName)) table.AddSeparator() - table.AddRow("METRICS PATH", *config.MetricsPath) + table.AddRow("METRICS PATH", utils.PtrString(config.MetricsPath)) table.AddSeparator() - table.AddRow("SCHEME", *config.Scheme) + table.AddRow("SCHEME", utils.PtrString(config.Scheme)) table.AddSeparator() - table.AddRow("SCRAPE INTERVAL", *config.ScrapeInterval) + table.AddRow("SCRAPE INTERVAL", utils.PtrString(config.ScrapeInterval)) table.AddSeparator() - table.AddRow("SCRAPE TIMEOUT", *config.ScrapeTimeout) + table.AddRow("SCRAPE TIMEOUT", utils.PtrString(config.ScrapeTimeout)) table.AddSeparator() table.AddRow("SAML2", saml2Enabled) table.AddSeparator() @@ -164,9 +164,9 @@ func outputResult(p *print.Printer, outputFormat string, config *observability.J } else { table.AddRow("AUTHENTICATION", "Basic Auth") table.AddSeparator() - table.AddRow("USERNAME", *config.BasicAuth.Username) + table.AddRow("USERNAME", utils.PtrString(config.BasicAuth.Username)) table.AddSeparator() - table.AddRow("PASSWORD", *config.BasicAuth.Password) + table.AddRow("PASSWORD", utils.PtrString(config.BasicAuth.Password)) } table.AddSeparator() for i, target := range targets { diff --git a/internal/cmd/observability/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go index b1a33f886..6e2543869 100644 --- a/internal/cmd/observability/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" @@ -160,7 +161,11 @@ func outputResult(p *print.Printer, outputFormat string, configs []observability } } - table.AddRow(*c.JobName, targets, *c.ScrapeInterval) + table.AddRow( + utils.PtrString(c.JobName), + targets, + utils.PtrString(c.ScrapeInterval), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index 44cef8420..015c41cc9 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -145,18 +145,20 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res 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.ShowPassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) + // The username field cannot be set by the user so we only display it if it's not returned empty + if resp.HasRaw() && resp.Raw.Credentials != nil { + if username := resp.Raw.Credentials.Username; username != nil && *username != "" { + p.Outputf("Username: %s\n", *username) + } + if !model.ShowPassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) + } + p.Outputf("Host: %s\n", utils.PtrString(resp.Raw.Credentials.Host)) + p.Outputf("Port: %s\n", utils.PtrString(resp.Raw.Credentials.Port)) } - 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/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index 596ffc3eb..838521396 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -131,17 +131,18 @@ func outputResult(p *print.Printer, outputFormat string, credentials *opensearch return nil default: table := tables.NewTable() - table.AddRow("ID", *credentials.Id) + table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty - username := *credentials.Raw.Credentials.Username - if username != "" { - table.AddRow("USERNAME", *credentials.Raw.Credentials.Username) + if credentials.HasRaw() && credentials.Raw.Credentials != nil { + if username := credentials.Raw.Credentials.Username; username != nil && *username != "" { + table.AddRow("USERNAME", *username) + table.AddSeparator() + } + table.AddRow("PASSWORD", utils.PtrString(credentials.Raw.Credentials.Password)) table.AddSeparator() + table.AddRow("URI", utils.PtrString(credentials.Raw.Credentials.Uri)) } - table.AddRow("PASSWORD", *credentials.Raw.Credentials.Password) - table.AddSeparator() - table.AddRow("URI", *credentials.Raw.Credentials.Uri) err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index a6e1a8e48..7f5636691 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -15,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/client" opensearchUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -157,7 +158,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []opensearc table.SetHeader("ID") for i := range credentials { c := credentials[i] - table.AddRow(*c.Id) + table.AddRow(utils.PtrString(c.Id)) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index b1f06faff..8fd2f081b 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -119,15 +119,15 @@ func outputResult(p *print.Printer, outputFormat string, instance *opensearch.In return nil default: table := tables.NewTable() - table.AddRow("ID", *instance.InstanceId) + table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", *instance.LastOperation.Type) + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) table.AddSeparator() - table.AddRow("LAST OPERATION STATE", *instance.LastOperation.State) + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) table.AddSeparator() - table.AddRow("PLAN ID", *instance.PlanId) + table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty acl := (*instance.Parameters)[aclParameterKey] aclStr, ok := acl.(string) diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index dc116b510..c53fa0176 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -152,7 +152,12 @@ func outputResult(p *print.Printer, outputFormat string, instances []opensearch. table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] - table.AddRow(*instance.InstanceId, *instance.Name, *instance.LastOperation.Type, *instance.LastOperation.State) + table.AddRow( + utils.PtrString(instance.InstanceId), + utils.PtrString(instance.Name), + utils.PtrString(instance.LastOperation.Type), + utils.PtrString(instance.LastOperation.State), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index 89409a89a..f72dc67a1 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" @@ -154,7 +155,13 @@ func outputResult(p *print.Printer, outputFormat string, plans []opensearch.Offe o := plans[i] for j := range *o.Plans { plan := (*o.Plans)[j] - table.AddRow(*o.Name, *o.Version, *plan.Id, *plan.Name, *plan.Description) + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + ) } table.AddSeparator() } diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index 8ff1a1826..3a4c38a41 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/authorization/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/authorization" @@ -183,7 +184,7 @@ func outputResult(p *print.Printer, model *inputModel, members []authorization.M if i > 0 && sortFn(i-1, i) { table.AddSeparator() } - table.AddRow(*m.Subject, *m.Role) + table.AddRow(utils.PtrString(m.Subject), utils.PtrString(m.Role)) } if model.SortBy == "subject" { diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index 6d62f190e..51e9390af 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/authorization/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/authorization" @@ -154,7 +155,12 @@ func outputRolesResult(p *print.Printer, outputFormat string, roles []authorizat r := roles[i] for j := range *r.Permissions { p := (*r.Permissions)[j] - table.AddRow(*r.Name, *r.Description, *p.Name, *p.Description) + table.AddRow( + utils.PtrString(r.Name), + utils.PtrString(r.Description), + utils.PtrString(p.Name), + utils.PtrString(p.Description), + ) } table.AddSeparator() } diff --git a/internal/cmd/postgresflex/backup/describe/describe.go b/internal/cmd/postgresflex/backup/describe/describe.go index 9e306e2b4..10c3bdda8 100644 --- a/internal/cmd/postgresflex/backup/describe/describe.go +++ b/internal/cmd/postgresflex/backup/describe/describe.go @@ -4,11 +4,9 @@ import ( "context" "encoding/json" "fmt" - "time" "github.com/goccy/go-yaml" - "github.com/inhies/go-bytesize" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -18,6 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -133,13 +132,15 @@ func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, bac return nil default: table := tables.NewTable() - table.AddRow("ID", *backup.Id) + table.AddRow("ID", utils.PtrString(backup.Id)) table.AddSeparator() - table.AddRow("CREATED AT", *backup.StartTime) + table.AddRow("CREATED AT", utils.PtrString(backup.StartTime)) table.AddSeparator() table.AddRow("EXPIRES AT", backupExpireDate) table.AddSeparator() - table.AddRow("BACKUP SIZE", bytesize.New(float64(*backup.Size))) + + backupSize := utils.PtrByteSizeDefault(backup.Size, "n/a") + table.AddRow("BACKUP SIZE", backupSize) err := table.Display(p) if err != nil { diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index 519b2065f..c03a3afb6 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/goccy/go-yaml" - "github.com/inhies/go-bytesize" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -16,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client" postgresflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "time" @@ -163,7 +163,13 @@ func outputResult(p *print.Printer, outputFormat string, backups []postgresflex. } backupExpireDate := backupStartTime.AddDate(backupExpireYearOffset, backupExpireMonthOffset, backupExpireDayOffset).Format(time.DateOnly) - table.AddRow(*backup.Id, *backup.StartTime, backupExpireDate, bytesize.New(float64(*backup.Size))) + backupSize := utils.PtrByteSizeDefault(backup.Size, "n/a") + table.AddRow( + utils.PtrString(backup.Id), + utils.PtrString(backup.StartTime), + backupExpireDate, + backupSize, + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/postgresflex/instance/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index 3ca2e291a..404a1c23d 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -120,8 +120,11 @@ func outputResult(p *print.Printer, outputFormat string, instance *postgresflex. return nil default: - aclsArray := *instance.Acl.Items - acls := strings.Join(aclsArray, ",") + acls := "" + if instance.HasAcl() && instance.Acl.HasItems() { + aclsArray := *instance.Acl.Items + acls = strings.Join(aclsArray, ",") + } instanceType, err := postgresflexUtils.GetInstanceType(*instance.Replicas) if err != nil { @@ -130,29 +133,29 @@ func outputResult(p *print.Printer, outputFormat string, instance *postgresflex. } table := tables.NewTable() - table.AddRow("ID", *instance.Id) + table.AddRow("ID", utils.PtrString(instance.Id)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("STATUS", cases.Title(language.English).String(*instance.Status)) + table.AddRow("STATUS", cases.Title(language.English).String(utils.PtrString(instance.Status))) table.AddSeparator() - table.AddRow("STORAGE SIZE (GB)", *instance.Storage.Size) + table.AddRow("STORAGE SIZE (GB)", utils.PtrString(instance.Storage.Size)) table.AddSeparator() - table.AddRow("VERSION", *instance.Version) + table.AddRow("VERSION", utils.PtrString(instance.Version)) table.AddSeparator() table.AddRow("ACL", acls) table.AddSeparator() - table.AddRow("FLAVOR DESCRIPTION", *instance.Flavor.Description) + table.AddRow("FLAVOR DESCRIPTION", utils.PtrString(instance.Flavor.Description)) table.AddSeparator() table.AddRow("TYPE", instanceType) table.AddSeparator() - table.AddRow("REPLICAS", *instance.Replicas) + table.AddRow("REPLICAS", utils.PtrString(instance.Replicas)) table.AddSeparator() - table.AddRow("CPU", *instance.Flavor.Cpu) + table.AddRow("CPU", utils.PtrString(instance.Flavor.Cpu)) table.AddSeparator() - table.AddRow("RAM (GB)", *instance.Flavor.Memory) + table.AddRow("RAM (GB)", utils.PtrString(instance.Flavor.Memory)) table.AddSeparator() - table.AddRow("BACKUP SCHEDULE (UTC)", *instance.BackupSchedule) + table.AddRow("BACKUP SCHEDULE (UTC)", utils.PtrString(instance.BackupSchedule)) table.AddSeparator() err = table.Display(p) if err != nil { diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index cb469bfbe..349f7d872 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -155,7 +155,11 @@ func outputResult(p *print.Printer, outputFormat string, instances []postgresfle table.SetHeader("ID", "NAME", "STATUS") for i := range instances { instance := instances[i] - table.AddRow(*instance.Id, *instance.Name, caser.String(*instance.Status)) + table.AddRow( + utils.PtrString(instance.Id), + utils.PtrString(instance.Name), + caser.String(utils.PtrString(instance.Status)), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index f5833d151..22950039d 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -13,8 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -179,7 +179,7 @@ func outputResult(p *print.Printer, model *inputModel, flavors *postgresflex.Lis } if storages != nil && model.FlavorId != nil { options.Storages = &flavorStorages{ - FlavorId: *model.FlavorId, + FlavorId: utils.PtrString(model.FlavorId), Storages: storages, } } @@ -231,7 +231,12 @@ func buildFlavorsTable(flavors []postgresflex.Flavor) tables.Table { table.SetHeader("ID", "CPU", "MEMORY", "DESCRIPTION") for i := range flavors { f := flavors[i] - table.AddRow(*f.Id, *f.Cpu, *f.Memory, *f.Description) + table.AddRow( + utils.PtrString(f.Id), + utils.PtrString(f.Cpu), + utils.PtrString(f.Memory), + utils.PtrString(f.Description), + ) } return table } @@ -254,7 +259,11 @@ func buildStoragesTable(storagesResp postgresflex.ListStoragesResponse) tables.T table.SetHeader("MINIMUM", "MAXIMUM", "STORAGE CLASS") for i := range storages { sc := storages[i] - table.AddRow(*storagesResp.StorageRange.Min, *storagesResp.StorageRange.Max, sc) + table.AddRow( + utils.PtrString(storagesResp.StorageRange.Min), + utils.PtrString(storagesResp.StorageRange.Max), + sc, + ) } table.EnableAutoMergeOnColumns(1, 2, 3) return table diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index c3399ab98..f8d65bf01 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client" postgresflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/utils" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -163,13 +163,13 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res 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) + p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) + p.Outputf("Username: %s\n", utils.PtrString(user.Username)) + p.Outputf("Password: %s\n", utils.PtrString(user.Password)) + p.Outputf("Roles: %v\n", utils.PtrString(user.Roles)) + p.Outputf("Host: %s\n", utils.PtrString(user.Host)) + p.Outputf("Port: %s\n", utils.PtrString(user.Port)) + p.Outputf("URI: %s\n", utils.PtrString(user.Uri)) return nil } diff --git a/internal/cmd/postgresflex/user/describe/describe.go b/internal/cmd/postgresflex/user/describe/describe.go index 5855ca07d..b63e08bd7 100644 --- a/internal/cmd/postgresflex/user/describe/describe.go +++ b/internal/cmd/postgresflex/user/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -136,15 +136,15 @@ func outputResult(p *print.Printer, outputFormat string, user postgresflex.UserR return nil default: table := tables.NewTable() - table.AddRow("ID", *user.Id) + table.AddRow("ID", utils.PtrString(user.Id)) table.AddSeparator() - table.AddRow("USERNAME", *user.Username) + table.AddRow("USERNAME", utils.PtrString(user.Username)) table.AddSeparator() - table.AddRow("ROLES", *user.Roles) + table.AddRow("ROLES", utils.PtrString(user.Roles)) table.AddSeparator() - table.AddRow("HOST", *user.Host) + table.AddRow("HOST", utils.PtrString(user.Host)) table.AddSeparator() - table.AddRow("PORT", *user.Port) + table.AddRow("PORT", utils.PtrString(user.Port)) err := table.Display(p) if err != nil { diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index bb1f601f1..ae76e7958 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client" postgresflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -160,7 +160,10 @@ func outputResult(p *print.Printer, outputFormat string, users []postgresflex.Li table.SetHeader("ID", "USERNAME") for i := range users { user := users[i] - table.AddRow(*user.Id, *user.Username) + table.AddRow( + utils.PtrString(user.Id), + utils.PtrString(user.Username), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index 77c881189..35d097168 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client" postgresflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/utils" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -152,9 +152,9 @@ func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel 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) + p.Outputf("Username: %s\n", utils.PtrString(user.Item.Username)) + p.Outputf("New password: %s\n", utils.PtrString(user.Item.Password)) + p.Outputf("New URI: %s\n", utils.PtrString(user.Item.Uri)) return nil } } diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index 23b0cd9fc..bb67f8cf1 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -231,7 +231,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *resourcemanager.Pro return nil default: - p.Outputf("Created project under the parent with ID %q. Project ID: %s\n", *model.ParentId, *resp.ProjectId) + p.Outputf("Created project under the parent with ID %q. Project ID: %s\n", utils.PtrString(model.ParentId), utils.PtrString(resp.ProjectId)) return nil } } diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index 69662f53f..a9d948e67 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -138,15 +138,15 @@ func outputResult(p *print.Printer, outputFormat string, project *resourcemanage return nil default: table := tables.NewTable() - table.AddRow("ID", *project.ProjectId) + table.AddRow("ID", utils.PtrString(project.ProjectId)) table.AddSeparator() - table.AddRow("NAME", *project.Name) + table.AddRow("NAME", utils.PtrString(project.Name)) table.AddSeparator() - table.AddRow("CREATION", *project.CreationTime) + table.AddRow("CREATION", utils.PtrString(project.CreationTime)) table.AddSeparator() - table.AddRow("STATE", *project.LifecycleState) + table.AddRow("STATE", utils.PtrString(project.LifecycleState)) table.AddSeparator() - table.AddRow("PARENT ID", *project.Parent.Id) + table.AddRow("PARENT ID", utils.PtrString(project.Parent.Id)) err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 8b346322c..8c9bb0d8e 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -7,6 +7,7 @@ import ( "time" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -16,8 +17,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" ) @@ -242,7 +242,12 @@ func outputResult(p *print.Printer, outputFormat string, projects []resourcemana table.SetHeader("ID", "NAME", "STATE", "PARENT ID") for i := range projects { p := projects[i] - table.AddRow(*p.ProjectId, *p.Name, *p.LifecycleState, *p.Parent.Id) + table.AddRow( + utils.PtrString(p.ProjectId), + utils.PtrString(p.Name), + utils.PtrString(p.LifecycleState), + utils.PtrString(p.Parent.Id), + ) } err := table.Display(p) diff --git a/internal/cmd/project/member/add/add.go b/internal/cmd/project/member/add/add.go index d1deff0e8..23436f039 100644 --- a/internal/cmd/project/member/add/add.go +++ b/internal/cmd/project/member/add/add.go @@ -84,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("add member: %w", err) } - p.Info("Added the role %q to %s on project %q\n", *model.Role, model.Subject, projectLabel) + p.Info("Added the role %q to %s on project %q\n", utils.PtrString(model.Role), model.Subject, projectLabel) return nil }, } diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index 538934344..a95a95fbe 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -7,6 +7,7 @@ import ( "sort" "github.com/goccy/go-yaml" + "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" @@ -16,8 +17,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/authorization/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -185,7 +185,7 @@ func outputResult(p *print.Printer, model *inputModel, members []authorization.M if i > 0 && sortFn(i-1, i) { table.AddSeparator() } - table.AddRow(*m.Subject, *m.Role) + table.AddRow(utils.PtrString(m.Subject), utils.PtrString(m.Role)) } if model.SortBy == "subject" { diff --git a/internal/cmd/project/member/remove/remove.go b/internal/cmd/project/member/remove/remove.go index 2c7142b6b..56004a03b 100644 --- a/internal/cmd/project/member/remove/remove.go +++ b/internal/cmd/project/member/remove/remove.go @@ -90,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("remove member: %w", err) } - p.Info("Removed the role %q from %s on project %q\n", *model.Role, model.Subject, projectLabel) + p.Info("Removed the role %q from %s on project %q\n", utils.PtrString(model.Role), model.Subject, projectLabel) return nil }, } diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index 13b3f79e1..991a00665 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/authorization/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -156,7 +156,12 @@ func outputRolesResult(p *print.Printer, outputFormat string, roles []authorizat r := roles[i] for j := range *r.Permissions { p := (*r.Permissions)[j] - table.AddRow(*r.Name, *r.Description, *p.Name, *p.Description) + table.AddRow( + utils.PtrString(r.Name), + utils.PtrString(r.Description), + utils.PtrString(p.Name), + utils.PtrString(p.Description), + ) } table.AddSeparator() } diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index a2b7b09af..2b73dd453 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -144,20 +144,21 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(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.ShowPassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + if resp.HasRaw() && resp.Raw.Credentials != nil { + if username := resp.Raw.Credentials.Username; username != nil && *username != "" { + p.Outputf("Username: %s\n", *username) + } + if !model.ShowPassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) + } + p.Outputf("Host: %s\n", utils.PtrString(resp.Raw.Credentials.Host)) + p.Outputf("Port: %s\n", utils.PtrString(resp.Raw.Credentials.Port)) } - 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) + p.Outputf("URI: %s\n", utils.PtrString(resp.Uri)) return nil } } diff --git a/internal/cmd/rabbitmq/credentials/describe/describe.go b/internal/cmd/rabbitmq/credentials/describe/describe.go index 175488d16..178027280 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe.go @@ -134,14 +134,15 @@ func outputResult(p *print.Printer, outputFormat string, credentials *rabbitmq.C table.AddRow("ID", *credentials.Id) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty - username := *credentials.Raw.Credentials.Username - if username != "" { - table.AddRow("USERNAME", *credentials.Raw.Credentials.Username) + if credentials.HasRaw() && credentials.Raw.Credentials != nil { + if username := credentials.Raw.Credentials.Username; username != nil && *username != "" { + table.AddRow("USERNAME", *username) + table.AddSeparator() + } + table.AddRow("PASSWORD", utils.PtrString(credentials.Raw.Credentials.Password)) table.AddSeparator() + table.AddRow("URI", utils.PtrString(credentials.Raw.Credentials.Uri)) } - table.AddRow("PASSWORD", *credentials.Raw.Credentials.Password) - table.AddSeparator() - table.AddRow("URI", *credentials.Raw.Credentials.Uri) err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index 95854a129..6911f04c7 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/rabbitmq/client" rabbitmqUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/rabbitmq/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -157,7 +157,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []rabbitmq. table.SetHeader("ID") for i := range credentials { c := credentials[i] - table.AddRow(*c.Id) + table.AddRow(utils.PtrString(c.Id)) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/rabbitmq/instance/describe/describe.go b/internal/cmd/rabbitmq/instance/describe/describe.go index 4aeb8fdf8..e5038f212 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe.go +++ b/internal/cmd/rabbitmq/instance/describe/describe.go @@ -119,15 +119,15 @@ func outputResult(p *print.Printer, outputFormat string, instance *rabbitmq.Inst return nil default: table := tables.NewTable() - table.AddRow("ID", *instance.InstanceId) + table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", *instance.LastOperation.Type) + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) table.AddSeparator() - table.AddRow("LAST OPERATION STATE", *instance.LastOperation.State) + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) table.AddSeparator() - table.AddRow("PLAN ID", *instance.PlanId) + table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty acl := (*instance.Parameters)[aclParameterKey] aclStr, ok := acl.(string) diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index b5802e849..a371d0f68 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/rabbitmq/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -152,7 +152,12 @@ func outputResult(p *print.Printer, outputFormat string, instances []rabbitmq.In table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] - table.AddRow(*instance.InstanceId, *instance.Name, *instance.LastOperation.Type, *instance.LastOperation.State) + table.AddRow( + utils.PtrString(instance.InstanceId), + utils.PtrString(instance.Name), + utils.PtrString(instance.LastOperation.Type), + utils.PtrString(instance.LastOperation.State), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index 385858e8f..7255baae7 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/rabbitmq/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" @@ -154,7 +155,13 @@ func outputResult(p *print.Printer, outputFormat string, plans []rabbitmq.Offeri o := plans[i] for j := range *o.Plans { plan := (*o.Plans)[j] - table.AddRow(*o.Name, *o.Version, *plan.Id, *plan.Name, *plan.Description) + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + ) } table.AddSeparator() } diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index f96a6d1a9..e241a2d27 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -148,18 +148,19 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res 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.ShowPassword { - p.Outputf("Password: \n") - } else { - p.Outputf("Password: %s\n", *resp.Raw.Credentials.Password) + if resp.HasRaw() && resp.Raw.Credentials != nil { + if username := resp.Raw.Credentials.Username; username != nil && *username != "" { + p.Outputf("Username: %s\n", *username) + } + if !model.ShowPassword { + p.Outputf("Password: \n") + } else { + p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) + } + p.Outputf("Host: %s\n", utils.PtrString(resp.Raw.Credentials.Host)) + p.Outputf("Port: %s\n", utils.PtrString(resp.Raw.Credentials.Port)) } - 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) + p.Outputf("URI: %s\n", utils.PtrString(resp.Uri)) return nil } } diff --git a/internal/cmd/redis/credentials/describe/describe.go b/internal/cmd/redis/credentials/describe/describe.go index 48ec11a7c..238b67bc5 100644 --- a/internal/cmd/redis/credentials/describe/describe.go +++ b/internal/cmd/redis/credentials/describe/describe.go @@ -134,14 +134,15 @@ func outputResult(p *print.Printer, outputFormat string, credentials *redis.Cred table.AddRow("ID", *credentials.Id) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty - username := *credentials.Raw.Credentials.Username - if username != "" { - table.AddRow("USERNAME", *credentials.Raw.Credentials.Username) + if credentials.HasRaw() && credentials.Raw.Credentials != nil { + if username := credentials.Raw.Credentials.Username; username != nil && *username != "" { + table.AddRow("USERNAME", *username) + table.AddSeparator() + } + table.AddRow("PASSWORD", utils.PtrString(credentials.Raw.Credentials.Password)) table.AddSeparator() + table.AddRow("URI", utils.PtrString(credentials.Raw.Credentials.Uri)) } - table.AddRow("PASSWORD", *credentials.Raw.Credentials.Password) - table.AddSeparator() - table.AddRow("URI", *credentials.Raw.Credentials.Uri) err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index 8ec94d500..78be560f1 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/redis/client" redisUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/redis/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -157,7 +157,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []redis.Cre table.SetHeader("ID") for i := range credentials { c := credentials[i] - table.AddRow(*c.Id) + table.AddRow(utils.PtrString(c.Id)) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/redis/instance/describe/describe.go b/internal/cmd/redis/instance/describe/describe.go index b89ac51f1..1b41c20d4 100644 --- a/internal/cmd/redis/instance/describe/describe.go +++ b/internal/cmd/redis/instance/describe/describe.go @@ -119,15 +119,15 @@ func outputResult(p *print.Printer, outputFormat string, instance *redis.Instanc return nil default: table := tables.NewTable() - table.AddRow("ID", *instance.InstanceId) + table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", *instance.LastOperation.Type) + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) table.AddSeparator() - table.AddRow("LAST OPERATION STATE", *instance.LastOperation.State) + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) table.AddSeparator() - table.AddRow("PLAN ID", *instance.PlanId) + table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty acl := (*instance.Parameters)[aclParameterKey] aclStr, ok := acl.(string) diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index de9db7f81..2eff0bf8c 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/redis/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -152,7 +152,12 @@ func outputResult(p *print.Printer, outputFormat string, instances []redis.Insta table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] - table.AddRow(*instance.InstanceId, *instance.Name, *instance.LastOperation.Type, *instance.LastOperation.State) + table.AddRow( + utils.PtrString(instance.InstanceId), + utils.PtrString(instance.Name), + utils.PtrString(instance.LastOperation.Type), + utils.PtrString(instance.LastOperation.State), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 564fb75e5..ef94c2a12 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/redis/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -154,7 +154,13 @@ func outputResult(p *print.Printer, outputFormat string, plans []redis.Offering) o := plans[i] for j := range *o.Plans { plan := (*o.Plans)[j] - table.AddRow(*o.Name, *o.Version, *plan.Id, *plan.Name, *plan.Description) + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + ) } table.AddSeparator() } diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index e299138de..416717ef1 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -135,17 +135,17 @@ func outputResult(p *print.Printer, outputFormat string, instance *secretsmanage return nil default: table := tables.NewTable() - table.AddRow("ID", *instance.Id) + table.AddRow("ID", utils.PtrString(instance.Id)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("STATE", *instance.State) + table.AddRow("STATE", utils.PtrString(instance.State)) table.AddSeparator() - table.AddRow("SECRETS", *instance.SecretCount) + table.AddRow("SECRETS", utils.PtrString(instance.SecretCount)) table.AddSeparator() - table.AddRow("ENGINE", *instance.SecretsEngine) + table.AddRow("ENGINE", utils.PtrString(instance.SecretsEngine)) table.AddSeparator() - table.AddRow("CREATION DATE", *instance.CreationStartDate) + table.AddRow("CREATION DATE", utils.PtrString(instance.CreationStartDate)) table.AddSeparator() // Only show ACL if it's present and not empty if aclList != nil && aclList.Acls != nil && len(*aclList.Acls) > 0 { diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index 952ca13d0..a207cc98d 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,9 +16,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/secrets-manager/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/secretsmanager" - - "github.com/spf13/cobra" ) const ( @@ -153,7 +153,12 @@ func outputResult(p *print.Printer, outputFormat string, instances []secretsmana table.SetHeader("ID", "NAME", "STATE", "SECRETS") for i := range instances { instance := instances[i] - table.AddRow(*instance.Id, *instance.Name, *instance.State, *instance.SecretCount) + table.AddRow( + utils.PtrString(instance.Id), + utils.PtrString(instance.Name), + utils.PtrString(instance.State), + utils.PtrString(instance.SecretCount), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 5506ea3d7..6143b7d98 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -156,11 +156,11 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res 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) + p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) + p.Outputf("Username: %s\n", utils.PtrString(resp.Username)) + p.Outputf("Password: %s\n", utils.PtrString(resp.Password)) + p.Outputf("Description: %s\n", utils.PtrString(resp.Description)) + p.Outputf("Write Access: %s\n", utils.PtrString(resp.Write)) return nil } diff --git a/internal/cmd/secrets-manager/user/describe/describe.go b/internal/cmd/secrets-manager/user/describe/describe.go index 35b8f927f..f93e19a24 100644 --- a/internal/cmd/secrets-manager/user/describe/describe.go +++ b/internal/cmd/secrets-manager/user/describe/describe.go @@ -133,9 +133,9 @@ func outputResult(p *print.Printer, outputFormat string, user secretsmanager.Use return nil default: table := tables.NewTable() - table.AddRow("ID", *user.Id) + table.AddRow("ID", utils.PtrString(user.Id)) table.AddSeparator() - table.AddRow("USERNAME", *user.Username) + table.AddRow("USERNAME", utils.PtrString(user.Username)) table.AddSeparator() if user.Description != nil && *user.Description != "" { table.AddRow("DESCRIPTION", *user.Description) @@ -145,7 +145,7 @@ func outputResult(p *print.Printer, outputFormat string, user secretsmanager.Use table.AddRow("PASSWORD", *user.Password) table.AddSeparator() } - table.AddRow("WRITE ACCESS", *user.Write) + table.AddRow("WRITE ACCESS", utils.PtrString(user.Write)) err := table.Display(p) if err != nil { diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index a4feee550..ad0bc0e67 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/secrets-manager/client" secretsManagerUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/secrets-manager/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/secretsmanager" ) @@ -160,7 +160,12 @@ func outputResult(p *print.Printer, outputFormat string, users []secretsmanager. table.SetHeader("ID", "USERNAME", "DESCRIPTION", "WRITE ACCESS") for i := range users { user := users[i] - table.AddRow(*user.Id, *user.Username, *user.Description, *user.Write) + table.AddRow( + utils.PtrString(user.Id), + utils.PtrString(user.Username), + utils.PtrString(user.Description), + utils.PtrString(user.Write), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index d4aa6b026..3faec270c 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-account/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" @@ -137,7 +138,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, serv return nil default: - p.Outputf("Created service account for project %q. Email: %s\n", projectLabel, *serviceAccount.Email) + p.Outputf("Created service account for project %q. Email: %s\n", projectLabel, utils.PtrString(serviceAccount.Email)) return nil } } diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index 5d9b1186e..13040757d 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -14,8 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-account/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" ) @@ -166,7 +166,12 @@ func outputResult(p *print.Printer, outputFormat string, keys []serviceaccount.S if k.ValidUntil != nil { validUntil = k.ValidUntil.String() } - table.AddRow(*k.Id, *k.Active, *k.CreatedAt, validUntil) + table.AddRow( + utils.PtrString(k.Id), + utils.PtrString(k.Active), + utils.PtrString(k.CreatedAt), + validUntil, + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index 8dc2e178d..e3e6f3b83 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-account/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" ) @@ -142,7 +142,10 @@ func outputResult(p *print.Printer, outputFormat string, serviceAccounts []servi table.SetHeader("ID", "EMAIL") for i := range serviceAccounts { account := serviceAccounts[i] - table.AddRow(*account.Id, *account.Email) + table.AddRow( + utils.PtrString(account.Id), + utils.PtrString(account.Email), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index 97c08dbbf..12e0ce6fa 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -13,8 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-account/client" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" ) @@ -161,9 +161,9 @@ func outputResult(p *print.Printer, model *inputModel, token *serviceaccount.Acc 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) + p.Outputf("Created access token for service account %s. Token ID: %s\n\n", model.ServiceAccountEmail, utils.PtrString(token.Id)) + p.Outputf("Valid until: %s\n", utils.PtrString(token.ValidUntil)) + p.Outputf("Token: %s\n", utils.PtrString(token.Token)) return nil } } diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index 3bb6aa2bb..e9395d668 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-account/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" @@ -166,7 +167,12 @@ func outputResult(p *print.Printer, outputFormat string, tokensMetadata []servic table.SetHeader("ID", "ACTIVE", "CREATED_AT", "VALID_UNTIL") for i := range tokensMetadata { t := tokensMetadata[i] - table.AddRow(*t.Id, *t.Active, *t.CreatedAt, *t.ValidUntil) + table.AddRow( + utils.PtrString(t.Id), + utils.PtrString(t.Active), + utils.PtrString(t.CreatedAt), + utils.PtrString(t.ValidUntil), + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 31fad09f4..cb5981d52 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -18,8 +19,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" skeUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/ske" "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" ) @@ -220,7 +220,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, *resp.Name) + p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name)) return nil } } diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 75a432bdb..5a4b4ec0e 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -13,8 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) @@ -121,11 +121,11 @@ func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) e } table := tables.NewTable() - table.AddRow("NAME", *cluster.Name) + table.AddRow("NAME", utils.PtrString(cluster.Name)) table.AddSeparator() - table.AddRow("STATE", *cluster.Status.Aggregated) + table.AddRow("STATE", utils.PtrString(cluster.Status.Aggregated)) table.AddSeparator() - table.AddRow("VERSION", *cluster.Kubernetes.Version) + table.AddRow("VERSION", utils.PtrString(cluster.Kubernetes.Version)) table.AddSeparator() table.AddRow("ACL", acl) err := table.Display(p) diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 834b2ea38..785f645c1 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -17,6 +17,7 @@ import ( serviceEnablementUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/ske" @@ -173,7 +174,13 @@ func outputResult(p *print.Printer, outputFormat string, clusters []ske.Cluster) if c.Extensions != nil && c.Extensions.Argus != nil && *c.Extensions.Argus.Enabled { monitoring = "Enabled" } - table.AddRow(*c.Name, *c.Status.Aggregated, *c.Kubernetes.Version, len(*c.Nodepools), monitoring) + table.AddRow( + utils.PtrString(c.Name), + utils.PtrString(c.Status.Aggregated), + utils.PtrString(c.Kubernetes.Version), + len(*c.Nodepools), + monitoring, + ) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index 3f54a607d..53d9dd848 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -6,17 +6,17 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/client" - "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" + skeUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" - - "github.com/spf13/cobra" ) type inputModel struct { @@ -82,7 +82,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiGetServiceStatusRequest { - req := apiClient.GetServiceStatus(ctx, model.ProjectId, utils.SKEServiceId) + req := apiClient.GetServiceStatus(ctx, model.ProjectId, skeUtils.SKEServiceId) return req } @@ -108,7 +108,7 @@ func outputResult(p *print.Printer, outputFormat string, project *serviceenablem table := tables.NewTable() table.AddRow("ID", projectId) table.AddSeparator() - table.AddRow("STATE", *project.State) + table.AddRow("STATE", utils.PtrString(project.State)) err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index 4d2549e04..adc74b0e5 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" skeUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/ske" @@ -274,7 +275,7 @@ func outputResult(p *print.Printer, model *inputModel, kubeconfigPath string, re default: var expiration string if respKubeconfig != nil { - expiration = fmt.Sprintf(", with expiration date %v (UTC)", *respKubeconfig.ExpirationTimestamp) + expiration = fmt.Sprintf(", with expiration date %v (UTC)", utils.ConvertTimePToDateTimeString(respKubeconfig.ExpirationTimestamp)) } p.Outputf("Updated kubeconfig file for cluster %s in %q%s\n", model.ClusterName, kubeconfigPath, expiration) diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index 51a8abb93..e8ad07eea 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -8,6 +8,7 @@ import ( "time" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -15,8 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - - "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) @@ -241,7 +241,11 @@ func buildKubernetesVersionsTable(resp *ske.ProviderOptions) (tables.Table, erro if v.ExpirationDate != nil { expirationDate = v.ExpirationDate.Format(time.RFC3339) } - table.AddRow(*v.Version, *v.State, expirationDate, string(featureGate)) + table.AddRow( + utils.PtrString(v.Version), + utils.PtrString(v.State), + expirationDate, + string(featureGate)) } return table, nil } @@ -268,7 +272,13 @@ func buildMachineImagesTable(resp *ske.ProviderOptions) tables.Table { if version.ExpirationDate != nil { expirationDate = version.ExpirationDate.Format(time.RFC3339) } - table.AddRow(*image.Name, *version.Version, *version.State, expirationDate, criNamesString) + table.AddRow( + utils.PtrString(image.Name), + utils.PtrString(version.Version), + utils.PtrString(version.State), + expirationDate, + criNamesString, + ) } } table.EnableAutoMergeOnColumns(1) @@ -283,7 +293,11 @@ func buildMachineTypesTable(resp *ske.ProviderOptions) tables.Table { table.SetHeader("TYPE", "CPU", "MEMORY") for i := range types { t := types[i] - table.AddRow(*t.Name, *t.Cpu, *t.Memory) + table.AddRow( + utils.PtrString(t.Name), + utils.PtrString(t.Cpu), + utils.PtrString(t.Memory), + ) } return table } @@ -296,7 +310,7 @@ func buildVolumeTypesTable(resp *ske.ProviderOptions) tables.Table { table.SetHeader("TYPE") for i := range types { z := types[i] - table.AddRow(*z.Name) + table.AddRow(utils.PtrString(z.Name)) } return table } diff --git a/internal/pkg/utils/strings.go b/internal/pkg/utils/strings.go index 6c33cfc82..36cfda139 100644 --- a/internal/pkg/utils/strings.go +++ b/internal/pkg/utils/strings.go @@ -24,3 +24,12 @@ func JoinStringKeysPtr(m map[string]any, sep string) string { } return JoinStringKeys(m, sep) } + +// JoinStringPtr concatenates the strings of a string slice pointer, each separatore by the +// [sep] string. +func JoinStringPtr(vals *[]string, sep string) string { + if vals == nil || len(*vals) == 0 { + return "" + } + return strings.Join(*vals, sep) +} diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index 1b4a4ad5e..e8fea5884 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -7,6 +7,7 @@ import ( "time" "github.com/google/uuid" + "github.com/inhies/go-bytesize" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -89,3 +90,20 @@ func ConvertTimePToDateTimeString(t *time.Time) string { } return t.Format(time.DateTime) } + +// PtrStringDefault return the value of a pointer [v] as string. If the pointer is nil, it returns the [defaultValue]. +func PtrStringDefault[T any](v *T, defaultValue string) string { + if v == nil { + return defaultValue + } + return fmt.Sprintf("%v", *v) +} + +// PtrByteSizeDefault return the value of an in64 pointer to a string representation of bytesize. If the pointer is nil, +// it returns the [defaultValue]. +func PtrByteSizeDefault(size *int64, defaultValue string) string { + if size == nil { + return defaultValue + } + return bytesize.New(float64(*size)).String() +} From 1390b50b9a33e4187c03f83e0d7fee1d0031d857 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 10 Feb 2025 09:03:52 +0100 Subject: [PATCH 175/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.19 (#593) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c00bae78b..49e03010f 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.17 + github.com/goccy/go-yaml v1.15.19 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 75b404731..16d902c7f 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.17 h1:dK4FbbTTEOZTLH/NW3/xBqg0JdC14YKVmYwS9GT3H60= -github.com/goccy/go-yaml v1.15.17/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.19 h1:ivDxLiW6SbmqPZwSAM9Yq+Yr68C9FLbTNyuH3ITizxQ= +github.com/goccy/go-yaml v1.15.19/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 7e094aa534c85abb83d56127e68ff3c905004d9a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:02:01 +0100 Subject: [PATCH 176/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.6.6 (#596) Co-authored-by: Renovate Bot --- go.mod | 6 +++--- go.sum | 15 ++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 49e03010f..ce10bc432 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.5 + github.com/jedib0t/go-pretty/v6 v6.6.6 github.com/lmittmann/tint v1.0.7 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.8.1 @@ -67,12 +67,12 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect diff --git a/go.sum b/go.sum index 16d902c7f..30fe47e4f 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.5 h1:9PgMJOVBedpgYLI56jQRJYqngxYAAzfEUua+3NgSqAo= -github.com/jedib0t/go-pretty/v6 v6.6.5/go.mod h1:Uq/HrbhuFty5WSVNfjpQQe47x16RwVGXIveNGEyGtHs= +github.com/jedib0t/go-pretty/v6 v6.6.6 h1:LyezkL+1SuqH2z47e5IMQkYUIcs2BD+MnpdPRiRcN0c= +github.com/jedib0t/go-pretty/v6 v6.6.6/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -78,8 +78,8 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -95,8 +95,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -173,8 +173,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= From 8479ad99e5d0d94928137071886337c5d2e3aa33 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:50:25 +0100 Subject: [PATCH 177/619] Add `yaml.UseJSONMarshaler()` to all `yaml.MarshalWithOptions()`` calls (#595) --- internal/cmd/beta/image/create/create.go | 2 +- internal/cmd/beta/image/list/list.go | 2 +- internal/cmd/beta/key-pair/create/create.go | 2 +- internal/cmd/beta/key-pair/describe/describe.go | 4 ++-- internal/cmd/beta/key-pair/list/list.go | 2 +- internal/cmd/beta/key-pair/update/update.go | 2 +- internal/cmd/beta/network-area/create/create.go | 2 +- internal/cmd/beta/network-area/describe/describe.go | 2 +- internal/cmd/beta/network-area/list/list.go | 2 +- internal/cmd/beta/network-area/network-range/create/create.go | 2 +- .../cmd/beta/network-area/network-range/describe/describe.go | 2 +- internal/cmd/beta/network-area/network-range/list/list.go | 2 +- internal/cmd/beta/network-area/route/create/create.go | 2 +- internal/cmd/beta/network-area/route/describe/describe.go | 2 +- internal/cmd/beta/network-area/route/list/list.go | 2 +- internal/cmd/beta/network-area/route/update/update.go | 2 +- internal/cmd/beta/network-area/update/update.go | 2 +- internal/cmd/beta/network-interface/create/create.go | 2 +- internal/cmd/beta/network-interface/describe/describe.go | 2 +- internal/cmd/beta/network-interface/list/list.go | 2 +- internal/cmd/beta/network-interface/update/update.go | 2 +- internal/cmd/beta/network/create/create.go | 2 +- internal/cmd/beta/network/describe/describe.go | 2 +- internal/cmd/beta/network/list/list.go | 2 +- internal/cmd/beta/public-ip/create/create.go | 2 +- internal/cmd/beta/public-ip/describe/describe.go | 2 +- internal/cmd/beta/public-ip/list/list.go | 2 +- internal/cmd/beta/public-ip/update/update.go | 2 +- internal/cmd/beta/security-group/create/create.go | 2 +- internal/cmd/beta/security-group/describe/describe.go | 2 +- internal/cmd/beta/security-group/list/list.go | 2 +- internal/cmd/beta/security-group/rule/create/create.go | 2 +- internal/cmd/beta/security-group/rule/describe/describe.go | 2 +- internal/cmd/beta/security-group/rule/list/list.go | 2 +- internal/cmd/beta/server/backup/create/create.go | 2 +- internal/cmd/beta/server/backup/describe/describe.go | 2 +- internal/cmd/beta/server/backup/list/list.go | 2 +- internal/cmd/beta/server/backup/schedule/create/create.go | 2 +- internal/cmd/beta/server/backup/schedule/describe/describe.go | 2 +- internal/cmd/beta/server/backup/schedule/list/list.go | 2 +- internal/cmd/beta/server/backup/schedule/update/update.go | 2 +- internal/cmd/beta/server/command/create/create.go | 2 +- internal/cmd/beta/server/command/describe/describe.go | 2 +- internal/cmd/beta/server/command/list/list.go | 2 +- .../cmd/beta/server/command/template/describe/describe.go | 2 +- internal/cmd/beta/server/command/template/list/list.go | 2 +- internal/cmd/beta/server/console/console.go | 2 +- internal/cmd/beta/server/create/create.go | 2 +- internal/cmd/beta/server/describe/describe.go | 2 +- internal/cmd/beta/server/list/list.go | 2 +- internal/cmd/beta/server/log/log.go | 2 +- internal/cmd/beta/server/machine-type/describe/describe.go | 2 +- internal/cmd/beta/server/machine-type/list/list.go | 2 +- internal/cmd/beta/server/network-interface/list/list.go | 2 +- internal/cmd/beta/server/os-update/create/create.go | 2 +- internal/cmd/beta/server/os-update/describe/describe.go | 2 +- internal/cmd/beta/server/os-update/list/list.go | 2 +- internal/cmd/beta/server/os-update/schedule/create/create.go | 2 +- .../cmd/beta/server/os-update/schedule/describe/describe.go | 2 +- internal/cmd/beta/server/os-update/schedule/list/list.go | 2 +- internal/cmd/beta/server/os-update/schedule/update/update.go | 2 +- internal/cmd/beta/server/service-account/attach/attach.go | 2 +- internal/cmd/beta/server/service-account/detach/detach.go | 2 +- internal/cmd/beta/server/service-account/list/list.go | 2 +- internal/cmd/beta/server/update/update.go | 2 +- internal/cmd/beta/server/volume/attach/attach.go | 2 +- internal/cmd/beta/server/volume/describe/describe.go | 2 +- internal/cmd/beta/server/volume/list/list.go | 2 +- internal/cmd/beta/server/volume/update/update.go | 2 +- internal/cmd/beta/sqlserverflex/database/create/create.go | 2 +- internal/cmd/beta/sqlserverflex/database/describe/describe.go | 2 +- internal/cmd/beta/sqlserverflex/database/list/list.go | 2 +- internal/cmd/beta/sqlserverflex/instance/create/create.go | 2 +- internal/cmd/beta/sqlserverflex/instance/describe/describe.go | 2 +- internal/cmd/beta/sqlserverflex/instance/list/list.go | 2 +- internal/cmd/beta/sqlserverflex/instance/update/update.go | 2 +- internal/cmd/beta/sqlserverflex/options/options.go | 2 +- internal/cmd/beta/sqlserverflex/user/create/create.go | 2 +- internal/cmd/beta/sqlserverflex/user/describe/describe.go | 2 +- internal/cmd/beta/sqlserverflex/user/list/list.go | 2 +- .../beta/sqlserverflex/user/reset-password/reset_password.go | 2 +- internal/cmd/beta/volume/create/create.go | 2 +- internal/cmd/beta/volume/describe/describe.go | 2 +- internal/cmd/beta/volume/list/list.go | 2 +- .../cmd/beta/volume/performance-class/describe/describe.go | 2 +- internal/cmd/beta/volume/performance-class/list/list.go | 2 +- internal/cmd/beta/volume/update/update.go | 2 +- internal/cmd/config/list/list.go | 2 +- internal/cmd/config/profile/list/list.go | 2 +- internal/cmd/dns/record-set/create/create.go | 2 +- internal/cmd/dns/record-set/describe/describe.go | 2 +- internal/cmd/dns/record-set/list/list.go | 2 +- internal/cmd/dns/zone/clone/clone.go | 2 +- internal/cmd/dns/zone/create/create.go | 2 +- internal/cmd/dns/zone/describe/describe.go | 2 +- internal/cmd/dns/zone/list/list.go | 2 +- internal/cmd/load-balancer/describe/describe.go | 2 +- internal/cmd/load-balancer/list/list.go | 2 +- .../cmd/load-balancer/observability-credentials/add/add.go | 2 +- .../observability-credentials/describe/describe.go | 2 +- .../cmd/load-balancer/observability-credentials/list/list.go | 2 +- internal/cmd/load-balancer/quota/quota.go | 2 +- internal/cmd/load-balancer/target-pool/describe/describe.go | 2 +- internal/cmd/logme/credentials/create/create.go | 2 +- internal/cmd/logme/credentials/describe/describe.go | 2 +- internal/cmd/logme/credentials/list/list.go | 2 +- internal/cmd/logme/instance/create/create.go | 2 +- internal/cmd/logme/instance/describe/describe.go | 2 +- internal/cmd/logme/instance/list/list.go | 2 +- internal/cmd/logme/plans/plans.go | 2 +- internal/cmd/mariadb/credentials/create/create.go | 2 +- internal/cmd/mariadb/credentials/describe/describe.go | 2 +- internal/cmd/mariadb/credentials/list/list.go | 2 +- internal/cmd/mariadb/instance/create/create.go | 2 +- internal/cmd/mariadb/instance/describe/describe.go | 2 +- internal/cmd/mariadb/instance/list/list.go | 2 +- internal/cmd/mariadb/plans/plans.go | 2 +- internal/cmd/mongodbflex/backup/describe/describe.go | 2 +- internal/cmd/mongodbflex/backup/list/list.go | 2 +- internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go | 2 +- internal/cmd/mongodbflex/backup/schedule/schedule.go | 2 +- internal/cmd/mongodbflex/instance/create/create.go | 2 +- internal/cmd/mongodbflex/instance/describe/describe.go | 2 +- internal/cmd/mongodbflex/instance/list/list.go | 2 +- internal/cmd/mongodbflex/instance/update/update.go | 2 +- internal/cmd/mongodbflex/options/options.go | 2 +- internal/cmd/mongodbflex/user/create/create.go | 2 +- internal/cmd/mongodbflex/user/describe/describe.go | 2 +- internal/cmd/mongodbflex/user/list/list.go | 2 +- .../cmd/mongodbflex/user/reset-password/reset_password.go | 2 +- internal/cmd/object-storage/bucket/create/create.go | 2 +- internal/cmd/object-storage/bucket/describe/describe.go | 2 +- internal/cmd/object-storage/bucket/list/list.go | 2 +- .../cmd/object-storage/credentials-group/create/create.go | 2 +- internal/cmd/object-storage/credentials-group/list/list.go | 2 +- internal/cmd/object-storage/credentials/create/create.go | 2 +- internal/cmd/object-storage/credentials/list/list.go | 2 +- internal/cmd/observability/credentials/create/create.go | 2 +- internal/cmd/observability/credentials/list/list.go | 2 +- internal/cmd/observability/grafana/describe/describe.go | 2 +- internal/cmd/observability/instance/create/create.go | 2 +- internal/cmd/observability/instance/describe/describe.go | 2 +- internal/cmd/observability/instance/list/list.go | 2 +- internal/cmd/observability/plans/plans.go | 2 +- internal/cmd/observability/scrape-config/describe/describe.go | 2 +- internal/cmd/observability/scrape-config/list/list.go | 2 +- internal/cmd/opensearch/credentials/create/create.go | 2 +- internal/cmd/opensearch/credentials/describe/describe.go | 2 +- internal/cmd/opensearch/credentials/list/list.go | 2 +- internal/cmd/opensearch/instance/create/create.go | 2 +- internal/cmd/opensearch/instance/describe/describe.go | 2 +- internal/cmd/opensearch/instance/list/list.go | 2 +- internal/cmd/opensearch/plans/plans.go | 2 +- internal/cmd/organization/member/list/list.go | 2 +- internal/cmd/organization/role/list/list.go | 2 +- internal/cmd/postgresflex/backup/describe/describe.go | 2 +- internal/cmd/postgresflex/backup/list/list.go | 2 +- internal/cmd/postgresflex/instance/clone/clone.go | 2 +- internal/cmd/postgresflex/instance/create/create.go | 2 +- internal/cmd/postgresflex/instance/describe/describe.go | 2 +- internal/cmd/postgresflex/instance/list/list.go | 2 +- internal/cmd/postgresflex/instance/update/update.go | 2 +- internal/cmd/postgresflex/options/options.go | 2 +- internal/cmd/postgresflex/user/create/create.go | 2 +- internal/cmd/postgresflex/user/describe/describe.go | 2 +- internal/cmd/postgresflex/user/list/list.go | 2 +- .../cmd/postgresflex/user/reset-password/reset_password.go | 2 +- internal/cmd/project/create/create.go | 2 +- internal/cmd/project/describe/describe.go | 2 +- internal/cmd/project/list/list.go | 2 +- internal/cmd/project/member/list/list.go | 2 +- internal/cmd/project/role/list/list.go | 2 +- internal/cmd/rabbitmq/credentials/create/create.go | 2 +- internal/cmd/rabbitmq/credentials/describe/describe.go | 2 +- internal/cmd/rabbitmq/credentials/list/list.go | 2 +- internal/cmd/rabbitmq/instance/create/create.go | 2 +- internal/cmd/rabbitmq/instance/describe/describe.go | 2 +- internal/cmd/rabbitmq/instance/list/list.go | 2 +- internal/cmd/rabbitmq/plans/plans.go | 2 +- internal/cmd/redis/credentials/create/create.go | 2 +- internal/cmd/redis/credentials/describe/describe.go | 2 +- internal/cmd/redis/credentials/list/list.go | 2 +- internal/cmd/redis/instance/create/create.go | 2 +- internal/cmd/redis/instance/describe/describe.go | 2 +- internal/cmd/redis/instance/list/list.go | 2 +- internal/cmd/redis/plans/plans.go | 2 +- internal/cmd/secrets-manager/instance/create/create.go | 2 +- internal/cmd/secrets-manager/instance/describe/describe.go | 2 +- internal/cmd/secrets-manager/instance/list/list.go | 2 +- internal/cmd/secrets-manager/user/create/create.go | 2 +- internal/cmd/secrets-manager/user/describe/describe.go | 2 +- internal/cmd/secrets-manager/user/list/list.go | 2 +- internal/cmd/service-account/create/create.go | 2 +- internal/cmd/service-account/key/list/list.go | 2 +- internal/cmd/service-account/list/list.go | 2 +- internal/cmd/service-account/token/create/create.go | 2 +- internal/cmd/service-account/token/list/list.go | 2 +- internal/cmd/ske/cluster/create/create.go | 2 +- internal/cmd/ske/cluster/describe/describe.go | 2 +- internal/cmd/ske/cluster/list/list.go | 2 +- internal/cmd/ske/cluster/update/update.go | 2 +- internal/cmd/ske/describe/describe.go | 2 +- internal/cmd/ske/kubeconfig/create/create.go | 4 ++-- internal/cmd/ske/options/options.go | 2 +- 204 files changed, 206 insertions(+), 206 deletions(-) diff --git a/internal/cmd/beta/image/create/create.go b/internal/cmd/beta/image/create/create.go index 7b259010e..1203f70a6 100644 --- a/internal/cmd/beta/image/create/create.go +++ b/internal/cmd/beta/image/create/create.go @@ -387,7 +387,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.ImageCreateRes return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal image: %w", err) } diff --git a/internal/cmd/beta/image/list/list.go b/internal/cmd/beta/image/list/list.go index 1447f75a7..2452c7443 100644 --- a/internal/cmd/beta/image/list/list.go +++ b/internal/cmd/beta/image/list/list.go @@ -145,7 +145,7 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) err return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal image list: %w", err) } diff --git a/internal/cmd/beta/key-pair/create/create.go b/internal/cmd/beta/key-pair/create/create.go index b4bd759bb..a69d75505 100644 --- a/internal/cmd/beta/key-pair/create/create.go +++ b/internal/cmd/beta/key-pair/create/create.go @@ -154,7 +154,7 @@ func outputResult(p *print.Printer, outputFormat string, item *iaas.Keypair) err } p.Outputln(string(details)) case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(item, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(item, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal key pair: %w", err) } diff --git a/internal/cmd/beta/key-pair/describe/describe.go b/internal/cmd/beta/key-pair/describe/describe.go index 85981bde3..b9efb0907 100644 --- a/internal/cmd/beta/key-pair/describe/describe.go +++ b/internal/cmd/beta/key-pair/describe/describe.go @@ -131,12 +131,12 @@ func outputResult(p *print.Printer, outputFormat string, showOnlyPublicKey bool, return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keyPair, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(keyPair, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if showOnlyPublicKey { onlyPublicKey := map[string]string{ "publicKey": *keyPair.PublicKey, } - details, err = yaml.MarshalWithOptions(onlyPublicKey, yaml.IndentSequence(true)) + details, err = yaml.MarshalWithOptions(onlyPublicKey, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) } if err != nil { diff --git a/internal/cmd/beta/key-pair/list/list.go b/internal/cmd/beta/key-pair/list/list.go index b25e6d6f6..9a1c9c624 100644 --- a/internal/cmd/beta/key-pair/list/list.go +++ b/internal/cmd/beta/key-pair/list/list.go @@ -146,7 +146,7 @@ func outputResult(p *print.Printer, outputFormat string, keyPairs []iaas.Keypair p.Outputln(string(details)) case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keyPairs, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(keyPairs, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal key pairs: %w", err) } diff --git a/internal/cmd/beta/key-pair/update/update.go b/internal/cmd/beta/key-pair/update/update.go index de9b9f5d4..90cf02e07 100644 --- a/internal/cmd/beta/key-pair/update/update.go +++ b/internal/cmd/beta/key-pair/update/update.go @@ -135,7 +135,7 @@ func outputResult(p *print.Printer, model inputModel, keyPair iaas.Keypair) erro } p.Outputln(string(details)) case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keyPair, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(keyPair, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal key pair: %w", err) } diff --git a/internal/cmd/beta/network-area/create/create.go b/internal/cmd/beta/network-area/create/create.go index 576fd8904..2df562c6d 100644 --- a/internal/cmd/beta/network-area/create/create.go +++ b/internal/cmd/beta/network-area/create/create.go @@ -189,7 +189,7 @@ func outputResult(p *print.Printer, model *inputModel, orgLabel string, networkA return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network area: %w", err) } diff --git a/internal/cmd/beta/network-area/describe/describe.go b/internal/cmd/beta/network-area/describe/describe.go index 61c329af9..13d2707d4 100644 --- a/internal/cmd/beta/network-area/describe/describe.go +++ b/internal/cmd/beta/network-area/describe/describe.go @@ -137,7 +137,7 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network area: %w", err) } diff --git a/internal/cmd/beta/network-area/list/list.go b/internal/cmd/beta/network-area/list/list.go index 984ebb4df..cb4916a79 100644 --- a/internal/cmd/beta/network-area/list/list.go +++ b/internal/cmd/beta/network-area/list/list.go @@ -152,7 +152,7 @@ func outputResult(p *print.Printer, outputFormat string, networkAreas []iaas.Net return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkAreas, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(networkAreas, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal area: %w", err) } diff --git a/internal/cmd/beta/network-area/network-range/create/create.go b/internal/cmd/beta/network-area/network-range/create/create.go index 4efb43d49..812ea18a7 100644 --- a/internal/cmd/beta/network-area/network-range/create/create.go +++ b/internal/cmd/beta/network-area/network-range/create/create.go @@ -149,7 +149,7 @@ func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkRange, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(networkRange, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network range: %w", err) } diff --git a/internal/cmd/beta/network-area/network-range/describe/describe.go b/internal/cmd/beta/network-area/network-range/describe/describe.go index 8ca934686..f97fc0b57 100644 --- a/internal/cmd/beta/network-area/network-range/describe/describe.go +++ b/internal/cmd/beta/network-area/network-range/describe/describe.go @@ -119,7 +119,7 @@ func outputResult(p *print.Printer, outputFormat string, networkRange *iaas.Netw return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkRange, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(networkRange, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network range: %w", err) } diff --git a/internal/cmd/beta/network-area/network-range/list/list.go b/internal/cmd/beta/network-area/network-range/list/list.go index b5b28f688..e2115d9a7 100644 --- a/internal/cmd/beta/network-area/network-range/list/list.go +++ b/internal/cmd/beta/network-area/network-range/list/list.go @@ -150,7 +150,7 @@ func outputResult(p *print.Printer, outputFormat string, networkRanges []iaas.Ne return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkRanges, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(networkRanges, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network ranges: %w", err) } diff --git a/internal/cmd/beta/network-area/route/create/create.go b/internal/cmd/beta/network-area/route/create/create.go index a6f14b1c8..e1b330329 100644 --- a/internal/cmd/beta/network-area/route/create/create.go +++ b/internal/cmd/beta/network-area/route/create/create.go @@ -176,7 +176,7 @@ func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal static route: %w", err) } diff --git a/internal/cmd/beta/network-area/route/describe/describe.go b/internal/cmd/beta/network-area/route/describe/describe.go index 9a4c91300..2e99f8c67 100644 --- a/internal/cmd/beta/network-area/route/describe/describe.go +++ b/internal/cmd/beta/network-area/route/describe/describe.go @@ -124,7 +124,7 @@ func outputResult(p *print.Printer, outputFormat string, route *iaas.Route) erro return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal static route: %w", err) } diff --git a/internal/cmd/beta/network-area/route/list/list.go b/internal/cmd/beta/network-area/route/list/list.go index 6d5baa093..c948e271a 100644 --- a/internal/cmd/beta/network-area/route/list/list.go +++ b/internal/cmd/beta/network-area/route/list/list.go @@ -150,7 +150,7 @@ func outputResult(p *print.Printer, outputFormat string, routes []iaas.Route) er return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(routes, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(routes, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal static routes: %w", err) } diff --git a/internal/cmd/beta/network-area/route/update/update.go b/internal/cmd/beta/network-area/route/update/update.go index f022e0d2d..511f9ed4d 100644 --- a/internal/cmd/beta/network-area/route/update/update.go +++ b/internal/cmd/beta/network-area/route/update/update.go @@ -152,7 +152,7 @@ func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal static route: %w", err) } diff --git a/internal/cmd/beta/network-area/update/update.go b/internal/cmd/beta/network-area/update/update.go index c59a80af1..a7d7bb722 100644 --- a/internal/cmd/beta/network-area/update/update.go +++ b/internal/cmd/beta/network-area/update/update.go @@ -171,7 +171,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, netw return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network area: %w", err) } diff --git a/internal/cmd/beta/network-interface/create/create.go b/internal/cmd/beta/network-interface/create/create.go index ac3686652..99fa2dc7f 100644 --- a/internal/cmd/beta/network-interface/create/create.go +++ b/internal/cmd/beta/network-interface/create/create.go @@ -237,7 +237,7 @@ func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network interface: %w", err) } diff --git a/internal/cmd/beta/network-interface/describe/describe.go b/internal/cmd/beta/network-interface/describe/describe.go index 02332642f..c83e79897 100644 --- a/internal/cmd/beta/network-interface/describe/describe.go +++ b/internal/cmd/beta/network-interface/describe/describe.go @@ -127,7 +127,7 @@ func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network interface: %w", err) } diff --git a/internal/cmd/beta/network-interface/list/list.go b/internal/cmd/beta/network-interface/list/list.go index 994cdf096..4b8d6b314 100644 --- a/internal/cmd/beta/network-interface/list/list.go +++ b/internal/cmd/beta/network-interface/list/list.go @@ -162,7 +162,7 @@ func outputResult(p *print.Printer, outputFormat string, nics []iaas.NIC) error return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(nics, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(nics, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal nics: %w", err) } diff --git a/internal/cmd/beta/network-interface/update/update.go b/internal/cmd/beta/network-interface/update/update.go index 5128e26cc..2b74557ac 100644 --- a/internal/cmd/beta/network-interface/update/update.go +++ b/internal/cmd/beta/network-interface/update/update.go @@ -229,7 +229,7 @@ func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network interface: %w", err) } diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go index 74abb08a4..e3832171b 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/beta/network/create/create.go @@ -245,7 +245,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, netw return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(network, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(network, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network: %w", err) } diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/beta/network/describe/describe.go index 26efcc3dc..6bdb139af 100644 --- a/internal/cmd/beta/network/describe/describe.go +++ b/internal/cmd/beta/network/describe/describe.go @@ -111,7 +111,7 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(network, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(network, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network: %w", err) } diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index 62ca68e6f..71cff5509 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -143,7 +143,7 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networks, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(networks, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal network: %w", err) } diff --git a/internal/cmd/beta/public-ip/create/create.go b/internal/cmd/beta/public-ip/create/create.go index dd1db3e5f..ad6196e82 100644 --- a/internal/cmd/beta/public-ip/create/create.go +++ b/internal/cmd/beta/public-ip/create/create.go @@ -151,7 +151,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, publ return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal public IP: %w", err) } diff --git a/internal/cmd/beta/public-ip/describe/describe.go b/internal/cmd/beta/public-ip/describe/describe.go index 19d03a4c9..c07e9e981 100644 --- a/internal/cmd/beta/public-ip/describe/describe.go +++ b/internal/cmd/beta/public-ip/describe/describe.go @@ -112,7 +112,7 @@ func outputResult(p *print.Printer, outputFormat string, publicIp *iaas.PublicIp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal public IP: %w", err) } diff --git a/internal/cmd/beta/public-ip/list/list.go b/internal/cmd/beta/public-ip/list/list.go index 2ac5b56ba..2293600aa 100644 --- a/internal/cmd/beta/public-ip/list/list.go +++ b/internal/cmd/beta/public-ip/list/list.go @@ -156,7 +156,7 @@ func outputResult(p *print.Printer, outputFormat string, publicIps []iaas.Public return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIps, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(publicIps, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal public IP: %w", err) } diff --git a/internal/cmd/beta/public-ip/update/update.go b/internal/cmd/beta/public-ip/update/update.go index 58c77e73c..e36d92a70 100644 --- a/internal/cmd/beta/public-ip/update/update.go +++ b/internal/cmd/beta/public-ip/update/update.go @@ -156,7 +156,7 @@ func outputResult(p *print.Printer, model *inputModel, publicIpLabel string, pub return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal public IP: %w", err) } diff --git a/internal/cmd/beta/security-group/create/create.go b/internal/cmd/beta/security-group/create/create.go index e70273a44..1f7072e29 100644 --- a/internal/cmd/beta/security-group/create/create.go +++ b/internal/cmd/beta/security-group/create/create.go @@ -155,7 +155,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal security group: %w", err) } diff --git a/internal/cmd/beta/security-group/describe/describe.go b/internal/cmd/beta/security-group/describe/describe.go index 2a01e8515..2feb18203 100644 --- a/internal/cmd/beta/security-group/describe/describe.go +++ b/internal/cmd/beta/security-group/describe/describe.go @@ -107,7 +107,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal security group: %w", err) } diff --git a/internal/cmd/beta/security-group/list/list.go b/internal/cmd/beta/security-group/list/list.go index 9ecb4a360..e9a4e31cf 100644 --- a/internal/cmd/beta/security-group/list/list.go +++ b/internal/cmd/beta/security-group/list/list.go @@ -129,7 +129,7 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.SecurityGr return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgreSQL Flex instance list: %w", err) } diff --git a/internal/cmd/beta/security-group/rule/create/create.go b/internal/cmd/beta/security-group/rule/create/create.go index 2dcd875b6..2d8958e27 100644 --- a/internal/cmd/beta/security-group/rule/create/create.go +++ b/internal/cmd/beta/security-group/rule/create/create.go @@ -229,7 +229,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, securityGro return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(securityGroupRule, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(securityGroupRule, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal security group rule: %w", err) } diff --git a/internal/cmd/beta/security-group/rule/describe/describe.go b/internal/cmd/beta/security-group/rule/describe/describe.go index 64ff2834d..5c1ef384f 100644 --- a/internal/cmd/beta/security-group/rule/describe/describe.go +++ b/internal/cmd/beta/security-group/rule/describe/describe.go @@ -123,7 +123,7 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRule *iaas return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(securityGroupRule, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(securityGroupRule, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal security group rule: %w", err) } diff --git a/internal/cmd/beta/security-group/rule/list/list.go b/internal/cmd/beta/security-group/rule/list/list.go index 385b98dd8..4e8d63481 100644 --- a/internal/cmd/beta/security-group/rule/list/list.go +++ b/internal/cmd/beta/security-group/rule/list/list.go @@ -158,7 +158,7 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRules []ia return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(securityGroupRules, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(securityGroupRules, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal security group rules: %w", err) } diff --git a/internal/cmd/beta/server/backup/create/create.go b/internal/cmd/beta/server/backup/create/create.go index 2ae95c259..f53f3b9ef 100644 --- a/internal/cmd/beta/server/backup/create/create.go +++ b/internal/cmd/beta/server/backup/create/create.go @@ -151,7 +151,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.Backup return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server backup: %w", err) } diff --git a/internal/cmd/beta/server/backup/describe/describe.go b/internal/cmd/beta/server/backup/describe/describe.go index a14f7a64d..3396fd18c 100644 --- a/internal/cmd/beta/server/backup/describe/describe.go +++ b/internal/cmd/beta/server/backup/describe/describe.go @@ -120,7 +120,7 @@ func outputResult(p *print.Printer, outputFormat string, backup *serverbackup.Ba return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server backup: %w", err) } diff --git a/internal/cmd/beta/server/backup/list/list.go b/internal/cmd/beta/server/backup/list/list.go index f5c2dbf0e..244444766 100644 --- a/internal/cmd/beta/server/backup/list/list.go +++ b/internal/cmd/beta/server/backup/list/list.go @@ -136,7 +136,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []serverbackup. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Server Backup list: %w", err) } diff --git a/internal/cmd/beta/server/backup/schedule/create/create.go b/internal/cmd/beta/server/backup/schedule/create/create.go index e35755d8e..dc10d8bcd 100644 --- a/internal/cmd/beta/server/backup/schedule/create/create.go +++ b/internal/cmd/beta/server/backup/schedule/create/create.go @@ -170,7 +170,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.Backup return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server backup schedule: %w", err) } diff --git a/internal/cmd/beta/server/backup/schedule/describe/describe.go b/internal/cmd/beta/server/backup/schedule/describe/describe.go index c94144658..7c91a0bee 100644 --- a/internal/cmd/beta/server/backup/schedule/describe/describe.go +++ b/internal/cmd/beta/server/backup/schedule/describe/describe.go @@ -120,7 +120,7 @@ func outputResult(p *print.Printer, outputFormat string, schedule *serverbackup. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(schedule, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(schedule, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server backup schedule: %w", err) } diff --git a/internal/cmd/beta/server/backup/schedule/list/list.go b/internal/cmd/beta/server/backup/schedule/list/list.go index 0709f81bd..366d6a09b 100644 --- a/internal/cmd/beta/server/backup/schedule/list/list.go +++ b/internal/cmd/beta/server/backup/schedule/list/list.go @@ -136,7 +136,7 @@ func outputResult(p *print.Printer, outputFormat string, schedules []serverbacku return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(schedules, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(schedules, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Server Backup Schedules list: %w", err) } diff --git a/internal/cmd/beta/server/backup/schedule/update/update.go b/internal/cmd/beta/server/backup/schedule/update/update.go index 88691fc82..02fe6c92a 100644 --- a/internal/cmd/beta/server/backup/schedule/update/update.go +++ b/internal/cmd/beta/server/backup/schedule/update/update.go @@ -195,7 +195,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.Backup return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal update server backup schedule: %w", err) } diff --git a/internal/cmd/beta/server/command/create/create.go b/internal/cmd/beta/server/command/create/create.go index 15d3a0d40..2729653f7 100644 --- a/internal/cmd/beta/server/command/create/create.go +++ b/internal/cmd/beta/server/command/create/create.go @@ -148,7 +148,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *runcommand.NewComma return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server command: %w", err) } diff --git a/internal/cmd/beta/server/command/describe/describe.go b/internal/cmd/beta/server/command/describe/describe.go index e7964c189..7bc408969 100644 --- a/internal/cmd/beta/server/command/describe/describe.go +++ b/internal/cmd/beta/server/command/describe/describe.go @@ -119,7 +119,7 @@ func outputResult(p *print.Printer, outputFormat string, command *runcommand.Com return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(command, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(command, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server command: %w", err) } diff --git a/internal/cmd/beta/server/command/list/list.go b/internal/cmd/beta/server/command/list/list.go index 5cdedac7d..5768eef26 100644 --- a/internal/cmd/beta/server/command/list/list.go +++ b/internal/cmd/beta/server/command/list/list.go @@ -136,7 +136,7 @@ func outputResult(p *print.Printer, outputFormat string, commands []runcommand.C return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(commands, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(commands, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server command list: %w", err) } diff --git a/internal/cmd/beta/server/command/template/describe/describe.go b/internal/cmd/beta/server/command/template/describe/describe.go index 054e81940..c44216b17 100644 --- a/internal/cmd/beta/server/command/template/describe/describe.go +++ b/internal/cmd/beta/server/command/template/describe/describe.go @@ -120,7 +120,7 @@ func outputResult(p *print.Printer, outputFormat string, commandTemplate *runcom return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(commandTemplate, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(commandTemplate, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server command template: %w", err) } diff --git a/internal/cmd/beta/server/command/template/list/list.go b/internal/cmd/beta/server/command/template/list/list.go index 03485da5a..5290173a2 100644 --- a/internal/cmd/beta/server/command/template/list/list.go +++ b/internal/cmd/beta/server/command/template/list/list.go @@ -129,7 +129,7 @@ func outputResult(p *print.Printer, outputFormat string, templates []runcommand. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(templates, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(templates, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server command template list: %w", err) } diff --git a/internal/cmd/beta/server/console/console.go b/internal/cmd/beta/server/console/console.go index 006936dcf..d5af1372e 100644 --- a/internal/cmd/beta/server/console/console.go +++ b/internal/cmd/beta/server/console/console.go @@ -119,7 +119,7 @@ func outputResult(p *print.Printer, model *inputModel, serverLabel string, serve return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serverUrl, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(serverUrl, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal url: %w", err) } diff --git a/internal/cmd/beta/server/create/create.go b/internal/cmd/beta/server/create/create.go index f1c4bf0cf..23a22a3ba 100644 --- a/internal/cmd/beta/server/create/create.go +++ b/internal/cmd/beta/server/create/create.go @@ -345,7 +345,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, serv return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server: %w", err) } diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/beta/server/describe/describe.go index 0f69c92d6..3b4b0cef8 100644 --- a/internal/cmd/beta/server/describe/describe.go +++ b/internal/cmd/beta/server/describe/describe.go @@ -116,7 +116,7 @@ func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) erro return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server: %w", err) } diff --git a/internal/cmd/beta/server/list/list.go b/internal/cmd/beta/server/list/list.go index 366d31e8f..b6a20939c 100644 --- a/internal/cmd/beta/server/list/list.go +++ b/internal/cmd/beta/server/list/list.go @@ -157,7 +157,7 @@ func outputResult(p *print.Printer, outputFormat string, servers []iaas.Server) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(servers, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(servers, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server: %w", err) } diff --git a/internal/cmd/beta/server/log/log.go b/internal/cmd/beta/server/log/log.go index 20e791b27..2de1b3246 100644 --- a/internal/cmd/beta/server/log/log.go +++ b/internal/cmd/beta/server/log/log.go @@ -151,7 +151,7 @@ func outputResult(p *print.Printer, model *inputModel, serverLabel, log string) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(log, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(log, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal url: %w", err) } diff --git a/internal/cmd/beta/server/machine-type/describe/describe.go b/internal/cmd/beta/server/machine-type/describe/describe.go index 4caf15d8b..6274f85ac 100644 --- a/internal/cmd/beta/server/machine-type/describe/describe.go +++ b/internal/cmd/beta/server/machine-type/describe/describe.go @@ -111,7 +111,7 @@ func outputResult(p *print.Printer, outputFormat string, machineType *iaas.Machi return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(machineType, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(machineType, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server machine type: %w", err) } diff --git a/internal/cmd/beta/server/machine-type/list/list.go b/internal/cmd/beta/server/machine-type/list/list.go index db378a1e7..ffa6343b5 100644 --- a/internal/cmd/beta/server/machine-type/list/list.go +++ b/internal/cmd/beta/server/machine-type/list/list.go @@ -145,7 +145,7 @@ func outputResult(p *print.Printer, model *inputModel, machineTypes *iaas.Machin return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(machineTypes, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(machineTypes, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal machineTypes: %w", err) } diff --git a/internal/cmd/beta/server/network-interface/list/list.go b/internal/cmd/beta/server/network-interface/list/list.go index b715527f4..8f0d3b928 100644 --- a/internal/cmd/beta/server/network-interface/list/list.go +++ b/internal/cmd/beta/server/network-interface/list/list.go @@ -149,7 +149,7 @@ func outputResult(p *print.Printer, outputFormat, serverId string, serverNics [] return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serverNics, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(serverNics, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server network interfaces: %w", err) } diff --git a/internal/cmd/beta/server/os-update/create/create.go b/internal/cmd/beta/server/os-update/create/create.go index 076a4d204..db998a374 100644 --- a/internal/cmd/beta/server/os-update/create/create.go +++ b/internal/cmd/beta/server/os-update/create/create.go @@ -134,7 +134,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server os-update: %w", err) } diff --git a/internal/cmd/beta/server/os-update/describe/describe.go b/internal/cmd/beta/server/os-update/describe/describe.go index 2a3c1fbed..820edddda 100644 --- a/internal/cmd/beta/server/os-update/describe/describe.go +++ b/internal/cmd/beta/server/os-update/describe/describe.go @@ -119,7 +119,7 @@ func outputResult(p *print.Printer, outputFormat string, update *serverupdate.Up return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(update, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(update, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server update: %w", err) } diff --git a/internal/cmd/beta/server/os-update/list/list.go b/internal/cmd/beta/server/os-update/list/list.go index 5a25607dd..10e71108f 100644 --- a/internal/cmd/beta/server/os-update/list/list.go +++ b/internal/cmd/beta/server/os-update/list/list.go @@ -138,7 +138,7 @@ func outputResult(p *print.Printer, outputFormat string, updates []serverupdate. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(updates, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(updates, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server os-update list: %w", err) } diff --git a/internal/cmd/beta/server/os-update/schedule/create/create.go b/internal/cmd/beta/server/os-update/schedule/create/create.go index fb767e690..861ec9629 100644 --- a/internal/cmd/beta/server/os-update/schedule/create/create.go +++ b/internal/cmd/beta/server/os-update/schedule/create/create.go @@ -154,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server os-update schedule: %w", err) } diff --git a/internal/cmd/beta/server/os-update/schedule/describe/describe.go b/internal/cmd/beta/server/os-update/schedule/describe/describe.go index 33a5caefa..e0a20bf1f 100644 --- a/internal/cmd/beta/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/beta/server/os-update/schedule/describe/describe.go @@ -119,7 +119,7 @@ func outputResult(p *print.Printer, outputFormat string, schedule *serverupdate. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(schedule, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(schedule, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server os-update schedule: %w", err) } diff --git a/internal/cmd/beta/server/os-update/schedule/list/list.go b/internal/cmd/beta/server/os-update/schedule/list/list.go index b9d1f0cff..8efd95198 100644 --- a/internal/cmd/beta/server/os-update/schedule/list/list.go +++ b/internal/cmd/beta/server/os-update/schedule/list/list.go @@ -136,7 +136,7 @@ func outputResult(p *print.Printer, outputFormat string, schedules []serverupdat return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(schedules, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(schedules, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Server os-update Schedules list: %w", err) } diff --git a/internal/cmd/beta/server/os-update/schedule/update/update.go b/internal/cmd/beta/server/os-update/schedule/update/update.go index 5b8251d70..7b4b057a3 100644 --- a/internal/cmd/beta/server/os-update/schedule/update/update.go +++ b/internal/cmd/beta/server/os-update/schedule/update/update.go @@ -177,7 +177,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal update server os-update schedule: %w", err) } diff --git a/internal/cmd/beta/server/service-account/attach/attach.go b/internal/cmd/beta/server/service-account/attach/attach.go index 00dd4ac8c..87bfbaa31 100644 --- a/internal/cmd/beta/server/service-account/attach/attach.go +++ b/internal/cmd/beta/server/service-account/attach/attach.go @@ -131,7 +131,7 @@ func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel st return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal service account: %w", err) } diff --git a/internal/cmd/beta/server/service-account/detach/detach.go b/internal/cmd/beta/server/service-account/detach/detach.go index 954463974..7c5587842 100644 --- a/internal/cmd/beta/server/service-account/detach/detach.go +++ b/internal/cmd/beta/server/service-account/detach/detach.go @@ -131,7 +131,7 @@ func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel st return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(service, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(service, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal service account: %w", err) } diff --git a/internal/cmd/beta/server/service-account/list/list.go b/internal/cmd/beta/server/service-account/list/list.go index c938f2b80..e02b9d3ae 100644 --- a/internal/cmd/beta/server/service-account/list/list.go +++ b/internal/cmd/beta/server/service-account/list/list.go @@ -148,7 +148,7 @@ func outputResult(p *print.Printer, outputFormat, serverId, serverName string, s return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal service accounts list: %w", err) } diff --git a/internal/cmd/beta/server/update/update.go b/internal/cmd/beta/server/update/update.go index 6d4a39d7f..9067d5a45 100644 --- a/internal/cmd/beta/server/update/update.go +++ b/internal/cmd/beta/server/update/update.go @@ -154,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, serverLabel string, serve return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server: %w", err) } diff --git a/internal/cmd/beta/server/volume/attach/attach.go b/internal/cmd/beta/server/volume/attach/attach.go index ba020e467..25b2a722a 100644 --- a/internal/cmd/beta/server/volume/attach/attach.go +++ b/internal/cmd/beta/server/volume/attach/attach.go @@ -154,7 +154,7 @@ func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel strin return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server volume: %w", err) } diff --git a/internal/cmd/beta/server/volume/describe/describe.go b/internal/cmd/beta/server/volume/describe/describe.go index cc77e843d..29648759e 100644 --- a/internal/cmd/beta/server/volume/describe/describe.go +++ b/internal/cmd/beta/server/volume/describe/describe.go @@ -138,7 +138,7 @@ func outputResult(p *print.Printer, outputFormat, serverLabel, volumeLabel strin return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server volume: %w", err) } diff --git a/internal/cmd/beta/server/volume/list/list.go b/internal/cmd/beta/server/volume/list/list.go index eefc47f94..f6f39e7ad 100644 --- a/internal/cmd/beta/server/volume/list/list.go +++ b/internal/cmd/beta/server/volume/list/list.go @@ -137,7 +137,7 @@ func outputResult(p *print.Printer, outputFormat, serverLabel string, volumeName return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volumes, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(volumes, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server volume list: %w", err) } diff --git a/internal/cmd/beta/server/volume/update/update.go b/internal/cmd/beta/server/volume/update/update.go index 41252e79f..289593b65 100644 --- a/internal/cmd/beta/server/volume/update/update.go +++ b/internal/cmd/beta/server/volume/update/update.go @@ -150,7 +150,7 @@ func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel strin return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server volume: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index fa3467d2d..920d06c9b 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -143,7 +143,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *sqlserverflex.Creat return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex database: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index 009ebfc0c..750488b50 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -120,7 +120,7 @@ func outputResult(p *print.Printer, outputFormat string, database *sqlserverflex return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(database, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(database, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex database: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index aac09fc65..195dc860b 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -147,7 +147,7 @@ func outputResult(p *print.Printer, outputFormat string, databases []sqlserverfl return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(databases, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(databases, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex database list: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 82ec72f8b..c4e7b3877 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -272,7 +272,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServerFlex instance: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index 59525c85d..11a4ac39b 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -109,7 +109,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *sqlserverflex return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex instance: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index b524c088a..855273e5f 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []sqlserverfl return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex instance list: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index 67ffc6acd..f1a53a3e6 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -257,7 +257,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal update SQLServerFlex instance: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index 1a3763735..8d8e2c681 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -287,7 +287,7 @@ func outputResult(p *print.Printer, model *inputModel, flavors *sqlserverflex.Li p.Outputln(string(details)) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQL Server Flex options: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 7153f4dca..82740c25a 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -154,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, use return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex user: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index a679a3e05..ec54158df 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -129,7 +129,7 @@ func outputResult(p *print.Printer, outputFormat string, user sqlserverflex.User return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex user: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index 32f9d1557..e2600d2fa 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -148,7 +148,7 @@ func outputResult(p *print.Printer, outputFormat string, users []sqlserverflex.I return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex user list: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index 6218406a6..5cb34aa27 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -144,7 +144,7 @@ func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex reset password: %w", err) } diff --git a/internal/cmd/beta/volume/create/create.go b/internal/cmd/beta/volume/create/create.go index 0374c5f46..38cfdbe4f 100644 --- a/internal/cmd/beta/volume/create/create.go +++ b/internal/cmd/beta/volume/create/create.go @@ -209,7 +209,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, volu return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal volume: %w", err) } diff --git a/internal/cmd/beta/volume/describe/describe.go b/internal/cmd/beta/volume/describe/describe.go index c62a0cedf..4dab40860 100644 --- a/internal/cmd/beta/volume/describe/describe.go +++ b/internal/cmd/beta/volume/describe/describe.go @@ -112,7 +112,7 @@ func outputResult(p *print.Printer, outputFormat string, volume *iaas.Volume) er return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal volume: %w", err) } diff --git a/internal/cmd/beta/volume/list/list.go b/internal/cmd/beta/volume/list/list.go index a9920f438..f283037a3 100644 --- a/internal/cmd/beta/volume/list/list.go +++ b/internal/cmd/beta/volume/list/list.go @@ -155,7 +155,7 @@ func outputResult(p *print.Printer, outputFormat string, volumes []iaas.Volume) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volumes, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(volumes, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal volume: %w", err) } diff --git a/internal/cmd/beta/volume/performance-class/describe/describe.go b/internal/cmd/beta/volume/performance-class/describe/describe.go index b867f2e70..6ed6c261b 100644 --- a/internal/cmd/beta/volume/performance-class/describe/describe.go +++ b/internal/cmd/beta/volume/performance-class/describe/describe.go @@ -112,7 +112,7 @@ func outputResult(p *print.Printer, outputFormat string, performanceClass *iaas. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(performanceClass, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(performanceClass, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal volume performance class: %w", err) } diff --git a/internal/cmd/beta/volume/performance-class/list/list.go b/internal/cmd/beta/volume/performance-class/list/list.go index 3bc6ed37f..9e51bd0d6 100644 --- a/internal/cmd/beta/volume/performance-class/list/list.go +++ b/internal/cmd/beta/volume/performance-class/list/list.go @@ -156,7 +156,7 @@ func outputResult(p *print.Printer, outputFormat string, performanceClasses []ia return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(performanceClasses, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(performanceClasses, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal volume performance class: %w", err) } diff --git a/internal/cmd/beta/volume/update/update.go b/internal/cmd/beta/volume/update/update.go index 3288062ff..c8a49a617 100644 --- a/internal/cmd/beta/volume/update/update.go +++ b/internal/cmd/beta/volume/update/update.go @@ -163,7 +163,7 @@ func outputResult(p *print.Printer, model *inputModel, volumeLabel string, volum return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal volume: %w", err) } diff --git a/internal/cmd/config/list/list.go b/internal/cmd/config/list/list.go index ab5599d7a..7fd7b51ce 100644 --- a/internal/cmd/config/list/list.go +++ b/internal/cmd/config/list/list.go @@ -84,7 +84,7 @@ func outputResult(p *print.Printer, outputFormat string, configData map[string]a p.Outputln(string(details)) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(configData, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(configData, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal config list: %w", err) } diff --git a/internal/cmd/config/profile/list/list.go b/internal/cmd/config/profile/list/list.go index 98cd68cb7..10f2e239b 100644 --- a/internal/cmd/config/profile/list/list.go +++ b/internal/cmd/config/profile/list/list.go @@ -100,7 +100,7 @@ func outputResult(p *print.Printer, outputFormat string, profiles []profileInfo) p.Outputln(string(details)) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(profiles, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(profiles, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal config list: %w", err) } diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 3ed23f57d..442a52794 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -191,7 +191,7 @@ func outputResult(p *print.Printer, model *inputModel, zoneLabel string, resp *d return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal DNS record-set: %w", err) } diff --git a/internal/cmd/dns/record-set/describe/describe.go b/internal/cmd/dns/record-set/describe/describe.go index 536ff5c64..2a934c8ff 100644 --- a/internal/cmd/dns/record-set/describe/describe.go +++ b/internal/cmd/dns/record-set/describe/describe.go @@ -124,7 +124,7 @@ func outputResult(p *print.Printer, outputFormat string, recordSet *dns.RecordSe return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(recordSet, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(recordSet, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal DNS record set: %w", err) } diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index 3e2bf0f81..2062a7c84 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -259,7 +259,7 @@ func outputResult(p *print.Printer, outputFormat string, recordSets []dns.Record return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(recordSets, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(recordSets, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal DNS record set list: %w", err) } diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index e950cdcce..b6d3b3cdb 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -170,7 +170,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal DNS zone: %w", err) } diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 2ad572f5a..132a9337c 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -207,7 +207,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal DNS zone: %w", err) } diff --git a/internal/cmd/dns/zone/describe/describe.go b/internal/cmd/dns/zone/describe/describe.go index 56308972f..8345bfc15 100644 --- a/internal/cmd/dns/zone/describe/describe.go +++ b/internal/cmd/dns/zone/describe/describe.go @@ -109,7 +109,7 @@ func outputResult(p *print.Printer, outputFormat string, zone *dns.Zone) error { return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(zone, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(zone, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal DNS zone: %w", err) } diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index 7f1bd2a34..73239b2c3 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -249,7 +249,7 @@ func outputResult(p *print.Printer, outputFormat string, zones []dns.Zone) error return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(zones, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(zones, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal DNS zone list: %w", err) } diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index bd98be64c..0a0ae869e 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -109,7 +109,7 @@ func outputResult(p *print.Printer, outputFormat string, loadBalancer *loadbalan return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(loadBalancer, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(loadBalancer, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal load balancer: %w", err) } diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index dde4f20ec..ecd1b4212 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -142,7 +142,7 @@ func outputResult(p *print.Printer, outputFormat string, loadBalancers []loadbal return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(loadBalancers, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(loadBalancers, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal load balancer list: %w", err) } diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index 26c09bb90..a188bcdd7 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -159,7 +159,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Load Balancer observability credentials: %w", err) } diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index 2fd1bc6e3..68781a17e 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -106,7 +106,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *loadbalanc return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Load Balancer observability credentials: %w", err) } diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 8ed74da16..bafed9561 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -177,7 +177,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []loadbalan return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Load Balancer observability credentials list: %w", err) } diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index eb6b3ea21..beecd9db2 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -98,7 +98,7 @@ func outputResult(p *print.Printer, outputFormat string, quota *loadbalancer.Get return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(quota, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(quota, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal quota: %w", err) } diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index 8eeceef88..3ffa3af70 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -138,7 +138,7 @@ func outputResult(p *print.Printer, outputFormat string, targetPool loadbalancer return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal load balancer: %w", err) } diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index b21bed0f0..22685cedc 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -136,7 +136,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal LogMe credentials: %w", err) } diff --git a/internal/cmd/logme/credentials/describe/describe.go b/internal/cmd/logme/credentials/describe/describe.go index 2d51fe40b..968c2b3ef 100644 --- a/internal/cmd/logme/credentials/describe/describe.go +++ b/internal/cmd/logme/credentials/describe/describe.go @@ -122,7 +122,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *logme.Cred return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal LogMe credentials: %w", err) } diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index cac18139b..a149a6090 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -146,7 +146,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []logme.Cre return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal LogMe credentials list: %w", err) } diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index d77f9f64e..7effe9a74 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -262,7 +262,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal LogMe instance: %w", err) } diff --git a/internal/cmd/logme/instance/describe/describe.go b/internal/cmd/logme/instance/describe/describe.go index 896f42982..9a19a4a9c 100644 --- a/internal/cmd/logme/instance/describe/describe.go +++ b/internal/cmd/logme/instance/describe/describe.go @@ -110,7 +110,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *logme.Instanc return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal LogMe instance: %w", err) } diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index e8784d054..593aff6da 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []logme.Insta return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal LogMe instance list: %w", err) } diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index 6177a4143..385ee2639 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, plans []logme.Offering) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal LogMe plans: %w", err) } diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 404d5e8a9..8fd77e4c1 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -137,7 +137,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MariaDB credentials list: %w", err) } diff --git a/internal/cmd/mariadb/credentials/describe/describe.go b/internal/cmd/mariadb/credentials/describe/describe.go index 31a09a17e..8739c7d59 100644 --- a/internal/cmd/mariadb/credentials/describe/describe.go +++ b/internal/cmd/mariadb/credentials/describe/describe.go @@ -122,7 +122,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *mariadb.Cr return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MariaDB credentials: %w", err) } diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index 47e15f379..b854d6c66 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -145,7 +145,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []mariadb.C return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MariaDB credentials list: %w", err) } diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index 031ef8930..81732c1a6 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -262,7 +262,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MariaDB instance: %w", err) } diff --git a/internal/cmd/mariadb/instance/describe/describe.go b/internal/cmd/mariadb/instance/describe/describe.go index 49788795c..952754762 100644 --- a/internal/cmd/mariadb/instance/describe/describe.go +++ b/internal/cmd/mariadb/instance/describe/describe.go @@ -110,7 +110,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *mariadb.Insta return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MariaDB instance: %w", err) } diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index f360462d3..37c5afff4 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []mariadb.Ins return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MariaDB instance list: %w", err) } diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index 6d6053c21..bd3d31957 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, plans []mariadb.Offerin return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MariaDB plans: %w", err) } diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index 4d2d9d108..b675b69ee 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -136,7 +136,7 @@ func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat, restoreSta return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex backup: %w", err) } diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index 9f19d9c3c..1b251571a 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -155,7 +155,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []mongodbflex.B return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex backups list: %w", err) } diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index e77538fd3..30a48be34 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -149,7 +149,7 @@ func outputResult(p *print.Printer, outputFormat string, restoreJobs []mongodbfl return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(restoreJobs, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(restoreJobs, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex restore jobs list: %w", err) } diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index e4b0cbb75..9445055a6 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -130,7 +130,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex backup schedule: %w", err) } diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index f4882ab95..d601a92a9 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -284,7 +284,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDBFlex instance: %w", err) } diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index bac7b7205..ca4858da5 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -110,7 +110,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex instance: %w", err) } diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index 40ac2ef8d..5b65f8d5e 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -141,7 +141,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []mongodbflex return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex instance list: %w", err) } diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index bc3dba632..68f2f85ba 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -318,7 +318,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal update MongoDBFlex instance: %w", err) } diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index abe1cca69..1b869a5c1 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -193,7 +193,7 @@ func outputResult(p *print.Printer, model *inputModel, flavors *mongodbflex.List p.Outputln(string(details)) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex options: %w", err) } diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index f3744c3cb..cd383eac2 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -160,7 +160,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, use return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex user: %w", err) } diff --git a/internal/cmd/mongodbflex/user/describe/describe.go b/internal/cmd/mongodbflex/user/describe/describe.go index 5f95804a3..b94f4b453 100644 --- a/internal/cmd/mongodbflex/user/describe/describe.go +++ b/internal/cmd/mongodbflex/user/describe/describe.go @@ -128,7 +128,7 @@ func outputResult(p *print.Printer, outputFormat string, user mongodbflex.Instan return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex user: %w", err) } diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index 365f5ee36..ae690568b 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -149,7 +149,7 @@ func outputResult(p *print.Printer, outputFormat string, users []mongodbflex.Lis return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex user list: %w", err) } diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index e04fa7b90..f35c252f3 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -144,7 +144,7 @@ func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal MongoDB Flex reset password: %w", err) } diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index 9e030b954..c1b8fe50c 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -137,7 +137,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *objectstorage.Creat return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Object Storage bucket: %w", err) } diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index f23a2fc85..1f2912a5f 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -108,7 +108,7 @@ func outputResult(p *print.Printer, outputFormat string, bucket *objectstorage.B return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(bucket, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(bucket, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Object Storage bucket: %w", err) } diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index d9409ff45..ffde74c04 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, buckets []objectstorage return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(buckets, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(buckets, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Object Storage bucket list: %w", err) } diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index 9a611b5b3..01bb89ac0 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -123,7 +123,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *objectstorage.Creat return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Object Storage credentials group: %w", err) } diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index 7f2962c23..c2c2028be 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -132,7 +132,7 @@ func outputResult(p *print.Printer, outputFormat string, credentialsGroups []obj return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentialsGroups, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentialsGroups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Object Storage credentials group list: %w", err) } diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index 1e659cdb7..662f02937 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -148,7 +148,7 @@ func outputResult(p *print.Printer, model *inputModel, credentialsGroupLabel str return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Object Storage credentials: %w", err) } diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index 237d74c61..181f43371 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -147,7 +147,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []objectsto return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Object Storage credentials list: %w", err) } diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index 6ee744588..b965364a3 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -121,7 +121,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Observability credentials: %w", err) } diff --git a/internal/cmd/observability/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go index 397f1c6a9..9c9452832 100644 --- a/internal/cmd/observability/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -135,7 +135,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []observabi return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Observability credentials list: %w", err) } diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index 9c50a7c6a..245a4b8b4 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -135,7 +135,7 @@ func outputResult(p *print.Printer, inputModel *inputModel, grafanaConfigs *obse return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(grafanaConfigs, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(grafanaConfigs, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Grafana configs: %w", err) } diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 134b8388e..99b7fe5f2 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -211,7 +211,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Observability instance: %w", err) } diff --git a/internal/cmd/observability/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go index dfd0717c7..3b4a62e40 100644 --- a/internal/cmd/observability/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -108,7 +108,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *observability return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Observability instance: %w", err) } diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index db212da21..b540bee32 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []observabili return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Observability instance list: %w", err) } diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index 872d5efea..d42cfb8a0 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -141,7 +141,7 @@ func outputResult(p *print.Printer, outputFormat string, plans []observability.P return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Observability plans: %w", err) } diff --git a/internal/cmd/observability/scrape-config/describe/describe.go b/internal/cmd/observability/scrape-config/describe/describe.go index 37dd359e7..7e92bd58f 100644 --- a/internal/cmd/observability/scrape-config/describe/describe.go +++ b/internal/cmd/observability/scrape-config/describe/describe.go @@ -110,7 +110,7 @@ func outputResult(p *print.Printer, outputFormat string, config *observability.J return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(config, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(config, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal scrape configuration: %w", err) } diff --git a/internal/cmd/observability/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go index 6e2543869..5dbdde095 100644 --- a/internal/cmd/observability/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -138,7 +138,7 @@ func outputResult(p *print.Printer, outputFormat string, configs []observability return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(configs, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(configs, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal scrape configurations list: %w", err) } diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index 015c41cc9..b2e4dde55 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -137,7 +137,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal OpenSearch credentials: %w", err) } diff --git a/internal/cmd/opensearch/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index 838521396..64817d66a 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -122,7 +122,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *opensearch return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal OpenSearch credentials: %w", err) } diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index 7f5636691..b58c99796 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -146,7 +146,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []opensearc return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal OpenSearch credentials list: %w", err) } diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index b287e54e8..d6eeaf951 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -267,7 +267,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal OpenSearch instance: %w", err) } diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index 8fd2f081b..fffdc1f86 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -110,7 +110,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *opensearch.In return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal OpenSearch instance: %w", err) } diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index c53fa0176..024619beb 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []opensearch. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal OpenSearch instance list: %w", err) } diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index f72dc67a1..50be3aae8 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -141,7 +141,7 @@ func outputResult(p *print.Printer, outputFormat string, plans []opensearch.Offe return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal OpenSearch plans: %w", err) } diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index 3a4c38a41..65f38a490 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -168,7 +168,7 @@ func outputResult(p *print.Printer, model *inputModel, members []authorization.M return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(members, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(members, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal members: %w", err) } diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index 51e9390af..5818142ff 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -141,7 +141,7 @@ func outputRolesResult(p *print.Printer, outputFormat string, roles []authorizat return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(roles, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(roles, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal roles: %w", err) } diff --git a/internal/cmd/postgresflex/backup/describe/describe.go b/internal/cmd/postgresflex/backup/describe/describe.go index 10c3bdda8..80cae356a 100644 --- a/internal/cmd/postgresflex/backup/describe/describe.go +++ b/internal/cmd/postgresflex/backup/describe/describe.go @@ -123,7 +123,7 @@ func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, bac return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal backup for PostgreSQL Flex backup: %w", err) } diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index c03a3afb6..a8416f602 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -144,7 +144,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []postgresflex. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgreSQL Flex backup list: %w", err) } diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index b9d10e78b..4ca79de4b 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -216,7 +216,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel, instanceId return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgresFlex instance clone: %w", err) } diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 5fb8b931c..062107375 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -284,7 +284,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgresFlex instance: %w", err) } diff --git a/internal/cmd/postgresflex/instance/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index 404a1c23d..c65ebfda1 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -112,7 +112,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *postgresflex. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgreSQL Flex instance: %w", err) } diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index 349f7d872..aa0e92a03 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -142,7 +142,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []postgresfle return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgreSQL Flex instance list: %w", err) } diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 975c7c860..c5f1857f6 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -318,7 +318,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgresFlex instance: %w", err) } diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index 22950039d..d21067aa1 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -193,7 +193,7 @@ func outputResult(p *print.Printer, model *inputModel, flavors *postgresflex.Lis p.Outputln(string(details)) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgreSQL Flex options: %w", err) } diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index f8d65bf01..4638da73d 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -154,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgresFlex user: %w", err) } diff --git a/internal/cmd/postgresflex/user/describe/describe.go b/internal/cmd/postgresflex/user/describe/describe.go index b63e08bd7..896154984 100644 --- a/internal/cmd/postgresflex/user/describe/describe.go +++ b/internal/cmd/postgresflex/user/describe/describe.go @@ -127,7 +127,7 @@ func outputResult(p *print.Printer, outputFormat string, user postgresflex.UserR return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgreSQL Flex user: %w", err) } diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index ae76e7958..bf540ad4c 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -148,7 +148,7 @@ func outputResult(p *print.Printer, outputFormat string, users []postgresflex.Li return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgreSQL Flex user list: %w", err) } diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index 35d097168..60abaf04a 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -143,7 +143,7 @@ func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal PostgresFlex user: %w", err) } diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index bb67f8cf1..19d20beed 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -223,7 +223,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *resourcemanager.Pro return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal project: %w", err) } diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index a9d948e67..62b997b64 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -129,7 +129,7 @@ func outputResult(p *print.Printer, outputFormat string, project *resourcemanage return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(project, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(project, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal project details: %w", err) } diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 8c9bb0d8e..99afb9b1f 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -230,7 +230,7 @@ func outputResult(p *print.Printer, outputFormat string, projects []resourcemana return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(projects, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(projects, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal projects list: %w", err) } diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index a95a95fbe..1d5056303 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -169,7 +169,7 @@ func outputResult(p *print.Printer, model *inputModel, members []authorization.M return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(members, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(members, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal members: %w", err) } diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index 991a00665..4b98bf977 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -142,7 +142,7 @@ func outputRolesResult(p *print.Printer, outputFormat string, roles []authorizat return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(roles, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(roles, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal roles: %w", err) } diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index 2b73dd453..1a7cd75ad 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -136,7 +136,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal RabbitMQ credentials: %w", err) } diff --git a/internal/cmd/rabbitmq/credentials/describe/describe.go b/internal/cmd/rabbitmq/credentials/describe/describe.go index 178027280..990fcad69 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe.go @@ -122,7 +122,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *rabbitmq.C return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal RabbitMQ credentials: %w", err) } diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index 6911f04c7..e9b03d199 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -145,7 +145,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []rabbitmq. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal RabbitMQ credentials list: %w", err) } diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index d4c970321..2810d24e8 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -267,7 +267,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal RabbitMQ instance: %w", err) } diff --git a/internal/cmd/rabbitmq/instance/describe/describe.go b/internal/cmd/rabbitmq/instance/describe/describe.go index e5038f212..2aad472cd 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe.go +++ b/internal/cmd/rabbitmq/instance/describe/describe.go @@ -110,7 +110,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *rabbitmq.Inst return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal RabbitMQ instance: %w", err) } diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index a371d0f68..3ffc1a146 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []rabbitmq.In return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal RabbitMQ instance list: %w", err) } diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index 7255baae7..6156c0724 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -141,7 +141,7 @@ func outputResult(p *print.Printer, outputFormat string, plans []rabbitmq.Offeri return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal RabbitMQ plans: %w", err) } diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index e241a2d27..388e269a4 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -138,7 +138,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Redis credentials: %w", err) } diff --git a/internal/cmd/redis/credentials/describe/describe.go b/internal/cmd/redis/credentials/describe/describe.go index 238b67bc5..6d342002f 100644 --- a/internal/cmd/redis/credentials/describe/describe.go +++ b/internal/cmd/redis/credentials/describe/describe.go @@ -122,7 +122,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *redis.Cred return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Redis credentials: %w", err) } diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index 78be560f1..a83492451 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -145,7 +145,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []redis.Cre return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Redis credentials list: %w", err) } diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index eec468709..84d8e19ee 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -262,7 +262,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Redis instance: %w", err) } diff --git a/internal/cmd/redis/instance/describe/describe.go b/internal/cmd/redis/instance/describe/describe.go index 1b41c20d4..5e8737212 100644 --- a/internal/cmd/redis/instance/describe/describe.go +++ b/internal/cmd/redis/instance/describe/describe.go @@ -110,7 +110,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *redis.Instanc return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Redis instance: %w", err) } diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index 2eff0bf8c..d75ea93b4 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []redis.Insta return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Redis instance list: %w", err) } diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index ef94c2a12..0f7dbde6b 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -140,7 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, plans []redis.Offering) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Redis plans: %w", err) } diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index 016a4326e..3d16d252e 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -168,7 +168,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Secrets Manager instance: %w", err) } diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index 416717ef1..e40278256 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -126,7 +126,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *secretsmanage return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Secrets Manager instance: %w", err) } diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index a207cc98d..019aff8f6 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -141,7 +141,7 @@ func outputResult(p *print.Printer, outputFormat string, instances []secretsmana return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Secrets Manager instance list: %w", err) } diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 6143b7d98..33edfbe3a 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -148,7 +148,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Secrets Manager user: %w", err) } diff --git a/internal/cmd/secrets-manager/user/describe/describe.go b/internal/cmd/secrets-manager/user/describe/describe.go index f93e19a24..2bfb18b08 100644 --- a/internal/cmd/secrets-manager/user/describe/describe.go +++ b/internal/cmd/secrets-manager/user/describe/describe.go @@ -124,7 +124,7 @@ func outputResult(p *print.Printer, outputFormat string, user secretsmanager.Use return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Secrets Manager user: %w", err) } diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index ad0bc0e67..19ff7f8ea 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -148,7 +148,7 @@ func outputResult(p *print.Printer, outputFormat string, users []secretsmanager. return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Secrets Manager user list: %w", err) } diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index 3faec270c..390e5a15b 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -130,7 +130,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, serv return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccount, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(serviceAccount, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal service account: %w", err) } diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index 13040757d..66c7fafcb 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -150,7 +150,7 @@ func outputResult(p *print.Printer, outputFormat string, keys []serviceaccount.S return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keys, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(keys, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal keys metadata: %w", err) } diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index e3e6f3b83..c4ea786d2 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -132,7 +132,7 @@ func outputResult(p *print.Printer, outputFormat string, serviceAccounts []servi } p.Outputln(string(details)) case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal service accounts list: %w", err) } diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index 12e0ce6fa..19a52faee 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -153,7 +153,7 @@ func outputResult(p *print.Printer, model *inputModel, token *serviceaccount.Acc return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(token, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(token, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal service account access token: %w", err) } diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index e9395d668..48b793f42 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -155,7 +155,7 @@ func outputResult(p *print.Printer, outputFormat string, tokensMetadata []servic return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(tokensMetadata, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(tokensMetadata, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal tokens metadata: %w", err) } diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index cb5981d52..967b1fe37 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -208,7 +208,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SKE cluster: %w", err) } diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 5a4b4ec0e..9740abf39 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -107,7 +107,7 @@ func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) e return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SKE cluster: %w", err) } diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 785f645c1..0a39805aa 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -158,7 +158,7 @@ func outputResult(p *print.Printer, outputFormat string, clusters []ske.Cluster) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(clusters, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(clusters, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SKE cluster list: %w", err) } diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index 491daf86e..48d73784b 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -170,7 +170,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *ske.Cluster) error return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SKE cluster: %w", err) } diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index 53d9dd848..025cd78a1 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -97,7 +97,7 @@ func outputResult(p *print.Printer, outputFormat string, project *serviceenablem return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(project, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(project, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SKE project details: %w", err) } diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index adc74b0e5..a8fb68437 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -262,9 +262,9 @@ func outputResult(p *print.Printer, model *inputModel, kubeconfigPath string, re var err error var details []byte if respKubeconfig != nil { - details, err = yaml.MarshalWithOptions(respKubeconfig, yaml.IndentSequence(true)) + details, err = yaml.MarshalWithOptions(respKubeconfig, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) } else if respLogin != nil { - details, err = yaml.MarshalWithOptions(respLogin, yaml.IndentSequence(true)) + details, err = yaml.MarshalWithOptions(respLogin, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) } if err != nil { return fmt.Errorf("marshal SKE Kubeconfig: %w", err) diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index e8ad07eea..82105321c 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -166,7 +166,7 @@ func outputResult(p *print.Printer, model *inputModel, options *ske.ProviderOpti p.Outputln(string(details)) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true)) + details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SKE options: %w", err) } From 9ba08963822558810f315a6fc29a9edf48d088d8 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Tue, 11 Feb 2025 09:38:01 +0100 Subject: [PATCH 178/619] feat: Onboard affinity-group command (#594) * Onboard affinity-group command - create - delete AFFINITY_GROUP_ID - describe AFFINITY_GROUP_ID - list * Add `yaml.UseJSONMarshaler()` to `yaml.MarshalWithOptions()`` calls --- docs/stackit_beta.md | 1 + docs/stackit_beta_affinity-group.md | 37 +++ docs/stackit_beta_affinity-group_create.md | 42 ++++ docs/stackit_beta_affinity-group_delete.md | 40 +++ docs/stackit_beta_affinity-group_describe.md | 40 +++ docs/stackit_beta_affinity-group_list.md | 44 ++++ .../beta/affinity-groups/affinity-groups.go | 33 +++ .../cmd/beta/affinity-groups/create/create.go | 148 +++++++++++ .../affinity-groups/create/create_test.go | 232 ++++++++++++++++++ .../cmd/beta/affinity-groups/delete/delete.go | 113 +++++++++ .../affinity-groups/delete/delete_test.go | 176 +++++++++++++ .../beta/affinity-groups/describe/describe.go | 141 +++++++++++ .../affinity-groups/describe/describe_test.go | 212 ++++++++++++++++ .../cmd/beta/affinity-groups/list/list.go | 155 ++++++++++++ .../beta/affinity-groups/list/list_test.go | 206 ++++++++++++++++ internal/cmd/beta/beta.go | 4 +- internal/pkg/services/iaas/utils/utils.go | 12 + .../pkg/services/iaas/utils/utils_test.go | 54 ++++ 18 files changed, 1689 insertions(+), 1 deletion(-) create mode 100644 docs/stackit_beta_affinity-group.md create mode 100644 docs/stackit_beta_affinity-group_create.md create mode 100644 docs/stackit_beta_affinity-group_delete.md create mode 100644 docs/stackit_beta_affinity-group_describe.md create mode 100644 docs/stackit_beta_affinity-group_list.md create mode 100644 internal/cmd/beta/affinity-groups/affinity-groups.go create mode 100644 internal/cmd/beta/affinity-groups/create/create.go create mode 100644 internal/cmd/beta/affinity-groups/create/create_test.go create mode 100644 internal/cmd/beta/affinity-groups/delete/delete.go create mode 100644 internal/cmd/beta/affinity-groups/delete/delete_test.go create mode 100644 internal/cmd/beta/affinity-groups/describe/describe.go create mode 100644 internal/cmd/beta/affinity-groups/describe/describe_test.go create mode 100644 internal/cmd/beta/affinity-groups/list/list.go create mode 100644 internal/cmd/beta/affinity-groups/list/list_test.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index fde3ac259..9cbcd94d0 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -41,6 +41,7 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups * [stackit beta image](./stackit_beta_image.md) - Manage server images * [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs * [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_affinity-group.md b/docs/stackit_beta_affinity-group.md new file mode 100644 index 000000000..cf63d5263 --- /dev/null +++ b/docs/stackit_beta_affinity-group.md @@ -0,0 +1,37 @@ +## stackit beta affinity-group + +Manage server affinity groups + +### Synopsis + +Manage the lifecycle of server affinity groups. + +``` +stackit beta affinity-group [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta affinity-group" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta affinity-group create](./stackit_beta_affinity-group_create.md) - Creates an affinity groups +* [stackit beta affinity-group delete](./stackit_beta_affinity-group_delete.md) - Deletes an affinity group +* [stackit beta affinity-group describe](./stackit_beta_affinity-group_describe.md) - Show details of an affinity group +* [stackit beta affinity-group list](./stackit_beta_affinity-group_list.md) - Lists affinity groups + diff --git a/docs/stackit_beta_affinity-group_create.md b/docs/stackit_beta_affinity-group_create.md new file mode 100644 index 000000000..2eab22578 --- /dev/null +++ b/docs/stackit_beta_affinity-group_create.md @@ -0,0 +1,42 @@ +## stackit beta affinity-group create + +Creates an affinity groups + +### Synopsis + +Creates an affinity groups. + +``` +stackit beta affinity-group create [flags] +``` + +### Examples + +``` + Create an affinity group with name "AFFINITY_GROUP_NAME" and policy "soft-affinity" + $ stackit beta affinity-group create --name AFFINITY_GROUP_NAME --policy soft-affinity +``` + +### Options + +``` + -h, --help Help for "stackit beta affinity-group create" + --name string The name of the affinity group. + --policy string The policy for the affinity group. Valid values for the policy are: "hard-affinity", "hard-anti-affinity", "soft-affinity", "soft-anti-affinity" +``` + +### 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 beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups + diff --git a/docs/stackit_beta_affinity-group_delete.md b/docs/stackit_beta_affinity-group_delete.md new file mode 100644 index 000000000..e4e43be34 --- /dev/null +++ b/docs/stackit_beta_affinity-group_delete.md @@ -0,0 +1,40 @@ +## stackit beta affinity-group delete + +Deletes an affinity group + +### Synopsis + +Deletes an affinity group. + +``` +stackit beta affinity-group delete AFFINITY_GROUP [flags] +``` + +### Examples + +``` + Delete an affinity group with ID "xxx" + $ stackit beta affinity-group delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta affinity-group delete" +``` + +### 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 beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups + diff --git a/docs/stackit_beta_affinity-group_describe.md b/docs/stackit_beta_affinity-group_describe.md new file mode 100644 index 000000000..272c9b291 --- /dev/null +++ b/docs/stackit_beta_affinity-group_describe.md @@ -0,0 +1,40 @@ +## stackit beta affinity-group describe + +Show details of an affinity group + +### Synopsis + +Show details of an affinity group. + +``` +stackit beta affinity-group describe AFFINITY_GROUP_ID [flags] +``` + +### Examples + +``` + Get details about an affinity group with the ID "xxx" + $ stackit beta affinity-group describe xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta affinity-group 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 beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups + diff --git a/docs/stackit_beta_affinity-group_list.md b/docs/stackit_beta_affinity-group_list.md new file mode 100644 index 000000000..ac79cb40a --- /dev/null +++ b/docs/stackit_beta_affinity-group_list.md @@ -0,0 +1,44 @@ +## stackit beta affinity-group list + +Lists affinity groups + +### Synopsis + +Lists affinity groups. + +``` +stackit beta affinity-group list [flags] +``` + +### Examples + +``` + Lists all affinity groups + $ stackit beta affinity-group list + + Lists up to 10 affinity groups + $ stackit beta affinity-group list --limit=10 +``` + +### Options + +``` + -h, --help Help for "stackit beta affinity-group list" + --limit int Limit the output to the first n elements +``` + +### 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 beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups + diff --git a/internal/cmd/beta/affinity-groups/affinity-groups.go b/internal/cmd/beta/affinity-groups/affinity-groups.go new file mode 100644 index 000000000..f05389de3 --- /dev/null +++ b/internal/cmd/beta/affinity-groups/affinity-groups.go @@ -0,0 +1,33 @@ +package affinity_groups + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "affinity-group", + Short: "Manage server affinity groups", + Long: "Manage the lifecycle of server affinity groups.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand( + create.NewCmd(p), + delete.NewCmd(p), + describe.NewCmd(p), + list.NewCmd(p), + ) +} diff --git a/internal/cmd/beta/affinity-groups/create/create.go b/internal/cmd/beta/affinity-groups/create/create.go new file mode 100644 index 000000000..fb3a3dae7 --- /dev/null +++ b/internal/cmd/beta/affinity-groups/create/create.go @@ -0,0 +1,148 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + nameFlag = "name" + policyFlag = "policy" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name string + Policy string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates an affinity groups", + Long: `Creates an affinity groups.`, + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create an affinity group with name "AFFINITY_GROUP_NAME" and policy "soft-affinity"`, + "$ stackit beta affinity-group create --name AFFINITY_GROUP_NAME --policy soft-affinity", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create the affinity group %q?", model.Name) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + request := buildRequest(ctx, *model, apiClient) + + result, err := request.Execute() + if err != nil { + return fmt.Errorf("create affinity group: %w", err) + } + if resp := result; resp != nil { + return outputResult(p, *model, *resp) + } + return fmt.Errorf("create affinity group: nil result") + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "The name of the affinity group.") + cmd.Flags().String(policyFlag, "", `The policy for the affinity group. Valid values for the policy are: "hard-affinity", "hard-anti-affinity", "soft-affinity", "soft-anti-affinity"`) + + if err := flags.MarkFlagsRequired(cmd, nameFlag, policyFlag); err != nil { + cobra.CheckErr(err) + } +} + +func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClient) iaas.ApiCreateAffinityGroupRequest { + req := apiClient.CreateAffinityGroup(ctx, model.ProjectId) + req = req.CreateAffinityGroupPayload( + iaas.CreateAffinityGroupPayload{ + Name: utils.Ptr(model.Name), + Policy: utils.Ptr(model.Policy), + }, + ) + return req +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringValue(p, cmd, nameFlag), + Policy: flags.FlagToStringValue(p, cmd, policyFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func outputResult(p *print.Printer, model inputModel, resp iaas.AffinityGroup) error { + outputFormat := "" + if model.GlobalFlagModel != nil { + outputFormat = model.GlobalFlagModel.OutputFormat + } + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal affinity group: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal affinity group: %w", err) + } + p.Outputln(string(details)) + default: + p.Outputf("Created affinity group %q with id %s\n", model.Name, utils.PtrString(resp.Id)) + } + return nil +} diff --git a/internal/cmd/beta/affinity-groups/create/create_test.go b/internal/cmd/beta/affinity-groups/create/create_test.go new file mode 100644 index 000000000..3ab7db59f --- /dev/null +++ b/internal/cmd/beta/affinity-groups/create/create_test.go @@ -0,0 +1,232 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() +) + +const ( + testName = "test-name" + testPolicy = "test-policy" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + + nameFlag: testName, + policyFlag: testPolicy, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + Name: testName, + Policy: testPolicy, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateAffinityGroupRequest)) iaas.ApiCreateAffinityGroupRequest { + request := testClient.CreateAffinityGroup(testCtx, testProjectId) + request = request.CreateAffinityGroupPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateAffinityGroupPayload)) iaas.CreateAffinityGroupPayload { + payload := iaas.CreateAffinityGroupPayload{ + Name: utils.Ptr(testName), + Policy: utils.Ptr(testPolicy), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "without name flag", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + delete(flagValues, "name") + }, + ), + isValid: false, + }, + { + description: "without policy flag", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + delete(flagValues, "policy") + }, + ), + isValid: false, + }, + { + description: "without name and policy flag", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + delete(flagValues, "policy") + delete(flagValues, "name") + }, + ), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Fatalf("configure global flags: %v", err) + } + + for flag, value := range tt.flagValues { + if err := cmd.Flags().Set(flag, value); err != nil { + if !tt.isValid { + return + } + t.Fatalf("setting flag --%s=%s: %v", flag, value, err) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model inputModel + expectedRequest iaas.ApiCreateAffinityGroupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx)) + if diff != "" { + t.Fatalf("Request does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + model inputModel + response iaas.AffinityGroup + isValid bool + }{ + { + description: "empty", + model: inputModel{}, + response: iaas.AffinityGroup{}, + isValid: true, + }, + { + description: "base", + model: *fixtureInputModel(), + response: iaas.AffinityGroup{ + Id: utils.Ptr(testProjectId), + Members: utils.Ptr([]string{uuid.NewString(), uuid.NewString()}), + Name: utils.Ptr("test-project"), + Policy: utils.Ptr("hard-affinity"), + }, + isValid: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.model, tt.response) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error output result: %v", err) + return + } + if !tt.isValid { + t.Fatalf("did not fail on invalid input") + return + } + }) + } +} diff --git a/internal/cmd/beta/affinity-groups/delete/delete.go b/internal/cmd/beta/affinity-groups/delete/delete.go new file mode 100644 index 000000000..f48dbd6a6 --- /dev/null +++ b/internal/cmd/beta/affinity-groups/delete/delete.go @@ -0,0 +1,113 @@ +package delete + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + AffinityGroupId string +} + +const ( + affinityGroupIdArg = "AFFINITY_GROUP" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", affinityGroupIdArg), + Short: "Deletes an affinity group", + Long: `Deletes an affinity group.`, + Args: args.SingleArg(affinityGroupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete an affinity group with ID "xxx"`, + "$ stackit beta affinity-group delete xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + affinityGroupLabel, err := iaasUtils.GetAffinityGroupName(ctx, apiClient, model.ProjectId, model.AffinityGroupId) + if err != nil { + p.Debug(print.ErrorLevel, "get affinity group name: %v", err) + affinityGroupLabel = model.AffinityGroupId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete affinity group %q?", affinityGroupLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + request := buildRequest(ctx, *model, apiClient) + err = request.Execute() + if err != nil { + return fmt.Errorf("delete affinity group: %w", err) + } + p.Info("Deleted affinity group %q for %q\n", affinityGroupLabel, projectLabel) + + return nil + }, + } + return cmd +} + +func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteAffinityGroupRequest { + return apiClient.DeleteAffinityGroup(ctx, model.ProjectId, model.AffinityGroupId) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + AffinityGroupId: cliArgs[0], + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} diff --git a/internal/cmd/beta/affinity-groups/delete/delete_test.go b/internal/cmd/beta/affinity-groups/delete/delete_test.go new file mode 100644 index 000000000..71f2b84a7 --- /dev/null +++ b/internal/cmd/beta/affinity-groups/delete/delete_test.go @@ -0,0 +1,176 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + + testAffinityGroupId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testAffinityGroupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + AffinityGroupId: testAffinityGroupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteAffinityGroupRequest)) iaas.ApiDeleteAffinityGroupRequest { + request := testClient.DeleteAffinityGroup(testCtx, testProjectId, testAffinityGroupId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "without args", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "without flags", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model inputModel + expectedRequest iaas.ApiDeleteAffinityGroupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/affinity-groups/describe/describe.go b/internal/cmd/beta/affinity-groups/describe/describe.go new file mode 100644 index 000000000..197cf1b37 --- /dev/null +++ b/internal/cmd/beta/affinity-groups/describe/describe.go @@ -0,0 +1,141 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + AffinityGroupId string +} + +const ( + affinityGroupId = "AFFINITY_GROUP_ID" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", affinityGroupId), + Short: "Show details of an affinity group", + Long: `Show details of an affinity group.`, + Args: args.SingleArg(affinityGroupId, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get details about an affinity group with the ID "xxx"`, + "$ stackit beta affinity-group describe xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + request := buildRequest(ctx, *model, apiClient) + result, err := request.Execute() + if err != nil { + return fmt.Errorf("get affinity group: %w", err) + } + + if err := outputResult(p, *model, *result); err != nil { + return err + } + return nil + }, + } + return cmd +} + +func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClient) iaas.ApiGetAffinityGroupRequest { + return apiClient.GetAffinityGroup(ctx, model.ProjectId, model.AffinityGroupId) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + AffinityGroupId: cliArgs[0], + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func outputResult(p *print.Printer, model inputModel, resp iaas.AffinityGroup) error { + var outputFormat string + if model.GlobalFlagModel != nil { + outputFormat = model.GlobalFlagModel.OutputFormat + } + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal affinity group: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal affinity group: %w", err) + } + p.Outputln(string(details)) + default: + table := tables.NewTable() + + if resp.HasId() { + table.AddRow("ID", utils.PtrString(resp.Id)) + table.AddSeparator() + } + if resp.Name != nil { + table.AddRow("NAME", utils.PtrString(resp.Name)) + table.AddSeparator() + } + if resp.Policy != nil { + table.AddRow("POLICY", utils.PtrString(resp.Policy)) + table.AddSeparator() + } + if resp.HasMembers() { + table.AddRow("Members", utils.JoinStringPtr(resp.Members, ", ")) + table.AddSeparator() + } + + if err := table.Display(p); err != nil { + return fmt.Errorf("render table: %w", err) + } + } + return nil +} diff --git a/internal/cmd/beta/affinity-groups/describe/describe_test.go b/internal/cmd/beta/affinity-groups/describe/describe_test.go new file mode 100644 index 000000000..1d8a1f23b --- /dev/null +++ b/internal/cmd/beta/affinity-groups/describe/describe_test.go @@ -0,0 +1,212 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), &testCtxKey{}, projectIdFlag) + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + + testAffinityGroupId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testAffinityGroupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + AffinityGroupId: testAffinityGroupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetAffinityGroupRequest)) iaas.ApiGetAffinityGroupRequest { + request := testClient.GetAffinityGroup(testCtx, testProjectId, testAffinityGroupId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "without args", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "without flags", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + {}, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model inputModel + expectedRequest iaas.ApiGetAffinityGroupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + model inputModel + isValid bool + response iaas.AffinityGroup + }{ + { + description: "empty", + model: inputModel{}, + isValid: true, + response: iaas.AffinityGroup{}, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.model, tt.response) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error output result: %v", err) + return + } + if !tt.isValid { + t.Fatalf("did not fail on invalid input") + return + } + }) + } +} diff --git a/internal/cmd/beta/affinity-groups/list/list.go b/internal/cmd/beta/affinity-groups/list/list.go new file mode 100644 index 000000000..260eb787b --- /dev/null +++ b/internal/cmd/beta/affinity-groups/list/list.go @@ -0,0 +1,155 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +const limitFlag = "limit" + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists affinity groups", + Long: `Lists affinity groups.`, + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + "Lists all affinity groups", + "$ stackit beta affinity-group list", + ), + examples.NewExample( + "Lists up to 10 affinity groups", + "$ stackit beta affinity-group list --limit=10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + request := buildRequest(ctx, *model, apiClient) + result, err := request.Execute() + if err != nil { + return fmt.Errorf("list affinity groups: %w", err) + } + + if items := result.Items; items != nil { + if model.Limit != nil && len(*items) > int(*model.Limit) { + *items = (*items)[:*model.Limit] + } + return outputResult(p, *model, *items) + } + + p.Outputln("No affinity groups found") + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") +} + +func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClient) iaas.ApiListAffinityGroupsRequest { + return apiClient.ListAffinityGroups(ctx, model.ProjectId) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func outputResult(p *print.Printer, model inputModel, items []iaas.AffinityGroup) error { + var outputFormat string + if model.GlobalFlagModel != nil { + outputFormat = model.GlobalFlagModel.OutputFormat + } + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(items, "", " ") + if err != nil { + return fmt.Errorf("marshal affinity groups: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal affinity groups: %w", err) + } + p.Outputln(string(details)) + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "POLICY") + for _, item := range items { + table.AddRow( + utils.PtrString(item.Id), + utils.PtrString(item.Name), + utils.PtrString(item.Policy), + ) + table.AddSeparator() + } + + if err := table.Display(p); err != nil { + return fmt.Errorf("render table: %w", err) + } + } + return nil +} diff --git a/internal/cmd/beta/affinity-groups/list/list_test.go b/internal/cmd/beta/affinity-groups/list/list_test.go new file mode 100644 index 000000000..da35b5778 --- /dev/null +++ b/internal/cmd/beta/affinity-groups/list/list_test.go @@ -0,0 +1,206 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() +) + +const ( + testLimit = 10 +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListAffinityGroupsRequest)) iaas.ApiListAffinityGroupsRequest { + request := testClient.ListAffinityGroups(testCtx, testProjectId) + 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: "without flags", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "with limit flag", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(testLimit) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(testLimit)) + }), + }, + { + description: "with limit flag == 0", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(0) + }), + isValid: false, + }, + { + description: "with limit flag < 0", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(-1) + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Fatalf("configure global flags: %v", err) + } + + for flag, value := range tt.flagValues { + if err := cmd.Flags().Set(flag, value); err != nil { + if !tt.isValid { + return + } + t.Fatalf("setting flag --%s=%s: %v", flag, value, err) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model inputModel + expectedRequest iaas.ApiListAffinityGroupsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx)) + if diff != "" { + t.Fatalf("Request does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + model inputModel + response []iaas.AffinityGroup + isValid bool + }{ + { + description: "empty", + model: inputModel{}, + response: []iaas.AffinityGroup{}, + isValid: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.model, tt.response) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error output result: %v", err) + return + } + if !tt.isValid { + t.Fatalf("did not fail on invalid input") + return + } + }) + } +} diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 72ed0c5f2..d5b30e94a 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,7 +3,8 @@ package beta import ( "fmt" - image "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image" + affinityGroups "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image" keypair "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network" networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" @@ -56,4 +57,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(keypair.NewCmd(p)) cmd.AddCommand(image.NewCmd(p)) cmd.AddCommand(quota.NewCmd(p)) + cmd.AddCommand(affinityGroups.NewCmd(p)) } diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index c3102cfed..b3456d254 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -18,6 +18,7 @@ type IaaSClient interface { ListNetworkAreaProjectsExecute(ctx context.Context, organizationId, areaId string) (*iaas.ProjectListResponse, error) GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) GetImageExecute(ctx context.Context, projectId string, imageId string) (*iaas.Image, error) + GetAffinityGroupExecute(ctx context.Context, projectId string, affinityGroupId string) (*iaas.AffinityGroup, error) } func GetSecurityGroupRuleName(ctx context.Context, apiClient IaaSClient, projectId, securityGroupRuleId, securityGroupId string) (string, error) { @@ -129,3 +130,14 @@ func GetImageName(ctx context.Context, apiClient IaaSClient, projectId, imageId } return *resp.Name, nil } + +func GetAffinityGroupName(ctx context.Context, apiClient IaaSClient, projectId, affinityGroupId string) (string, error) { + resp, err := apiClient.GetAffinityGroupExecute(ctx, projectId, affinityGroupId) + if err != nil { + return "", fmt.Errorf("get affinity group: %w", err) + } + if resp.Name == nil { + return "", nil + } + return *resp.Name, nil +} diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index 01c59aa70..d62dac35c 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -31,6 +31,15 @@ type IaaSClientMocked struct { GetNetworkAreaRangeResp *iaas.NetworkRange GetImageFails bool GetImageResp *iaas.Image + GetAffinityGroupsFails bool + GetAffinityGroupResp *iaas.AffinityGroup +} + +func (m *IaaSClientMocked) GetAffinityGroupExecute(_ context.Context, _, _ string) (*iaas.AffinityGroup, error) { + if m.GetAffinityGroupsFails { + return nil, fmt.Errorf("could not get affinity groups") + } + return m.GetAffinityGroupResp, nil } func (m *IaaSClientMocked) GetSecurityGroupRuleExecute(_ context.Context, _, _, _ string) (*iaas.SecurityGroupRule, error) { @@ -715,3 +724,48 @@ func TestGetImageName(t *testing.T) { }) } } + +func TestGetAffinityGroupName(t *testing.T) { + tests := []struct { + name string + affinityResp *iaas.AffinityGroup + affinityErr bool + want string + wantErr bool + }{ + { + name: "successful retrieval", + affinityResp: &iaas.AffinityGroup{Name: utils.Ptr("test-affinity")}, + want: "test-affinity", + wantErr: false, + }, + { + name: "error on retrieval", + affinityErr: true, + wantErr: true, + }, + { + name: "nil affinity group name", + affinityErr: false, + affinityResp: &iaas.AffinityGroup{}, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + client := &IaaSClientMocked{ + GetAffinityGroupsFails: tt.affinityErr, + GetAffinityGroupResp: tt.affinityResp, + } + got, err := GetAffinityGroupName(ctx, client, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetAffinityGroupName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetAffinityGroupName() = %v, want %v", got, tt.want) + } + }) + } +} From d2bc80cfe27a47e47984d67e2a4789b57e56f9c0 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 12 Feb 2025 09:25:14 +0100 Subject: [PATCH 179/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.20 (#597) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ce10bc432..ab7c250a1 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.19 + github.com/goccy/go-yaml v1.15.20 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 30fe47e4f..f10024282 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.19 h1:ivDxLiW6SbmqPZwSAM9Yq+Yr68C9FLbTNyuH3ITizxQ= -github.com/goccy/go-yaml v1.15.19/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.20 h1:eQHFLrr1lpLYAxupPD9ThZbGtncPl9nyu3nkAayEZgY= +github.com/goccy/go-yaml v1.15.20/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From e214df10b064a7fdd8a321becec9e798c4fb9dcf Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Wed, 12 Feb 2025 09:46:24 +0100 Subject: [PATCH 180/619] feat: region adjustment object storage (#592) * Region adjustment of object-storage regarding the SDK update * upgrade dependency github.com/stackitcloud/stackit-sdk-go/services/objectstorage to version 1.0.0 * fix: Renamed `model.GlobalFlagModel.Region` to `model.Region` to stay consistent --- go.mod | 2 +- go.sum | 2 ++ .../cmd/object-storage/bucket/create/create.go | 6 +++--- .../bucket/create/create_test.go | 6 +++++- .../cmd/object-storage/bucket/delete/delete.go | 4 ++-- .../bucket/delete/delete_test.go | 6 +++++- .../object-storage/bucket/describe/describe.go | 2 +- .../bucket/describe/describe_test.go | 6 +++++- .../cmd/object-storage/bucket/list/list.go | 2 +- .../object-storage/bucket/list/list_test.go | 6 +++++- .../credentials-group/create/create.go | 2 +- .../credentials-group/create/create_test.go | 6 +++++- .../credentials-group/delete/delete.go | 4 ++-- .../credentials-group/delete/delete_test.go | 6 +++++- .../credentials-group/list/list.go | 2 +- .../credentials-group/list/list_test.go | 6 +++++- .../credentials/create/create.go | 4 ++-- .../credentials/create/create_test.go | 6 +++++- .../credentials/delete/delete.go | 6 +++--- .../credentials/delete/delete_test.go | 6 +++++- .../object-storage/credentials/list/list.go | 4 ++-- .../credentials/list/list_test.go | 6 +++++- internal/cmd/object-storage/disable/disable.go | 2 +- .../cmd/object-storage/disable/disable_test.go | 6 +++++- internal/cmd/object-storage/enable/enable.go | 2 +- .../cmd/object-storage/enable/enable_test.go | 6 +++++- .../pkg/services/object-storage/utils/utils.go | 18 +++++++++--------- .../object-storage/utils/utils_test.go | 13 +++++++------ 28 files changed, 99 insertions(+), 48 deletions(-) diff --git a/go.mod b/go.mod index ab7c250a1..80db6dcb7 100644 --- a/go.mod +++ b/go.mod @@ -82,7 +82,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.2 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1 diff --git a/go.sum b/go.sum index f10024282..b5a5df0f8 100644 --- a/go.sum +++ b/go.sum @@ -136,6 +136,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0 h1:SXNkKaAsG github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0/go.mod h1:5hMtm08NrL+QcgKl94zUDrY7VEzKRcvCJOEOvENBxqc= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1 h1:Df3fTAHaVgyiiyp9LyTTQI8jXSVeGo49eW5ya4AATCY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1/go.mod h1:V2LEHKyTaaiEBi9L3v62mNQ7xyJSred4OK+himLJOZQ= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.0.0 h1:/0n2zcH1nMw2noroGhz0fgu2YqtNo9v3AsVhXMRtmtw= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.0.0/go.mod h1:0XumGX33DT6ItyD8yMlogSPWvpIuoqN7RZBrpUBPX+k= github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 h1:sIz4wJIz6/9Eh6nSoi2sQ+Ef53iOrFsqLKIp2oRkmgo= github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1/go.mod h1:okcRTrNDTI3d7MQcYJMliK0qoXeLq0b1wvZuEqgJIWE= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 h1:hwRkCCUSWMhKTc7fLakL89V6+9xkxsFQlRthVmrvi1U= diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index c1b8fe50c..4695a1416 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -62,7 +62,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // Check if the project is enabled before trying to create - enabled, err := utils.ProjectEnabled(ctx, apiClient, model.ProjectId) + enabled, err := utils.ProjectEnabled(ctx, apiClient, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("check if Object Storage is enabled: %w", err) } @@ -83,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Creating bucket") - _, err = wait.CreateBucketWaitHandler(ctx, apiClient, model.ProjectId, model.BucketName).WaitWithContext(ctx) + _, err = wait.CreateBucketWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for Object Storage bucket creation: %w", err) } @@ -122,7 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiCreateBucketRequest { - req := apiClient.CreateBucket(ctx, model.ProjectId, model.BucketName) + req := apiClient.CreateBucket(ctx, model.ProjectId, model.Region, model.BucketName) return req } diff --git a/internal/cmd/object-storage/bucket/create/create_test.go b/internal/cmd/object-storage/bucket/create/create_test.go index 1e53ed260..42a2bf0a5 100644 --- a/internal/cmd/object-storage/bucket/create/create_test.go +++ b/internal/cmd/object-storage/bucket/create/create_test.go @@ -14,12 +14,14 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" var testBucketName = "my-bucket" func fixtureArgValues(mods ...func(argValues []string)) []string { @@ -35,6 +37,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, BucketName: testBucketName, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiCreateBucketRequest)) objectstorage.ApiCreateBucketRequest { - request := testClient.CreateBucket(testCtx, testProjectId, testBucketName) + request := testClient.CreateBucket(testCtx, testProjectId, testRegion, testBucketName) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/object-storage/bucket/delete/delete.go b/internal/cmd/object-storage/bucket/delete/delete.go index 359fcef99..1c6edbf90 100644 --- a/internal/cmd/object-storage/bucket/delete/delete.go +++ b/internal/cmd/object-storage/bucket/delete/delete.go @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Deleting bucket") - _, err = wait.DeleteBucketWaitHandler(ctx, apiClient, model.ProjectId, model.BucketName).WaitWithContext(ctx) + _, err = wait.DeleteBucketWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for Object Storage bucket deletion: %w", err) } @@ -113,6 +113,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiDeleteBucketRequest { - req := apiClient.DeleteBucket(ctx, model.ProjectId, model.BucketName) + req := apiClient.DeleteBucket(ctx, model.ProjectId, model.Region, model.BucketName) return req } diff --git a/internal/cmd/object-storage/bucket/delete/delete_test.go b/internal/cmd/object-storage/bucket/delete/delete_test.go index 1379397ea..be5bd0028 100644 --- a/internal/cmd/object-storage/bucket/delete/delete_test.go +++ b/internal/cmd/object-storage/bucket/delete/delete_test.go @@ -14,12 +14,14 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" var testBucketName = "my-bucket" func fixtureArgValues(mods ...func(argValues []string)) []string { @@ -35,6 +37,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, BucketName: testBucketName, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiDeleteBucketRequest)) objectstorage.ApiDeleteBucketRequest { - request := testClient.DeleteBucket(testCtx, testProjectId, testBucketName) + request := testClient.DeleteBucket(testCtx, testProjectId, testRegion, testBucketName) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index 1f2912a5f..aad7f7fbd 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -93,7 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiGetBucketRequest { - req := apiClient.GetBucket(ctx, model.ProjectId, model.BucketName) + req := apiClient.GetBucket(ctx, model.ProjectId, model.Region, model.BucketName) return req } diff --git a/internal/cmd/object-storage/bucket/describe/describe_test.go b/internal/cmd/object-storage/bucket/describe/describe_test.go index 8ba16b48f..ec6702dae 100644 --- a/internal/cmd/object-storage/bucket/describe/describe_test.go +++ b/internal/cmd/object-storage/bucket/describe/describe_test.go @@ -14,12 +14,14 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" var testBucketName = "my-bucket" func fixtureArgValues(mods ...func(argValues []string)) []string { @@ -35,6 +37,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, BucketName: testBucketName, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiGetBucketRequest)) objectstorage.ApiGetBucketRequest { - request := testClient.GetBucket(testCtx, testProjectId, testBucketName) + request := testClient.GetBucket(testCtx, testProjectId, testRegion, testBucketName) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index ffde74c04..66f94a399 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -125,7 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiListBucketsRequest { - req := apiClient.ListBuckets(ctx, model.ProjectId) + req := apiClient.ListBuckets(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/object-storage/bucket/list/list_test.go b/internal/cmd/object-storage/bucket/list/list_test.go index 35d34ab64..8f4d655bb 100644 --- a/internal/cmd/object-storage/bucket/list/list_test.go +++ b/internal/cmd/object-storage/bucket/list/list_test.go @@ -16,17 +16,20 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, limitFlag: "10", + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -39,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), } @@ -49,7 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiListBucketsRequest)) objectstorage.ApiListBucketsRequest { - request := testClient.ListBuckets(testCtx, testProjectId) + request := testClient.ListBuckets(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index 01bb89ac0..cb30ede3f 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -105,7 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiCreateCredentialsGroupRequest { - req := apiClient.CreateCredentialsGroup(ctx, model.ProjectId) + req := apiClient.CreateCredentialsGroup(ctx, model.ProjectId, model.Region) req = req.CreateCredentialsGroupPayload(objectstorage.CreateCredentialsGroupPayload{ DisplayName: utils.Ptr(model.CredentialsGroupName), }) diff --git a/internal/cmd/object-storage/credentials-group/create/create_test.go b/internal/cmd/object-storage/credentials-group/create/create_test.go index 88c212867..f7b1a447b 100644 --- a/internal/cmd/object-storage/credentials-group/create/create_test.go +++ b/internal/cmd/object-storage/credentials-group/create/create_test.go @@ -15,6 +15,7 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} @@ -22,11 +23,13 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() var testCredentialsGroupName = "test-name" +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, credentialsGroupNameFlag: testCredentialsGroupName, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -39,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, CredentialsGroupName: testCredentialsGroupName, } @@ -59,7 +63,7 @@ func fixturePayload(mods ...func(payload *objectstorage.CreateCredentialsGroupPa } func fixtureRequest(mods ...func(request *objectstorage.ApiCreateCredentialsGroupRequest)) objectstorage.ApiCreateCredentialsGroupRequest { - request := testClient.CreateCredentialsGroup(testCtx, testProjectId) + request := testClient.CreateCredentialsGroup(testCtx, testProjectId, testRegion) request = request.CreateCredentialsGroupPayload(fixturePayload()) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/object-storage/credentials-group/delete/delete.go b/internal/cmd/object-storage/credentials-group/delete/delete.go index 4f64600fb..27dda8460 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete.go @@ -50,7 +50,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId) + credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get credentials group name: %v", err) credentialsGroupLabel = model.CredentialsGroupId @@ -104,6 +104,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiDeleteCredentialsGroupRequest { - req := apiClient.DeleteCredentialsGroup(ctx, model.ProjectId, model.CredentialsGroupId) + req := apiClient.DeleteCredentialsGroup(ctx, model.ProjectId, model.Region, model.CredentialsGroupId) return req } diff --git a/internal/cmd/object-storage/credentials-group/delete/delete_test.go b/internal/cmd/object-storage/credentials-group/delete/delete_test.go index 4630501a0..1711bd33c 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete_test.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete_test.go @@ -14,6 +14,7 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} @@ -21,6 +22,7 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() var testCredentialsGroupId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,6 +37,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, CredentialsGroupId: testCredentialsGroupId, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiDeleteCredentialsGroupRequest)) objectstorage.ApiDeleteCredentialsGroupRequest { - request := testClient.DeleteCredentialsGroup(testCtx, testProjectId, testCredentialsGroupId) + request := testClient.DeleteCredentialsGroup(testCtx, testProjectId, testRegion, testCredentialsGroupId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index c2c2028be..876392113 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -117,7 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiListCredentialsGroupsRequest { - req := apiClient.ListCredentialsGroups(ctx, model.ProjectId) + req := apiClient.ListCredentialsGroups(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/object-storage/credentials-group/list/list_test.go b/internal/cmd/object-storage/credentials-group/list/list_test.go index 43cd2e46a..7c9580330 100644 --- a/internal/cmd/object-storage/credentials-group/list/list_test.go +++ b/internal/cmd/object-storage/credentials-group/list/list_test.go @@ -15,17 +15,20 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, limitFlag: "10", + regionFlag: "eu01", } for _, mod := range mods { mod(flagValues) @@ -38,6 +41,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), } @@ -48,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiListCredentialsGroupsRequest)) objectstorage.ApiListCredentialsGroupsRequest { - request := testClient.ListCredentialsGroups(testCtx, testProjectId) + request := testClient.ListCredentialsGroups(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index 662f02937..8e4944d87 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -60,7 +60,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId) + credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get credentials group name: %v", err) credentialsGroupLabel = model.CredentialsGroupId @@ -129,7 +129,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiCreateAccessKeyRequest { - req := apiClient.CreateAccessKey(ctx, model.ProjectId) + req := apiClient.CreateAccessKey(ctx, model.ProjectId, model.Region) req = req.CredentialsGroup(model.CredentialsGroupId) req = req.CreateAccessKeyPayload(objectstorage.CreateAccessKeyPayload{ Expires: model.ExpireDate, diff --git a/internal/cmd/object-storage/credentials/create/create_test.go b/internal/cmd/object-storage/credentials/create/create_test.go index 41e19eddd..c26ddf0ee 100644 --- a/internal/cmd/object-storage/credentials/create/create_test.go +++ b/internal/cmd/object-storage/credentials/create/create_test.go @@ -16,6 +16,7 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} @@ -24,12 +25,14 @@ var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() var testCredentialsGroupId = uuid.NewString() var testExpirationDate = "2024-01-01T00:00:00Z" +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, credentialsGroupIdFlag: testCredentialsGroupId, expireDateFlag: testExpirationDate, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, ExpireDate: utils.Ptr(testExpirationDate), CredentialsGroupId: testCredentialsGroupId, @@ -72,7 +76,7 @@ func fixturePayload(mods ...func(payload *objectstorage.CreateAccessKeyPayload)) } func fixtureRequest(mods ...func(request *objectstorage.ApiCreateAccessKeyRequest)) objectstorage.ApiCreateAccessKeyRequest { - request := testClient.CreateAccessKey(testCtx, testProjectId) + request := testClient.CreateAccessKey(testCtx, testProjectId, testRegion) request = request.CreateAccessKeyPayload(fixturePayload()) request = request.CredentialsGroup(testCredentialsGroupId) for _, mod := range mods { diff --git a/internal/cmd/object-storage/credentials/delete/delete.go b/internal/cmd/object-storage/credentials/delete/delete.go index a1baaf529..ed7fedb5e 100644 --- a/internal/cmd/object-storage/credentials/delete/delete.go +++ b/internal/cmd/object-storage/credentials/delete/delete.go @@ -51,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId) + credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get credentials group name: %v", err) credentialsGroupLabel = model.CredentialsGroupId } - credentialsLabel, err := objectStorageUtils.GetCredentialsName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.CredentialsId) + credentialsLabel, err := objectStorageUtils.GetCredentialsName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.CredentialsId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get credentials name: %v", err) credentialsLabel = model.CredentialsId @@ -120,7 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiDeleteAccessKeyRequest { - req := apiClient.DeleteAccessKey(ctx, model.ProjectId, model.CredentialsId) + req := apiClient.DeleteAccessKey(ctx, model.ProjectId, model.Region, model.CredentialsId) req = req.CredentialsGroup(model.CredentialsGroupId) return req } diff --git a/internal/cmd/object-storage/credentials/delete/delete_test.go b/internal/cmd/object-storage/credentials/delete/delete_test.go index 146a52fee..09ee7d04b 100644 --- a/internal/cmd/object-storage/credentials/delete/delete_test.go +++ b/internal/cmd/object-storage/credentials/delete/delete_test.go @@ -14,6 +14,7 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} @@ -22,6 +23,7 @@ var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() var testCredentialsGroupId = uuid.NewString() var testCredentialsId = "keyID" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -37,6 +39,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st flagValues := map[string]string{ projectIdFlag: testProjectId, credentialsGroupIdFlag: testCredentialsGroupId, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, CredentialsGroupId: testCredentialsGroupId, CredentialsId: testCredentialsId, @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiDeleteAccessKeyRequest)) objectstorage.ApiDeleteAccessKeyRequest { - request := testClient.DeleteAccessKey(testCtx, testProjectId, testCredentialsId) + request := testClient.DeleteAccessKey(testCtx, testProjectId, testRegion, testCredentialsId) request = request.CredentialsGroup(testCredentialsGroupId) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index 181f43371..c1a6d63dd 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } credentials := *resp.AccessKeys if len(credentials) == 0 { - credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId) + credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get credentials group name: %v", err) credentialsGroupLabel = model.CredentialsGroupId @@ -131,7 +131,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiListAccessKeysRequest { - req := apiClient.ListAccessKeys(ctx, model.ProjectId) + req := apiClient.ListAccessKeys(ctx, model.ProjectId, model.Region) req = req.CredentialsGroup(model.CredentialsGroupId) return req } diff --git a/internal/cmd/object-storage/credentials/list/list_test.go b/internal/cmd/object-storage/credentials/list/list_test.go index 27845efa5..b778e5dc1 100644 --- a/internal/cmd/object-storage/credentials/list/list_test.go +++ b/internal/cmd/object-storage/credentials/list/list_test.go @@ -15,6 +15,7 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} @@ -22,12 +23,14 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() var testCredentialsGroupId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, credentialsGroupIdFlag: testCredentialsGroupId, limitFlag: "10", + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -40,6 +43,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, CredentialsGroupId: testCredentialsGroupId, Limit: utils.Ptr(int64(10)), @@ -51,7 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiListAccessKeysRequest)) objectstorage.ApiListAccessKeysRequest { - request := testClient.ListAccessKeys(testCtx, testProjectId) + request := testClient.ListAccessKeys(testCtx, testProjectId, testRegion) request = request.CredentialsGroup(testCredentialsGroupId) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/object-storage/disable/disable.go b/internal/cmd/object-storage/disable/disable.go index 40303b8da..56e6f940d 100644 --- a/internal/cmd/object-storage/disable/disable.go +++ b/internal/cmd/object-storage/disable/disable.go @@ -99,6 +99,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiDisableServiceRequest { - req := apiClient.DisableService(ctx, model.ProjectId) + req := apiClient.DisableService(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/object-storage/disable/disable_test.go b/internal/cmd/object-storage/disable/disable_test.go index 969b92b71..cb65e8961 100644 --- a/internal/cmd/object-storage/disable/disable_test.go +++ b/internal/cmd/object-storage/disable/disable_test.go @@ -15,16 +15,19 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, } for _, mod := range mods { @@ -46,7 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiDisableServiceRequest)) objectstorage.ApiDisableServiceRequest { - request := testClient.DisableService(testCtx, testProjectId) + request := testClient.DisableService(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/object-storage/enable/enable.go b/internal/cmd/object-storage/enable/enable.go index 52bbec6f9..cec0d6e7d 100644 --- a/internal/cmd/object-storage/enable/enable.go +++ b/internal/cmd/object-storage/enable/enable.go @@ -99,6 +99,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstorage.APIClient) objectstorage.ApiEnableServiceRequest { - req := apiClient.EnableService(ctx, model.ProjectId) + req := apiClient.EnableService(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/object-storage/enable/enable_test.go b/internal/cmd/object-storage/enable/enable_test.go index 3fbca13d1..562bb6907 100644 --- a/internal/cmd/object-storage/enable/enable_test.go +++ b/internal/cmd/object-storage/enable/enable_test.go @@ -15,16 +15,19 @@ import ( ) var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, + regionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, } for _, mod := range mods { @@ -46,7 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *objectstorage.ApiEnableServiceRequest)) objectstorage.ApiEnableServiceRequest { - request := testClient.EnableService(testCtx, testProjectId) + request := testClient.EnableService(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } diff --git a/internal/pkg/services/object-storage/utils/utils.go b/internal/pkg/services/object-storage/utils/utils.go index e596eb203..bd23d0854 100644 --- a/internal/pkg/services/object-storage/utils/utils.go +++ b/internal/pkg/services/object-storage/utils/utils.go @@ -10,13 +10,13 @@ import ( ) type ObjectStorageClient interface { - GetServiceStatusExecute(ctx context.Context, projectId string) (*objectstorage.ProjectStatus, error) - ListCredentialsGroupsExecute(ctx context.Context, projectId string) (*objectstorage.ListCredentialsGroupsResponse, error) - ListAccessKeys(ctx context.Context, projectId string) objectstorage.ApiListAccessKeysRequest + GetServiceStatusExecute(ctx context.Context, projectId, region string) (*objectstorage.ProjectStatus, error) + ListCredentialsGroupsExecute(ctx context.Context, projectId, region string) (*objectstorage.ListCredentialsGroupsResponse, error) + ListAccessKeys(ctx context.Context, projectId, region string) objectstorage.ApiListAccessKeysRequest } -func ProjectEnabled(ctx context.Context, apiClient ObjectStorageClient, projectId string) (bool, error) { - _, err := apiClient.GetServiceStatusExecute(ctx, projectId) +func ProjectEnabled(ctx context.Context, apiClient ObjectStorageClient, projectId, region string) (bool, error) { + _, err := apiClient.GetServiceStatusExecute(ctx, projectId, region) if err != nil { oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped if !ok { @@ -30,8 +30,8 @@ func ProjectEnabled(ctx context.Context, apiClient ObjectStorageClient, projectI return true, nil } -func GetCredentialsGroupName(ctx context.Context, apiClient ObjectStorageClient, projectId, credentialsGroupId string) (string, error) { - resp, err := apiClient.ListCredentialsGroupsExecute(ctx, projectId) +func GetCredentialsGroupName(ctx context.Context, apiClient ObjectStorageClient, projectId, credentialsGroupId, region string) (string, error) { + resp, err := apiClient.ListCredentialsGroupsExecute(ctx, projectId, region) if err != nil { return "", fmt.Errorf("list Object Storage credentials groups: %w", err) } @@ -50,8 +50,8 @@ func GetCredentialsGroupName(ctx context.Context, apiClient ObjectStorageClient, return "", fmt.Errorf("could not find Object Storage credentials group name") } -func GetCredentialsName(ctx context.Context, apiClient ObjectStorageClient, projectId, credentialsGroupId, keyId string) (string, error) { - req := apiClient.ListAccessKeys(ctx, projectId) +func GetCredentialsName(ctx context.Context, apiClient ObjectStorageClient, projectId, credentialsGroupId, keyId, region string) (string, error) { + req := apiClient.ListAccessKeys(ctx, projectId, region) req = req.CredentialsGroup(credentialsGroupId) resp, err := req.Execute() diff --git a/internal/pkg/services/object-storage/utils/utils_test.go b/internal/pkg/services/object-storage/utils/utils_test.go index c2dc0bb61..65b176172 100644 --- a/internal/pkg/services/object-storage/utils/utils_test.go +++ b/internal/pkg/services/object-storage/utils/utils_test.go @@ -20,6 +20,7 @@ var ( testProjectId = uuid.NewString() testCredentialsGroupId = uuid.NewString() testCredentialsId = "credentialsID" //nolint:gosec // linter false positive + testRegion = "eu01" ) const ( @@ -35,7 +36,7 @@ type objectStorageClientMocked struct { listAccessKeysReq objectstorage.ApiListAccessKeysRequest } -func (m *objectStorageClientMocked) GetServiceStatusExecute(_ context.Context, _ string) (*objectstorage.ProjectStatus, error) { +func (m *objectStorageClientMocked) GetServiceStatusExecute(_ context.Context, _, _ string) (*objectstorage.ProjectStatus, error) { if m.getServiceStatusFails { return nil, fmt.Errorf("could not get service status") } @@ -45,14 +46,14 @@ func (m *objectStorageClientMocked) GetServiceStatusExecute(_ context.Context, _ return &objectstorage.ProjectStatus{}, nil } -func (m *objectStorageClientMocked) ListCredentialsGroupsExecute(_ context.Context, _ string) (*objectstorage.ListCredentialsGroupsResponse, error) { +func (m *objectStorageClientMocked) ListCredentialsGroupsExecute(_ context.Context, _, _ string) (*objectstorage.ListCredentialsGroupsResponse, error) { if m.listCredentialsGroupsFails { return nil, fmt.Errorf("could not list credentials groups") } return m.listCredentialsGroupsResp, nil } -func (m *objectStorageClientMocked) ListAccessKeys(_ context.Context, _ string) objectstorage.ApiListAccessKeysRequest { +func (m *objectStorageClientMocked) ListAccessKeys(_ context.Context, _, _ string) objectstorage.ApiListAccessKeysRequest { return m.listAccessKeysReq } @@ -89,7 +90,7 @@ func TestProjectEnabled(t *testing.T) { getServiceStatusFails: tt.getProjectFails, } - output, err := ProjectEnabled(context.Background(), client, testProjectId) + output, err := ProjectEnabled(context.Background(), client, testProjectId, testRegion) if tt.isValid && err != nil { fmt.Printf("failed on valid input: %v", err) @@ -202,7 +203,7 @@ func TestGetCredentialsGroupName(t *testing.T) { listCredentialsGroupsResp: tt.listCredentialsGroupsResp, } - output, err := GetCredentialsGroupName(context.Background(), client, testProjectId, testCredentialsGroupId) + output, err := GetCredentialsGroupName(context.Background(), client, testProjectId, testCredentialsGroupId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -341,7 +342,7 @@ func TestGetCredentialsName(t *testing.T) { t.Fatalf("Failed to initialize client: %v", err) } - output, err := GetCredentialsName(context.Background(), client, testProjectId, testCredentialsGroupId, testCredentialsId) + output, err := GetCredentialsName(context.Background(), client, testProjectId, testCredentialsGroupId, testCredentialsId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") From d69d30155797138a769bc5253594186fdbd1fd16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 12 Feb 2025 15:17:51 +0100 Subject: [PATCH 181/619] setup github codeowners (#599) Co-authored-by: Ruben Hoenle --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..eab47aae8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @marceljk @bahkauv70 @Fyusel @rubenhoenle \ No newline at end of file From ce2ad2bdf9e38659d8f9efe36ee7248bbafdbbcf Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 13 Feb 2025 08:34:19 +0100 Subject: [PATCH 182/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.22 (#600) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 80db6dcb7..6859178fa 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.20 + github.com/goccy/go-yaml v1.15.22 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index b5a5df0f8..242a895f2 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.20 h1:eQHFLrr1lpLYAxupPD9ThZbGtncPl9nyu3nkAayEZgY= -github.com/goccy/go-yaml v1.15.20/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.22 h1:iQI1hvCoiYYiVFq76P4AI8ImgDOfgiyKnl/AWjK8/gA= +github.com/goccy/go-yaml v1.15.22/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -134,8 +134,6 @@ github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1 h1:J+GLgfDIDnNpq github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1/go.mod h1:nuZK6OXyZ4zlGsC1gZDj9+ajJzzFi9vVgSSRQlEJAqA= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0 h1:SXNkKaAsGOkr9C6bv2i7q3kucxL3kril+z2wnshlXK0= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0/go.mod h1:5hMtm08NrL+QcgKl94zUDrY7VEzKRcvCJOEOvENBxqc= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1 h1:Df3fTAHaVgyiiyp9LyTTQI8jXSVeGo49eW5ya4AATCY= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.11.1/go.mod h1:V2LEHKyTaaiEBi9L3v62mNQ7xyJSred4OK+himLJOZQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.0.0 h1:/0n2zcH1nMw2noroGhz0fgu2YqtNo9v3AsVhXMRtmtw= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.0.0/go.mod h1:0XumGX33DT6ItyD8yMlogSPWvpIuoqN7RZBrpUBPX+k= github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 h1:sIz4wJIz6/9Eh6nSoi2sQ+Ef53iOrFsqLKIp2oRkmgo= From ccc55c8740a33afc0a43bf2ac93f756d7f643471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 17 Feb 2025 09:29:32 +0100 Subject: [PATCH 183/619] feat(auth): add get-access-token cmd (#598) relates to STACKITCLI-11 --- docs/stackit_auth.md | 1 + docs/stackit_auth_get-access-token.md | 40 +++++++++++++++ internal/cmd/auth/auth.go | 2 + .../auth/get-access-token/get_access_token.go | 50 +++++++++++++++++++ internal/pkg/auth/auth.go | 8 +-- internal/pkg/auth/user_token_flow.go | 4 +- internal/pkg/errors/errors.go | 28 +++++++++++ 7 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 docs/stackit_auth_get-access-token.md create mode 100644 internal/cmd/auth/get-access-token/get_access_token.go diff --git a/docs/stackit_auth.md b/docs/stackit_auth.md index 5c891583a..3f9406c46 100644 --- a/docs/stackit_auth.md +++ b/docs/stackit_auth.md @@ -31,6 +31,7 @@ stackit auth [flags] * [stackit](./stackit.md) - Manage STACKIT resources using the command line * [stackit auth activate-service-account](./stackit_auth_activate-service-account.md) - Authenticates using a service account +* [stackit auth get-access-token](./stackit_auth_get-access-token.md) - Prints a short-lived access token. * [stackit auth login](./stackit_auth_login.md) - Logs in to the STACKIT CLI * [stackit auth logout](./stackit_auth_logout.md) - Logs the user account out of the STACKIT CLI diff --git a/docs/stackit_auth_get-access-token.md b/docs/stackit_auth_get-access-token.md new file mode 100644 index 000000000..cc5218002 --- /dev/null +++ b/docs/stackit_auth_get-access-token.md @@ -0,0 +1,40 @@ +## stackit auth get-access-token + +Prints a short-lived access token. + +### Synopsis + +Prints a short-lived access token which can be used e.g. for API calls. + +``` +stackit auth get-access-token [flags] +``` + +### Examples + +``` + Print a short-lived access token + $ stackit auth get-access-token +``` + +### Options + +``` + -h, --help Help for "stackit auth get-access-token" +``` + +### 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 auth](./stackit_auth.md) - Authenticates the STACKIT CLI + diff --git a/internal/cmd/auth/auth.go b/internal/cmd/auth/auth.go index 5513451d0..2a8b3a7f2 100644 --- a/internal/cmd/auth/auth.go +++ b/internal/cmd/auth/auth.go @@ -2,6 +2,7 @@ package auth import ( activateserviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/auth/activate-service-account" + getaccesstoken "github.com/stackitcloud/stackit-cli/internal/cmd/auth/get-access-token" "github.com/stackitcloud/stackit-cli/internal/cmd/auth/login" "github.com/stackitcloud/stackit-cli/internal/cmd/auth/logout" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -27,4 +28,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(login.NewCmd(p)) cmd.AddCommand(logout.NewCmd(p)) cmd.AddCommand(activateserviceaccount.NewCmd(p)) + cmd.AddCommand(getaccesstoken.NewCmd(p)) } diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go new file mode 100644 index 000000000..cbaa82eb6 --- /dev/null +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -0,0 +1,50 @@ +package getaccesstoken + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "get-access-token", + Short: "Prints a short-lived access token.", + Long: "Prints a short-lived access token which can be used e.g. for API calls.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Print a short-lived access token`, + "$ stackit auth get-access-token"), + ), + RunE: func(_ *cobra.Command, _ []string) error { + userSessionExpired, err := auth.UserSessionExpired() + if err != nil { + return err + } + if userSessionExpired { + return &cliErr.SessionExpiredError{} + } + + accessToken, err := auth.GetAccessToken() + if err != nil { + return err + } + + accessTokenExpired, err := auth.TokenExpired(accessToken) + if err != nil { + return err + } + if accessTokenExpired { + return &cliErr.AccessTokenExpiredError{} + } + + p.Info("%s\n", accessToken) + return nil + }, + } + return cmd +} diff --git a/internal/pkg/auth/auth.go b/internal/pkg/auth/auth.go index a036227ed..fdd64354d 100644 --- a/internal/pkg/auth/auth.go +++ b/internal/pkg/auth/auth.go @@ -31,7 +31,7 @@ func AuthenticationConfig(p *print.Printer, reauthorizeUserRoutine func(p *print return nil, fmt.Errorf("authentication flow not set") } - userSessionExpired, err := userSessionExpired() + userSessionExpired, err := UserSessionExpired() if err != nil { return nil, fmt.Errorf("check if user session expired: %w", err) } @@ -42,7 +42,7 @@ func AuthenticationConfig(p *print.Printer, reauthorizeUserRoutine func(p *print if userSessionExpired { return nil, fmt.Errorf("session expired") } - accessToken, err := getAccessToken() + accessToken, err := GetAccessToken() if err != nil { return nil, fmt.Errorf("get service account access token: %w", err) } @@ -73,7 +73,7 @@ func AuthenticationConfig(p *print.Printer, reauthorizeUserRoutine func(p *print return authCfgOption, nil } -func userSessionExpired() (bool, error) { +func UserSessionExpired() (bool, error) { sessionExpiresAtString, err := GetAuthField(SESSION_EXPIRES_AT_UNIX) if err != nil { return false, fmt.Errorf("get %s: %w", SESSION_EXPIRES_AT_UNIX, err) @@ -87,7 +87,7 @@ func userSessionExpired() (bool, error) { return now.After(sessionExpiresAt), nil } -func getAccessToken() (string, error) { +func GetAccessToken() (string, error) { accessToken, err := GetAuthField(ACCESS_TOKEN) if err != nil { return "", fmt.Errorf("get %s: %w", ACCESS_TOKEN, err) diff --git a/internal/pkg/auth/user_token_flow.go b/internal/pkg/auth/user_token_flow.go index 93d10b13a..8a49c6b45 100644 --- a/internal/pkg/auth/user_token_flow.go +++ b/internal/pkg/auth/user_token_flow.go @@ -44,7 +44,7 @@ func (utf *userTokenFlow) RoundTrip(req *http.Request) (*http.Response, error) { } accessTokenValid := false - accessTokenExpired, err := tokenExpired(utf.accessToken) + accessTokenExpired, err := TokenExpired(utf.accessToken) if err != nil { return nil, fmt.Errorf("check if access token has expired: %w", err) } else if !accessTokenExpired { @@ -108,7 +108,7 @@ func reauthenticateUser(utf *userTokenFlow) error { return nil } -func tokenExpired(token string) (bool, error) { +func TokenExpired(token string) (bool, error) { // We can safely use ParseUnverified because we are not authenticating the user at this point. // We're just checking the expiration time tokenParsed, _, err := jwt.NewParser().ParseUnverified(token, &jwt.RegisteredClaims{}) diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index e67efde5b..9c83fb4f1 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -32,6 +32,22 @@ You can authenticate as a user by running: or use a service account by running: $ stackit auth activate-service-account` + SESSION_EXPIRED = `Session is expired. Please log in again first. + +You can authenticate as a user by running: +$ stackit auth login + +or use a service account by running: +$ stackit auth activate-service-account` + + ACCESS_TOKEN_EXPIRED = `Access token is expired. Please log in again first. + +You can authenticate as a user by running: +$ stackit auth login + +or use a service account by running: +$ stackit auth activate-service-account` + FAILED_SERVICE_ACCOUNT_ACTIVATION = `could not setup authentication based on the provided service account credentials. Please double check if they are correctly configured. @@ -230,6 +246,18 @@ func (e *AuthError) Error() string { return FAILED_AUTH } +type SessionExpiredError struct{} + +func (e *SessionExpiredError) Error() string { + return SESSION_EXPIRED +} + +type AccessTokenExpiredError struct{} + +func (e *AccessTokenExpiredError) Error() string { + return ACCESS_TOKEN_EXPIRED +} + type ActivateServiceAccountError struct{} func (e *ActivateServiceAccountError) Error() string { From afb9986a2837351d642b84be086b2582bf2e16b9 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:41:50 +0100 Subject: [PATCH 184/619] fix(deps): update module github.com/goccy/go-yaml to v1.15.23 (#601) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6859178fa..64817f1f8 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.22 + github.com/goccy/go-yaml v1.15.23 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 242a895f2..8eadb3f72 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.22 h1:iQI1hvCoiYYiVFq76P4AI8ImgDOfgiyKnl/AWjK8/gA= -github.com/goccy/go-yaml v1.15.22/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.15.23 h1:WS0GAX1uNPDLUvLkNU2vXq6oTnsmfVFocjQ/4qA48qo= +github.com/goccy/go-yaml v1.15.23/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 6213bb54eecbd31b515f083979a3a5462404e70a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:46:59 +0100 Subject: [PATCH 185/619] fix(deps): update module github.com/spf13/cobra to v1.9.1 (#602) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update module github.com/spf13/cobra to v1.9.1 * fix deprecation warning --------- Co-authored-by: Renovate Bot Co-authored-by: Rüdiger Schmitz <152157960+bahkauv70@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 9 ++++----- internal/pkg/print/print_test.go | 21 ++++++++++++++------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 64817f1f8..2cdefd53d 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/jedib0t/go-pretty/v6 v6.6.6 github.com/lmittmann/tint v1.0.7 github.com/mattn/go-colorable v0.1.14 - github.com/spf13/cobra v1.8.1 + github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.19.0 github.com/stackitcloud/stackit-sdk-go/core v0.15.1 @@ -54,7 +54,7 @@ require ( ) require ( - github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect diff --git a/go.sum b/go.sum index 8eadb3f72..c1c2d4e1a 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho= al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -111,9 +111,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= diff --git a/internal/pkg/print/print_test.go b/internal/pkg/print/print_test.go index 942689ce4..5c68dc2cf 100644 --- a/internal/pkg/print/print_test.go +++ b/internal/pkg/print/print_test.go @@ -57,7 +57,8 @@ func TestOutputf(t *testing.T) { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer cmd := &cobra.Command{} - cmd.SetOutput(&buf) + cmd.SetOut(&buf) + cmd.SetErr(&buf) p := &Printer{ Cmd: cmd, Verbosity: tt.verbosity, @@ -128,7 +129,8 @@ func TestOutputln(t *testing.T) { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer cmd := &cobra.Command{} - cmd.SetOutput(&buf) + cmd.SetOut(&buf) + cmd.SetErr(&buf) p := &Printer{ Cmd: cmd, Verbosity: tt.verbosity, @@ -192,7 +194,8 @@ func TestPagerDisplay(t *testing.T) { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer cmd := &cobra.Command{} - cmd.SetOutput(&buf) + cmd.SetOut(&buf) + cmd.SetErr(&buf) p := &Printer{ Cmd: cmd, Verbosity: tt.verbosity, @@ -291,7 +294,8 @@ func TestDebug(t *testing.T) { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer cmd := &cobra.Command{} - cmd.SetOutput(&buf) + cmd.SetOut(&buf) + cmd.SetErr(&buf) logger := slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{AddSource: true, Level: slog.LevelDebug})) slog.SetDefault(logger) p := &Printer{ @@ -354,7 +358,8 @@ func TestInfo(t *testing.T) { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer cmd := &cobra.Command{} - cmd.SetOutput(&buf) + cmd.SetOut(&buf) + cmd.SetErr(&buf) p := &Printer{ Cmd: cmd, Verbosity: tt.verbosity, @@ -413,7 +418,8 @@ func TestWarn(t *testing.T) { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer cmd := &cobra.Command{} - cmd.SetOutput(&buf) + cmd.SetOut(&buf) + cmd.SetErr(&buf) p := &Printer{ Cmd: cmd, Verbosity: tt.verbosity, @@ -472,7 +478,8 @@ func TestError(t *testing.T) { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer cmd := &cobra.Command{} - cmd.SetOutput(&buf) + cmd.SetOut(&buf) + cmd.SetErr(&buf) p := &Printer{ Cmd: cmd, Verbosity: tt.verbosity, From e12c8c20b9bfaddc944eb4eb127e68303e556ad4 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 20 Feb 2025 10:42:39 +0100 Subject: [PATCH 186/619] fix: `stackit beta server` commands - add nil pointer checks and tests for the outputResult functions (#604) * Add nil pointer checks and tests for the outputResult functions * Add checks if serverLabel is empty --- .../cmd/beta/server/backup/create/create.go | 21 ++++-- .../beta/server/backup/create/create_test.go | 28 ++++++++ .../beta/server/backup/describe/describe.go | 11 ++- .../server/backup/describe/describe_test.go | 35 ++++++++++ .../cmd/beta/server/backup/disable/disable.go | 19 +++++- .../cmd/beta/server/backup/enable/enable.go | 17 ++++- internal/cmd/beta/server/backup/list/list.go | 20 +++++- .../cmd/beta/server/backup/list/list_test.go | 36 ++++++++++ .../server/backup/schedule/create/create.go | 23 +++++-- .../backup/schedule/create/create_test.go | 27 ++++++++ .../server/backup/schedule/delete/delete.go | 15 +++- .../backup/schedule/describe/describe.go | 8 +-- .../backup/schedule/describe/describe_test.go | 68 ++++++++++++++++++- .../beta/server/backup/schedule/list/list.go | 15 +++- .../server/backup/schedule/list/list_test.go | 47 +++++++++++++ .../server/backup/schedule/update/update.go | 6 +- .../backup/schedule/update/update_test.go | 27 ++++++++ .../cmd/beta/server/command/create/create.go | 23 +++++-- .../beta/server/command/create/create_test.go | 27 ++++++++ .../beta/server/command/describe/describe.go | 4 +- .../server/command/describe/describe_test.go | 27 ++++++++ internal/cmd/beta/server/command/list/list.go | 20 ++++-- .../cmd/beta/server/command/list/list_test.go | 27 ++++++++ .../command/template/describe/describe.go | 7 +- .../template/describe/describe_test.go | 27 ++++++++ .../beta/server/command/template/list/list.go | 4 +- .../server/command/template/list/list_test.go | 35 ++++++++++ internal/cmd/beta/server/console/console.go | 8 +-- .../cmd/beta/server/console/console_test.go | 37 ++++++++++ internal/cmd/beta/server/create/create.go | 9 ++- .../cmd/beta/server/create/create_test.go | 35 ++++++++++ .../cmd/beta/server/deallocate/deallocate.go | 2 + internal/cmd/beta/server/delete/delete.go | 2 + internal/cmd/beta/server/describe/describe.go | 9 +-- .../cmd/beta/server/describe/describe_test.go | 35 ++++++++++ internal/cmd/beta/server/list/list_test.go | 27 ++++++++ internal/cmd/beta/server/log/log.go | 10 +-- internal/cmd/beta/server/log/log_test.go | 28 ++++++++ .../server/machine-type/describe/describe.go | 3 + .../machine-type/describe/describe_test.go | 27 ++++++++ .../cmd/beta/server/machine-type/list/list.go | 12 ++-- .../server/machine-type/list/list_test.go | 27 ++++++++ .../server/network-interface/detach/detach.go | 2 + .../server/network-interface/list/list.go | 2 + .../network-interface/list/list_test.go | 37 ++++++++++ .../beta/server/os-update/create/create.go | 23 +++++-- .../server/os-update/create/create_test.go | 28 ++++++++ .../server/os-update/describe/describe.go | 4 +- .../os-update/describe/describe_test.go | 27 ++++++++ .../beta/server/os-update/disable/disable.go | 17 ++++- .../beta/server/os-update/enable/enable.go | 17 ++++- .../cmd/beta/server/os-update/list/list.go | 14 +++- .../beta/server/os-update/list/list_test.go | 27 ++++++++ .../os-update/schedule/create/create.go | 23 +++++-- .../os-update/schedule/create/create_test.go | 28 ++++++++ .../os-update/schedule/describe/describe.go | 4 +- .../schedule/describe/describe_test.go | 27 ++++++++ .../server/os-update/schedule/list/list.go | 14 +++- .../os-update/schedule/list/list_test.go | 27 ++++++++ .../os-update/schedule/update/update.go | 6 +- .../os-update/schedule/update/update_test.go | 27 ++++++++ .../beta/server/public-ip/attach/attach.go | 6 +- .../beta/server/public-ip/detach/detach.go | 5 +- internal/cmd/beta/server/reboot/reboot.go | 3 +- internal/cmd/beta/server/rescue/rescue.go | 2 + internal/cmd/beta/server/resize/resize.go | 2 + .../server/service-account/attach/attach.go | 6 +- .../service-account/attach/attach_test.go | 29 ++++++++ .../server/service-account/detach/detach.go | 6 +- .../service-account/detach/detach_test.go | 29 ++++++++ .../beta/server/service-account/list/list.go | 4 +- .../server/service-account/list/list_test.go | 38 +++++++++++ internal/cmd/beta/server/start/start.go | 2 + internal/cmd/beta/server/stop/stop.go | 2 + internal/cmd/beta/server/unrescue/unrescue.go | 2 + internal/cmd/beta/server/update/update.go | 8 ++- .../cmd/beta/server/update/update_test.go | 28 ++++++++ .../cmd/beta/server/volume/attach/attach.go | 9 +-- .../beta/server/volume/attach/attach_test.go | 29 ++++++++ .../beta/server/volume/describe/describe.go | 10 ++- .../server/volume/describe/describe_test.go | 29 ++++++++ .../cmd/beta/server/volume/detach/detach.go | 5 +- internal/cmd/beta/server/volume/list/list.go | 10 ++- .../cmd/beta/server/volume/list/list_test.go | 38 +++++++++++ .../cmd/beta/server/volume/update/update.go | 9 +-- .../beta/server/volume/update/update_test.go | 29 ++++++++ 86 files changed, 1468 insertions(+), 121 deletions(-) diff --git a/internal/cmd/beta/server/backup/create/create.go b/internal/cmd/beta/server/backup/create/create.go index f53f3b9ef..d64d14c0a 100644 --- a/internal/cmd/beta/server/backup/create/create.go +++ b/internal/cmd/beta/server/backup/create/create.go @@ -12,6 +12,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -65,6 +67,17 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a Backup for server %s?", model.ServerId) err = p.PromptForConfirmation(prompt) @@ -83,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server Backup: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) @@ -140,8 +153,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.BackupJob) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, serverLabel string, resp serverbackup.BackupJob) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -159,7 +172,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.Backup return nil default: - p.Outputf("Triggered creation of server backup for server %s. Backup ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) + p.Outputf("Triggered creation of server backup for server %s. Backup ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/backup/create/create_test.go b/internal/cmd/beta/server/backup/create/create_test.go index 18bf4046d..a4fd801f3 100644 --- a/internal/cmd/beta/server/backup/create/create_test.go +++ b/internal/cmd/beta/server/backup/create/create_test.go @@ -208,3 +208,31 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverLabel string + resp serverbackup.BackupJob + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/describe/describe.go b/internal/cmd/beta/server/backup/describe/describe.go index 3396fd18c..2f55048cd 100644 --- a/internal/cmd/beta/server/backup/describe/describe.go +++ b/internal/cmd/beta/server/backup/describe/describe.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strconv" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -64,7 +65,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server backup: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -109,7 +110,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku return req } -func outputResult(p *print.Printer, outputFormat string, backup *serverbackup.Backup) error { +func outputResult(p *print.Printer, outputFormat string, backup serverbackup.Backup) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(backup, "", " ") @@ -145,7 +146,11 @@ func outputResult(p *print.Printer, outputFormat string, backup *serverbackup.Ba lastRestored := utils.PtrStringDefault(backup.LastRestoredAt, "") table.AddRow("LAST RESTORED AT", lastRestored) table.AddSeparator() - table.AddRow("VOLUME BACKUPS", len(*backup.VolumeBackups)) + volBackups := "" + if backups := backup.VolumeBackups; backups != nil { + volBackups = strconv.Itoa(len(*backups)) + } + table.AddRow("VOLUME BACKUPS", volBackups) table.AddSeparator() err := table.Display(p) diff --git a/internal/cmd/beta/server/backup/describe/describe_test.go b/internal/cmd/beta/server/backup/describe/describe_test.go index a4f979e0a..efa3e370a 100644 --- a/internal/cmd/beta/server/backup/describe/describe_test.go +++ b/internal/cmd/beta/server/backup/describe/describe_test.go @@ -209,3 +209,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + backup serverbackup.Backup + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "output format json", + args: args{ + outputFormat: print.JSONOutputFormat, + backup: serverbackup.Backup{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.backup); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/disable/disable.go b/internal/cmd/beta/server/backup/disable/disable.go index 3f3777ccb..1d1ff797b 100644 --- a/internal/cmd/beta/server/backup/disable/disable.go +++ b/internal/cmd/beta/server/backup/disable/disable.go @@ -10,6 +10,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" serverbackupUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/utils" @@ -50,17 +52,28 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + canDisable, err := serverbackupUtils.CanDisableBackupService(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { return err } if !canDisable { - p.Info("Cannot disable backup service for server %s - existing backups or existing backup schedules found\n", model.ServerId) + p.Info("Cannot disable backup service for server %s - existing backups or existing backup schedules found\n", serverLabel) return nil } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable the backup service for server %s?", model.ServerId) + prompt := fmt.Sprintf("Are you sure you want to disable the backup service for server %s?", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -74,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("disable server backup service: %w", err) } - p.Info("Disabled Server Backup service for server %s\n", model.ServerId) + p.Info("Disabled Server Backup service for server %s\n", serverLabel) return nil }, } diff --git a/internal/cmd/beta/server/backup/enable/enable.go b/internal/cmd/beta/server/backup/enable/enable.go index b4192a177..c6e6bc01c 100644 --- a/internal/cmd/beta/server/backup/enable/enable.go +++ b/internal/cmd/beta/server/backup/enable/enable.go @@ -11,6 +11,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/spf13/cobra" @@ -50,8 +52,19 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable the Server Backup service for server %s?", model.ServerId) + prompt := fmt.Sprintf("Are you sure you want to enable the Server Backup service for server %s?", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -67,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - p.Info("Enabled backup service for server %s\n", model.ServerId) + p.Info("Enabled backup service for server %s\n", serverLabel) return nil }, } diff --git a/internal/cmd/beta/server/backup/list/list.go b/internal/cmd/beta/server/backup/list/list.go index 244444766..fa060a413 100644 --- a/internal/cmd/beta/server/backup/list/list.go +++ b/internal/cmd/beta/server/backup/list/list.go @@ -13,6 +13,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -65,7 +67,17 @@ func NewCmd(p *print.Printer) *cobra.Command { } backups := *resp.Items if len(backups) == 0 { - p.Info("No backups found for server %s\n", model.ServerId) + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + p.Info("No backups found for server %s\n", serverLabel) return nil } @@ -150,6 +162,10 @@ func outputResult(p *print.Printer, outputFormat string, backups []serverbackup. s := backups[i] lastRestored := utils.PtrStringDefault(s.LastRestoredAt, "") + var volBackups int + if s.VolumeBackups != nil { + volBackups = len(*s.VolumeBackups) + } table.AddRow( utils.PtrString(s.Id), utils.PtrString(s.Name), @@ -158,7 +174,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []serverbackup. utils.PtrString(s.CreatedAt), utils.PtrString(s.ExpireAt), lastRestored, - len(*s.VolumeBackups), + volBackups, ) } err := table.Display(p) diff --git a/internal/cmd/beta/server/backup/list/list_test.go b/internal/cmd/beta/server/backup/list/list_test.go index fccc16027..087803962 100644 --- a/internal/cmd/beta/server/backup/list/list_test.go +++ b/internal/cmd/beta/server/backup/list/list_test.go @@ -186,3 +186,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + backups []serverbackup.Backup + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty backup", + args: args{ + backups: []serverbackup.Backup{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.backups); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/create/create.go b/internal/cmd/beta/server/backup/schedule/create/create.go index dc10d8bcd..19b789291 100644 --- a/internal/cmd/beta/server/backup/schedule/create/create.go +++ b/internal/cmd/beta/server/backup/schedule/create/create.go @@ -12,6 +12,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -73,8 +75,19 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a Backup Schedule for server %s?", model.ServerId) + prompt := fmt.Sprintf("Are you sure you want to create a Backup Schedule for server %s?", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -91,7 +104,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server Backup Schedule: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) @@ -159,8 +172,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.BackupSchedule) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, serverLabel string, resp serverbackup.BackupSchedule) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -178,7 +191,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.Backup return nil default: - p.Outputf("Created server backup schedule for server %s. Backup Schedule ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) + p.Outputf("Created server backup schedule for server %s. Backup Schedule ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/backup/schedule/create/create_test.go b/internal/cmd/beta/server/backup/schedule/create/create_test.go index 54307cb30..fbbb4e08e 100644 --- a/internal/cmd/beta/server/backup/schedule/create/create_test.go +++ b/internal/cmd/beta/server/backup/schedule/create/create_test.go @@ -219,3 +219,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat, serverLabel string + resp serverbackup.BackupSchedule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/delete/delete.go b/internal/cmd/beta/server/backup/schedule/delete/delete.go index 60e30643a..1417aba8e 100644 --- a/internal/cmd/beta/server/backup/schedule/delete/delete.go +++ b/internal/cmd/beta/server/backup/schedule/delete/delete.go @@ -10,6 +10,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/spf13/cobra" @@ -51,8 +53,19 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete server backup schedule %q? (This cannot be undone)", model.ScheduleId) + prompt := fmt.Sprintf("Are you sure you want to delete server backup schedule %q? (This cannot be undone)", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err diff --git a/internal/cmd/beta/server/backup/schedule/describe/describe.go b/internal/cmd/beta/server/backup/schedule/describe/describe.go index 7c91a0bee..4fd94511d 100644 --- a/internal/cmd/beta/server/backup/schedule/describe/describe.go +++ b/internal/cmd/beta/server/backup/schedule/describe/describe.go @@ -64,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server backup schedule: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -109,7 +109,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku return req } -func outputResult(p *print.Printer, outputFormat string, schedule *serverbackup.BackupSchedule) error { +func outputResult(p *print.Printer, outputFormat string, schedule serverbackup.BackupSchedule) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(schedule, "", " ") @@ -138,9 +138,9 @@ func outputResult(p *print.Printer, outputFormat string, schedule *serverbackup. table.AddRow("RRULE", utils.PtrString(schedule.Rrule)) table.AddSeparator() if schedule.BackupProperties != nil { - table.AddRow("BACKUP NAME", *schedule.BackupProperties.Name) + table.AddRow("BACKUP NAME", utils.PtrString(schedule.BackupProperties.Name)) table.AddSeparator() - table.AddRow("BACKUP RETENTION DAYS", *schedule.BackupProperties.RetentionPeriod) + table.AddRow("BACKUP RETENTION DAYS", utils.PtrString(schedule.BackupProperties.RetentionPeriod)) table.AddSeparator() ids := schedule.BackupProperties.VolumeIds table.AddRow("BACKUP VOLUME IDS", utils.JoinStringPtr(ids, "\n")) diff --git a/internal/cmd/beta/server/backup/schedule/describe/describe_test.go b/internal/cmd/beta/server/backup/schedule/describe/describe_test.go index 985989f62..d199f2dd3 100644 --- a/internal/cmd/beta/server/backup/schedule/describe/describe_test.go +++ b/internal/cmd/beta/server/backup/schedule/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) @@ -209,3 +208,66 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + schedule serverbackup.BackupSchedule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "nil backup properties", + args: args{ + schedule: serverbackup.BackupSchedule{ + BackupProperties: nil, + }, + }, + }, + { + name: "empty backup properties", + args: args{ + schedule: serverbackup.BackupSchedule{ + BackupProperties: &serverbackup.BackupProperties{}, + }, + }, + }, + { + name: "nil volume ids", + args: args{ + schedule: serverbackup.BackupSchedule{ + BackupProperties: &serverbackup.BackupProperties{ + VolumeIds: nil, + }, + }, + }, + }, + { + name: "empty volume ids", + args: args{ + schedule: serverbackup.BackupSchedule{ + BackupProperties: &serverbackup.BackupProperties{ + VolumeIds: &[]string{}, + }, + }, + }, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.schedule); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/list/list.go b/internal/cmd/beta/server/backup/schedule/list/list.go index 366d6a09b..ff8ba067d 100644 --- a/internal/cmd/beta/server/backup/schedule/list/list.go +++ b/internal/cmd/beta/server/backup/schedule/list/list.go @@ -13,6 +13,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -57,6 +59,17 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + // Call API req := buildRequest(ctx, model, apiClient) resp, err := req.Execute() @@ -65,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } schedules := *resp.Items if len(schedules) == 0 { - p.Info("No backup schedules found for server %s\n", model.ServerId) + p.Info("No backup schedules found for server %s\n", serverLabel) return nil } diff --git a/internal/cmd/beta/server/backup/schedule/list/list_test.go b/internal/cmd/beta/server/backup/schedule/list/list_test.go index e8667ba02..66bcf4748 100644 --- a/internal/cmd/beta/server/backup/schedule/list/list_test.go +++ b/internal/cmd/beta/server/backup/schedule/list/list_test.go @@ -186,3 +186,50 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + schedules []serverbackup.BackupSchedule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty backup properties", + args: args{ + outputFormat: "", + schedules: []serverbackup.BackupSchedule{ + { + BackupProperties: &serverbackup.BackupProperties{}, + }, + }, + }, + wantErr: false, + }, + { + name: "output format json", + args: args{ + outputFormat: print.JSONOutputFormat, + schedules: []serverbackup.BackupSchedule{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.schedules); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/backup/schedule/update/update.go b/internal/cmd/beta/server/backup/schedule/update/update.go index 02fe6c92a..7c278c270 100644 --- a/internal/cmd/beta/server/backup/schedule/update/update.go +++ b/internal/cmd/beta/server/backup/schedule/update/update.go @@ -100,7 +100,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update Server Backup Schedule: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -184,8 +184,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *serverbackup.BackupSchedule) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, resp serverbackup.BackupSchedule) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { diff --git a/internal/cmd/beta/server/backup/schedule/update/update_test.go b/internal/cmd/beta/server/backup/schedule/update/update_test.go index 86a5be4bc..c30a67cbd 100644 --- a/internal/cmd/beta/server/backup/schedule/update/update_test.go +++ b/internal/cmd/beta/server/backup/schedule/update/update_test.go @@ -276,3 +276,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp serverbackup.BackupSchedule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/create/create.go b/internal/cmd/beta/server/command/create/create.go index 2729653f7..1ca0577f9 100644 --- a/internal/cmd/beta/server/command/create/create.go +++ b/internal/cmd/beta/server/command/create/create.go @@ -13,6 +13,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" runcommandUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -61,8 +63,19 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a Command for server %s?", model.ServerId) + prompt := fmt.Sprintf("Are you sure you want to create a Command for server %s?", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -79,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server Command: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) @@ -137,8 +150,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand. return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *runcommand.NewCommandResponse) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, serverLabel string, resp runcommand.NewCommandResponse) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -156,7 +169,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *runcommand.NewComma return nil default: - p.Outputf("Created server command for server %s. Command ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) + p.Outputf("Created server command for server %s. Command ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/command/create/create_test.go b/internal/cmd/beta/server/command/create/create_test.go index 31ea154bf..c1a72f8b6 100644 --- a/internal/cmd/beta/server/command/create/create_test.go +++ b/internal/cmd/beta/server/command/create/create_test.go @@ -201,3 +201,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat, serverLabel string + resp runcommand.NewCommandResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/describe/describe.go b/internal/cmd/beta/server/command/describe/describe.go index 7bc408969..cfc1f067f 100644 --- a/internal/cmd/beta/server/command/describe/describe.go +++ b/internal/cmd/beta/server/command/describe/describe.go @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server command: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -108,7 +108,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand. return req } -func outputResult(p *print.Printer, outputFormat string, command *runcommand.CommandDetails) error { +func outputResult(p *print.Printer, outputFormat string, command runcommand.CommandDetails) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(command, "", " ") diff --git a/internal/cmd/beta/server/command/describe/describe_test.go b/internal/cmd/beta/server/command/describe/describe_test.go index 46fac2707..0d0b76f25 100644 --- a/internal/cmd/beta/server/command/describe/describe_test.go +++ b/internal/cmd/beta/server/command/describe/describe_test.go @@ -239,3 +239,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + command runcommand.CommandDetails + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.command); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/list/list.go b/internal/cmd/beta/server/command/list/list.go index 5768eef26..8db186da9 100644 --- a/internal/cmd/beta/server/command/list/list.go +++ b/internal/cmd/beta/server/command/list/list.go @@ -13,6 +13,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -57,18 +59,28 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + // Call API req := buildRequest(ctx, model, apiClient) resp, err := req.Execute() if err != nil { return fmt.Errorf("list server commands: %w", err) } - commands := *resp.Items - if len(commands) == 0 { - p.Info("No commands found for server %s\n", model.ServerId) + if commands := resp.Items; commands == nil || len(*commands) == 0 { + p.Info("No commands found for server %s\n", serverLabel) return nil } - + commands := *resp.Items // Truncate output if model.Limit != nil && len(commands) > int(*model.Limit) { commands = commands[:*model.Limit] diff --git a/internal/cmd/beta/server/command/list/list_test.go b/internal/cmd/beta/server/command/list/list_test.go index e49a614c7..3d8ced5f2 100644 --- a/internal/cmd/beta/server/command/list/list_test.go +++ b/internal/cmd/beta/server/command/list/list_test.go @@ -186,3 +186,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + commands []runcommand.Commands + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.commands); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/template/describe/describe.go b/internal/cmd/beta/server/command/template/describe/describe.go index c44216b17..fd60b8c46 100644 --- a/internal/cmd/beta/server/command/template/describe/describe.go +++ b/internal/cmd/beta/server/command/template/describe/describe.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/goccy/go-yaml" "github.com/spf13/cobra" @@ -64,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server command template: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -109,7 +108,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand. return req } -func outputResult(p *print.Printer, outputFormat string, commandTemplate *runcommand.CommandTemplateSchema) error { +func outputResult(p *print.Printer, outputFormat string, commandTemplate runcommand.CommandTemplateSchema) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(commandTemplate, "", " ") @@ -136,7 +135,7 @@ func outputResult(p *print.Printer, outputFormat string, commandTemplate *runcom table.AddRow("DESCRIPTION", utils.PtrString(commandTemplate.Description)) table.AddSeparator() if commandTemplate.OsType != nil { - table.AddRow("OS TYPE", strings.Join(*commandTemplate.OsType, "\n")) + table.AddRow("OS TYPE", utils.JoinStringPtr(commandTemplate.OsType, "\n")) table.AddSeparator() } if commandTemplate.ParameterSchema != nil { diff --git a/internal/cmd/beta/server/command/template/describe/describe_test.go b/internal/cmd/beta/server/command/template/describe/describe_test.go index 560d0ee93..b01268ae6 100644 --- a/internal/cmd/beta/server/command/template/describe/describe_test.go +++ b/internal/cmd/beta/server/command/template/describe/describe_test.go @@ -239,3 +239,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + commandTemplate runcommand.CommandTemplateSchema + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.commandTemplate); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/command/template/list/list.go b/internal/cmd/beta/server/command/template/list/list.go index 5290173a2..8be97f03b 100644 --- a/internal/cmd/beta/server/command/template/list/list.go +++ b/internal/cmd/beta/server/command/template/list/list.go @@ -61,11 +61,11 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("list server command templates: %w", err) } - templates := *resp.Items - if len(templates) == 0 { + if templates := resp.Items; templates == nil || len(*templates) == 0 { p.Info("No commands templates found\n") return nil } + templates := *resp.Items // Truncate output if model.Limit != nil && len(templates) > int(*model.Limit) { diff --git a/internal/cmd/beta/server/command/template/list/list_test.go b/internal/cmd/beta/server/command/template/list/list_test.go index 119302574..5c6cb12c8 100644 --- a/internal/cmd/beta/server/command/template/list/list_test.go +++ b/internal/cmd/beta/server/command/template/list/list_test.go @@ -183,3 +183,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + templates []runcommand.CommandTemplate + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty command template", + args: args{ + templates: []runcommand.CommandTemplate{ + {}, + }, + }, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.templates); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/console/console.go b/internal/cmd/beta/server/console/console.go index d5af1372e..026c942cb 100644 --- a/internal/cmd/beta/server/console/console.go +++ b/internal/cmd/beta/server/console/console.go @@ -62,6 +62,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } // Call API @@ -71,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("server console: %w", err) } - return outputResult(p, model, serverLabel, resp) + return outputResult(p, model.OutputFormat, serverLabel, *resp) }, } return cmd @@ -106,9 +108,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return apiClient.GetServerConsole(ctx, model.ProjectId, model.ServerId) } -func outputResult(p *print.Printer, model *inputModel, serverLabel string, serverUrl *iaas.ServerConsoleUrl) error { - outputFormat := model.OutputFormat - +func outputResult(p *print.Printer, outputFormat, serverLabel string, serverUrl iaas.ServerConsoleUrl) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(serverUrl, "", " ") diff --git a/internal/cmd/beta/server/console/console_test.go b/internal/cmd/beta/server/console/console_test.go index 1dfc48384..4d9b9e6c1 100644 --- a/internal/cmd/beta/server/console/console_test.go +++ b/internal/cmd/beta/server/console/console_test.go @@ -6,6 +6,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -206,3 +207,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat, serverLabel string + serverUrl iaas.ServerConsoleUrl + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set server url", + args: args{ + serverUrl: iaas.ServerConsoleUrl{ + Url: utils.Ptr(""), + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.serverUrl); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/create/create.go b/internal/cmd/beta/server/create/create.go index 23a22a3ba..fb0cb24f6 100644 --- a/internal/cmd/beta/server/create/create.go +++ b/internal/cmd/beta/server/create/create.go @@ -155,7 +155,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, projectLabel, resp) }, } configureFlags(cmd) @@ -334,8 +334,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateServerPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, projectLabel string, server *iaas.Server) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, projectLabel string, server *iaas.Server) error { + if server == nil { + return fmt.Errorf("server response is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(server, "", " ") if err != nil { diff --git a/internal/cmd/beta/server/create/create_test.go b/internal/cmd/beta/server/create/create_test.go index 2ac1afcac..b5ffb23f9 100644 --- a/internal/cmd/beta/server/create/create_test.go +++ b/internal/cmd/beta/server/create/create_test.go @@ -408,3 +408,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + projectLabel string + server *iaas.Server + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty with iaas server", + args: args{ + server: &iaas.Server{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(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.server); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/deallocate/deallocate.go b/internal/cmd/beta/server/deallocate/deallocate.go index 0bfe4205a..3cb27fb0b 100644 --- a/internal/cmd/beta/server/deallocate/deallocate.go +++ b/internal/cmd/beta/server/deallocate/deallocate.go @@ -57,6 +57,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/delete/delete.go b/internal/cmd/beta/server/delete/delete.go index 43b2a77cb..eaf994419 100644 --- a/internal/cmd/beta/server/delete/delete.go +++ b/internal/cmd/beta/server/delete/delete.go @@ -60,6 +60,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ProjectId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/beta/server/describe/describe.go index 3b4b0cef8..ab87b4ba5 100644 --- a/internal/cmd/beta/server/describe/describe.go +++ b/internal/cmd/beta/server/describe/describe.go @@ -65,7 +65,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, resp) }, } return cmd @@ -103,9 +103,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req } -func outputResult(p *print.Printer, model *inputModel, server *iaas.Server) error { - outputFormat := model.OutputFormat - +func outputResult(p *print.Printer, outputFormat string, server *iaas.Server) error { + if server == nil { + return fmt.Errorf("api response is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(server, "", " ") diff --git a/internal/cmd/beta/server/describe/describe_test.go b/internal/cmd/beta/server/describe/describe_test.go index defc5dec6..d16a3ec04 100644 --- a/internal/cmd/beta/server/describe/describe_test.go +++ b/internal/cmd/beta/server/describe/describe_test.go @@ -217,3 +217,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + server *iaas.Server + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty server", + args: args{ + outputFormat: "", + server: &iaas.Server{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.server); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/list/list_test.go b/internal/cmd/beta/server/list/list_test.go index 8cc72571b..a8dfe0e1e 100644 --- a/internal/cmd/beta/server/list/list_test.go +++ b/internal/cmd/beta/server/list/list_test.go @@ -203,3 +203,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + servers []iaas.Server + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.servers); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/log/log.go b/internal/cmd/beta/server/log/log.go index 2de1b3246..3aaa51ed7 100644 --- a/internal/cmd/beta/server/log/log.go +++ b/internal/cmd/beta/server/log/log.go @@ -71,6 +71,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } // Call API @@ -86,10 +88,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(lines) > int(*model.Length) { // Truncate output and show most recent logs start := len(lines) - int(*model.Length) - return outputResult(p, model, serverLabel, strings.Join(lines[start:], "\n")) + return outputResult(p, model.OutputFormat, serverLabel, strings.Join(lines[start:], "\n")) } - return outputResult(p, model, serverLabel, log) + return outputResult(p, model.OutputFormat, serverLabel, log) }, } configureFlags(cmd) @@ -138,9 +140,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return apiClient.GetServerLog(ctx, model.ProjectId, model.ServerId) } -func outputResult(p *print.Printer, model *inputModel, serverLabel, log string) error { - outputFormat := model.OutputFormat - +func outputResult(p *print.Printer, outputFormat, serverLabel, log string) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(log, "", " ") diff --git a/internal/cmd/beta/server/log/log_test.go b/internal/cmd/beta/server/log/log_test.go index 5e10870d6..50ce7c723 100644 --- a/internal/cmd/beta/server/log/log_test.go +++ b/internal/cmd/beta/server/log/log_test.go @@ -220,3 +220,31 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverLabel string + log string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.log); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/machine-type/describe/describe.go b/internal/cmd/beta/server/machine-type/describe/describe.go index 6274f85ac..365a07205 100644 --- a/internal/cmd/beta/server/machine-type/describe/describe.go +++ b/internal/cmd/beta/server/machine-type/describe/describe.go @@ -101,6 +101,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, machineType *iaas.MachineType) error { + if machineType == nil { + return fmt.Errorf("api response for machine type is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(machineType, "", " ") diff --git a/internal/cmd/beta/server/machine-type/describe/describe_test.go b/internal/cmd/beta/server/machine-type/describe/describe_test.go index 44c5bcb78..32f6d9a0b 100644 --- a/internal/cmd/beta/server/machine-type/describe/describe_test.go +++ b/internal/cmd/beta/server/machine-type/describe/describe_test.go @@ -204,3 +204,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + machineType *iaas.MachineType + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.machineType); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/machine-type/list/list.go b/internal/cmd/beta/server/machine-type/list/list.go index ffa6343b5..a8511e53a 100644 --- a/internal/cmd/beta/server/machine-type/list/list.go +++ b/internal/cmd/beta/server/machine-type/list/list.go @@ -85,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { *resp.Items = (*resp.Items)[:*model.Limit] } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, *resp) }, } @@ -132,9 +132,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return apiClient.ListMachineTypes(ctx, model.ProjectId) } -func outputResult(p *print.Printer, model *inputModel, machineTypes *iaas.MachineTypeListResponse) error { - outputFormat := model.OutputFormat - +func outputResult(p *print.Printer, outputFormat string, machineTypes iaas.MachineTypeListResponse) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(machineTypes, "", " ") @@ -157,8 +155,10 @@ func outputResult(p *print.Printer, model *inputModel, machineTypes *iaas.Machin table.SetTitle("Machine-Types") table.SetHeader("NAME", "DESCRIPTION") - for _, machineType := range *machineTypes.GetItems() { - table.AddRow(*machineType.Name, utils.PtrString(machineType.Description)) + if items := machineTypes.GetItems(); items != nil && len(*items) > 0 { + for _, machineType := range *items { + table.AddRow(*machineType.Name, utils.PtrString(machineType.Description)) + } } err := table.Display(p) diff --git a/internal/cmd/beta/server/machine-type/list/list_test.go b/internal/cmd/beta/server/machine-type/list/list_test.go index a76fcf00b..a38d4f386 100644 --- a/internal/cmd/beta/server/machine-type/list/list_test.go +++ b/internal/cmd/beta/server/machine-type/list/list_test.go @@ -188,3 +188,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + machineTypes iaas.MachineTypeListResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.machineTypes); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/network-interface/detach/detach.go b/internal/cmd/beta/server/network-interface/detach/detach.go index 57e9c1f7a..993c4426c 100644 --- a/internal/cmd/beta/server/network-interface/detach/detach.go +++ b/internal/cmd/beta/server/network-interface/detach/detach.go @@ -68,6 +68,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } // if the delete flag is provided a network interface is detached and deleted diff --git a/internal/cmd/beta/server/network-interface/list/list.go b/internal/cmd/beta/server/network-interface/list/list.go index 8f0d3b928..de6fd5100 100644 --- a/internal/cmd/beta/server/network-interface/list/list.go +++ b/internal/cmd/beta/server/network-interface/list/list.go @@ -76,6 +76,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } p.Info("No attached network interfaces found for server %q\n", serverLabel) return nil diff --git a/internal/cmd/beta/server/network-interface/list/list_test.go b/internal/cmd/beta/server/network-interface/list/list_test.go index 9f729b86a..5ce4e90c6 100644 --- a/internal/cmd/beta/server/network-interface/list/list_test.go +++ b/internal/cmd/beta/server/network-interface/list/list_test.go @@ -209,3 +209,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverId string + serverNics []iaas.NIC + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty nic", + args: args{ + serverNics: []iaas.NIC{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverId, tt.args.serverNics); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/create/create.go b/internal/cmd/beta/server/os-update/create/create.go index db998a374..ac00b378e 100644 --- a/internal/cmd/beta/server/os-update/create/create.go +++ b/internal/cmd/beta/server/os-update/create/create.go @@ -12,6 +12,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -60,8 +62,19 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a os-update for server %s?", model.ServerId) + prompt := fmt.Sprintf("Are you sure you want to create a os-update for server %s?", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -78,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server os-update: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) @@ -123,8 +136,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, serverLabel string, resp serverupdate.Update) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -142,7 +155,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update return nil default: - p.Outputf("Triggered creation of server os-update for server %s. Update ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) + p.Outputf("Triggered creation of server os-update for server %s. Update ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/os-update/create/create_test.go b/internal/cmd/beta/server/os-update/create/create_test.go index 2402f81a8..e2a38ea36 100644 --- a/internal/cmd/beta/server/os-update/create/create_test.go +++ b/internal/cmd/beta/server/os-update/create/create_test.go @@ -203,3 +203,31 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverLabel string + resp serverupdate.Update + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/describe/describe.go b/internal/cmd/beta/server/os-update/describe/describe.go index 820edddda..ac3a588d7 100644 --- a/internal/cmd/beta/server/os-update/describe/describe.go +++ b/internal/cmd/beta/server/os-update/describe/describe.go @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server os-update: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -108,7 +108,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat return req } -func outputResult(p *print.Printer, outputFormat string, update *serverupdate.Update) error { +func outputResult(p *print.Printer, outputFormat string, update serverupdate.Update) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(update, "", " ") diff --git a/internal/cmd/beta/server/os-update/describe/describe_test.go b/internal/cmd/beta/server/os-update/describe/describe_test.go index e02f0298f..fb345e40a 100644 --- a/internal/cmd/beta/server/os-update/describe/describe_test.go +++ b/internal/cmd/beta/server/os-update/describe/describe_test.go @@ -209,3 +209,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + update serverupdate.Update + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.update); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/disable/disable.go b/internal/cmd/beta/server/os-update/disable/disable.go index 1fbc89823..cfd937ec1 100644 --- a/internal/cmd/beta/server/os-update/disable/disable.go +++ b/internal/cmd/beta/server/os-update/disable/disable.go @@ -10,6 +10,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/spf13/cobra" @@ -49,8 +51,19 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable the os-update service for server %s?", model.ServerId) + prompt := fmt.Sprintf("Are you sure you want to disable the os-update service for server %s?", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -64,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("disable server os-update service: %w", err) } - p.Info("Disabled Server os-update service for server %s\n", model.ServerId) + p.Info("Disabled Server os-update service for server %s\n", serverLabel) return nil }, } diff --git a/internal/cmd/beta/server/os-update/enable/enable.go b/internal/cmd/beta/server/os-update/enable/enable.go index c16d19318..9cb96b806 100644 --- a/internal/cmd/beta/server/os-update/enable/enable.go +++ b/internal/cmd/beta/server/os-update/enable/enable.go @@ -11,6 +11,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/spf13/cobra" @@ -50,8 +52,19 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable the server os-update service for server %s?", model.ServerId) + prompt := fmt.Sprintf("Are you sure you want to enable the server os-update service for server %s?", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -67,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - p.Info("Enabled os-update service for server %s\n", model.ServerId) + p.Info("Enabled os-update service for server %s\n", serverLabel) return nil }, } diff --git a/internal/cmd/beta/server/os-update/list/list.go b/internal/cmd/beta/server/os-update/list/list.go index 10e71108f..6da7e4fcc 100644 --- a/internal/cmd/beta/server/os-update/list/list.go +++ b/internal/cmd/beta/server/os-update/list/list.go @@ -12,6 +12,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -67,7 +69,17 @@ func NewCmd(p *print.Printer) *cobra.Command { } updates := *resp.Items if len(updates) == 0 { - p.Info("No os-updates found for server %s\n", model.ServerId) + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + p.Info("No os-updates found for server %s\n", serverLabel) return nil } diff --git a/internal/cmd/beta/server/os-update/list/list_test.go b/internal/cmd/beta/server/os-update/list/list_test.go index 32f75311c..4b6df9161 100644 --- a/internal/cmd/beta/server/os-update/list/list_test.go +++ b/internal/cmd/beta/server/os-update/list/list_test.go @@ -186,3 +186,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + updates []serverupdate.Update + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.updates); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/create/create.go b/internal/cmd/beta/server/os-update/schedule/create/create.go index 861ec9629..f36756391 100644 --- a/internal/cmd/beta/server/os-update/schedule/create/create.go +++ b/internal/cmd/beta/server/os-update/schedule/create/create.go @@ -12,6 +12,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -69,8 +71,19 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a os-update Schedule for server %s?", model.ServerId) + prompt := fmt.Sprintf("Are you sure you want to create a os-update Schedule for server %s?", serverLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -87,7 +100,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server os-update Schedule: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) @@ -143,8 +156,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.UpdateSchedule) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, serverLabel string, resp serverupdate.UpdateSchedule) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -162,7 +175,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.Update return nil default: - p.Outputf("Created server os-update schedule for server %s. os-update Schedule ID: %s\n", model.ServerId, utils.PtrString(resp.Id)) + p.Outputf("Created server os-update schedule for server %s. os-update Schedule ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil } } diff --git a/internal/cmd/beta/server/os-update/schedule/create/create_test.go b/internal/cmd/beta/server/os-update/schedule/create/create_test.go index 31e6f781b..169167532 100644 --- a/internal/cmd/beta/server/os-update/schedule/create/create_test.go +++ b/internal/cmd/beta/server/os-update/schedule/create/create_test.go @@ -210,3 +210,31 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverLabel string + resp serverupdate.UpdateSchedule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/describe/describe.go b/internal/cmd/beta/server/os-update/schedule/describe/describe.go index e0a20bf1f..efacb1fbe 100644 --- a/internal/cmd/beta/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/beta/server/os-update/schedule/describe/describe.go @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server os-update schedule: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -108,7 +108,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat return req } -func outputResult(p *print.Printer, outputFormat string, schedule *serverupdate.UpdateSchedule) error { +func outputResult(p *print.Printer, outputFormat string, schedule serverupdate.UpdateSchedule) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(schedule, "", " ") diff --git a/internal/cmd/beta/server/os-update/schedule/describe/describe_test.go b/internal/cmd/beta/server/os-update/schedule/describe/describe_test.go index f1165bb00..411148262 100644 --- a/internal/cmd/beta/server/os-update/schedule/describe/describe_test.go +++ b/internal/cmd/beta/server/os-update/schedule/describe/describe_test.go @@ -209,3 +209,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + schedule serverupdate.UpdateSchedule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.schedule); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/list/list.go b/internal/cmd/beta/server/os-update/schedule/list/list.go index 8efd95198..ad46f0de2 100644 --- a/internal/cmd/beta/server/os-update/schedule/list/list.go +++ b/internal/cmd/beta/server/os-update/schedule/list/list.go @@ -13,6 +13,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -65,7 +67,17 @@ func NewCmd(p *print.Printer) *cobra.Command { } schedules := *resp.Items if len(schedules) == 0 { - p.Info("No os-update schedules found for server %s\n", model.ServerId) + serverLabel := model.ServerId + // Get server name + if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + if err != nil { + p.Debug(print.ErrorLevel, "get server name: %v", err) + } else if serverName != "" { + serverLabel = serverName + } + } + p.Info("No os-update schedules found for server %s\n", serverLabel) return nil } diff --git a/internal/cmd/beta/server/os-update/schedule/list/list_test.go b/internal/cmd/beta/server/os-update/schedule/list/list_test.go index 6c0ce72f7..61a3ca5ca 100644 --- a/internal/cmd/beta/server/os-update/schedule/list/list_test.go +++ b/internal/cmd/beta/server/os-update/schedule/list/list_test.go @@ -186,3 +186,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + schedules []serverupdate.UpdateSchedule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.schedules); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/os-update/schedule/update/update.go b/internal/cmd/beta/server/os-update/schedule/update/update.go index 7b4b057a3..cea340336 100644 --- a/internal/cmd/beta/server/os-update/schedule/update/update.go +++ b/internal/cmd/beta/server/os-update/schedule/update/update.go @@ -92,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update Server os-update Schedule: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -166,8 +166,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *serverupdate.UpdateSchedule) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, resp serverupdate.UpdateSchedule) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { diff --git a/internal/cmd/beta/server/os-update/schedule/update/update_test.go b/internal/cmd/beta/server/os-update/schedule/update/update_test.go index 20d8afe36..a821be003 100644 --- a/internal/cmd/beta/server/os-update/schedule/update/update_test.go +++ b/internal/cmd/beta/server/os-update/schedule/update/update_test.go @@ -263,3 +263,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp serverupdate.UpdateSchedule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/public-ip/attach/attach.go b/internal/cmd/beta/server/public-ip/attach/attach.go index 47d55e750..ff6e6c05d 100644 --- a/internal/cmd/beta/server/public-ip/attach/attach.go +++ b/internal/cmd/beta/server/public-ip/attach/attach.go @@ -56,8 +56,8 @@ func NewCmd(p *print.Printer) *cobra.Command { publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) if err != nil { p.Debug(print.ErrorLevel, "get public ip name: %v", err) - } - if publicIpLabel == "" { + publicIpLabel = model.PublicIpId + } else if publicIpLabel == "" { publicIpLabel = model.PublicIpId } @@ -65,6 +65,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/public-ip/detach/detach.go b/internal/cmd/beta/server/public-ip/detach/detach.go index d476db50f..a5c0d366e 100644 --- a/internal/cmd/beta/server/public-ip/detach/detach.go +++ b/internal/cmd/beta/server/public-ip/detach/detach.go @@ -58,8 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get public ip: %v", err) publicIpLabel = model.PublicIpId - } - if publicIpLabel == "" { + } else if publicIpLabel == "" { publicIpLabel = model.PublicIpId } @@ -67,6 +66,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/reboot/reboot.go b/internal/cmd/beta/server/reboot/reboot.go index d5ec2bae5..2c32ac2c4 100644 --- a/internal/cmd/beta/server/reboot/reboot.go +++ b/internal/cmd/beta/server/reboot/reboot.go @@ -65,8 +65,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } - if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to reboot server %q?", serverLabel) err = p.PromptForConfirmation(prompt) diff --git a/internal/cmd/beta/server/rescue/rescue.go b/internal/cmd/beta/server/rescue/rescue.go index ef6474220..69f4be349 100644 --- a/internal/cmd/beta/server/rescue/rescue.go +++ b/internal/cmd/beta/server/rescue/rescue.go @@ -61,6 +61,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/resize/resize.go b/internal/cmd/beta/server/resize/resize.go index 105967c6e..6cd7da807 100644 --- a/internal/cmd/beta/server/resize/resize.go +++ b/internal/cmd/beta/server/resize/resize.go @@ -61,6 +61,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/service-account/attach/attach.go b/internal/cmd/beta/server/service-account/attach/attach.go index 87bfbaa31..cb822440d 100644 --- a/internal/cmd/beta/server/service-account/attach/attach.go +++ b/internal/cmd/beta/server/service-account/attach/attach.go @@ -59,6 +59,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } if !model.AssumeYes { @@ -76,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("attach service account to server: %w", err) } - return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, resp) + return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, *resp) }, } configureFlags(cmd) @@ -120,7 +122,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req } -func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, serviceAccounts *iaas.ServiceAccountMailListResponse) error { +func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, serviceAccounts iaas.ServiceAccountMailListResponse) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(serviceAccounts, "", " ") diff --git a/internal/cmd/beta/server/service-account/attach/attach_test.go b/internal/cmd/beta/server/service-account/attach/attach_test.go index f7854c24b..fddde577b 100644 --- a/internal/cmd/beta/server/service-account/attach/attach_test.go +++ b/internal/cmd/beta/server/service-account/attach/attach_test.go @@ -224,3 +224,32 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serviceAccMail string + serverLabel string + serviceAccounts iaas.ServiceAccountMailListResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serviceAccMail, tt.args.serverLabel, tt.args.serviceAccounts); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/service-account/detach/detach.go b/internal/cmd/beta/server/service-account/detach/detach.go index 7c5587842..e6ed7df88 100644 --- a/internal/cmd/beta/server/service-account/detach/detach.go +++ b/internal/cmd/beta/server/service-account/detach/detach.go @@ -59,6 +59,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } if !model.AssumeYes { @@ -76,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("detach service account request: %w", err) } - return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, resp) + return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, *resp) }, } configureFlags(cmd) @@ -120,7 +122,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req } -func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, service *iaas.ServiceAccountMailListResponse) error { +func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, service iaas.ServiceAccountMailListResponse) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(service, "", " ") diff --git a/internal/cmd/beta/server/service-account/detach/detach_test.go b/internal/cmd/beta/server/service-account/detach/detach_test.go index 5250e0a6f..ffee083d4 100644 --- a/internal/cmd/beta/server/service-account/detach/detach_test.go +++ b/internal/cmd/beta/server/service-account/detach/detach_test.go @@ -224,3 +224,32 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serviceAccMail string + serverLabel string + service iaas.ServiceAccountMailListResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serviceAccMail, tt.args.serverLabel, tt.args.service); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/service-account/list/list.go b/internal/cmd/beta/server/service-account/list/list.go index e02b9d3ae..0b5120e7d 100644 --- a/internal/cmd/beta/server/service-account/list/list.go +++ b/internal/cmd/beta/server/service-account/list/list.go @@ -67,6 +67,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverName = *model.ServerId + } else if serverName == "" { + serverName = *model.ServerId } // Call API @@ -77,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } serviceAccounts := *resp.Items if len(serviceAccounts) == 0 { - p.Info("No service accounts found for server %s\n", *model.ServerId) + p.Info("No service accounts found for server %s\n", serverName) return nil } diff --git a/internal/cmd/beta/server/service-account/list/list_test.go b/internal/cmd/beta/server/service-account/list/list_test.go index 04ba8c721..961ba2a0a 100644 --- a/internal/cmd/beta/server/service-account/list/list_test.go +++ b/internal/cmd/beta/server/service-account/list/list_test.go @@ -219,3 +219,41 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverId string + serverName string + serviceAccounts []string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty service account", + args: args{ + serviceAccounts: []string{ + "", + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverId, tt.args.serverName, tt.args.serviceAccounts); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/start/start.go b/internal/cmd/beta/server/start/start.go index 9c8447982..e9f908703 100644 --- a/internal/cmd/beta/server/start/start.go +++ b/internal/cmd/beta/server/start/start.go @@ -57,6 +57,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } // Call API diff --git a/internal/cmd/beta/server/stop/stop.go b/internal/cmd/beta/server/stop/stop.go index d16a636de..53952101f 100644 --- a/internal/cmd/beta/server/stop/stop.go +++ b/internal/cmd/beta/server/stop/stop.go @@ -57,6 +57,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/unrescue/unrescue.go b/internal/cmd/beta/server/unrescue/unrescue.go index 39a7040f7..647a15e85 100644 --- a/internal/cmd/beta/server/unrescue/unrescue.go +++ b/internal/cmd/beta/server/unrescue/unrescue.go @@ -57,6 +57,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/update/update.go b/internal/cmd/beta/server/update/update.go index 9067d5a45..223942890 100644 --- a/internal/cmd/beta/server/update/update.go +++ b/internal/cmd/beta/server/update/update.go @@ -67,6 +67,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId + } else if serverLabel == "" { + serverLabel = model.ServerId } if !model.AssumeYes { @@ -84,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update server: %w", err) } - return outputResult(p, model, serverLabel, resp) + return outputResult(p, model.OutputFormat, serverLabel, resp) }, } configureFlags(cmd) @@ -143,8 +145,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.UpdateServerPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, serverLabel string, server *iaas.Server) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, serverLabel string, server *iaas.Server) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(server, "", " ") if err != nil { diff --git a/internal/cmd/beta/server/update/update_test.go b/internal/cmd/beta/server/update/update_test.go index f06cbd6a5..5286eb70f 100644 --- a/internal/cmd/beta/server/update/update_test.go +++ b/internal/cmd/beta/server/update/update_test.go @@ -250,3 +250,31 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverLabel string + server *iaas.Server + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.server); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/attach/attach.go b/internal/cmd/beta/server/volume/attach/attach.go index 25b2a722a..5a5f3b484 100644 --- a/internal/cmd/beta/server/volume/attach/attach.go +++ b/internal/cmd/beta/server/volume/attach/attach.go @@ -68,8 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId - } - if volumeLabel == "" { + } else if volumeLabel == "" { volumeLabel = model.VolumeId } @@ -77,6 +76,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } if !model.AssumeYes { @@ -94,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("attach server volume: %w", err) } - return outputResult(p, model.OutputFormat, volumeLabel, serverLabel, resp) + return outputResult(p, model.OutputFormat, volumeLabel, serverLabel, *resp) }, } configureFlags(cmd) @@ -143,7 +144,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.AddVolumeToServerPayload(payload) } -func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel string, volume *iaas.VolumeAttachment) error { +func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel string, volume iaas.VolumeAttachment) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(volume, "", " ") diff --git a/internal/cmd/beta/server/volume/attach/attach_test.go b/internal/cmd/beta/server/volume/attach/attach_test.go index 9dd33f77f..29dd0ff1f 100644 --- a/internal/cmd/beta/server/volume/attach/attach_test.go +++ b/internal/cmd/beta/server/volume/attach/attach_test.go @@ -249,3 +249,32 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + volumeLabel string + serverLabel string + volume iaas.VolumeAttachment + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.volumeLabel, tt.args.serverLabel, tt.args.volume); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/describe/describe.go b/internal/cmd/beta/server/volume/describe/describe.go index 29648759e..8ec3b488a 100644 --- a/internal/cmd/beta/server/volume/describe/describe.go +++ b/internal/cmd/beta/server/volume/describe/describe.go @@ -68,12 +68,16 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId + } else if volumeLabel == "" { + volumeLabel = model.VolumeId } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } // Call API @@ -83,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe server volume: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, volumeLabel, resp) + return outputResult(p, model.OutputFormat, serverLabel, volumeLabel, *resp) }, } configureFlags(cmd) @@ -127,7 +131,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req } -func outputResult(p *print.Printer, outputFormat, serverLabel, volumeLabel string, volume *iaas.VolumeAttachment) error { +func outputResult(p *print.Printer, outputFormat, serverLabel, volumeLabel string, volume iaas.VolumeAttachment) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(volume, "", " ") @@ -158,7 +162,7 @@ func outputResult(p *print.Printer, outputFormat, serverLabel, volumeLabel strin table.AddRow("VOLUME NAME", volumeLabel) table.AddSeparator() } - table.AddRow("DELETE ON TERMINATION", *volume.DeleteOnTermination) + table.AddRow("DELETE ON TERMINATION", utils.PtrString(volume.DeleteOnTermination)) table.AddSeparator() err := table.Display(p) diff --git a/internal/cmd/beta/server/volume/describe/describe_test.go b/internal/cmd/beta/server/volume/describe/describe_test.go index 1d53423de..c86b57259 100644 --- a/internal/cmd/beta/server/volume/describe/describe_test.go +++ b/internal/cmd/beta/server/volume/describe/describe_test.go @@ -225,3 +225,32 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverLabel string + volumeLabel string + volume iaas.VolumeAttachment + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.volumeLabel, tt.args.volume); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/detach/detach.go b/internal/cmd/beta/server/volume/detach/detach.go index 8e07fd216..858d749e5 100644 --- a/internal/cmd/beta/server/volume/detach/detach.go +++ b/internal/cmd/beta/server/volume/detach/detach.go @@ -58,8 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId - } - if volumeLabel == "" { + } else if volumeLabel == "" { volumeLabel = model.VolumeId } @@ -67,6 +66,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } if !model.AssumeYes { diff --git a/internal/cmd/beta/server/volume/list/list.go b/internal/cmd/beta/server/volume/list/list.go index f6f39e7ad..54bde7194 100644 --- a/internal/cmd/beta/server/volume/list/list.go +++ b/internal/cmd/beta/server/volume/list/list.go @@ -60,6 +60,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } // Call API @@ -70,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } volumes := *resp.Items if len(volumes) == 0 { - p.Info("No volumes found for server %s\n", *model.ServerId) + p.Info("No volumes found for server %s\n", serverLabel) return nil } @@ -149,7 +151,11 @@ func outputResult(p *print.Printer, outputFormat, serverLabel string, volumeName table.SetHeader("SERVER ID", "SERVER NAME", "VOLUME ID", "VOLUME NAME") for i := range volumes { s := volumes[i] - table.AddRow(utils.PtrString(s.ServerId), serverLabel, utils.PtrString(s.VolumeId), volumeNames[i]) + var volumeName string + if len(volumeNames)-1 > i { + volumeName = volumeNames[i] + } + table.AddRow(utils.PtrString(s.ServerId), serverLabel, utils.PtrString(s.VolumeId), volumeName) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/server/volume/list/list_test.go b/internal/cmd/beta/server/volume/list/list_test.go index 288c65fd6..b9c37814f 100644 --- a/internal/cmd/beta/server/volume/list/list_test.go +++ b/internal/cmd/beta/server/volume/list/list_test.go @@ -191,3 +191,41 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serverLabel string + volumeNames []string + volumes []iaas.VolumeAttachment + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty volume", + args: args{ + volumes: []iaas.VolumeAttachment{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.volumeNames, tt.args.volumes); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/server/volume/update/update.go b/internal/cmd/beta/server/volume/update/update.go index 289593b65..7b90de143 100644 --- a/internal/cmd/beta/server/volume/update/update.go +++ b/internal/cmd/beta/server/volume/update/update.go @@ -64,8 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId - } - if volumeLabel == "" { + } else if volumeLabel == "" { volumeLabel = model.VolumeId } @@ -73,6 +72,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId + } else if serverLabel == "" { + serverLabel = *model.ServerId } if !model.AssumeYes { @@ -90,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update server volume: %w", err) } - return outputResult(p, model.OutputFormat, volumeLabel, serverLabel, resp) + return outputResult(p, model.OutputFormat, volumeLabel, serverLabel, *resp) }, } configureFlags(cmd) @@ -139,7 +140,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.UpdateAttachedVolumePayload(payload) } -func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel string, volume *iaas.VolumeAttachment) error { +func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel string, volume iaas.VolumeAttachment) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(volume, "", " ") diff --git a/internal/cmd/beta/server/volume/update/update_test.go b/internal/cmd/beta/server/volume/update/update_test.go index 5d8171fbf..46d5a0d20 100644 --- a/internal/cmd/beta/server/volume/update/update_test.go +++ b/internal/cmd/beta/server/volume/update/update_test.go @@ -248,3 +248,32 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + volumeLabel string + serverLabel string + volume iaas.VolumeAttachment + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.volumeLabel, tt.args.serverLabel, tt.args.volume); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 908703a5216ae50abd9ab0f6ebe5dd884e0c649c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 20 Feb 2025 12:26:05 +0100 Subject: [PATCH 187/619] fix(object-storage): add nil pointer checks for cmd outputs (#612) relates to STACKITCLI-105 --- .../object-storage/bucket/create/create.go | 14 +++--- .../bucket/create/create_test.go | 36 ++++++++++++++++ .../bucket/describe/describe.go | 4 ++ .../bucket/describe/describe_test.go | 34 +++++++++++++++ .../cmd/object-storage/bucket/list/list.go | 4 ++ .../object-storage/bucket/list/list_test.go | 34 +++++++++++++++ .../credentials-group/create/create.go | 10 +++-- .../credentials-group/create/create_test.go | 43 +++++++++++++++++++ .../credentials-group/list/list_test.go | 41 ++++++++++++++++++ .../credentials/create/create.go | 10 +++-- .../credentials/create/create_test.go | 35 +++++++++++++++ .../credentials/list/list_test.go | 41 ++++++++++++++++++ 12 files changed, 295 insertions(+), 11 deletions(-) diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index 4695a1416..e96a4206c 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -90,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, model.Async, model.BucketName, resp) }, } return cmd @@ -126,8 +126,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora return req } -func outputResult(p *print.Printer, model *inputModel, resp *objectstorage.CreateBucketResponse) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, async bool, bucketName string, resp *objectstorage.CreateBucketResponse) error { + if resp == nil { + return fmt.Errorf("create bucket response is empty") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -146,10 +150,10 @@ func outputResult(p *print.Printer, model *inputModel, resp *objectstorage.Creat return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } - p.Outputf("%s bucket %q\n", operationState, model.BucketName) + p.Outputf("%s bucket %q\n", operationState, bucketName) return nil } } diff --git a/internal/cmd/object-storage/bucket/create/create_test.go b/internal/cmd/object-storage/bucket/create/create_test.go index 42a2bf0a5..49a089342 100644 --- a/internal/cmd/object-storage/bucket/create/create_test.go +++ b/internal/cmd/object-storage/bucket/create/create_test.go @@ -214,3 +214,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + bucketName string + createBucketResponse *objectstorage.CreateBucketResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty create bucket response", + args: args{ + createBucketResponse: &objectstorage.CreateBucketResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.bucketName, tt.args.createBucketResponse); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index aad7f7fbd..23a9e7011 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -98,6 +98,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora } func outputResult(p *print.Printer, outputFormat string, bucket *objectstorage.Bucket) error { + if bucket == nil { + return fmt.Errorf("bucket is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(bucket, "", " ") diff --git a/internal/cmd/object-storage/bucket/describe/describe_test.go b/internal/cmd/object-storage/bucket/describe/describe_test.go index ec6702dae..d233fc17f 100644 --- a/internal/cmd/object-storage/bucket/describe/describe_test.go +++ b/internal/cmd/object-storage/bucket/describe/describe_test.go @@ -214,3 +214,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + bucket *objectstorage.Bucket + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty bucket", + args: args{ + bucket: &objectstorage.Bucket{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.bucket); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index 66f94a399..19466184b 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -130,6 +130,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora } func outputResult(p *print.Printer, outputFormat string, buckets []objectstorage.Bucket) error { + if buckets == nil { + return fmt.Errorf("buckets is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(buckets, "", " ") diff --git a/internal/cmd/object-storage/bucket/list/list_test.go b/internal/cmd/object-storage/bucket/list/list_test.go index 8f4d655bb..31664679f 100644 --- a/internal/cmd/object-storage/bucket/list/list_test.go +++ b/internal/cmd/object-storage/bucket/list/list_test.go @@ -190,3 +190,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + buckets []objectstorage.Bucket + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty create bucket response", + args: args{ + buckets: []objectstorage.Bucket{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.buckets); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index cb30ede3f..55530ccc7 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -67,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Object Storage credentials group: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, resp) }, } configureFlags(cmd) @@ -112,8 +112,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, resp *objectstorage.CreateCredentialsGroupResponse) error { + if resp == nil || resp.CredentialsGroup == nil { + return fmt.Errorf("create createndials group response is empty") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { diff --git a/internal/cmd/object-storage/credentials-group/create/create_test.go b/internal/cmd/object-storage/credentials-group/create/create_test.go index f7b1a447b..60dd53fbd 100644 --- a/internal/cmd/object-storage/credentials-group/create/create_test.go +++ b/internal/cmd/object-storage/credentials-group/create/create_test.go @@ -192,3 +192,46 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + createCredentialsGroupResponse *objectstorage.CreateCredentialsGroupResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty create credentials group response", + args: args{ + createCredentialsGroupResponse: &objectstorage.CreateCredentialsGroupResponse{}, + }, + wantErr: true, + }, + { + name: "set create credentials group response", + args: args{ + createCredentialsGroupResponse: &objectstorage.CreateCredentialsGroupResponse{ + CredentialsGroup: &objectstorage.CredentialsGroup{}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.createCredentialsGroupResponse); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/object-storage/credentials-group/list/list_test.go b/internal/cmd/object-storage/credentials-group/list/list_test.go index 7c9580330..2a7ee01ff 100644 --- a/internal/cmd/object-storage/credentials-group/list/list_test.go +++ b/internal/cmd/object-storage/credentials-group/list/list_test.go @@ -187,3 +187,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentialsGroups []objectstorage.CredentialsGroup + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty credentials groups", + args: args{ + credentialsGroups: []objectstorage.CredentialsGroup{}, + }, + wantErr: false, + }, + { + name: "set empty credentials group", + args: args{ + credentialsGroups: []objectstorage.CredentialsGroup{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentialsGroups); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index 8e4944d87..71c854dd3 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -81,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Object Storage credentials: %w", err) } - return outputResult(p, model, credentialsGroupLabel, resp) + return outputResult(p, model.OutputFormat, credentialsGroupLabel, resp) }, } configureFlags(cmd) @@ -137,8 +137,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat, credentialsGroupLabel string, resp *objectstorage.CreateAccessKeyResponse) error { + if resp == nil { + return fmt.Errorf("create access key response is empty") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { diff --git a/internal/cmd/object-storage/credentials/create/create_test.go b/internal/cmd/object-storage/credentials/create/create_test.go index c26ddf0ee..03257beda 100644 --- a/internal/cmd/object-storage/credentials/create/create_test.go +++ b/internal/cmd/object-storage/credentials/create/create_test.go @@ -251,3 +251,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentialsGroupLabel string + createAccessKeyResponse *objectstorage.CreateAccessKeyResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty create access key response", + args: args{ + createAccessKeyResponse: &objectstorage.CreateAccessKeyResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentialsGroupLabel, tt.args.createAccessKeyResponse); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/object-storage/credentials/list/list_test.go b/internal/cmd/object-storage/credentials/list/list_test.go index b778e5dc1..a50921b69 100644 --- a/internal/cmd/object-storage/credentials/list/list_test.go +++ b/internal/cmd/object-storage/credentials/list/list_test.go @@ -212,3 +212,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []objectstorage.AccessKey + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty credentials", + args: args{ + credentials: []objectstorage.AccessKey{}, + }, + wantErr: false, + }, + { + name: "set empty access key", + args: args{ + credentials: []objectstorage.AccessKey{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From a90d86e5286b4f56a2a4112780feae966d9b9d2c Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:13:15 +0100 Subject: [PATCH 188/619] fix: stackit beta quota command - add nil pointer checks and tests for the outputResult functions (#610) * add nil pointer checks * add tests for the outputResult functions within the quota command --- internal/cmd/beta/quota/list/list.go | 5 ++++ internal/cmd/beta/quota/list/list_test.go | 34 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/internal/cmd/beta/quota/list/list.go b/internal/cmd/beta/quota/list/list.go index 32a2be9d4..97e9f956b 100644 --- a/internal/cmd/beta/quota/list/list.go +++ b/internal/cmd/beta/quota/list/list.go @@ -52,6 +52,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId } // Call API @@ -106,6 +108,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, quotas *iaas.QuotaList) error { + if quotas == nil { + return fmt.Errorf("quotas is nil") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(quotas, "", " ") diff --git a/internal/cmd/beta/quota/list/list_test.go b/internal/cmd/beta/quota/list/list_test.go index b8fa5319c..1daa3fcff 100644 --- a/internal/cmd/beta/quota/list/list_test.go +++ b/internal/cmd/beta/quota/list/list_test.go @@ -162,3 +162,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + quotas *iaas.QuotaList + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set quota empty", + args: args{ + quotas: &iaas.QuotaList{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.quotas); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 566ed85156a34d1746e53a1ec3a6f3281a4e5d87 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:13:39 +0100 Subject: [PATCH 189/619] fix: stackit beta public-ip commands - add nil pointer checks and tests for the outputResult functions (#609) * add nil pointer checks * add tests for the outputResult functions within the public-ip commands --- .../cmd/beta/public-ip/associate/associate.go | 2 ++ internal/cmd/beta/public-ip/create/create.go | 8 ++++-- .../cmd/beta/public-ip/create/create_test.go | 28 +++++++++++++++++++ internal/cmd/beta/public-ip/delete/delete.go | 4 ++- .../cmd/beta/public-ip/describe/describe.go | 4 +-- .../beta/public-ip/describe/describe_test.go | 27 ++++++++++++++++++ .../public-ip/disassociate/disassociate.go | 2 ++ internal/cmd/beta/public-ip/list/list.go | 2 ++ internal/cmd/beta/public-ip/list/list_test.go | 27 ++++++++++++++++++ 9 files changed, 98 insertions(+), 6 deletions(-) diff --git a/internal/cmd/beta/public-ip/associate/associate.go b/internal/cmd/beta/public-ip/associate/associate.go index 1c33b2b8d..d50bafb8d 100644 --- a/internal/cmd/beta/public-ip/associate/associate.go +++ b/internal/cmd/beta/public-ip/associate/associate.go @@ -59,6 +59,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId + } else if publicIpLabel == "" { + publicIpLabel = model.PublicIpId } if !model.AssumeYes { diff --git a/internal/cmd/beta/public-ip/create/create.go b/internal/cmd/beta/public-ip/create/create.go index ad6196e82..9bc05ab3d 100644 --- a/internal/cmd/beta/public-ip/create/create.go +++ b/internal/cmd/beta/public-ip/create/create.go @@ -67,6 +67,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId } if !model.AssumeYes { @@ -84,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create public IP: %w", err) } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, projectLabel, *resp) }, } configureFlags(cmd) @@ -140,8 +142,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreatePublicIPPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, projectLabel string, publicIp *iaas.PublicIp) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, projectLabel string, publicIp iaas.PublicIp) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(publicIp, "", " ") if err != nil { diff --git a/internal/cmd/beta/public-ip/create/create_test.go b/internal/cmd/beta/public-ip/create/create_test.go index 7411c0a9f..b204d561f 100644 --- a/internal/cmd/beta/public-ip/create/create_test.go +++ b/internal/cmd/beta/public-ip/create/create_test.go @@ -213,3 +213,31 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + projectLabel string + publicIp iaas.PublicIp + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(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.publicIp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/public-ip/delete/delete.go b/internal/cmd/beta/public-ip/delete/delete.go index bd87419da..0f257d8f0 100644 --- a/internal/cmd/beta/public-ip/delete/delete.go +++ b/internal/cmd/beta/public-ip/delete/delete.go @@ -57,6 +57,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId + } else if publicIpLabel == "" { + publicIpLabel = model.PublicIpId } if !model.AssumeYes { @@ -74,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete public IP: %w", err) } - p.Info("Deleted public IP %q\n", model.PublicIpId) + p.Info("Deleted public IP %q\n", publicIpLabel) return nil }, } diff --git a/internal/cmd/beta/public-ip/describe/describe.go b/internal/cmd/beta/public-ip/describe/describe.go index c07e9e981..bc532fd6b 100644 --- a/internal/cmd/beta/public-ip/describe/describe.go +++ b/internal/cmd/beta/public-ip/describe/describe.go @@ -66,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read public IP: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, *resp) }, } return cmd @@ -101,7 +101,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return apiClient.GetPublicIP(ctx, model.ProjectId, model.PublicIpId) } -func outputResult(p *print.Printer, outputFormat string, publicIp *iaas.PublicIp) error { +func outputResult(p *print.Printer, outputFormat string, publicIp iaas.PublicIp) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(publicIp, "", " ") diff --git a/internal/cmd/beta/public-ip/describe/describe_test.go b/internal/cmd/beta/public-ip/describe/describe_test.go index 9754de721..44ab876ff 100644 --- a/internal/cmd/beta/public-ip/describe/describe_test.go +++ b/internal/cmd/beta/public-ip/describe/describe_test.go @@ -216,3 +216,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + publicIp iaas.PublicIp + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.publicIp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/public-ip/disassociate/disassociate.go b/internal/cmd/beta/public-ip/disassociate/disassociate.go index 0ad28d773..eb8872d80 100644 --- a/internal/cmd/beta/public-ip/disassociate/disassociate.go +++ b/internal/cmd/beta/public-ip/disassociate/disassociate.go @@ -55,6 +55,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId + } else if publicIpLabel == "" { + publicIpLabel = model.PublicIpId } if !model.AssumeYes { diff --git a/internal/cmd/beta/public-ip/list/list.go b/internal/cmd/beta/public-ip/list/list.go index 2293600aa..c071e5069 100644 --- a/internal/cmd/beta/public-ip/list/list.go +++ b/internal/cmd/beta/public-ip/list/list.go @@ -81,6 +81,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId } p.Info("No public IPs found for project %q\n", projectLabel) return nil diff --git a/internal/cmd/beta/public-ip/list/list_test.go b/internal/cmd/beta/public-ip/list/list_test.go index b7f39f61d..0644d83e8 100644 --- a/internal/cmd/beta/public-ip/list/list_test.go +++ b/internal/cmd/beta/public-ip/list/list_test.go @@ -202,3 +202,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + publicIps []iaas.PublicIp + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.publicIps); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 4e8d53f78f53433892476c1b33f62fc5ea6807db Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:14:10 +0100 Subject: [PATCH 190/619] fix: stackit beta image commands - add nil pointer checks and tests for the outputResult functions (#608) * add nil pointer checks * add tests for the outputResult functions within the image commands --- internal/cmd/beta/image/create/create.go | 9 ++- internal/cmd/beta/image/create/create_test.go | 57 +++++++++++++++++-- internal/cmd/beta/image/delete/delete.go | 2 + internal/cmd/beta/image/describe/describe.go | 9 ++- .../cmd/beta/image/describe/describe_test.go | 34 +++++++++++ internal/cmd/beta/image/list/list.go | 12 +++- internal/cmd/beta/image/list/list_test.go | 38 +++++++++++++ internal/cmd/beta/image/update/update.go | 2 + 8 files changed, 154 insertions(+), 9 deletions(-) diff --git a/internal/cmd/beta/image/create/create.go b/internal/cmd/beta/image/create/create.go index 1203f70a6..149aae01e 100644 --- a/internal/cmd/beta/image/create/create.go +++ b/internal/cmd/beta/image/create/create.go @@ -377,7 +377,14 @@ func createPayload(_ context.Context, model *inputModel) iaas.CreateImagePayload } func outputResult(p *print.Printer, model *inputModel, resp *iaas.ImageCreateResponse) error { - switch model.OutputFormat { + if model == nil { + return fmt.Errorf("input model is nil") + } + var outputFormat string + if model.GlobalFlagModel != nil { + outputFormat = model.OutputFormat + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { diff --git a/internal/cmd/beta/image/create/create_test.go b/internal/cmd/beta/image/create/create_test.go index 5777a9cf8..5e0bee59d 100644 --- a/internal/cmd/beta/image/create/create_test.go +++ b/internal/cmd/beta/image/create/create_test.go @@ -6,13 +6,12 @@ import ( "strings" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -372,3 +371,53 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + resp *iaas.ImageCreateResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "nil", + args: args{ + model: nil, + resp: nil, + }, + wantErr: true, + }, + { + name: "empty input", + args: args{ + model: &inputModel{}, + resp: &iaas.ImageCreateResponse{}, + }, + wantErr: false, + }, + { + name: "output json", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + OutputFormat: print.JSONOutputFormat, + }, + }, + resp: nil, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/image/delete/delete.go b/internal/cmd/beta/image/delete/delete.go index 3e2b44260..609ced9ec 100644 --- a/internal/cmd/beta/image/delete/delete.go +++ b/internal/cmd/beta/image/delete/delete.go @@ -56,6 +56,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get image name: %v", err) imageName = model.ImageId + } else if imageName == "" { + imageName = model.ImageId } if !model.AssumeYes { diff --git a/internal/cmd/beta/image/describe/describe.go b/internal/cmd/beta/image/describe/describe.go index 6da572ad4..8c8b27023 100644 --- a/internal/cmd/beta/image/describe/describe.go +++ b/internal/cmd/beta/image/describe/describe.go @@ -56,7 +56,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get image: %w", err) } - if err := outputResult(p, model, image); err != nil { + if err := outputResult(p, model.OutputFormat, image); err != nil { return err } @@ -95,8 +95,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM return &model, nil } -func outputResult(p *print.Printer, model *inputModel, resp *iaas.Image) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, resp *iaas.Image) error { + if resp == nil { + return fmt.Errorf("image not found") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { diff --git a/internal/cmd/beta/image/describe/describe_test.go b/internal/cmd/beta/image/describe/describe_test.go index 4003e78d1..036648fee 100644 --- a/internal/cmd/beta/image/describe/describe_test.go +++ b/internal/cmd/beta/image/describe/describe_test.go @@ -192,3 +192,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp *iaas.Image + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + resp: &iaas.Image{}, + }, + wantErr: false, + }, + { + name: "nil", + args: args{}, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/image/list/list.go b/internal/cmd/beta/image/list/list.go index 2452c7443..035771d89 100644 --- a/internal/cmd/beta/image/list/list.go +++ b/internal/cmd/beta/image/list/list.go @@ -68,6 +68,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId } // Call API @@ -108,10 +110,18 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return nil, &errors.ProjectIdError{} } + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + model := inputModel{ GlobalFlagModel: globalFlags, LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), - Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), + Limit: limit, } if p.IsVerbosityDebug() { diff --git a/internal/cmd/beta/image/list/list_test.go b/internal/cmd/beta/image/list/list_test.go index 70c6112cb..49a27a16e 100644 --- a/internal/cmd/beta/image/list/list_test.go +++ b/internal/cmd/beta/image/list/list_test.go @@ -210,3 +210,41 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + items []iaas.Image + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + outputFormat: "", + items: []iaas.Image{}, + }, + wantErr: false, + }, + { + name: "output format json", + args: args{ + outputFormat: print.JSONOutputFormat, + items: []iaas.Image{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/image/update/update.go b/internal/cmd/beta/image/update/update.go index 8e8becebd..9a4603882 100644 --- a/internal/cmd/beta/image/update/update.go +++ b/internal/cmd/beta/image/update/update.go @@ -134,6 +134,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.WarningLevel, "cannot retrieve image name: %v", err) imageLabel = model.Id + } else if imageLabel == "" { + imageLabel = model.Id } if !model.AssumeYes { From b3fb7b1430bd142f63b41cf46a9652403f1b57f8 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:14:27 +0100 Subject: [PATCH 191/619] fix: stackit beta network commands - add nil pointer checks and tests for the outputResult functions (#607) * add nil pointer checks * add tests for the outputResult functions within the network command --- internal/cmd/beta/network/create/create.go | 16 ++++++--- .../cmd/beta/network/create/create_test.go | 36 +++++++++++++++++++ internal/cmd/beta/network/delete/delete.go | 2 ++ .../cmd/beta/network/describe/describe.go | 3 ++ .../beta/network/describe/describe_test.go | 34 ++++++++++++++++++ internal/cmd/beta/network/list/list.go | 7 ++-- internal/cmd/beta/network/list/list_test.go | 36 +++++++++++++++++++ internal/cmd/beta/network/update/update.go | 2 ++ 8 files changed, 127 insertions(+), 9 deletions(-) diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go index e3832171b..2d902e599 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/beta/network/create/create.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" @@ -97,6 +98,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId } if !model.AssumeYes { @@ -126,7 +129,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) @@ -234,8 +237,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateNetworkPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, projectLabel string, network *iaas.Network) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, network *iaas.Network) error { + if network == nil { + return fmt.Errorf("network cannot be nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(network, "", " ") if err != nil { @@ -254,10 +260,10 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, netw return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } - p.Outputf("%s network for project %q.\nNetwork ID: %s\n", operationState, projectLabel, *network.NetworkId) + p.Outputf("%s network for project %q.\nNetwork ID: %s\n", operationState, projectLabel, utils.PtrString(network.NetworkId)) return nil } } diff --git a/internal/cmd/beta/network/create/create_test.go b/internal/cmd/beta/network/create/create_test.go index 2cd2d606e..804cd0d25 100644 --- a/internal/cmd/beta/network/create/create_test.go +++ b/internal/cmd/beta/network/create/create_test.go @@ -423,3 +423,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + network *iaas.Network + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty network", + args: args{ + network: &iaas.Network{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.network); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network/delete/delete.go b/internal/cmd/beta/network/delete/delete.go index 001aefa84..17be9f0ed 100644 --- a/internal/cmd/beta/network/delete/delete.go +++ b/internal/cmd/beta/network/delete/delete.go @@ -60,6 +60,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = model.NetworkId + } else if networkLabel == "" { + networkLabel = model.NetworkId } if !model.AssumeYes { diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/beta/network/describe/describe.go index 6bdb139af..356e2540d 100644 --- a/internal/cmd/beta/network/describe/describe.go +++ b/internal/cmd/beta/network/describe/describe.go @@ -101,6 +101,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) error { + if network == nil { + return fmt.Errorf("network cannot be nil") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(network, "", " ") diff --git a/internal/cmd/beta/network/describe/describe_test.go b/internal/cmd/beta/network/describe/describe_test.go index b0fb47c6a..451b518b3 100644 --- a/internal/cmd/beta/network/describe/describe_test.go +++ b/internal/cmd/beta/network/describe/describe_test.go @@ -216,3 +216,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + network *iaas.Network + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty network", + args: args{ + network: &iaas.Network{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.network); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index 71cff5509..9b3a9a0cc 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -75,6 +75,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId } p.Info("No networks found for project %q\n", projectLabel) return nil @@ -155,10 +157,7 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network table.SetHeader("ID", "NAME", "STATUS", "PUBLIC IP", "PREFIXES", "ROUTED") for _, network := range networks { - publicIp := "" - if network.PublicIp != nil { - publicIp = *network.PublicIp - } + publicIp := utils.PtrString(network.PublicIp) routed := false if network.Routed != nil { diff --git a/internal/cmd/beta/network/list/list_test.go b/internal/cmd/beta/network/list/list_test.go index 22de7baea..0d69a3f5e 100644 --- a/internal/cmd/beta/network/list/list_test.go +++ b/internal/cmd/beta/network/list/list_test.go @@ -188,3 +188,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + networks []iaas.Network + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty network", + args: args{ + networks: []iaas.Network{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networks); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/beta/network/update/update.go index 9c7b6247d..2148fa58d 100644 --- a/internal/cmd/beta/network/update/update.go +++ b/internal/cmd/beta/network/update/update.go @@ -85,6 +85,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = model.NetworkId + } else if networkLabel == "" { + networkLabel = model.NetworkId } if !model.AssumeYes { From 317ce8f76b1bd753ceb3c6ec782a463b12a9a0ea Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:15:29 +0100 Subject: [PATCH 192/619] fix: stackit beta network-interface commands - add nil pointer checks and tests for the outputResult functions (#605) * add nil pointer checks * add tests for the outputResult functions within the network-interface commands --- .../beta/network-interface/create/create.go | 13 ++++--- .../network-interface/create/create_test.go | 35 +++++++++++++++++++ .../network-interface/describe/describe.go | 17 +++++---- .../describe/describe_test.go | 34 ++++++++++++++++++ .../cmd/beta/network-interface/list/list.go | 2 ++ .../beta/network-interface/list/list_test.go | 27 ++++++++++++++ .../beta/network-interface/update/update.go | 11 +++--- .../network-interface/update/update_test.go | 35 +++++++++++++++++++ 8 files changed, 159 insertions(+), 15 deletions(-) diff --git a/internal/cmd/beta/network-interface/create/create.go b/internal/cmd/beta/network-interface/create/create.go index 99fa2dc7f..eb6bb301b 100644 --- a/internal/cmd/beta/network-interface/create/create.go +++ b/internal/cmd/beta/network-interface/create/create.go @@ -82,6 +82,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId } if !model.AssumeYes { @@ -99,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create network interface: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, model.ProjectId, resp) }, } configureFlags(cmd) @@ -226,8 +228,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateNicPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, projectId string, nic *iaas.NIC) error { + if nic == nil { + return fmt.Errorf("nic is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(nic, "", " ") if err != nil { @@ -245,7 +250,7 @@ func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { return nil default: - p.Outputf("Created network interface for project %q.\nNIC ID: %s\n", model.ProjectId, utils.PtrString(nic.Id)) + p.Outputf("Created network interface for project %q.\nNIC ID: %s\n", projectId, utils.PtrString(nic.Id)) return nil } } diff --git a/internal/cmd/beta/network-interface/create/create_test.go b/internal/cmd/beta/network-interface/create/create_test.go index 2173cf1ea..843b15f69 100644 --- a/internal/cmd/beta/network-interface/create/create_test.go +++ b/internal/cmd/beta/network-interface/create/create_test.go @@ -260,3 +260,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + projectId string + nic *iaas.NIC + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty nic", + args: args{ + nic: &iaas.NIC{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectId, tt.args.nic); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-interface/describe/describe.go b/internal/cmd/beta/network-interface/describe/describe.go index c83e79897..a1d741bdf 100644 --- a/internal/cmd/beta/network-interface/describe/describe.go +++ b/internal/cmd/beta/network-interface/describe/describe.go @@ -117,6 +117,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { + if nic == nil { + return fmt.Errorf("nic is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(nic, "", " ") @@ -136,27 +139,27 @@ func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { return nil default: table := tables.NewTable() - table.AddRow("ID", *nic.Id) + table.AddRow("ID", utils.PtrString(nic.Id)) table.AddSeparator() - table.AddRow("NETWORK ID", *nic.NetworkId) + table.AddRow("NETWORK ID", utils.PtrString(nic.NetworkId)) table.AddSeparator() if nic.Name != nil { - table.AddRow("NAME", *nic.Name) + table.AddRow("NAME", utils.PtrString(nic.Name)) table.AddSeparator() } if nic.Ipv4 != nil { - table.AddRow("IPV4", *nic.Ipv4) + table.AddRow("IPV4", utils.PtrString(nic.Ipv4)) table.AddSeparator() } if nic.Ipv6 != nil { - table.AddRow("IPV6", *nic.Ipv6) + table.AddRow("IPV6", utils.PtrString(nic.Ipv6)) table.AddSeparator() } table.AddRow("MAC", utils.PtrString(nic.Mac)) table.AddSeparator() table.AddRow("NIC SECURITY", utils.PtrString(nic.NicSecurity)) if nic.AllowedAddresses != nil && len(*nic.AllowedAddresses) > 0 { - allowedAddresses := []string{} + var allowedAddresses []string for _, value := range *nic.AllowedAddresses { allowedAddresses = append(allowedAddresses, *value.String) } @@ -164,7 +167,7 @@ func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { table.AddRow("ALLOWED ADDRESSES", strings.Join(allowedAddresses, "\n")) } if nic.Labels != nil && len(*nic.Labels) > 0 { - labels := []string{} + var labels []string for key, value := range *nic.Labels { labels = append(labels, fmt.Sprintf("%s: %s", key, value)) } diff --git a/internal/cmd/beta/network-interface/describe/describe_test.go b/internal/cmd/beta/network-interface/describe/describe_test.go index 145a12cc8..967057b02 100644 --- a/internal/cmd/beta/network-interface/describe/describe_test.go +++ b/internal/cmd/beta/network-interface/describe/describe_test.go @@ -200,3 +200,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + nic *iaas.NIC + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty nic", + args: args{ + nic: &iaas.NIC{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.nic); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-interface/list/list.go b/internal/cmd/beta/network-interface/list/list.go index 4b8d6b314..b4925b7a5 100644 --- a/internal/cmd/beta/network-interface/list/list.go +++ b/internal/cmd/beta/network-interface/list/list.go @@ -82,6 +82,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = *model.NetworkId + } else if networkLabel == "" { + networkLabel = *model.NetworkId } p.Info("No network interfaces found for network %q\n", networkLabel) return nil diff --git a/internal/cmd/beta/network-interface/list/list_test.go b/internal/cmd/beta/network-interface/list/list_test.go index 3058072b0..97610156a 100644 --- a/internal/cmd/beta/network-interface/list/list_test.go +++ b/internal/cmd/beta/network-interface/list/list_test.go @@ -205,3 +205,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + nics []iaas.NIC + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.nics); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-interface/update/update.go b/internal/cmd/beta/network-interface/update/update.go index 2b74557ac..9e7c12022 100644 --- a/internal/cmd/beta/network-interface/update/update.go +++ b/internal/cmd/beta/network-interface/update/update.go @@ -95,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update network interface: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, model.ProjectId, resp) }, } configureFlags(cmd) @@ -218,8 +218,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.UpdateNicPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, projectId string, nic *iaas.NIC) error { + if nic == nil { + return fmt.Errorf("nic is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(nic, "", " ") if err != nil { @@ -237,7 +240,7 @@ func outputResult(p *print.Printer, model *inputModel, nic *iaas.NIC) error { return nil default: - p.Outputf("Updated network interface for project %q.\n", model.ProjectId) + p.Outputf("Updated network interface for project %q.\n", projectId) return nil } } diff --git a/internal/cmd/beta/network-interface/update/update_test.go b/internal/cmd/beta/network-interface/update/update_test.go index 00eeda71f..98987b829 100644 --- a/internal/cmd/beta/network-interface/update/update_test.go +++ b/internal/cmd/beta/network-interface/update/update_test.go @@ -291,3 +291,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + projectId string + nic *iaas.NIC + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty nic", + args: args{ + nic: &iaas.NIC{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectId, tt.args.nic); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 84d7fb6ded86a1c1d8836148c475a00aedfd4ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 21 Feb 2025 09:10:59 +0100 Subject: [PATCH 193/619] fix(organization): add nil pointer checks for cmd outputs (#615) relates to STACKITCLI-108 --- internal/cmd/organization/member/add/add.go | 3 +- internal/cmd/organization/member/list/list.go | 15 ++++--- .../cmd/organization/member/list/list_test.go | 42 +++++++++++++++++++ internal/cmd/organization/role/list/list.go | 23 +++++----- .../cmd/organization/role/list/list_test.go | 41 ++++++++++++++++++ 5 files changed, 103 insertions(+), 21 deletions(-) diff --git a/internal/cmd/organization/member/add/add.go b/internal/cmd/organization/member/add/add.go index 523c6ad22..b03ae495f 100644 --- a/internal/cmd/organization/member/add/add.go +++ b/internal/cmd/organization/member/add/add.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -11,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/authorization/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index 65f38a490..e3376d584 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -7,6 +7,7 @@ import ( "sort" "github.com/goccy/go-yaml" + "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" @@ -16,8 +17,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/authorization/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -86,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { members = members[:*model.Limit] } - return outputResult(p, model, members) + return outputResult(p, model.OutputFormat, model.SortBy, members) }, } configureFlags(cmd) @@ -144,9 +143,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *authorizati return req } -func outputResult(p *print.Printer, model *inputModel, members []authorization.Member) error { +func outputResult(p *print.Printer, outputFormat, sortBy string, members []authorization.Member) error { sortFn := func(i, j int) bool { - switch model.SortBy { + switch sortBy { case "subject": return *members[i].Subject < *members[j].Subject case "role": @@ -157,7 +156,7 @@ func outputResult(p *print.Printer, model *inputModel, members []authorization.M } sort.SliceStable(members, sortFn) - switch model.OutputFormat { + switch outputFormat { case print.JSONOutputFormat: // Show details details, err := json.MarshalIndent(members, "", " ") @@ -187,9 +186,9 @@ func outputResult(p *print.Printer, model *inputModel, members []authorization.M table.AddRow(utils.PtrString(m.Subject), utils.PtrString(m.Role)) } - if model.SortBy == "subject" { + if sortBy == "subject" { table.EnableAutoMergeOnColumns(1) - } else if model.SortBy == "role" { + } else if sortBy == "role" { table.EnableAutoMergeOnColumns(2) } diff --git a/internal/cmd/organization/member/list/list_test.go b/internal/cmd/organization/member/list/list_test.go index a740b961c..2c73681c0 100644 --- a/internal/cmd/organization/member/list/list_test.go +++ b/internal/cmd/organization/member/list/list_test.go @@ -204,3 +204,45 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + sortBy string + members []authorization.Member + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty members slice", + args: args{ + members: []authorization.Member{}, + }, + wantErr: false, + }, + { + name: "set empty role in roles slice", + args: args{ + members: []authorization.Member{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.sortBy, tt.args.members); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index 5818142ff..c9e175323 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/authorization/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -153,16 +152,18 @@ func outputRolesResult(p *print.Printer, outputFormat string, roles []authorizat table.SetHeader("ROLE NAME", "ROLE DESCRIPTION", "PERMISSION NAME", "PERMISSION DESCRIPTION") for i := range roles { r := roles[i] - for j := range *r.Permissions { - p := (*r.Permissions)[j] - table.AddRow( - utils.PtrString(r.Name), - utils.PtrString(r.Description), - utils.PtrString(p.Name), - utils.PtrString(p.Description), - ) + if r.Permissions != nil { + for j := range *r.Permissions { + p := (*r.Permissions)[j] + table.AddRow( + utils.PtrString(r.Name), + utils.PtrString(r.Description), + utils.PtrString(p.Name), + utils.PtrString(p.Description), + ) + } + table.AddSeparator() } - table.AddSeparator() } table.EnableAutoMergeOnColumns(1, 2) err := table.Display(p) diff --git a/internal/cmd/organization/role/list/list_test.go b/internal/cmd/organization/role/list/list_test.go index 684ea2e26..1268fb039 100644 --- a/internal/cmd/organization/role/list/list_test.go +++ b/internal/cmd/organization/role/list/list_test.go @@ -167,3 +167,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + roles []authorization.Role + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty roles slice", + args: args{ + roles: []authorization.Role{}, + }, + wantErr: false, + }, + { + name: "set empty role in roles slice", + args: args{ + roles: []authorization.Role{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputRolesResult(p, tt.args.outputFormat, tt.args.roles); (err != nil) != tt.wantErr { + t.Errorf("outputRolesResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 0f5e3a2239d81c53189ce3093fac79e8fee821e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 21 Feb 2025 09:11:15 +0100 Subject: [PATCH 194/619] fix(opensearch): add nil pointer checks for cmd outputs (#616) relates to STACKITCLI-107 --- .../opensearch/credentials/create/create.go | 17 ++-- .../credentials/create/create_test.go | 86 ++++++++++++++++++- .../credentials/describe/describe.go | 4 + .../credentials/describe/describe_test.go | 34 ++++++++ .../opensearch/credentials/list/list_test.go | 41 +++++++++ .../cmd/opensearch/instance/create/create.go | 8 +- .../opensearch/instance/create/create_test.go | 37 ++++++++ .../opensearch/instance/describe/describe.go | 28 +++--- .../instance/describe/describe_test.go | 34 ++++++++ .../cmd/opensearch/instance/list/list_test.go | 41 +++++++++ internal/cmd/opensearch/plans/plans.go | 23 ++--- internal/cmd/opensearch/plans/plans_test.go | 41 +++++++++ 12 files changed, 359 insertions(+), 35 deletions(-) diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index b2e4dde55..9a4174db8 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -15,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/client" opensearchUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -79,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create OpenSearch credentials: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, model.ShowPassword, instanceLabel, resp) }, } configureFlags(cmd) @@ -123,11 +122,15 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *opensearch.CredentialsResponse) error { - if !model.ShowPassword { +func outputResult(p *print.Printer, outputFormat string, showPassword bool, instanceLabel string, resp *opensearch.CredentialsResponse) error { + if resp == nil || resp.Raw == nil || resp.Raw.Credentials == nil || resp.Uri == nil { + return fmt.Errorf("response or response content is nil") + } + + if !showPassword { resp.Raw.Credentials.Password = utils.Ptr("hidden") } - switch model.OutputFormat { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -151,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res if username := resp.Raw.Credentials.Username; username != nil && *username != "" { p.Outputf("Username: %s\n", *username) } - if !model.ShowPassword { + if !showPassword { p.Outputf("Password: \n") } else { p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) diff --git a/internal/cmd/opensearch/credentials/create/create_test.go b/internal/cmd/opensearch/credentials/create/create_test.go index cd8559b64..1424c9729 100644 --- a/internal/cmd/opensearch/credentials/create/create_test.go +++ b/internal/cmd/opensearch/credentials/create/create_test.go @@ -4,12 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -200,3 +200,83 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + showPassword bool + instanceLabel string + resp *opensearch.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set no raw in response", + args: args{ + resp: &opensearch.CredentialsResponse{ + Uri: utils.Ptr("https://opensearch.example.com"), + }, + }, + wantErr: true, + }, + { + name: "set empty raw in response", + args: args{ + resp: &opensearch.CredentialsResponse{ + Raw: &opensearch.RawCredentials{}, + Uri: utils.Ptr("https://opensearch.example.com"), + }, + }, + wantErr: true, + }, + { + name: "set raw but no uri in response", + args: args{ + resp: &opensearch.CredentialsResponse{ + Raw: &opensearch.RawCredentials{ + Credentials: &opensearch.Credentials{}, + }, + }, + }, + wantErr: true, + }, + { + name: "set uri but no raw in response", + args: args{ + resp: &opensearch.CredentialsResponse{ + Uri: utils.Ptr("https://opensearch.example.com"), + }, + }, + wantErr: true, + }, + { + name: "set response correctly", + args: args{ + resp: &opensearch.CredentialsResponse{ + Raw: &opensearch.RawCredentials{ + Credentials: &opensearch.Credentials{}, + }, + Uri: utils.Ptr("https://opensearch.example.com"), + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index 64817d66a..fb8012012 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -112,6 +112,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. } func outputResult(p *print.Printer, outputFormat string, credentials *opensearch.CredentialsResponse) error { + if credentials == nil { + return fmt.Errorf("credentials is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(credentials, "", " ") diff --git a/internal/cmd/opensearch/credentials/describe/describe_test.go b/internal/cmd/opensearch/credentials/describe/describe_test.go index 30fb04ded..3618a4cc7 100644 --- a/internal/cmd/opensearch/credentials/describe/describe_test.go +++ b/internal/cmd/opensearch/credentials/describe/describe_test.go @@ -243,3 +243,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials *opensearch.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty credentials", + args: args{ + credentials: &opensearch.CredentialsResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/credentials/list/list_test.go b/internal/cmd/opensearch/credentials/list/list_test.go index 44336f34b..d6b041f57 100644 --- a/internal/cmd/opensearch/credentials/list/list_test.go +++ b/internal/cmd/opensearch/credentials/list/list_test.go @@ -207,3 +207,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []opensearch.CredentialsListItem + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty credentials slice", + args: args{ + credentials: []opensearch.CredentialsListItem{}, + }, + wantErr: false, + }, + { + name: "set empty credential in credentials slice", + args: args{ + credentials: []opensearch.CredentialsListItem{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index d6eeaf951..62d447f82 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -127,7 +127,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, instanceId, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -256,8 +256,8 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel, instanceId string, resp *opensearch.CreateInstanceResponse) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -276,7 +276,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) diff --git a/internal/cmd/opensearch/instance/create/create_test.go b/internal/cmd/opensearch/instance/create/create_test.go index 7fd34113f..3aceed814 100644 --- a/internal/cmd/opensearch/instance/create/create_test.go +++ b/internal/cmd/opensearch/instance/create/create_test.go @@ -488,3 +488,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + instanceId string + resp *opensearch.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + resp: &opensearch.CreateInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index fffdc1f86..1358aef39 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -100,6 +100,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. } func outputResult(p *print.Printer, outputFormat string, instance *opensearch.Instance) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -123,18 +127,22 @@ func outputResult(p *print.Printer, outputFormat string, instance *opensearch.In table.AddSeparator() table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) - table.AddSeparator() - table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) - table.AddSeparator() + if instance.LastOperation != nil { + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) + table.AddSeparator() + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) + table.AddSeparator() + } table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty - acl := (*instance.Parameters)[aclParameterKey] - aclStr, ok := acl.(string) - if ok { - if aclStr != "" { - table.AddSeparator() - table.AddRow("ACL", aclStr) + if instance.Parameters != nil { + acl := (*instance.Parameters)[aclParameterKey] + aclStr, ok := acl.(string) + if ok { + if aclStr != "" { + table.AddSeparator() + table.AddRow("ACL", aclStr) + } } } err := table.Display(p) diff --git a/internal/cmd/opensearch/instance/describe/describe_test.go b/internal/cmd/opensearch/instance/describe/describe_test.go index b7c27a2b7..d4b58656f 100644 --- a/internal/cmd/opensearch/instance/describe/describe_test.go +++ b/internal/cmd/opensearch/instance/describe/describe_test.go @@ -216,3 +216,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *opensearch.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty instance", + args: args{ + instance: &opensearch.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/instance/list/list_test.go b/internal/cmd/opensearch/instance/list/list_test.go index 4036a79b7..baa22ac9f 100644 --- a/internal/cmd/opensearch/instance/list/list_test.go +++ b/internal/cmd/opensearch/instance/list/list_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instances []opensearch.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty instances slice", + args: args{ + instances: []opensearch.Instance{}, + }, + wantErr: false, + }, + { + name: "set empty instance in instances slice", + args: args{ + instances: []opensearch.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index 50be3aae8..013e486e1 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "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" @@ -16,8 +17,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -153,15 +152,17 @@ func outputResult(p *print.Printer, outputFormat string, plans []opensearch.Offe table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { o := plans[i] - for j := range *o.Plans { - plan := (*o.Plans)[j] - table.AddRow( - utils.PtrString(o.Name), - utils.PtrString(o.Version), - utils.PtrString(plan.Id), - utils.PtrString(plan.Name), - utils.PtrString(plan.Description), - ) + if o.Plans != nil { + for j := range *o.Plans { + plan := (*o.Plans)[j] + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + ) + } } table.AddSeparator() } diff --git a/internal/cmd/opensearch/plans/plans_test.go b/internal/cmd/opensearch/plans/plans_test.go index bff8c20ef..a1d162d4a 100644 --- a/internal/cmd/opensearch/plans/plans_test.go +++ b/internal/cmd/opensearch/plans/plans_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + plans []opensearch.Offering + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty plans slice", + args: args{ + plans: []opensearch.Offering{}, + }, + wantErr: false, + }, + { + name: "set empty plan in plans slice", + args: args{ + plans: []opensearch.Offering{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 22b1f747b77172a0c90d96538973ca5d5365f3f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 21 Feb 2025 09:11:36 +0100 Subject: [PATCH 195/619] fix(mongodbflex): add nil pointer checks for cmd outputs (#614) relates to STACKITCLI-104 --- .../mongodbflex/backup/describe/describe.go | 6 +- .../backup/describe/describe_test.go | 35 +++++ internal/cmd/mongodbflex/backup/list/list.go | 4 + .../cmd/mongodbflex/backup/list/list_test.go | 50 ++++++ .../backup/restore-jobs/restore_jobs_test.go | 41 +++++ .../mongodbflex/backup/schedule/schedule.go | 43 +++--- .../backup/schedule/schedule_test.go | 34 +++++ .../cmd/mongodbflex/instance/create/create.go | 15 +- .../instance/create/create_test.go | 36 +++++ .../mongodbflex/instance/describe/describe.go | 43 ++++-- .../instance/describe/describe_test.go | 34 +++++ .../mongodbflex/instance/list/list_test.go | 41 +++++ .../cmd/mongodbflex/instance/update/update.go | 12 +- .../instance/update/update_test.go | 36 +++++ internal/cmd/mongodbflex/options/options.go | 10 ++ .../cmd/mongodbflex/options/options_test.go | 142 ++++++++++++++++++ .../cmd/mongodbflex/user/create/create.go | 10 +- .../mongodbflex/user/create/create_test.go | 35 +++++ .../user/describe/describe_test.go | 34 +++++ .../cmd/mongodbflex/user/list/list_test.go | 41 +++++ .../user/reset-password/reset_password.go | 10 +- .../reset-password/reset_password_test.go | 36 +++++ 22 files changed, 694 insertions(+), 54 deletions(-) diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index b675b69ee..a30fb3f63 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -80,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } restoreJobState := mongoUtils.GetRestoreStatus(model.BackupId, restoreJobs) - return outputResult(p, cmd, model.OutputFormat, restoreJobState, *resp.Item) + return outputResult(p, model.OutputFormat, restoreJobState, *resp.Item) }, } configureFlags(cmd) @@ -125,14 +125,14 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex return req } -func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat, restoreStatus string, backup mongodbflex.Backup) error { +func outputResult(p *print.Printer, outputFormat, restoreStatus string, backup mongodbflex.Backup) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(backup, "", " ") if err != nil { return fmt.Errorf("marshal MongoDB Flex backup: %w", err) } - cmd.Println(string(details)) + p.Outputln(string(details)) return nil case print.YAMLOutputFormat: diff --git a/internal/cmd/mongodbflex/backup/describe/describe_test.go b/internal/cmd/mongodbflex/backup/describe/describe_test.go index 1d6dc44e4..0b761904d 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe_test.go +++ b/internal/cmd/mongodbflex/backup/describe/describe_test.go @@ -237,3 +237,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + backup mongodbflex.Backup + restoreStatus string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set backup", + args: args{ + backup: mongodbflex.Backup{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.restoreStatus, tt.args.backup); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index 1b251571a..b145685fb 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -145,6 +145,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex } func outputResult(p *print.Printer, outputFormat string, backups []mongodbflex.Backup, restoreJobs *mongodbflex.ListRestoreJobsResponse) error { + if restoreJobs == nil { + return fmt.Errorf("restore jobs is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(backups, "", " ") diff --git a/internal/cmd/mongodbflex/backup/list/list_test.go b/internal/cmd/mongodbflex/backup/list/list_test.go index 82de1efca..362b35c78 100644 --- a/internal/cmd/mongodbflex/backup/list/list_test.go +++ b/internal/cmd/mongodbflex/backup/list/list_test.go @@ -207,3 +207,53 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + backups []mongodbflex.Backup + restoreJobs *mongodbflex.ListRestoreJobsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty backups", + args: args{ + backups: []mongodbflex.Backup{}, + }, + wantErr: true, + }, + { + name: "set restore jobs", + args: args{ + restoreJobs: &mongodbflex.ListRestoreJobsResponse{}, + }, + wantErr: false, + }, + { + name: "set restore jobs and empty backups", + args: args{ + backups: []mongodbflex.Backup{}, + restoreJobs: &mongodbflex.ListRestoreJobsResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.backups, tt.args.restoreJobs); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go index c7c5ec84a..5135be262 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go @@ -207,3 +207,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + restoreJobs []mongodbflex.RestoreInstanceStatus + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty restore jobs", + args: args{ + restoreJobs: []mongodbflex.RestoreInstanceStatus{}, + }, + wantErr: false, + }, + { + name: "set empty restore job", + args: args{ + restoreJobs: []mongodbflex.RestoreInstanceStatus{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.restoreJobs); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index 9445055a6..b21167724 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -104,6 +104,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex } func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.Instance) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + output := struct { BackupSchedule string `json:"backup_schedule"` DailySnaphotRetentionDays string `json:"daily_snapshot_retention_days"` @@ -112,12 +116,14 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I SnapshotRetentionDays string `json:"snapshot_retention_days"` WeeklySnapshotRetentionWeeks string `json:"weekly_snapshot_retention_weeks"` }{ - BackupSchedule: *instance.BackupSchedule, - DailySnaphotRetentionDays: (*instance.Options)["dailySnapshotRetentionDays"], - MonthlySnapshotRetentionMonths: (*instance.Options)["monthlySnapshotRetentionDays"], - PointInTimeWindowHours: (*instance.Options)["pointInTimeWindowHours"], - SnapshotRetentionDays: (*instance.Options)["snapshotRetentionDays"], - WeeklySnapshotRetentionWeeks: (*instance.Options)["weeklySnapshotRetentionWeeks"], + BackupSchedule: utils.PtrString(instance.BackupSchedule), + } + if instance.Options != nil { + output.DailySnaphotRetentionDays = (*instance.Options)["dailySnapshotRetentionDays"] + output.MonthlySnapshotRetentionMonths = (*instance.Options)["monthlySnapshotRetentionDays"] + output.PointInTimeWindowHours = (*instance.Options)["pointInTimeWindowHours"] + output.SnapshotRetentionDays = (*instance.Options)["snapshotRetentionDays"] + output.WeeklySnapshotRetentionWeeks = (*instance.Options)["weeklySnapshotRetentionWeeks"] } switch outputFormat { @@ -139,20 +145,19 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I return nil default: table := tables.NewTable() - table.AddRow("BACKUP SCHEDULE (UTC)", utils.PtrString(instance.BackupSchedule)) + table.AddRow("BACKUP SCHEDULE (UTC)", output.BackupSchedule) table.AddSeparator() - if instance.Options != nil { - table.AddRow("DAILY SNAPSHOT RETENTION (DAYS)", (*instance.Options)["dailySnapshotRetentionDays"]) - table.AddSeparator() - table.AddRow("MONTHLY SNAPSHOT RETENTION (MONTHS)", (*instance.Options)["monthlySnapshotRetentionMonths"]) - table.AddSeparator() - table.AddRow("POINT IN TIME WINDOW (HOURS)", (*instance.Options)["pointInTimeWindowHours"]) - table.AddSeparator() - table.AddRow("SNAPSHOT RETENTION (DAYS)", (*instance.Options)["snapshotRetentionDays"]) - table.AddSeparator() - table.AddRow("WEEKLY SNAPSHOT RETENTION (WEEKS)", (*instance.Options)["weeklySnapshotRetentionWeeks"]) - table.AddSeparator() - } + table.AddRow("DAILY SNAPSHOT RETENTION (DAYS)", output.DailySnaphotRetentionDays) + table.AddSeparator() + table.AddRow("MONTHLY SNAPSHOT RETENTION (MONTHS)", output.MonthlySnapshotRetentionMonths) + table.AddSeparator() + table.AddRow("POINT IN TIME WINDOW (HOURS)", output.PointInTimeWindowHours) + table.AddSeparator() + table.AddRow("SNAPSHOT RETENTION (DAYS)", output.SnapshotRetentionDays) + table.AddSeparator() + table.AddRow("WEEKLY SNAPSHOT RETENTION (WEEKS)", output.WeeklySnapshotRetentionWeeks) + table.AddSeparator() + err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go index e25957058..018cefc28 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go @@ -193,3 +193,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *mongodbflex.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty instance", + args: args{ + instance: &mongodbflex.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index d601a92a9..c6c4d3322 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -18,8 +19,6 @@ import ( mongodbflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/mongodbflex/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex/wait" ) @@ -133,7 +132,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) @@ -273,8 +272,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, resp *mongodbflex.CreateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("create instance response is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -293,7 +296,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Id)) diff --git a/internal/cmd/mongodbflex/instance/create/create_test.go b/internal/cmd/mongodbflex/instance/create/create_test.go index 712718e95..23fa109b7 100644 --- a/internal/cmd/mongodbflex/instance/create/create_test.go +++ b/internal/cmd/mongodbflex/instance/create/create_test.go @@ -546,3 +546,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + createInstanceResponse *mongodbflex.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty create instance response", + args: args{ + createInstanceResponse: &mongodbflex.CreateInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.createInstanceResponse); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index ca4858da5..79ca55b64 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -100,6 +100,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex } func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.Instance) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -118,28 +122,35 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I return nil default: - aclsArray := *instance.Acl.Items - acls := strings.Join(aclsArray, ",") - - instanceType, err := mongodbflexUtils.GetInstanceType(*instance.Replicas) - if err != nil { - // Should never happen - instanceType = "" + var instanceType string + if instance.HasReplicas() { + var err error + instanceType, err = mongodbflexUtils.GetInstanceType(*instance.Replicas) + if err != nil { + // Should never happen + instanceType = "" + } } table := tables.NewTable() - table.AddRow("ID", *instance.Id) + table.AddRow("ID", utils.PtrString(instance.Id)) table.AddSeparator() - table.AddRow("NAME", *instance.Name) + table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("STATUS", *instance.Status) + table.AddRow("STATUS", utils.PtrString(instance.Status)) table.AddSeparator() - table.AddRow("STORAGE SIZE (GB)", *instance.Storage.Size) - table.AddSeparator() - table.AddRow("VERSION", *instance.Version) - table.AddSeparator() - table.AddRow("ACL", acls) + if instance.HasStorage() { + table.AddRow("STORAGE SIZE (GB)", utils.PtrString(instance.Storage.Size)) + table.AddSeparator() + } + table.AddRow("VERSION", utils.PtrString(instance.Version)) table.AddSeparator() + if instance.HasAcl() { + aclsArray := *instance.Acl.Items + acls := strings.Join(aclsArray, ",") + table.AddRow("ACL", acls) + table.AddSeparator() + } if instance.HasFlavor() && instance.Flavor.HasDescription() { table.AddRow("FLAVOR DESCRIPTION", *instance.Flavor.Description) table.AddSeparator() @@ -158,7 +169,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I } table.AddRow("BACKUP SCHEDULE (UTC)", utils.PtrString(instance.BackupSchedule)) table.AddSeparator() - err = table.Display(p) + err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) } diff --git a/internal/cmd/mongodbflex/instance/describe/describe_test.go b/internal/cmd/mongodbflex/instance/describe/describe_test.go index dbdb934f7..1238f7bc0 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe_test.go +++ b/internal/cmd/mongodbflex/instance/describe/describe_test.go @@ -216,3 +216,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *mongodbflex.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty instance", + args: args{ + instance: &mongodbflex.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/instance/list/list_test.go b/internal/cmd/mongodbflex/instance/list/list_test.go index c8e8716d5..e6a9c1416 100644 --- a/internal/cmd/mongodbflex/instance/list/list_test.go +++ b/internal/cmd/mongodbflex/instance/list/list_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instanceList []mongodbflex.InstanceListInstance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty instance list slice", + args: args{ + instanceList: []mongodbflex.InstanceListInstance{}, + }, + wantErr: false, + }, + { + name: "empty instance in instance list slice", + args: args{ + instanceList: []mongodbflex.InstanceListInstance{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceList); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index 68f2f85ba..5f854005c 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -118,7 +118,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, model.Async, instanceLabel, resp) }, } configureFlags(cmd) @@ -307,8 +307,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, async bool, instanceLabel string, resp *mongodbflex.UpdateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("resp is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -327,7 +331,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: operationState := "Updated" - if model.Async { + if async { operationState = "Triggered update of" } p.Info("%s instance %q\n", operationState, instanceLabel) diff --git a/internal/cmd/mongodbflex/instance/update/update_test.go b/internal/cmd/mongodbflex/instance/update/update_test.go index 6e15e4408..a36f33454 100644 --- a/internal/cmd/mongodbflex/instance/update/update_test.go +++ b/internal/cmd/mongodbflex/instance/update/update_test.go @@ -590,3 +590,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + instanceLabel string + resp *mongodbflex.UpdateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty response", + args: args{ + resp: &mongodbflex.UpdateInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 1b869a5c1..82b43cbc5 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -170,6 +170,10 @@ func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputM } func outputResult(p *print.Printer, model *inputModel, flavors *mongodbflex.ListFlavorsResponse, versions *mongodbflex.ListVersionsResponse, storages *mongodbflex.ListStoragesResponse) error { + if model == nil || model.GlobalFlagModel == nil { + return fmt.Errorf("model is nil") + } + options := &options{} if flavors != nil { options.Flavors = flavors.Flavors @@ -206,6 +210,12 @@ func outputResult(p *print.Printer, model *inputModel, flavors *mongodbflex.List } func outputResultAsTable(p *print.Printer, model *inputModel, options *options) error { + if model == nil { + return fmt.Errorf("model is nil") + } else if options == nil { + return fmt.Errorf("options is nil") + } + content := []tables.Table{} if model.Flavors && len(*options.Flavors) != 0 { content = append(content, buildFlavorsTable(*options.Flavors)) diff --git a/internal/cmd/mongodbflex/options/options_test.go b/internal/cmd/mongodbflex/options/options_test.go index d750bc6e1..9b48a710b 100644 --- a/internal/cmd/mongodbflex/options/options_test.go +++ b/internal/cmd/mongodbflex/options/options_test.go @@ -322,3 +322,145 @@ func TestBuildAndExecuteRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + inputModel *inputModel + flavors *mongodbflex.ListFlavorsResponse + versions *mongodbflex.ListVersionsResponse + storages *mongodbflex.ListStoragesResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "missing model", + args: args{ + flavors: &mongodbflex.ListFlavorsResponse{}, + versions: &mongodbflex.ListVersionsResponse{}, + storages: &mongodbflex.ListStoragesResponse{}, + }, + wantErr: true, + }, + { + name: "empty model", + args: args{ + inputModel: &inputModel{}, + flavors: &mongodbflex.ListFlavorsResponse{}, + versions: &mongodbflex.ListVersionsResponse{}, + storages: &mongodbflex.ListStoragesResponse{}, + }, + wantErr: true, + }, + { + name: "ok", + args: args{ + inputModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + flavors: &mongodbflex.ListFlavorsResponse{}, + versions: &mongodbflex.ListVersionsResponse{}, + storages: &mongodbflex.ListStoragesResponse{}, + }, + wantErr: false, + }, + { + name: "missing flavors", + args: args{ + inputModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + versions: &mongodbflex.ListVersionsResponse{}, + storages: &mongodbflex.ListStoragesResponse{}, + }, + wantErr: false, + }, + { + name: "missing versions", + args: args{ + inputModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + flavors: &mongodbflex.ListFlavorsResponse{}, + storages: &mongodbflex.ListStoragesResponse{}, + }, + wantErr: false, + }, + { + name: "missing storages", + args: args{ + inputModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + flavors: &mongodbflex.ListFlavorsResponse{}, + versions: &mongodbflex.ListVersionsResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.inputModel, tt.args.flavors, tt.args.versions, tt.args.storages); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOutputResultAsTable(t *testing.T) { + type args struct { + model *inputModel + options *options + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "missing input model", + args: args{ + options: &options{}, + }, + wantErr: true, + }, + { + name: "missing options", + args: args{ + model: &inputModel{}, + }, + wantErr: true, + }, + { + name: "empty input model and empty options", + args: args{ + model: &inputModel{}, + options: &options{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResultAsTable(p, tt.args.model, tt.args.options); (err != nil) != tt.wantErr { + t.Errorf("outputResultAsTable() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index cd383eac2..be494fcdb 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -93,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } user := resp.Item - return outputResult(p, model, instanceLabel, user) + return outputResult(p, model.OutputFormat, instanceLabel, user) }, } @@ -149,8 +149,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, user *mongodbflex.User) error { + if user == nil { + return fmt.Errorf("user is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") if err != nil { diff --git a/internal/cmd/mongodbflex/user/create/create_test.go b/internal/cmd/mongodbflex/user/create/create_test.go index de4ab99dc..73f184a65 100644 --- a/internal/cmd/mongodbflex/user/create/create_test.go +++ b/internal/cmd/mongodbflex/user/create/create_test.go @@ -244,3 +244,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instanceLabel string + user *mongodbflex.User + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty user", + args: args{ + user: &mongodbflex.User{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/user/describe/describe_test.go b/internal/cmd/mongodbflex/user/describe/describe_test.go index c729e1c8e..7d5201075 100644 --- a/internal/cmd/mongodbflex/user/describe/describe_test.go +++ b/internal/cmd/mongodbflex/user/describe/describe_test.go @@ -243,3 +243,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instanceResponseUser mongodbflex.InstanceResponseUser + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty user", + args: args{ + instanceResponseUser: mongodbflex.InstanceResponseUser{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceResponseUser); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/user/list/list_test.go b/internal/cmd/mongodbflex/user/list/list_test.go index 6c1b85424..8cc901aef 100644 --- a/internal/cmd/mongodbflex/user/list/list_test.go +++ b/internal/cmd/mongodbflex/user/list/list_test.go @@ -203,3 +203,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + users []mongodbflex.ListUser + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty user slice", + args: args{ + users: []mongodbflex.ListUser{}, + }, + wantErr: false, + }, + { + name: "empty user in user slice", + args: args{ + users: []mongodbflex.ListUser{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index f35c252f3..5541b89a3 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -87,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("reset MongoDB Flex user password: %w", err) } - return outputResult(p, model, userLabel, instanceLabel, user) + return outputResult(p, model.OutputFormat, userLabel, instanceLabel, user) }, } @@ -133,8 +133,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex return req } -func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel string, user *mongodbflex.User) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, userLabel, instanceLabel string, user *mongodbflex.User) error { + if user == nil { + return fmt.Errorf("user is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") if err != nil { diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go index c477b7fa8..98abb2136 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go @@ -243,3 +243,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + userLabel string + instanceLabel string + user *mongodbflex.User + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty user", + args: args{ + user: &mongodbflex.User{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.userLabel, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From fdc925fa3b445bad62b8d9c3110a836c8653eefe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 21 Feb 2025 09:11:51 +0100 Subject: [PATCH 196/619] fix(observability): add nil pointer checks for cmd outputs (#617) relates to STACKITCLI-106 --- .../credentials/create/create.go | 21 +++--- .../credentials/create/create_test.go | 46 +++++++++++++ .../credentials/list/list_test.go | 42 +++++++++++ .../grafana/describe/describe.go | 16 +++-- .../grafana/describe/describe_test.go | 55 +++++++++++++++ .../observability/instance/create/create.go | 12 ++-- .../instance/create/create_test.go | 36 ++++++++++ .../instance/describe/describe.go | 4 ++ .../instance/describe/describe_test.go | 34 +++++++++ .../observability/instance/list/list_test.go | 41 +++++++++++ .../cmd/observability/plans/plans_test.go | 41 +++++++++++ .../scrape-config/describe/describe.go | 34 +++++---- .../scrape-config/describe/describe_test.go | 35 ++++++++++ .../generate-payload/generate_payload.go | 8 +++ .../generate-payload/generate_payload_test.go | 69 +++++++++++++++++++ .../scrape-config/list/list_test.go | 42 +++++++++++ 16 files changed, 505 insertions(+), 31 deletions(-) diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index b965364a3..9852ee352 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -79,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create credentials for Observability instance: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, instanceLabel, resp) }, } configureFlags(cmd) @@ -110,8 +110,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *observabili return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *observability.CreateCredentialsResponse) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, resp *observability.CreateCredentialsResponse) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -130,13 +134,14 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: p.Outputf("Created credentials for instance %q.\n\n", instanceLabel) - // The username field cannot be set by the user, so we only display it if it's not returned empty - username := *resp.Credentials.Username - if username != "" { - p.Outputf("Username: %s\n", username) - } if resp.Credentials != nil { + // The username field cannot be set by the user, so we only display it if it's not returned empty + username := *resp.Credentials.Username + if username != "" { + p.Outputf("Username: %s\n", username) + } + p.Outputf("Password: %s\n", utils.PtrString(resp.Credentials.Password)) } return nil diff --git a/internal/cmd/observability/credentials/create/create_test.go b/internal/cmd/observability/credentials/create/create_test.go index 395876a4f..146fc9090 100644 --- a/internal/cmd/observability/credentials/create/create_test.go +++ b/internal/cmd/observability/credentials/create/create_test.go @@ -5,6 +5,8 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/observability" "github.com/google/go-cmp/cmp" @@ -188,3 +190,47 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instanceLabel string + resp *observability.CreateCredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty response", + args: args{ + resp: &observability.CreateCredentialsResponse{}, + }, + wantErr: false, + }, + { + name: "set response with credentials", + args: args{ + resp: &observability.CreateCredentialsResponse{ + Credentials: observability.NewCredentials(utils.Ptr("dummy-pw"), utils.Ptr("dummy-user")), + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/credentials/list/list_test.go b/internal/cmd/observability/credentials/list/list_test.go index 3d188dba3..fa23d5dfe 100644 --- a/internal/cmd/observability/credentials/list/list_test.go +++ b/internal/cmd/observability/credentials/list/list_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" @@ -205,3 +206,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []observability.ServiceKeysList + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty credentials slice", + args: args{ + credentials: []observability.ServiceKeysList{}, + }, + wantErr: false, + }, + { + name: "set empty credential in credentials slice", + args: args{ + credentials: []observability.ServiceKeysList{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index 245a4b8b4..9a364499c 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -77,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get instance: %w", err) } - return outputResult(p, model, grafanaConfigsResp, instanceResp) + return outputResult(p, model.OutputFormat, model.ShowPassword, grafanaConfigsResp, instanceResp) }, } configureFlags(cmd) @@ -124,8 +124,14 @@ func buildGetInstanceRequest(ctx context.Context, model *inputModel, apiClient * return req } -func outputResult(p *print.Printer, inputModel *inputModel, grafanaConfigs *observability.GrafanaConfigs, instance *observability.GetInstanceResponse) error { - switch inputModel.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, showPassword bool, grafanaConfigs *observability.GrafanaConfigs, instance *observability.GetInstanceResponse) error { + if instance == nil || instance.Instance == nil { + return fmt.Errorf("instance or instance content is nil") + } else if grafanaConfigs == nil { + return fmt.Errorf("grafanaConfigs is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(grafanaConfigs, "", " ") if err != nil { @@ -143,8 +149,8 @@ func outputResult(p *print.Printer, inputModel *inputModel, grafanaConfigs *obse return nil default: - initialAdminPassword := *instance.Instance.GrafanaAdminPassword - if !inputModel.ShowPassword { + initialAdminPassword := utils.PtrString(instance.Instance.GrafanaAdminPassword) + if !showPassword { initialAdminPassword = "" } diff --git a/internal/cmd/observability/grafana/describe/describe_test.go b/internal/cmd/observability/grafana/describe/describe_test.go index d2b2daec0..f282c2964 100644 --- a/internal/cmd/observability/grafana/describe/describe_test.go +++ b/internal/cmd/observability/grafana/describe/describe_test.go @@ -276,3 +276,58 @@ func TestBuildGetInstanceRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + showPassword bool + grafanaConfig *observability.GrafanaConfigs + instance *observability.GetInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set grafana configs but no instance", + args: args{ + grafanaConfig: &observability.GrafanaConfigs{}, + }, + wantErr: true, + }, + { + name: "set instance but no grafana config", + args: args{ + instance: &observability.GetInstanceResponse{ + Instance: &observability.InstanceSensitiveData{}, + }, + }, + wantErr: true, + }, + { + name: "set instance and grafana configs", + args: args{ + grafanaConfig: &observability.GrafanaConfigs{}, + instance: &observability.GetInstanceResponse{ + Instance: &observability.InstanceSensitiveData{}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, tt.args.grafanaConfig, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 99b7fe5f2..57e9d888f 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -105,7 +105,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) @@ -200,8 +200,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient observabilit return req, nil } -func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *observability.CreateInstanceResponse) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, resp *observability.CreateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("resp is empty") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -220,7 +224,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) diff --git a/internal/cmd/observability/instance/create/create_test.go b/internal/cmd/observability/instance/create/create_test.go index 505a03be5..f36d5ae8a 100644 --- a/internal/cmd/observability/instance/create/create_test.go +++ b/internal/cmd/observability/instance/create/create_test.go @@ -334,3 +334,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + resp *observability.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty response", + args: args{ + resp: &observability.CreateInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go index 3b4a62e40..157bd28a4 100644 --- a/internal/cmd/observability/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -98,6 +98,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *observabili } func outputResult(p *print.Printer, outputFormat string, instance *observability.GetInstanceResponse) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") diff --git a/internal/cmd/observability/instance/describe/describe_test.go b/internal/cmd/observability/instance/describe/describe_test.go index f2eea2b4d..c55020fa7 100644 --- a/internal/cmd/observability/instance/describe/describe_test.go +++ b/internal/cmd/observability/instance/describe/describe_test.go @@ -216,3 +216,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *observability.GetInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty instance", + args: args{ + instance: &observability.GetInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/instance/list/list_test.go b/internal/cmd/observability/instance/list/list_test.go index 649f70e55..e8a87f48a 100644 --- a/internal/cmd/observability/instance/list/list_test.go +++ b/internal/cmd/observability/instance/list/list_test.go @@ -185,3 +185,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instances []observability.ProjectInstanceFull + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty instances slice", + args: args{ + instances: []observability.ProjectInstanceFull{}, + }, + wantErr: false, + }, + { + name: "empty instance in instances slice", + args: args{ + instances: []observability.ProjectInstanceFull{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/plans/plans_test.go b/internal/cmd/observability/plans/plans_test.go index 3c978a3a7..047c3c5f6 100644 --- a/internal/cmd/observability/plans/plans_test.go +++ b/internal/cmd/observability/plans/plans_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + plans []observability.Plan + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty plans slice", + args: args{ + plans: []observability.Plan{}, + }, + wantErr: false, + }, + { + name: "empty plan in plans slice", + args: args{ + plans: []observability.Plan{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/scrape-config/describe/describe.go b/internal/cmd/observability/scrape-config/describe/describe.go index 7e92bd58f..2687a72a3 100644 --- a/internal/cmd/observability/scrape-config/describe/describe.go +++ b/internal/cmd/observability/scrape-config/describe/describe.go @@ -100,6 +100,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *observabili } func outputResult(p *print.Printer, outputFormat string, config *observability.Job) error { + if config == nil { + return fmt.Errorf(`config is nil`) + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(config, "", " ") @@ -127,23 +131,25 @@ func outputResult(p *print.Printer, outputFormat string, config *observability.J } var targets []string - for _, target := range *config.StaticConfigs { - targetLabels := []string{} - targetLabelStr := "N/A" - if target.Labels != nil { - // make map prettier - for k, v := range *target.Labels { - targetLabels = append(targetLabels, fmt.Sprintf("%s:%s", k, v)) + if config.StaticConfigs != nil { + for _, target := range *config.StaticConfigs { + targetLabels := []string{} + targetLabelStr := "N/A" + if target.Labels != nil { + // make map prettier + for k, v := range *target.Labels { + targetLabels = append(targetLabels, fmt.Sprintf("%s:%s", k, v)) + } + if targetLabels != nil { + targetLabelStr = strings.Join(targetLabels, ",") + } } - if targetLabels != nil { - targetLabelStr = strings.Join(targetLabels, ",") + targetUrlsStr := "N/A" + if target.Targets != nil { + targetUrlsStr = strings.Join(*target.Targets, ",") } + targets = append(targets, fmt.Sprintf("labels: %s\nurls: %s", targetLabelStr, targetUrlsStr)) } - targetUrlsStr := "N/A" - if target.Targets != nil { - targetUrlsStr = strings.Join(*target.Targets, ",") - } - targets = append(targets, fmt.Sprintf("labels: %s\nurls: %s", targetLabelStr, targetUrlsStr)) } table := tables.NewTable() diff --git a/internal/cmd/observability/scrape-config/describe/describe_test.go b/internal/cmd/observability/scrape-config/describe/describe_test.go index f496da426..a0cf31413 100644 --- a/internal/cmd/observability/scrape-config/describe/describe_test.go +++ b/internal/cmd/observability/scrape-config/describe/describe_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -231,3 +232,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + config *observability.Job + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty config", + args: args{ + config: &observability.Job{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.config); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go index 363070be8..fe8a9f5ec 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go @@ -125,6 +125,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *observabili } func outputCreateResult(p *print.Printer, filePath *string, payload *observability.CreateScrapeConfigPayload) error { + if payload == nil { + return fmt.Errorf("payload is nil") + } + payloadBytes, err := json.MarshalIndent(*payload, "", " ") if err != nil { return fmt.Errorf("marshal payload: %w", err) @@ -143,6 +147,10 @@ func outputCreateResult(p *print.Printer, filePath *string, payload *observabili } func outputUpdateResult(p *print.Printer, filePath *string, payload *observability.UpdateScrapeConfigPayload) error { + if payload == nil { + return fmt.Errorf("payload is nil") + } + payloadBytes, err := json.MarshalIndent(*payload, "", " ") if err != nil { return fmt.Errorf("marshal payload: %w", err) diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go index e23f4fabc..b8740da53 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" @@ -248,3 +249,71 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputCreateResult(t *testing.T) { + type args struct { + filePath *string + payload *observability.CreateScrapeConfigPayload + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty payload", + args: args{ + payload: &observability.CreateScrapeConfigPayload{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputCreateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { + t.Errorf("outputCreateResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOutputUpdateResult(t *testing.T) { + type args struct { + filePath *string + payload *observability.UpdateScrapeConfigPayload + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty payload", + args: args{ + payload: &observability.UpdateScrapeConfigPayload{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputUpdateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { + t.Errorf("outputUpdateResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/observability/scrape-config/list/list_test.go b/internal/cmd/observability/scrape-config/list/list_test.go index 86836fc84..69e5b6ab5 100644 --- a/internal/cmd/observability/scrape-config/list/list_test.go +++ b/internal/cmd/observability/scrape-config/list/list_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" @@ -208,3 +209,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + configs []observability.Job + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty configs slice", + args: args{ + configs: []observability.Job{}, + }, + wantErr: false, + }, + { + name: "empty config in configs slice", + args: args{ + configs: []observability.Job{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.configs); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 1c79c47d5d644a132648253f46e185408c18c77a Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 21 Feb 2025 09:16:30 +0100 Subject: [PATCH 197/619] chore(security-group): Add nil pointer checks and tests for the outputResult functions (#613) Signed-off-by: Alexander Dahmen --- .../cmd/beta/security-group/create/create.go | 8 ++-- .../beta/security-group/create/create_test.go | 35 +++++++++++++-- .../beta/security-group/describe/describe.go | 9 ++-- .../security-group/describe/describe_test.go | 39 ++++++++++++++-- .../cmd/beta/security-group/list/list_test.go | 34 ++++++++++++-- .../beta/security-group/rule/create/create.go | 3 ++ .../security-group/rule/create/create_test.go | 44 +++++++++++++++++-- .../security-group/rule/describe/describe.go | 3 ++ .../rule/describe/describe_test.go | 41 +++++++++++++++-- .../security-group/rule/list/list_test.go | 34 ++++++++++++-- 10 files changed, 220 insertions(+), 30 deletions(-) diff --git a/internal/cmd/beta/security-group/create/create.go b/internal/cmd/beta/security-group/create/create.go index 1f7072e29..af66e0783 100644 --- a/internal/cmd/beta/security-group/create/create.go +++ b/internal/cmd/beta/security-group/create/create.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create security group: %w", err) } - if err := outputResult(p, model, group); err != nil { + if err := outputResult(p, model.OutputFormat, *model.Name, *group); err != nil { return err } @@ -144,8 +144,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return request.CreateSecurityGroupPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, name string, resp iaas.SecurityGroup) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -163,7 +163,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) return nil default: - p.Outputf("Created security group %q\n", *model.Name) + p.Outputf("Created security group %q\n", name) return nil } } diff --git a/internal/cmd/beta/security-group/create/create_test.go b/internal/cmd/beta/security-group/create/create_test.go index 1833e5c57..6a6a02898 100644 --- a/internal/cmd/beta/security-group/create/create_test.go +++ b/internal/cmd/beta/security-group/create/create_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -264,3 +263,31 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp iaas.SecurityGroup + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.name, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/describe/describe.go b/internal/cmd/beta/security-group/describe/describe.go index 2feb18203..2ea0084dc 100644 --- a/internal/cmd/beta/security-group/describe/describe.go +++ b/internal/cmd/beta/security-group/describe/describe.go @@ -57,7 +57,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get security group: %w", err) } - if err := outputResult(p, model, group); err != nil { + if err := outputResult(p, model.OutputFormat, group); err != nil { return err } @@ -96,8 +96,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM return &model, nil } -func outputResult(p *print.Printer, model *inputModel, resp *iaas.SecurityGroup) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, resp *iaas.SecurityGroup) error { + if resp == nil { + return fmt.Errorf("security group response is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { diff --git a/internal/cmd/beta/security-group/describe/describe_test.go b/internal/cmd/beta/security-group/describe/describe_test.go index 13a98fc84..6deaf042f 100644 --- a/internal/cmd/beta/security-group/describe/describe_test.go +++ b/internal/cmd/beta/security-group/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -192,3 +191,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp *iaas.SecurityGroup + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only security group as argument", + args: args{ + resp: &iaas.SecurityGroup{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/list/list_test.go b/internal/cmd/beta/security-group/list/list_test.go index c6f3a0c93..d19adf3a0 100644 --- a/internal/cmd/beta/security-group/list/list_test.go +++ b/internal/cmd/beta/security-group/list/list_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -205,3 +204,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + items []iaas.SecurityGroup + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/rule/create/create.go b/internal/cmd/beta/security-group/rule/create/create.go index 2d8958e27..d5e4ab6d4 100644 --- a/internal/cmd/beta/security-group/rule/create/create.go +++ b/internal/cmd/beta/security-group/rule/create/create.go @@ -219,6 +219,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, model *inputModel, projectLabel, securityGroupName string, securityGroupRule *iaas.SecurityGroupRule) error { + if securityGroupRule == nil { + return fmt.Errorf("security group rule is empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(securityGroupRule, "", " ") diff --git a/internal/cmd/beta/security-group/rule/create/create_test.go b/internal/cmd/beta/security-group/rule/create/create_test.go index 5d0fd2098..1a0024129 100644 --- a/internal/cmd/beta/security-group/rule/create/create_test.go +++ b/internal/cmd/beta/security-group/rule/create/create_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -333,3 +332,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + securityGroupName string + securityGroupRule *iaas.SecurityGroupRule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only security group rule", + args: args{ + model: fixtureInputModel(), + securityGroupRule: &iaas.SecurityGroupRule{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.securityGroupName, tt.args.securityGroupRule); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/rule/describe/describe.go b/internal/cmd/beta/security-group/rule/describe/describe.go index 5c1ef384f..2189d736f 100644 --- a/internal/cmd/beta/security-group/rule/describe/describe.go +++ b/internal/cmd/beta/security-group/rule/describe/describe.go @@ -113,6 +113,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, securityGroupRule *iaas.SecurityGroupRule) error { + if securityGroupRule == nil { + return fmt.Errorf("security group rule is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(securityGroupRule, "", " ") diff --git a/internal/cmd/beta/security-group/rule/describe/describe_test.go b/internal/cmd/beta/security-group/rule/describe/describe_test.go index 6463ef1fc..03060fcb2 100644 --- a/internal/cmd/beta/security-group/rule/describe/describe_test.go +++ b/internal/cmd/beta/security-group/rule/describe/describe_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -244,3 +243,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + securityGroupRule *iaas.SecurityGroupRule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only security group rule as argument", + args: args{ + securityGroupRule: &iaas.SecurityGroupRule{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.securityGroupRule); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/security-group/rule/list/list_test.go b/internal/cmd/beta/security-group/rule/list/list_test.go index 016039ed7..f72f89897 100644 --- a/internal/cmd/beta/security-group/rule/list/list_test.go +++ b/internal/cmd/beta/security-group/rule/list/list_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -212,3 +211,30 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + securityGroupRules []iaas.SecurityGroupRule + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.securityGroupRules); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From a59b7e563d19a9b18cfe91fc70feceae739dbeff Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 21 Feb 2025 09:16:49 +0100 Subject: [PATCH 198/619] chore(dns): Add nil pointer checks and tests for outputResult functions (#618) Signed-off-by: Alexander Dahmen --- internal/cmd/dns/record-set/create/create.go | 3 ++ .../cmd/dns/record-set/create/create_test.go | 43 +++++++++++++++++-- .../cmd/dns/record-set/describe/describe.go | 3 ++ .../dns/record-set/describe/describe_test.go | 39 +++++++++++++++-- internal/cmd/dns/record-set/list/list_test.go | 34 +++++++++++++-- internal/cmd/dns/zone/clone/clone.go | 3 ++ internal/cmd/dns/zone/clone/clone_test.go | 43 +++++++++++++++++-- internal/cmd/dns/zone/create/create.go | 3 ++ internal/cmd/dns/zone/create/create_test.go | 43 +++++++++++++++++-- internal/cmd/dns/zone/describe/describe.go | 3 ++ .../cmd/dns/zone/describe/describe_test.go | 39 +++++++++++++++-- internal/cmd/dns/zone/list/list_test.go | 34 +++++++++++++-- 12 files changed, 264 insertions(+), 26 deletions(-) diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 442a52794..65ea58911 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -181,6 +181,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClie } func outputResult(p *print.Printer, model *inputModel, zoneLabel string, resp *dns.RecordSetResponse) error { + if resp == nil { + return fmt.Errorf("record set response is empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/dns/record-set/create/create_test.go b/internal/cmd/dns/record-set/create/create_test.go index f1841d7bb..eed9f9424 100644 --- a/internal/cmd/dns/record-set/create/create_test.go +++ b/internal/cmd/dns/record-set/create/create_test.go @@ -6,13 +6,12 @@ import ( "strings" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -369,3 +368,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + zoneLabel string + resp *dns.RecordSetResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only record set as argument", + args: args{ + model: fixtureInputModel(), + resp: &dns.RecordSetResponse{Rrset: &dns.RecordSet{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.zoneLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/dns/record-set/describe/describe.go b/internal/cmd/dns/record-set/describe/describe.go index 2a934c8ff..03a757a7a 100644 --- a/internal/cmd/dns/record-set/describe/describe.go +++ b/internal/cmd/dns/record-set/describe/describe.go @@ -114,6 +114,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClie } func outputResult(p *print.Printer, outputFormat string, recordSet *dns.RecordSet) error { + if recordSet == nil { + return fmt.Errorf("record set response is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(recordSet, "", " ") diff --git a/internal/cmd/dns/record-set/describe/describe_test.go b/internal/cmd/dns/record-set/describe/describe_test.go index 1e33b5c94..a2cbc48e7 100644 --- a/internal/cmd/dns/record-set/describe/describe_test.go +++ b/internal/cmd/dns/record-set/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -245,3 +244,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + recordSet *dns.RecordSet + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only record set as argument", + args: args{ + recordSet: &dns.RecordSet{Records: &[]dns.Record{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.recordSet); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/dns/record-set/list/list_test.go b/internal/cmd/dns/record-set/list/list_test.go index 1ee21f9fb..d41e1f304 100644 --- a/internal/cmd/dns/record-set/list/list_test.go +++ b/internal/cmd/dns/record-set/list/list_test.go @@ -8,13 +8,12 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -501,3 +500,30 @@ func TestFetchRecordSets(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + recordSets []dns.RecordSet + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.recordSets); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index b6d3b3cdb..a7a4e42a0 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -160,6 +160,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClie } func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *dns.ZoneResponse) error { + if resp == nil { + return fmt.Errorf("dns zone response is empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/dns/zone/clone/clone_test.go b/internal/cmd/dns/zone/clone/clone_test.go index e450aae2b..ea4f0621b 100644 --- a/internal/cmd/dns/zone/clone/clone_test.go +++ b/internal/cmd/dns/zone/clone/clone_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -265,3 +264,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + resp *dns.ZoneResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only zone response as argument", + args: args{ + model: fixtureInputModel(), + resp: &dns.ZoneResponse{Zone: &dns.Zone{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 132a9337c..fadfbd183 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -197,6 +197,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClie } func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *dns.ZoneResponse) error { + if resp == nil { + return fmt.Errorf("dns zone response is empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/dns/zone/create/create_test.go b/internal/cmd/dns/zone/create/create_test.go index 8f8991c7e..5bcc8728a 100644 --- a/internal/cmd/dns/zone/create/create_test.go +++ b/internal/cmd/dns/zone/create/create_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -313,3 +312,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + resp *dns.ZoneResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only zone response as argument", + args: args{ + model: fixtureInputModel(), + resp: &dns.ZoneResponse{Zone: &dns.Zone{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/dns/zone/describe/describe.go b/internal/cmd/dns/zone/describe/describe.go index 8345bfc15..bd6ada66d 100644 --- a/internal/cmd/dns/zone/describe/describe.go +++ b/internal/cmd/dns/zone/describe/describe.go @@ -99,6 +99,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *dns.APIClie } func outputResult(p *print.Printer, outputFormat string, zone *dns.Zone) error { + if zone == nil { + return fmt.Errorf("zone response is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(zone, "", " ") diff --git a/internal/cmd/dns/zone/describe/describe_test.go b/internal/cmd/dns/zone/describe/describe_test.go index b5deb3f2c..e97810889 100644 --- a/internal/cmd/dns/zone/describe/describe_test.go +++ b/internal/cmd/dns/zone/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -218,3 +217,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + zone *dns.Zone + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only zone as argument", + args: args{ + zone: &dns.Zone{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.zone); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/dns/zone/list/list_test.go b/internal/cmd/dns/zone/list/list_test.go index 70b173864..d96b980d7 100644 --- a/internal/cmd/dns/zone/list/list_test.go +++ b/internal/cmd/dns/zone/list/list_test.go @@ -8,13 +8,12 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -495,3 +494,30 @@ func TestFetchZones(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + zones []dns.Zone + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.zones); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From ddfb512cbdbd630ed66f520198fa8054097e9b33 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 21 Feb 2025 09:54:58 +0100 Subject: [PATCH 199/619] chore(config): Add nil pointer checks and tests for the outputResult functions (#621) Signed-off-by: Alexander Dahmen --- internal/cmd/config/list/list_test.go | 35 +++++++++++++++++++ internal/cmd/config/profile/list/list_test.go | 34 ++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 internal/cmd/config/list/list_test.go create mode 100644 internal/cmd/config/profile/list/list_test.go diff --git a/internal/cmd/config/list/list_test.go b/internal/cmd/config/list/list_test.go new file mode 100644 index 000000000..d32d5d76a --- /dev/null +++ b/internal/cmd/config/list/list_test.go @@ -0,0 +1,35 @@ +package list + +import ( + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/print" +) + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + configData map[string]any + activeProfile string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.configData, tt.args.activeProfile); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/config/profile/list/list_test.go b/internal/cmd/config/profile/list/list_test.go new file mode 100644 index 000000000..80e080c56 --- /dev/null +++ b/internal/cmd/config/profile/list/list_test.go @@ -0,0 +1,34 @@ +package list + +import ( + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/print" +) + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + profiles []profileInfo + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.profiles); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From d8fd4e858a1983552d5c2c879820ecf565232a08 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 21 Feb 2025 10:19:32 +0100 Subject: [PATCH 200/619] chore(curl): Add nil pointer checks and tests for the outputResult functions (#620) Signed-off-by: Alexander Dahmen --- docs/stackit_curl.md | 2 +- internal/cmd/curl/curl.go | 7 +++-- internal/cmd/curl/curl_test.go | 52 ++++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/docs/stackit_curl.md b/docs/stackit_curl.md index 4dd7f453f..ef387edb5 100644 --- a/docs/stackit_curl.md +++ b/docs/stackit_curl.md @@ -17,7 +17,7 @@ stackit curl URL [flags] $ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones Get all the DNS zones for project with ID xxx via GET request to https://dns.api.stackit.cloud/v1/projects/xxx/zones, write complete response (headers and body) to file "./output.txt" - $ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones -include --output ./output.txt + $ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones --include --output ./output.txt Create a new DNS zone for project with ID xxx via POST request to https://dns.api.stackit.cloud/v1/projects/xxx/zones with payload from file "./payload.json" $ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones -X POST --data @./payload.json diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index e78accf1a..f52217b73 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -56,7 +56,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), examples.NewExample( `Get all the DNS zones for project with ID xxx via GET request to https://dns.api.stackit.cloud/v1/projects/xxx/zones, write complete response (headers and body) to file "./output.txt"`, - "$ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones -include --output ./output.txt", + "$ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones --include --output ./output.txt", ), examples.NewExample( `Create a new DNS zone for project with ID xxx via POST request to https://dns.api.stackit.cloud/v1/projects/xxx/zones with payload from file "./payload.json"`, @@ -198,6 +198,9 @@ func buildRequest(model *inputModel, bearerToken string) (*http.Request, error) } func outputResponse(p *print.Printer, model *inputModel, resp *http.Response) error { + if resp == nil { + return fmt.Errorf("http response is empty") + } output := make([]byte, 0) if model.IncludeResponseHeaders { respHeader, err := httputil.DumpResponse(resp, false) @@ -215,7 +218,7 @@ func outputResponse(p *print.Printer, model *inputModel, resp *http.Response) er if model.OutputFile == nil { p.Outputln(string(output)) } else { - err = os.WriteFile(*model.OutputFile, output, 0o600) + err = os.WriteFile(utils.PtrString(model.OutputFile), output, 0o600) if err != nil { return fmt.Errorf("write output to file: %w", err) } diff --git a/internal/cmd/curl/curl_test.go b/internal/cmd/curl/curl_test.go index 62d70e607..372d5663d 100644 --- a/internal/cmd/curl/curl_test.go +++ b/internal/cmd/curl/curl_test.go @@ -5,16 +5,16 @@ import ( "context" "fmt" "net/http" + "os" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" ) var testURL = "https://some-service.api.stackit.cloud/v1/foo?bar=baz" @@ -37,7 +37,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st dataFlag: "data", includeResponseHeadersFlag: "true", failOnHTTPErrorFlag: "true", - outputFileFlag: "path/to/output.txt", + outputFileFlag: "./output.txt", } for _, mod := range mods { mod(flagValues) @@ -53,7 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Data: utils.Ptr("data"), IncludeResponseHeaders: true, FailOnHTTPError: true, - OutputFile: utils.Ptr("path/to/output.txt"), + OutputFile: utils.Ptr("./output.txt"), } for _, mod := range mods { mod(model) @@ -403,3 +403,45 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResponse(t *testing.T) { + type args struct { + model *inputModel + resp *http.Response + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "http response as argument", + args: args{ + model: fixtureInputModel(), + resp: &http.Response{Body: http.NoBody}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResponse(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResponse() error = %v, wantErr %v", err, tt.wantErr) + } + if tt.args.model != nil { + if _, err := os.Stat(*tt.args.model.OutputFile); err == nil { + if err := os.Remove(*tt.args.model.OutputFile); err != nil { + t.Errorf("remove output file error = %v", err) + } + } + } + }) + } +} From a86c9369a316ca9419f35915d3c69b81400a8cc4 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 21 Feb 2025 11:05:15 +0100 Subject: [PATCH 201/619] Allow workaround if no browser can be opened (#603) In debug mode, print out full authorizationURL to provide workaround in circumstances where no window-server is available (hence no browser can be opened), as is the case when connect via ssh to headless systems. The workaround is to call ``stackit --verbosity debug auth login`` Copy the link from the debug output and paste it to an available browser. Co-authored-by: Tobias Weber --- internal/pkg/auth/user_login.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index fd9829348..b8a706a51 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -232,7 +232,7 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { } }) - p.Debug(print.DebugLevel, "opening browser for authentication") + p.Debug(print.DebugLevel, "opening browser for authentication: %s", authorizationURL) p.Debug(print.DebugLevel, "using authentication server on %s", idpWellKnownConfig.Issuer) p.Debug(print.DebugLevel, "using client ID %s for authentication ", idpClientID) From ca7fa426c979fa692752499e0db0dcb6bc56257e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 21 Feb 2025 12:31:44 +0100 Subject: [PATCH 202/619] fix(logme): add nil pointer checks for cmd outputs (#619) relates to STACKITCLI-102 --- .../cmd/logme/credentials/create/create.go | 14 ++++--- .../logme/credentials/create/create_test.go | 36 ++++++++++++++++ .../logme/credentials/describe/describe.go | 4 ++ .../credentials/describe/describe_test.go | 34 +++++++++++++++ .../cmd/logme/credentials/list/list_test.go | 41 +++++++++++++++++++ internal/cmd/logme/instance/create/create.go | 12 ++++-- .../cmd/logme/instance/create/create_test.go | 36 ++++++++++++++++ .../cmd/logme/instance/describe/describe.go | 22 ++++++---- .../logme/instance/describe/describe_test.go | 34 +++++++++++++++ internal/cmd/logme/instance/list/list.go | 11 ++++- internal/cmd/logme/instance/list/list_test.go | 41 +++++++++++++++++++ internal/cmd/logme/plans/plans.go | 22 +++++----- internal/cmd/logme/plans/plans_test.go | 41 +++++++++++++++++++ 13 files changed, 319 insertions(+), 29 deletions(-) diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 22685cedc..61df00f15 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -78,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create LogMe credentials: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, model.ShowPassword, instanceLabel, resp) }, } configureFlags(cmd) @@ -122,11 +122,15 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *logme.CredentialsResponse) error { - if !model.ShowPassword { +func outputResult(p *print.Printer, outputFormat string, showPassword bool, instanceLabel string, resp *logme.CredentialsResponse) error { + if resp == nil { + return fmt.Errorf("credentials response is empty") + } + + if !showPassword && resp.HasRaw() && resp.Raw.Credentials != nil { resp.Raw.Credentials.Password = utils.Ptr("hidden") } - switch model.OutputFormat { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -150,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res if username := resp.Raw.Credentials.Username; username != nil && *username != "" { p.Outputf("Username: %s\n", utils.PtrString(username)) } - if !model.ShowPassword { + if !showPassword { p.Outputf("Password: \n") } else { p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) diff --git a/internal/cmd/logme/credentials/create/create_test.go b/internal/cmd/logme/credentials/create/create_test.go index ff0d16fbd..3ad8aec16 100644 --- a/internal/cmd/logme/credentials/create/create_test.go +++ b/internal/cmd/logme/credentials/create/create_test.go @@ -200,3 +200,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + showPassword bool + instanceLabel string + credentials *logme.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty credentials", + args: args{ + credentials: &logme.CredentialsResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/logme/credentials/describe/describe.go b/internal/cmd/logme/credentials/describe/describe.go index 968c2b3ef..2a73c9a15 100644 --- a/internal/cmd/logme/credentials/describe/describe.go +++ b/internal/cmd/logme/credentials/describe/describe.go @@ -112,6 +112,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl } func outputResult(p *print.Printer, outputFormat string, credentials *logme.CredentialsResponse) error { + if credentials == nil { + return fmt.Errorf("credentials is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(credentials, "", " ") diff --git a/internal/cmd/logme/credentials/describe/describe_test.go b/internal/cmd/logme/credentials/describe/describe_test.go index 7726b725c..3ef166834 100644 --- a/internal/cmd/logme/credentials/describe/describe_test.go +++ b/internal/cmd/logme/credentials/describe/describe_test.go @@ -243,3 +243,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials *logme.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty credentials", + args: args{ + credentials: &logme.CredentialsResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/logme/credentials/list/list_test.go b/internal/cmd/logme/credentials/list/list_test.go index 570b58bae..dd9b71e66 100644 --- a/internal/cmd/logme/credentials/list/list_test.go +++ b/internal/cmd/logme/credentials/list/list_test.go @@ -207,3 +207,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []logme.CredentialsListItem + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty credentials slice", + args: args{ + credentials: []logme.CredentialsListItem{}, + }, + wantErr: false, + }, + { + name: "set empty credential in credentials slice", + args: args{ + credentials: []logme.CredentialsListItem{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index 7effe9a74..df11b20a2 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -125,7 +125,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) @@ -251,8 +251,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, resp *logme.CreateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -271,7 +275,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) diff --git a/internal/cmd/logme/instance/create/create_test.go b/internal/cmd/logme/instance/create/create_test.go index fe0cfcc0b..ac8928edf 100644 --- a/internal/cmd/logme/instance/create/create_test.go +++ b/internal/cmd/logme/instance/create/create_test.go @@ -463,3 +463,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + resp *logme.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty response", + args: args{ + resp: &logme.CreateInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/logme/instance/describe/describe.go b/internal/cmd/logme/instance/describe/describe.go index 9a19a4a9c..d32944bdf 100644 --- a/internal/cmd/logme/instance/describe/describe.go +++ b/internal/cmd/logme/instance/describe/describe.go @@ -100,6 +100,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl } func outputResult(p *print.Printer, outputFormat string, instance *logme.Instance) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -123,16 +127,18 @@ func outputResult(p *print.Printer, outputFormat string, instance *logme.Instanc table.AddSeparator() table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) - table.AddSeparator() - table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) - table.AddSeparator() + if instance.LastOperation != nil { + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) + table.AddSeparator() + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) + table.AddSeparator() + } table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty - acl := (*instance.Parameters)[aclParameterKey] - aclStr, ok := acl.(string) - if ok { - if aclStr != "" { + if instance.Parameters != nil { + acl := (*instance.Parameters)[aclParameterKey] + aclStr, ok := acl.(string) + if ok && aclStr != "" { table.AddSeparator() table.AddRow("ACL", aclStr) } diff --git a/internal/cmd/logme/instance/describe/describe_test.go b/internal/cmd/logme/instance/describe/describe_test.go index 60cdc69ab..3cc0b5e38 100644 --- a/internal/cmd/logme/instance/describe/describe_test.go +++ b/internal/cmd/logme/instance/describe/describe_test.go @@ -216,3 +216,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *logme.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty instance", + args: args{ + instance: &logme.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index 593aff6da..e59d09cb6 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -152,11 +152,18 @@ func outputResult(p *print.Printer, outputFormat string, instances []logme.Insta table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] + + lastOperationType, lastOperationState := "", "" + if instance.LastOperation != nil { + lastOperationType = utils.PtrString(instance.LastOperation.Type) + lastOperationState = utils.PtrString(instance.LastOperation.State) + } + table.AddRow( utils.PtrString(instance.InstanceId), utils.PtrString(instance.Name), - utils.PtrString(instance.LastOperation.Type), - utils.PtrString(instance.LastOperation.State), + lastOperationType, + lastOperationState, ) } err := table.Display(p) diff --git a/internal/cmd/logme/instance/list/list_test.go b/internal/cmd/logme/instance/list/list_test.go index 5524c41e9..97df7394c 100644 --- a/internal/cmd/logme/instance/list/list_test.go +++ b/internal/cmd/logme/instance/list/list_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instances []logme.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty instances slice", + args: args{ + instances: []logme.Instance{}, + }, + wantErr: false, + }, + { + name: "empty instance in instances slice", + args: args{ + instances: []logme.Instance{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index 385ee2639..ccfdc098b 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -152,17 +152,19 @@ func outputResult(p *print.Printer, outputFormat string, plans []logme.Offering) table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { o := plans[i] - for j := range *o.Plans { - p := (*o.Plans)[j] - table.AddRow( - utils.PtrString(o.Name), - utils.PtrString(o.Version), - utils.PtrString(p.Id), - utils.PtrString(p.Name), - utils.PtrString(p.Description), - ) + if o.Plans != nil { + for j := range *o.Plans { + p := (*o.Plans)[j] + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(p.Id), + utils.PtrString(p.Name), + utils.PtrString(p.Description), + ) + } + table.AddSeparator() } - table.AddSeparator() } table.EnableAutoMergeOnColumns(1, 2) err := table.Display(p) diff --git a/internal/cmd/logme/plans/plans_test.go b/internal/cmd/logme/plans/plans_test.go index f8214f2f2..bc8c78bb7 100644 --- a/internal/cmd/logme/plans/plans_test.go +++ b/internal/cmd/logme/plans/plans_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + plans []logme.Offering + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty plans slice", + args: args{ + plans: []logme.Offering{}, + }, + wantErr: false, + }, + { + name: "empty plan in plans slice", + args: args{ + plans: []logme.Offering{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From bb61f058ab9ce38cad1be9e6c9efff0431b62614 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:37:59 +0100 Subject: [PATCH 203/619] fix: stackit beta network-area commands - add nil pointer checks and tests for the outputResult functions (#606) * add nil pointer checks *nadd tests for the outputResult functions within the network-area commands --- .../cmd/beta/network-area/create/create.go | 11 +++-- .../beta/network-area/create/create_test.go | 35 ++++++++++++++++ .../cmd/beta/network-area/delete/delete.go | 2 + .../beta/network-area/describe/describe.go | 22 ++++++---- .../network-area/describe/describe_test.go | 35 ++++++++++++++++ internal/cmd/beta/network-area/list/list.go | 2 + .../cmd/beta/network-area/list/list_test.go | 41 +++++++++++++++++++ .../network-range/create/create.go | 6 +-- .../network-range/create/create_test.go | 35 ++++++++++++++++ .../network-range/delete/delete.go | 4 ++ .../network-range/describe/describe.go | 3 ++ .../network-range/describe/describe_test.go | 34 +++++++++++++++ .../network-area/network-range/list/list.go | 5 ++- .../network-range/list/list_test.go | 41 +++++++++++++++++++ .../beta/network-area/route/create/create.go | 8 ++-- .../network-area/route/create/create_test.go | 35 ++++++++++++++++ .../beta/network-area/route/delete/delete.go | 2 + .../network-area/route/describe/describe.go | 4 +- .../route/describe/describe_test.go | 34 +++++++++++++++ .../cmd/beta/network-area/route/list/list.go | 2 + .../beta/network-area/route/list/list_test.go | 41 +++++++++++++++++++ .../beta/network-area/route/update/update.go | 8 ++-- .../network-area/route/update/update_test.go | 35 ++++++++++++++++ .../cmd/beta/network-area/update/update.go | 8 ++-- .../beta/network-area/update/update_test.go | 35 ++++++++++++++++ 25 files changed, 462 insertions(+), 26 deletions(-) diff --git a/internal/cmd/beta/network-area/create/create.go b/internal/cmd/beta/network-area/create/create.go index 2df562c6d..0987e96c4 100644 --- a/internal/cmd/beta/network-area/create/create.go +++ b/internal/cmd/beta/network-area/create/create.go @@ -83,6 +83,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get organization name: %v", err) orgLabel = *model.OrganizationId + } else if orgLabel == "" { + orgLabel = *model.OrganizationId } } else { p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) @@ -103,7 +105,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create network area: %w", err) } - return outputResult(p, model, orgLabel, resp) + return outputResult(p, model.OutputFormat, orgLabel, resp) }, } configureFlags(cmd) @@ -178,8 +180,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateNetworkAreaPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, orgLabel string, networkArea *iaas.NetworkArea) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, orgLabel string, networkArea *iaas.NetworkArea) error { + if networkArea == nil { + return fmt.Errorf("network area is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(networkArea, "", " ") if err != nil { diff --git a/internal/cmd/beta/network-area/create/create_test.go b/internal/cmd/beta/network-area/create/create_test.go index 2912000db..b6a34625f 100644 --- a/internal/cmd/beta/network-area/create/create_test.go +++ b/internal/cmd/beta/network-area/create/create_test.go @@ -246,3 +246,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + orgLabel string + networkArea *iaas.NetworkArea + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty network area", + args: args{ + networkArea: &iaas.NetworkArea{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.orgLabel, tt.args.networkArea); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/delete/delete.go b/internal/cmd/beta/network-area/delete/delete.go index db4ddd117..3952efc42 100644 --- a/internal/cmd/beta/network-area/delete/delete.go +++ b/internal/cmd/beta/network-area/delete/delete.go @@ -62,6 +62,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = model.AreaId + } else if networkAreaLabel == "" { + networkAreaLabel = model.AreaId } if !model.AssumeYes { diff --git a/internal/cmd/beta/network-area/describe/describe.go b/internal/cmd/beta/network-area/describe/describe.go index 13d2707d4..51be436b9 100644 --- a/internal/cmd/beta/network-area/describe/describe.go +++ b/internal/cmd/beta/network-area/describe/describe.go @@ -127,6 +127,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.NetworkArea, attachedProjects []string) error { + if networkArea == nil { + return fmt.Errorf("network area is nil") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(networkArea, "", " ") @@ -146,16 +149,19 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo return nil default: var routes []string - if networkArea.Ipv4.Routes != nil { - for _, route := range *networkArea.Ipv4.Routes { - routes = append(routes, fmt.Sprintf("next hop: %s\nprefix: %s", *route.Nexthop, *route.Prefix)) + var networkRanges []string + + if networkArea.Ipv4 != nil { + if networkArea.Ipv4.Routes != nil { + for _, route := range *networkArea.Ipv4.Routes { + routes = append(routes, fmt.Sprintf("next hop: %s\nprefix: %s", *route.Nexthop, *route.Prefix)) + } } - } - var networkRanges []string - if networkArea.Ipv4.NetworkRanges != nil { - for _, networkRange := range *networkArea.Ipv4.NetworkRanges { - networkRanges = append(networkRanges, *networkRange.Prefix) + if networkArea.Ipv4.NetworkRanges != nil { + for _, networkRange := range *networkArea.Ipv4.NetworkRanges { + networkRanges = append(networkRanges, *networkRange.Prefix) + } } } diff --git a/internal/cmd/beta/network-area/describe/describe_test.go b/internal/cmd/beta/network-area/describe/describe_test.go index 98975e10e..24c18cb06 100644 --- a/internal/cmd/beta/network-area/describe/describe_test.go +++ b/internal/cmd/beta/network-area/describe/describe_test.go @@ -227,3 +227,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + networkArea *iaas.NetworkArea + attachedProjects []string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set networkArea", + args: args{ + networkArea: &iaas.NetworkArea{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networkArea, tt.args.attachedProjects); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/list/list.go b/internal/cmd/beta/network-area/list/list.go index cb4916a79..2280da2ad 100644 --- a/internal/cmd/beta/network-area/list/list.go +++ b/internal/cmd/beta/network-area/list/list.go @@ -80,6 +80,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get organization name: %v", err) orgLabel = *model.OrganizationId + } else if orgLabel == "" { + orgLabel = *model.OrganizationId } } else { p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) diff --git a/internal/cmd/beta/network-area/list/list_test.go b/internal/cmd/beta/network-area/list/list_test.go index 46282da26..01d94cb37 100644 --- a/internal/cmd/beta/network-area/list/list_test.go +++ b/internal/cmd/beta/network-area/list/list_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + networkAreas []iaas.NetworkArea + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty network areas slice", + args: args{ + networkAreas: []iaas.NetworkArea{}, + }, + wantErr: false, + }, + { + name: "empty network area in network areas slice", + args: args{ + networkAreas: []iaas.NetworkArea{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreas); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/network-range/create/create.go b/internal/cmd/beta/network-area/network-range/create/create.go index 812ea18a7..297ee0e7f 100644 --- a/internal/cmd/beta/network-area/network-range/create/create.go +++ b/internal/cmd/beta/network-area/network-range/create/create.go @@ -88,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - return outputResult(p, model, networkAreaLabel, networkRange) + return outputResult(p, model.OutputFormat, networkAreaLabel, networkRange) }, } configureFlags(cmd) @@ -138,8 +138,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateNetworkAreaRangePayload(payload) } -func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, networkRange iaas.NetworkRange) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, networkRange iaas.NetworkRange) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(networkRange, "", " ") if err != nil { diff --git a/internal/cmd/beta/network-area/network-range/create/create_test.go b/internal/cmd/beta/network-area/network-range/create/create_test.go index 028259648..f3eb51bf1 100644 --- a/internal/cmd/beta/network-area/network-range/create/create_test.go +++ b/internal/cmd/beta/network-area/network-range/create/create_test.go @@ -215,3 +215,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + networkAreaLabel string + networkRange iaas.NetworkRange + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty network range", + args: args{ + networkRange: iaas.NetworkRange{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreaLabel, tt.args.networkRange); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/network-range/delete/delete.go b/internal/cmd/beta/network-area/network-range/delete/delete.go index 90fb8a486..b7740dd9e 100644 --- a/internal/cmd/beta/network-area/network-range/delete/delete.go +++ b/internal/cmd/beta/network-area/network-range/delete/delete.go @@ -60,11 +60,15 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId + } else if networkAreaLabel == "" { + networkAreaLabel = *model.NetworkAreaId } networkRangeLabel, err := iaasUtils.GetNetworkRangePrefix(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) if err != nil { p.Debug(print.ErrorLevel, "get network range prefix: %v", err) networkRangeLabel = model.NetworkRangeId + } else if networkRangeLabel == "" { + networkRangeLabel = model.NetworkRangeId } if !model.AssumeYes { diff --git a/internal/cmd/beta/network-area/network-range/describe/describe.go b/internal/cmd/beta/network-area/network-range/describe/describe.go index f97fc0b57..a4c57f7eb 100644 --- a/internal/cmd/beta/network-area/network-range/describe/describe.go +++ b/internal/cmd/beta/network-area/network-range/describe/describe.go @@ -109,6 +109,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, networkRange *iaas.NetworkRange) error { + if networkRange == nil { + return fmt.Errorf("network range is nil") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(networkRange, "", " ") diff --git a/internal/cmd/beta/network-area/network-range/describe/describe_test.go b/internal/cmd/beta/network-area/network-range/describe/describe_test.go index bce857d1c..c03229238 100644 --- a/internal/cmd/beta/network-area/network-range/describe/describe_test.go +++ b/internal/cmd/beta/network-area/network-range/describe/describe_test.go @@ -234,3 +234,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + networkRange *iaas.NetworkRange + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set networkRange", + args: args{ + networkRange: &iaas.NetworkRange{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networkRange); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/network-range/list/list.go b/internal/cmd/beta/network-area/network-range/list/list.go index e2115d9a7..faace6c9c 100644 --- a/internal/cmd/beta/network-area/network-range/list/list.go +++ b/internal/cmd/beta/network-area/network-range/list/list.go @@ -15,6 +15,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/cobra" @@ -79,6 +80,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get organization name: %v", err) networkAreaLabel = *model.NetworkAreaId + } else if networkAreaLabel == "" { + networkAreaLabel = *model.NetworkAreaId } p.Info("No network ranges found for SNA %q\n", networkAreaLabel) return nil @@ -162,7 +165,7 @@ func outputResult(p *print.Printer, outputFormat string, networkRanges []iaas.Ne table.SetHeader("ID", "Network Range") for _, networkRange := range networkRanges { - table.AddRow(*networkRange.NetworkRangeId, *networkRange.Prefix) + table.AddRow(utils.PtrString(networkRange.NetworkRangeId), utils.PtrString(networkRange.Prefix)) } p.Outputln(table.Render()) diff --git a/internal/cmd/beta/network-area/network-range/list/list_test.go b/internal/cmd/beta/network-area/network-range/list/list_test.go index 07ca84414..26efc608c 100644 --- a/internal/cmd/beta/network-area/network-range/list/list_test.go +++ b/internal/cmd/beta/network-area/network-range/list/list_test.go @@ -210,3 +210,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + networkRanges []iaas.NetworkRange + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty network ranges slice", + args: args{ + networkRanges: []iaas.NetworkRange{}, + }, + wantErr: false, + }, + { + name: "empty network range in network ranges slice", + args: args{ + networkRanges: []iaas.NetworkRange{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networkRanges); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/route/create/create.go b/internal/cmd/beta/network-area/route/create/create.go index e1b330329..d73c337c3 100644 --- a/internal/cmd/beta/network-area/route/create/create.go +++ b/internal/cmd/beta/network-area/route/create/create.go @@ -73,6 +73,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId + } else if networkAreaLabel == "" { + networkAreaLabel = *model.NetworkAreaId } if !model.AssumeYes { @@ -99,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - return outputResult(p, model, networkAreaLabel, route) + return outputResult(p, model.OutputFormat, networkAreaLabel, route) }, } configureFlags(cmd) @@ -165,8 +167,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateNetworkAreaRoutePayload(payload) } -func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, route iaas.Route) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, route iaas.Route) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(route, "", " ") if err != nil { diff --git a/internal/cmd/beta/network-area/route/create/create_test.go b/internal/cmd/beta/network-area/route/create/create_test.go index b106a937b..4ffca7666 100644 --- a/internal/cmd/beta/network-area/route/create/create_test.go +++ b/internal/cmd/beta/network-area/route/create/create_test.go @@ -261,3 +261,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + networkAreaLabel string + route iaas.Route + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty route", + args: args{ + route: iaas.Route{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreaLabel, tt.args.route); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/route/delete/delete.go b/internal/cmd/beta/network-area/route/delete/delete.go index 48dad6918..0626c67a6 100644 --- a/internal/cmd/beta/network-area/route/delete/delete.go +++ b/internal/cmd/beta/network-area/route/delete/delete.go @@ -60,6 +60,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId + } else if networkAreaLabel == "" { + networkAreaLabel = *model.NetworkAreaId } if !model.AssumeYes { diff --git a/internal/cmd/beta/network-area/route/describe/describe.go b/internal/cmd/beta/network-area/route/describe/describe.go index 2e99f8c67..fa03a07b2 100644 --- a/internal/cmd/beta/network-area/route/describe/describe.go +++ b/internal/cmd/beta/network-area/route/describe/describe.go @@ -70,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe static route: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(p, model.OutputFormat, *resp) }, } configureFlags(cmd) @@ -113,7 +113,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req } -func outputResult(p *print.Printer, outputFormat string, route *iaas.Route) error { +func outputResult(p *print.Printer, outputFormat string, route iaas.Route) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(route, "", " ") diff --git a/internal/cmd/beta/network-area/route/describe/describe_test.go b/internal/cmd/beta/network-area/route/describe/describe_test.go index 08fba5d5f..d052d69f9 100644 --- a/internal/cmd/beta/network-area/route/describe/describe_test.go +++ b/internal/cmd/beta/network-area/route/describe/describe_test.go @@ -234,3 +234,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + route iaas.Route + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty route", + args: args{ + route: iaas.Route{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.route); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/route/list/list.go b/internal/cmd/beta/network-area/route/list/list.go index c948e271a..c7e4f46f0 100644 --- a/internal/cmd/beta/network-area/route/list/list.go +++ b/internal/cmd/beta/network-area/route/list/list.go @@ -79,6 +79,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId + } else if networkAreaLabel == "" { + networkAreaLabel = *model.NetworkAreaId } p.Info("No static routes found for STACKIT Network Area %q\n", networkAreaLabel) return nil diff --git a/internal/cmd/beta/network-area/route/list/list_test.go b/internal/cmd/beta/network-area/route/list/list_test.go index 929ed0543..573b332a8 100644 --- a/internal/cmd/beta/network-area/route/list/list_test.go +++ b/internal/cmd/beta/network-area/route/list/list_test.go @@ -210,3 +210,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + routes []iaas.Route + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty route slice", + args: args{ + routes: []iaas.Route{}, + }, + wantErr: false, + }, + { + name: "empty route in routes slice", + args: args{ + routes: []iaas.Route{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.routes); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/route/update/update.go b/internal/cmd/beta/network-area/route/update/update.go index 511f9ed4d..e378cdcf4 100644 --- a/internal/cmd/beta/network-area/route/update/update.go +++ b/internal/cmd/beta/network-area/route/update/update.go @@ -69,6 +69,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId + } else if networkAreaLabel == "" { + networkAreaLabel = *model.NetworkAreaId } // Call API @@ -78,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create static route: %w", err) } - return outputResult(p, model, networkAreaLabel, *resp) + return outputResult(p, model.OutputFormat, networkAreaLabel, *resp) }, } configureFlags(cmd) @@ -141,8 +143,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req } -func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, route iaas.Route) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, route iaas.Route) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(route, "", " ") if err != nil { diff --git a/internal/cmd/beta/network-area/route/update/update_test.go b/internal/cmd/beta/network-area/route/update/update_test.go index f9b1ddd06..813deae4d 100644 --- a/internal/cmd/beta/network-area/route/update/update_test.go +++ b/internal/cmd/beta/network-area/route/update/update_test.go @@ -267,3 +267,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + networkAreaLabel string + route iaas.Route + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty route", + args: args{ + route: iaas.Route{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreaLabel, tt.args.route); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/network-area/update/update.go b/internal/cmd/beta/network-area/update/update.go index a7d7bb722..7fe9f4602 100644 --- a/internal/cmd/beta/network-area/update/update.go +++ b/internal/cmd/beta/network-area/update/update.go @@ -75,6 +75,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { p.Debug(print.ErrorLevel, "get organization name: %v", err) orgLabel = *model.OrganizationId + } else if orgLabel == "" { + orgLabel = *model.OrganizationId } } else { p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) @@ -95,7 +97,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update network area: %w", err) } - return outputResult(p, model, orgLabel, resp) + return outputResult(p, model.OutputFormat, orgLabel, *resp) }, } configureFlags(cmd) @@ -160,8 +162,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.PartialUpdateNetworkAreaPayload(payload) } -func outputResult(p *print.Printer, model *inputModel, projectLabel string, networkArea *iaas.NetworkArea) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, projectLabel string, networkArea iaas.NetworkArea) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(networkArea, "", " ") if err != nil { diff --git a/internal/cmd/beta/network-area/update/update_test.go b/internal/cmd/beta/network-area/update/update_test.go index f91e0b583..2d1581b12 100644 --- a/internal/cmd/beta/network-area/update/update_test.go +++ b/internal/cmd/beta/network-area/update/update_test.go @@ -266,3 +266,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + projectLabel string + networkArea iaas.NetworkArea + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty network area", + args: args{ + networkArea: iaas.NetworkArea{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(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.networkArea); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 6c6273a8ef088b82ce029feff5bb2c15b9270007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 24 Feb 2025 09:18:18 +0100 Subject: [PATCH 204/619] chore(iaas): remove unneeded todo comment (#629) --- internal/cmd/beta/server/network-interface/list/list_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/cmd/beta/server/network-interface/list/list_test.go b/internal/cmd/beta/server/network-interface/list/list_test.go index 5ce4e90c6..f627b1d19 100644 --- a/internal/cmd/beta/server/network-interface/list/list_test.go +++ b/internal/cmd/beta/server/network-interface/list/list_test.go @@ -1,7 +1,5 @@ package list -// TODO: hier sind wir - import ( "context" "testing" From 5c2eed8d3be45d8355e577091bcbc7a63c709c14 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 24 Feb 2025 09:29:19 +0100 Subject: [PATCH 205/619] fix(deps): update stackit sdk modules (#631) Co-authored-by: Renovate Bot --- go.mod | 46 ++++++++++++++--------------- go.sum | 92 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/go.mod b/go.mod index 2cdefd53d..7e33bf0a6 100644 --- a/go.mod +++ b/go.mod @@ -15,22 +15,22 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.19.0 - github.com/stackitcloud/stackit-sdk-go/core v0.15.1 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.1 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.12.0 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0 + github.com/stackitcloud/stackit-sdk-go/core v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.20.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.18.0 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.10.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.23.0 golang.org/x/oauth2 v0.26.0 @@ -79,13 +79,13 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.2 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.0.0 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.18.0 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect diff --git a/go.sum b/go.sum index c1c2d4e1a..e4754a600 100644 --- a/go.sum +++ b/go.sum @@ -117,52 +117,52 @@ github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= -github.com/stackitcloud/stackit-sdk-go/core v0.15.1 h1:hIj/k/JXEuYmud3VWo3lr7Cfj2hfl4gG9nUIzcaZ9pM= -github.com/stackitcloud/stackit-sdk-go/core v0.15.1/go.mod h1:mDX1mSTsB3mP+tNBGcFNx6gH1mGBN4T+dVt+lcw7nlw= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.1 h1:MAB7z8Hr6nCNdPCiLy5uNOJB+1R/eYFseFNEQUYK7qc= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.5.1/go.mod h1:8xSVF4KRo4GbkGBmmiOYP/CzIIivppvGIafUpdctnZc= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1 h1:nzOZQ2X6joM2iStePoACZeYvXFBQIBjkYE9sLanOGvE= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.1/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0 h1:o9OAGh4mdYY5LZYZiJio0KYUhqPSpBY4vT08piGx0pI= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.19.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.2 h1:K921/2U8dJh1SAOClhPqmZtid+/kP+BPrGZjXWOABkQ= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.2/go.mod h1:mwKowXJhwB9/PQdvdmOyyqOzLF0AmkzpcwrQbDYxllo= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1 h1:J+GLgfDIDnNpq/z6ev1whfLbOwUn5XgSKh3aE2auHIs= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.1/go.mod h1:nuZK6OXyZ4zlGsC1gZDj9+ajJzzFi9vVgSSRQlEJAqA= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0 h1:SXNkKaAsGOkr9C6bv2i7q3kucxL3kril+z2wnshlXK0= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.17.0/go.mod h1:5hMtm08NrL+QcgKl94zUDrY7VEzKRcvCJOEOvENBxqc= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.0.0 h1:/0n2zcH1nMw2noroGhz0fgu2YqtNo9v3AsVhXMRtmtw= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.0.0/go.mod h1:0XumGX33DT6ItyD8yMlogSPWvpIuoqN7RZBrpUBPX+k= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1 h1:sIz4wJIz6/9Eh6nSoi2sQ+Ef53iOrFsqLKIp2oRkmgo= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.2.1/go.mod h1:okcRTrNDTI3d7MQcYJMliK0qoXeLq0b1wvZuEqgJIWE= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1 h1:hwRkCCUSWMhKTc7fLakL89V6+9xkxsFQlRthVmrvi1U= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.19.1/go.mod h1:U45gFwIAAdXWL/Wlp9rY3iPVWFHLGILz1C3Qc62o8KM= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.17.0 h1:2mxf7vAaQuEM28D78uSIdUyqHKqNLM+pZnYC0LqbDpc= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.17.0/go.mod h1:gPOT3o+b0mx2Z4r/ZXhSqt5MRHbZplGoUafxeClSSng= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1 h1:6XfGxsPFqci/geSDd1gCtiaRJun85X5JepXn4edobXQ= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.20.1/go.mod h1:42oYZOqin+rIUrUqgtCIE4wzCWWY30H4UFhzvo1Wg2w= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1 h1:/EVm0bD9a3KCk9aj/v2ivJIURlGsTr4O2OwMQ4ey3e4= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.20.1/go.mod h1:YJdkyuY7aK/clfE3lQDz7O369JLPcg0FO4yfCIPNUNE= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.12.0 h1:uYWg/wovldLquCsHsdJUWyUF3Z1Yz4rR64WPfcfudmg= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.12.0/go.mod h1:hLc1YDjcwnkkQntTMQ5pk1ZQyX6cuBZoaEe4lr8sppI= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1 h1:qAKT20siGhkIIg4gY0JBPD7TU+I/6UieYcivGU7hVKc= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.2.1/go.mod h1:LgCIIj7jA2lWX4DI3bxUYD+m0TbWCr1VgAyBYNJeghc= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1 h1:qShB0OuNR8EOffY36/DfJs/Yk12syy38xkE88Z15f4k= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.10.1/go.mod h1:268uoY2gKCa5xcDL169TGVjLUNTcZ2En77YdfYOcR1w= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0 h1:33zKhcNS1bZ2usGnYZ6YE6Vxm7c9U0aC8lDg96UN+e4= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.5.0/go.mod h1:thrCIDBjEHAcihjWUOMJ5mbYVhOWfS/bLTBJ+yl5W4g= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.4.0 h1:kHzmcwSs1vgwSHIjgRlDoavKyzByOxSEUJ1XfYZvqn4= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.4.0/go.mod h1:m/lZ3XH3wdKkkFb6vHxi0MhhMdRL2uAuCATeYChh+s0= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0 h1:yf9BxAZEG2hdaekWxaNt2BOX/4qmGkl0d268ggR+tCU= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.5.0/go.mod h1:Wpqj80yGruCNYGr2yxqhRaLLj4gPSkhJqZyWRXUh/QU= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0 h1:K5fVTcJxjOVwJBa3kiWRsYNAq+I3jAYdU1U+f6no5lE= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.4.0/go.mod h1:zyg0hpiNdZLRbelkJb2KDf9OHQKLqqcTpePQ1qHL5dE= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1 h1:oO+wCobC4OfH+vpfJQEnCUQuKVILRj5mQojBbzWgzDA= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.21.1/go.mod h1:iZyh3DMi2fUZxAIseykjKfDo2wf2FIDwpF43I22b8uk= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0 h1:OYWT7B63isBPyVuPxd3yobvky7/nhcXQxaBgPki5nR4= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.9.0/go.mod h1:vrl+OVJkjjupkvfkqY2T3HAB6x2x0S6zDhdFB5BWEnU= +github.com/stackitcloud/stackit-sdk-go/core v0.16.0 h1:9caGZwGLZDyBBe6ojk9VR4B2m3/0H5It6znBz76sH1w= +github.com/stackitcloud/stackit-sdk-go/core v0.16.0/go.mod h1:LRheSoXTFRHWAyA8Q9skWtWBp3ZZ+bFAKiKuf4lTDkE= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0 h1:nSaSvo9o4c9KGc0vct+JWk5T49Ic6i3hzbLKviJtVhA= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0/go.mod h1:LoOkWrUropfVm72oE5aWSC9yRiM3s8Vf3TvC7HtC3b8= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0 h1:gEoA2oj3OcDg3XI0KSJm8mCjQz9WOZENeSgfTFPK8ow= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0/go.mod h1:JE8POcTfSxTo+g1MkgVQ+OjT4jWEr08MIY8qx3Hi+Tw= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.20.0 h1:yg8YlMn7Sj3SeF6rxkCLp74N16JH5u6coOEN7GJH67Y= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.20.0/go.mod h1:w10/728sUT49t4WFbV8zI3dvn0u3tGEIq77rRsVm460= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.18.0 h1:7nNjIIcBQRDVnW4NL7+R8DaCKEqxxxsmVsgOVe50ZMU= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.18.0/go.mod h1:UFujBT+JlNvl6JNrY96UpLGqp+lZTD+JWL7siqhGPlw= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0 h1:P7bxaVzkZPGMWItLynKIvc88Xh6jCnK4dPTTT+L607o= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0/go.mod h1:os4Kp2+jkMUJ2dZtgU9A91N3EJSw3MMh2slxgK1609g= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0 h1:ks1i+cfD/YPRss//4aq6uvxbLvUwb5QvcUrOPeboLFY= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0/go.mod h1:kGAT87SO5Wkv/CSZevMZcPml3V38G6tnT1Wvdkdmkv4= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.0 h1:mXVFa5/5uvOibPAUU0HTM7uf7H95IbnYnIzNvR5gB00= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.0/go.mod h1:uuTdgDo4Ju2W0eMfHc3a5n9SXNKJPdxuq15e3AFss6Q= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.0 h1:kWfmDQeTMijx0ySPiPfL4EU1TL6lcpkRVrzXenSaX6w= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.0/go.mod h1:giKgWW+KXpBDiZFWt/9D7D+sU1WSp27CQy+NolyrL8s= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.0 h1:Hn4BwKCzzmUdIFCU74OD9KgDA9OgmzRJzGMGXjPCWkQ= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.0/go.mod h1:PxfwA6YFtxwOajB4iTp1Eq7G02qUC3HdQPJvHGjQ1hk= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0 h1:y83IhdbQv8EHovWPTqeulGgyZKJ39AQW1klo0g7a7og= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0/go.mod h1:Gk3hWaQDCJGgaixjGkUmoIr74VNWwdAakiUrvizpOWQ= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.18.0 h1:cwdmiwbSml70kE9xV9C25t9WggDT98NdSfWD9w/r4wU= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.18.0/go.mod h1:wNPezvzJUgUj+C50EqyMAj5PSkhawT+2Zsdh01WQpAM= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.0 h1:zEJXwsuasmYH8dONZrCsZzcann/+6HZDKUPhN3mOmY0= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.0/go.mod h1:SaL9BCTeWcEmU9JiKgNihEXKnFKDTn91L9ehgvauWuM= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0 h1:UDIRWwiZ2/2ukmn60wPo83PUSuWPaXqbuRzkRTjRQNQ= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0/go.mod h1:ErMQspxm7+XmtOsEM6lTD73oALPq3lUC5s+JQkm6Y/s= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0 h1:fPCdQOsdPB1QqwcgytrROk+h5va49CAnp5YSCIrKZWY= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0/go.mod h1:Hs8RwANfF2ZKqOowPBqMQqLoRHcMobiKAihWWirAdEU= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.3.0 h1:S1DFVy2wwSiAFgNPpB527Q/YDQpSaduIFOMX988sZOE= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.3.0/go.mod h1:1bANbviG6h5XaD3bBnC3v+eDWf5LBYLtLEF/ih+U4kA= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0 h1:PwfpDFGUUJ8+Go5hJf+/hA5CHfY+DPS1cqIUYH+zWtE= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0/go.mod h1:Hb21FmYP95q0fzOb9jk4/9CIxTsHzrSYDQZh6e82XUg= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 h1:cESGAkm0ftADRBfdbiyx3pp/KVQ8JgmUQdRzpwG61wE= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0/go.mod h1:aYPLsiImzWaYXEfYIZ0wJnV56PwcR+buy8Xu9jjbfGA= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 h1:TMUxDh8XGgWUpnWo7GsawVq2ICDsy/r8dMlfC26MR5g= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0/go.mod h1:giHnHz3kHeLY8Av9MZLsyJlaTXYz+BuGqdP/SKB5Vo0= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0 h1:y+XzJcntHJ7M+IWWvAUkiVFA8op+jZxwHs3ktW2aLoA= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0/go.mod h1:J/Wa67cbDI1wAyxib9PiEbNqGfIoFUH+DSLueVazQx8= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0 h1:QG+rGBHsyXOlJ3ZIeOgExGqu9PoTlGY1rltW/VpG6lw= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0/go.mod h1:16dOVT052cMuHhUJ3NIcPuY7TrpCr9QlxmvvfjLZubA= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0 h1:3KUVls8zXsbT2tOYRSHyp3/l0Kpjl4f3INmQKYTe65Y= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0/go.mod h1:63IvXpBJTIVONAnGPSDo0sRJ+6n6tzO918OLqfYBxto= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.10.0 h1:STq6VaVUeHLeXzl1r5E4+MK5lcNVtdKjjP7N0XOowY4= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.10.0/go.mod h1:hdeLDwSCOmGIYtY4DGN15kjL44DQvo/txHXtTEvZidA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= From bda75fca2861485d4b829f6685ecf598e0941f7e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 24 Feb 2025 09:30:31 +0100 Subject: [PATCH 206/619] fix(deps): update module github.com/google/go-cmp to v0.7.0 (#630) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7e33bf0a6..50526fe09 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/fatih/color v1.18.0 github.com/goccy/go-yaml v1.15.23 github.com/golang-jwt/jwt/v5 v5.2.1 - github.com/google/go-cmp v0.6.0 + github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jedib0t/go-pretty/v6 v6.6.6 diff --git a/go.sum b/go.sum index e4754a600..ee472c853 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6 github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= From bdf28fc067b64a58185f63f73f47a195091030fb Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Mon, 24 Feb 2025 12:20:54 +0100 Subject: [PATCH 207/619] Fix/network area and network missing label selector (#627) * Onboard: Labels for network-area Signed-off-by: Alexander Dahmen * Onboard: Labels for network Signed-off-by: Alexander Dahmen * generate-docs Signed-off-by: Alexander Dahmen --------- Signed-off-by: Alexander Dahmen --- docs/stackit_beta_network-area_create.md | 4 ++++ docs/stackit_beta_network-area_list.md | 4 ++++ docs/stackit_beta_network-area_update.md | 1 + docs/stackit_beta_network_create.md | 4 ++++ docs/stackit_beta_network_list.md | 8 ++++++-- docs/stackit_beta_network_update.md | 1 + .../cmd/beta/network-area/create/create.go | 20 ++++++++++++++++++- .../beta/network-area/create/create_test.go | 17 ++++++++++++++++ .../beta/network-area/describe/describe.go | 8 ++++++++ internal/cmd/beta/network-area/list/list.go | 14 ++++++++++++- .../cmd/beta/network-area/list/list_test.go | 14 +++++++++++++ .../cmd/beta/network-area/update/update.go | 16 ++++++++++++++- .../beta/network-area/update/update_test.go | 18 +++++++++++++++++ internal/cmd/beta/network/create/create.go | 18 +++++++++++++++++ .../cmd/beta/network/create/create_test.go | 17 ++++++++++++++++ .../cmd/beta/network/describe/describe.go | 8 ++++++++ internal/cmd/beta/network/list/list.go | 18 ++++++++++++++--- internal/cmd/beta/network/list/list_test.go | 20 ++++++++++++++++--- internal/cmd/beta/network/update/update.go | 16 ++++++++++++++- .../cmd/beta/network/update/update_test.go | 18 +++++++++++++++++ 20 files changed, 232 insertions(+), 12 deletions(-) diff --git a/docs/stackit_beta_network-area_create.md b/docs/stackit_beta_network-area_create.md index ed018d657..5edf5af6e 100644 --- a/docs/stackit_beta_network-area_create.md +++ b/docs/stackit_beta_network-area_create.md @@ -21,6 +21,9 @@ stackit beta network-area create [flags] Create a network area with name "network-area-3" in organization with ID "xxx" with network ranges, transfer network and additional options $ stackit beta network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24 + + Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network and labels "key=value,key1=value1" + $ stackit beta network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1 ``` ### Options @@ -29,6 +32,7 @@ stackit beta network-area create [flags] --default-prefix-length int The default prefix length for networks in the network area --dns-name-servers strings List of DNS name server IPs -h, --help Help for "stackit beta network-area create" + --labels stringToString Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...' (default []) --max-prefix-length int The maximum prefix length for networks in the network area --min-prefix-length int The minimum prefix length for networks in the network area -n, --name string Network area name diff --git a/docs/stackit_beta_network-area_list.md b/docs/stackit_beta_network-area_list.md index a76462e33..2cdfb14b5 100644 --- a/docs/stackit_beta_network-area_list.md +++ b/docs/stackit_beta_network-area_list.md @@ -21,12 +21,16 @@ stackit beta network-area list [flags] Lists up to 10 network areas of organization "xxx" $ stackit beta network-area list --organization-id xxx --limit 10 + + Lists all network areas of organization "xxx" which contains the label yyy + $ stackit beta network-area list --organization-id xxx --label-selector yyy ``` ### Options ``` -h, --help Help for "stackit beta network-area list" + --label-selector string Filter by label --limit int Maximum number of entries to list --organization-id string Organization ID ``` diff --git a/docs/stackit_beta_network-area_update.md b/docs/stackit_beta_network-area_update.md index 3616afaef..8c149885e 100644 --- a/docs/stackit_beta_network-area_update.md +++ b/docs/stackit_beta_network-area_update.md @@ -23,6 +23,7 @@ stackit beta network-area update AREA_ID [flags] --default-prefix-length int The default prefix length for networks in the network area --dns-name-servers strings List of DNS name server IPs -h, --help Help for "stackit beta network-area update" + --labels stringToString Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...' (default []) --max-prefix-length int The maximum prefix length for networks in the network area --min-prefix-length int The minimum prefix length for networks in the network area -n, --name string Network area name diff --git a/docs/stackit_beta_network_create.md b/docs/stackit_beta_network_create.md index 11e816773..9b4c711af 100644 --- a/docs/stackit_beta_network_create.md +++ b/docs/stackit_beta_network_create.md @@ -22,6 +22,9 @@ stackit beta network create [flags] Create a network with name "network-1" and no gateway $ stackit beta network create --name network-1 --no-ipv4-gateway + Create a network with name "network-1" and labels "key=value,key1=value1" + $ stackit beta network create --name network-1 --labels key=value,key1=value1 + Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway $ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3" @@ -41,6 +44,7 @@ stackit beta network create [flags] --ipv6-gateway string The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway --ipv6-prefix string The IPv6 prefix of the network (CIDR) --ipv6-prefix-length int The prefix length of the IPv6 network + --labels stringToString Labels are key-value string pairs which can be attached to a network. E.g. '--labels key1=value1,key2=value2,...' (default []) -n, --name string Network name --no-ipv4-gateway If set to true, the network doesn't have an IPv4 gateway --no-ipv6-gateway If set to true, the network doesn't have an IPv6 gateway diff --git a/docs/stackit_beta_network_list.md b/docs/stackit_beta_network_list.md index 0aa13029c..0edb4bbec 100644 --- a/docs/stackit_beta_network_list.md +++ b/docs/stackit_beta_network_list.md @@ -21,13 +21,17 @@ stackit beta network list [flags] Lists up to 10 networks $ stackit beta network list --limit 10 + + Lists all networks which contains the label xxx + $ tackit beta network list --label-selector xxx ``` ### Options ``` - -h, --help Help for "stackit beta network list" - --limit int Maximum number of entries to list + -h, --help Help for "stackit beta network list" + --label-selector string Filter by label + --limit int Maximum number of entries to list ``` ### Options inherited from parent commands diff --git a/docs/stackit_beta_network_update.md b/docs/stackit_beta_network_update.md index 24b1326d2..35b76c078 100644 --- a/docs/stackit_beta_network_update.md +++ b/docs/stackit_beta_network_update.md @@ -34,6 +34,7 @@ stackit beta network update NETWORK_ID [flags] --ipv4-gateway string The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway --ipv6-dns-name-servers strings List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks --ipv6-gateway string The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway + --labels stringToString Labels are key-value string pairs which can be attached to a network. E.g. '--labels key1=value1,key2=value2,...' (default []) -n, --name string Network name --no-ipv4-gateway If set to true, the network doesn't have an IPv4 gateway --no-ipv6-gateway If set to true, the network doesn't have an IPv6 gateway diff --git a/internal/cmd/beta/network-area/create/create.go b/internal/cmd/beta/network-area/create/create.go index 0987e96c4..3c348908f 100644 --- a/internal/cmd/beta/network-area/create/create.go +++ b/internal/cmd/beta/network-area/create/create.go @@ -29,6 +29,7 @@ const ( defaultPrefixLengthFlag = "default-prefix-length" maxPrefixLengthFlag = "max-prefix-length" minPrefixLengthFlag = "min-prefix-length" + labelFlag = "labels" ) type inputModel struct { @@ -41,6 +42,7 @@ type inputModel struct { DefaultPrefixLength *int64 MaxPrefixLength *int64 MinPrefixLength *int64 + Labels *map[string]string } func NewCmd(p *print.Printer) *cobra.Command { @@ -62,6 +64,10 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a network area with name "network-area-3" in organization with ID "xxx" with network ranges, transfer network and additional options`, `$ stackit beta network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24`, ), + examples.NewExample( + `Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network and labels "key=value,key1=value1"`, + `$ stackit beta network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1`, + ), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() @@ -121,6 +127,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(defaultPrefixLengthFlag, 0, "The default prefix length for networks in the network area") cmd.Flags().Int64(maxPrefixLengthFlag, 0, "The maximum prefix length for networks in the network area") cmd.Flags().Int64(minPrefixLengthFlag, 0, "The minimum prefix length for networks in the network area") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...'") err := flags.MarkFlagsRequired(cmd, nameFlag, organizationIdFlag, networkRangesFlag, transferNetworkFlag) cobra.CheckErr(err) @@ -139,6 +146,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { DefaultPrefixLength: flags.FlagToInt64Pointer(p, cmd, defaultPrefixLengthFlag), MaxPrefixLength: flags.FlagToInt64Pointer(p, cmd, maxPrefixLengthFlag), MinPrefixLength: flags.FlagToInt64Pointer(p, cmd, minPrefixLengthFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } if p.IsVerbosityDebug() { @@ -163,8 +171,18 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } } + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + payload := iaas.CreateNetworkAreaPayload{ - Name: model.Name, + Name: model.Name, + Labels: labelsMap, AddressFamily: &iaas.CreateAreaAddressFamily{ Ipv4: &iaas.CreateAreaIPv4{ DefaultNameservers: model.DnsNameServers, diff --git a/internal/cmd/beta/network-area/create/create_test.go b/internal/cmd/beta/network-area/create/create_test.go index b6a34625f..ee055ad5c 100644 --- a/internal/cmd/beta/network-area/create/create_test.go +++ b/internal/cmd/beta/network-area/create/create_test.go @@ -31,6 +31,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st defaultPrefixLengthFlag: "24", maxPrefixLengthFlag: "24", minPrefixLengthFlag: "24", + labelFlag: "key=value", } for _, mod := range mods { mod(flagValues) @@ -51,6 +52,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { DefaultPrefixLength: utils.Ptr(int64(24)), MaxPrefixLength: utils.Ptr(int64(24)), MinPrefixLength: utils.Ptr(int64(24)), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), } for _, mod := range mods { mod(model) @@ -70,6 +74,9 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkAreaRequest)) iaa func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaPayload)) iaas.CreateNetworkAreaPayload { payload := iaas.CreateNetworkAreaPayload{ Name: utils.Ptr("example-network-area-name"), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), AddressFamily: &iaas.CreateAreaAddressFamily{ Ipv4: &iaas.CreateAreaIPv4{ DefaultNameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), @@ -171,6 +178,16 @@ func TestParseInput(t *testing.T) { }), isValid: false, }, + { + description: "labels missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + isValid: true, + }, } for _, tt := range tests { diff --git a/internal/cmd/beta/network-area/describe/describe.go b/internal/cmd/beta/network-area/describe/describe.go index 51be436b9..22cc7018e 100644 --- a/internal/cmd/beta/network-area/describe/describe.go +++ b/internal/cmd/beta/network-area/describe/describe.go @@ -202,6 +202,14 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo table.AddSeparator() } } + if networkArea.Labels != nil && len(*networkArea.Labels) > 0 { + var labels []string + for key, value := range *networkArea.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } if len(attachedProjects) > 0 { table.AddRow("ATTACHED PROJECTS IDS", strings.Join(attachedProjects, "\n")) table.AddSeparator() diff --git a/internal/cmd/beta/network-area/list/list.go b/internal/cmd/beta/network-area/list/list.go index 2280da2ad..fef600ab3 100644 --- a/internal/cmd/beta/network-area/list/list.go +++ b/internal/cmd/beta/network-area/list/list.go @@ -24,12 +24,14 @@ import ( const ( limitFlag = "limit" organizationIdFlag = "organization-id" + labelSelectorFlag = "label-selector" ) type inputModel struct { *globalflags.GlobalFlagModel Limit *int64 OrganizationId *string + LabelSelector *string } func NewCmd(p *print.Printer) *cobra.Command { @@ -51,6 +53,10 @@ func NewCmd(p *print.Printer) *cobra.Command { `Lists up to 10 network areas of organization "xxx"`, "$ stackit beta network-area list --organization-id xxx --limit 10", ), + examples.NewExample( + `Lists all network areas of organization "xxx" which contains the label yyy`, + "$ stackit beta network-area list --organization-id xxx --label-selector yyy", + ), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() @@ -106,6 +112,7 @@ func NewCmd(p *print.Printer) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") err := flags.MarkFlagsRequired(cmd, organizationIdFlag) cobra.CheckErr(err) @@ -125,6 +132,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, Limit: limit, OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } if p.IsVerbosityDebug() { @@ -140,7 +148,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworkAreasRequest { - return apiClient.ListNetworkAreas(ctx, *model.OrganizationId) + req := apiClient.ListNetworkAreas(ctx, *model.OrganizationId) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + return req } func outputResult(p *print.Printer, outputFormat string, networkAreas []iaas.NetworkArea) error { diff --git a/internal/cmd/beta/network-area/list/list_test.go b/internal/cmd/beta/network-area/list/list_test.go index 01d94cb37..4b71b3dda 100644 --- a/internal/cmd/beta/network-area/list/list_test.go +++ b/internal/cmd/beta/network-area/list/list_test.go @@ -19,11 +19,13 @@ type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &iaas.APIClient{} var testOrganizationId = uuid.NewString() +var testLabelSelector = "foo=bar" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ organizationIdFlag: testOrganizationId, limitFlag: "10", + labelSelectorFlag: testLabelSelector, } for _, mod := range mods { mod(flagValues) @@ -38,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { }, OrganizationId: &testOrganizationId, Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr(testLabelSelector), } for _, mod := range mods { mod(model) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreasRequest)) iaas.ApiListNetworkAreasRequest { request := testClient.ListNetworkAreas(testCtx, testOrganizationId) + request = request.LabelSelector(testLabelSelector) for _, mod := range mods { mod(&request) } @@ -111,6 +115,16 @@ func TestParseInput(t *testing.T) { }), isValid: false, }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "" + }), + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.LabelSelector = utils.Ptr("") + }), + }, } for _, tt := range tests { diff --git a/internal/cmd/beta/network-area/update/update.go b/internal/cmd/beta/network-area/update/update.go index 7fe9f4602..9aab1f1d9 100644 --- a/internal/cmd/beta/network-area/update/update.go +++ b/internal/cmd/beta/network-area/update/update.go @@ -30,6 +30,7 @@ const ( defaultPrefixLengthFlag = "default-prefix-length" maxPrefixLengthFlag = "max-prefix-length" minPrefixLengthFlag = "min-prefix-length" + labelFlag = "labels" ) type inputModel struct { @@ -41,6 +42,7 @@ type inputModel struct { DefaultPrefixLength *int64 MaxPrefixLength *int64 MinPrefixLength *int64 + Labels *map[string]string } func NewCmd(p *print.Printer) *cobra.Command { @@ -111,6 +113,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(defaultPrefixLengthFlag, 0, "The default prefix length for networks in the network area") cmd.Flags().Int64(maxPrefixLengthFlag, 0, "The maximum prefix length for networks in the network area") cmd.Flags().Int64(minPrefixLengthFlag, 0, "The minimum prefix length for networks in the network area") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...'") err := flags.MarkFlagsRequired(cmd, organizationIdFlag) cobra.CheckErr(err) @@ -130,6 +133,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu DefaultPrefixLength: flags.FlagToInt64Pointer(p, cmd, defaultPrefixLengthFlag), MaxPrefixLength: flags.FlagToInt64Pointer(p, cmd, maxPrefixLengthFlag), MinPrefixLength: flags.FlagToInt64Pointer(p, cmd, minPrefixLengthFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } if p.IsVerbosityDebug() { @@ -147,8 +151,18 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiPartialUpdateNetworkAreaRequest { req := apiClient.PartialUpdateNetworkArea(ctx, *model.OrganizationId, model.AreaId) + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + payload := iaas.PartialUpdateNetworkAreaPayload{ - Name: model.Name, + Name: model.Name, + Labels: labelsMap, AddressFamily: &iaas.UpdateAreaAddressFamily{ Ipv4: &iaas.UpdateAreaIPv4{ DefaultNameservers: model.DnsNameServers, diff --git a/internal/cmd/beta/network-area/update/update_test.go b/internal/cmd/beta/network-area/update/update_test.go index 2d1581b12..807ec124f 100644 --- a/internal/cmd/beta/network-area/update/update_test.go +++ b/internal/cmd/beta/network-area/update/update_test.go @@ -40,6 +40,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st defaultPrefixLengthFlag: "24", maxPrefixLengthFlag: "24", minPrefixLengthFlag: "24", + labelFlag: "key=value", } for _, mod := range mods { mod(flagValues) @@ -59,6 +60,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { DefaultPrefixLength: utils.Ptr(int64(24)), MaxPrefixLength: utils.Ptr(int64(24)), MinPrefixLength: utils.Ptr(int64(24)), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), } for _, mod := range mods { mod(model) @@ -78,6 +82,9 @@ func fixtureRequest(mods ...func(request *iaas.ApiPartialUpdateNetworkAreaReques func fixturePayload(mods ...func(payload *iaas.PartialUpdateNetworkAreaPayload)) iaas.PartialUpdateNetworkAreaPayload { payload := iaas.PartialUpdateNetworkAreaPayload{ Name: utils.Ptr("example-network-area-name"), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), AddressFamily: &iaas.UpdateAreaAddressFamily{ Ipv4: &iaas.UpdateAreaIPv4{ DefaultNameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), @@ -183,6 +190,17 @@ func TestParseInput(t *testing.T) { }), isValid: false, }, + { + description: "labels missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + isValid: true, + }, } for _, tt := range tests { diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/beta/network/create/create.go index 2d902e599..38edf55ac 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/beta/network/create/create.go @@ -35,6 +35,7 @@ const ( nonRoutedFlag = "non-routed" noIpv4GatewayFlag = "no-ipv4-gateway" noIpv6GatewayFlag = "no-ipv6-gateway" + labelFlag = "labels" ) type inputModel struct { @@ -51,6 +52,7 @@ type inputModel struct { NonRouted bool NoIPv4Gateway bool NoIPv6Gateway bool + Labels *map[string]string } func NewCmd(p *print.Printer) *cobra.Command { @@ -72,6 +74,10 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a network with name "network-1" and no gateway`, `$ stackit beta network create --name network-1 --no-ipv4-gateway`, ), + examples.NewExample( + `Create a network with name "network-1" and labels "key=value,key1=value1"`, + `$ stackit beta network create --name network-1 --labels key=value,key1=value1`, + ), examples.NewExample( `Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway`, `$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3"`, @@ -149,6 +155,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(nonRoutedFlag, false, "If set to true, the network is not routed and therefore not accessible from other networks") cmd.Flags().Bool(noIpv4GatewayFlag, false, "If set to true, the network doesn't have an IPv4 gateway") cmd.Flags().Bool(noIpv6GatewayFlag, false, "If set to true, the network doesn't have an IPv6 gateway") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network. E.g. '--labels key1=value1,key2=value2,...'") err := flags.MarkFlagsRequired(cmd, nameFlag) cobra.CheckErr(err) @@ -174,6 +181,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { NonRouted: flags.FlagToBoolValue(p, cmd, nonRoutedFlag), NoIPv4Gateway: flags.FlagToBoolValue(p, cmd, noIpv4GatewayFlag), NoIPv6Gateway: flags.FlagToBoolValue(p, cmd, noIpv6GatewayFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } if p.IsVerbosityDebug() { @@ -220,6 +228,15 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } } + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + routed := true if model.NonRouted { routed = false @@ -227,6 +244,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli payload := iaas.CreateNetworkPayload{ Name: model.Name, + Labels: labelsMap, Routed: &routed, } diff --git a/internal/cmd/beta/network/create/create_test.go b/internal/cmd/beta/network/create/create_test.go index 804cd0d25..19edc1d40 100644 --- a/internal/cmd/beta/network/create/create_test.go +++ b/internal/cmd/beta/network/create/create_test.go @@ -36,6 +36,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st ipv6PrefixFlag: "2001:4860:4860::8888", ipv6GatewayFlag: "2001:4860:4860::8888", nonRoutedFlag: "false", + labelFlag: "key=value", } for _, mod := range mods { mod(flagValues) @@ -59,6 +60,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { IPv6Prefix: utils.Ptr("2001:4860:4860::8888"), IPv6Gateway: utils.Ptr("2001:4860:4860::8888"), NonRouted: false, + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), } for _, mod := range mods { mod(model) @@ -91,6 +95,9 @@ func fixturePayload(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.Creat payload := iaas.CreateNetworkPayload{ Name: utils.Ptr("example-network-name"), Routed: utils.Ptr(true), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), AddressFamily: &iaas.CreateNetworkAddressFamily{ Ipv4: &iaas.CreateNetworkIPv4Body{ Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), @@ -236,6 +243,16 @@ func TestParseInput(t *testing.T) { model.NonRouted = true }), }, + { + description: "labels missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + isValid: true, + }, } for _, tt := range tests { diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/beta/network/describe/describe.go index 356e2540d..e98cd01e6 100644 --- a/internal/cmd/beta/network/describe/describe.go +++ b/internal/cmd/beta/network/describe/describe.go @@ -190,6 +190,14 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) table.AddRow("IPv6 PREFIXES", strings.Join(ipv6prefixes, ", ")) } table.AddSeparator() + if network.Labels != nil && len(*network.Labels) > 0 { + var labels []string + for key, value := range *network.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } err := table.Display(p) if err != nil { diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/beta/network/list/list.go index 9b3a9a0cc..7ed81d62c 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/beta/network/list/list.go @@ -22,12 +22,14 @@ import ( ) const ( - limitFlag = "limit" + limitFlag = "limit" + labelSelectorFlag = "label-selector" ) type inputModel struct { *globalflags.GlobalFlagModel - Limit *int64 + Limit *int64 + LabelSelector *string } func NewCmd(p *print.Printer) *cobra.Command { @@ -49,6 +51,10 @@ func NewCmd(p *print.Printer) *cobra.Command { `Lists up to 10 networks`, "$ stackit beta network list --limit 10", ), + examples.NewExample( + `Lists all networks which contains the label xxx`, + "$ tackit beta network list --label-selector xxx", + ), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() @@ -97,6 +103,7 @@ func NewCmd(p *print.Printer) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter by label") } func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { @@ -116,6 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { model := inputModel{ GlobalFlagModel: globalFlags, Limit: limit, + LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } if p.IsVerbosityDebug() { @@ -131,7 +139,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworksRequest { - return apiClient.ListNetworks(ctx, model.ProjectId) + req := apiClient.ListNetworks(ctx, model.ProjectId) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + return req } func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network) error { diff --git a/internal/cmd/beta/network/list/list_test.go b/internal/cmd/beta/network/list/list_test.go index 0d69a3f5e..9bc47dfb5 100644 --- a/internal/cmd/beta/network/list/list_test.go +++ b/internal/cmd/beta/network/list/list_test.go @@ -21,11 +21,13 @@ type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &iaas.APIClient{} var testProjectId = uuid.NewString() +var testLabelSelector = "foo=bar" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + projectIdFlag: testProjectId, + limitFlag: "10", + labelSelectorFlag: testLabelSelector, } for _, mod := range mods { mod(flagValues) @@ -39,7 +41,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, }, - Limit: utils.Ptr(int64(10)), + Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr(testLabelSelector), } for _, mod := range mods { mod(model) @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func fixtureRequest(mods ...func(request *iaas.ApiListNetworksRequest)) iaas.ApiListNetworksRequest { request := testClient.ListNetworks(testCtx, testProjectId) + request = request.LabelSelector(testLabelSelector) for _, mod := range mods { mod(&request) } @@ -113,6 +117,16 @@ func TestParseInput(t *testing.T) { }), isValid: false, }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[labelSelectorFlag] = "" + }), + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.LabelSelector = utils.Ptr("") + }), + }, } for _, tt := range tests { diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/beta/network/update/update.go index 2148fa58d..24c1c5e74 100644 --- a/internal/cmd/beta/network/update/update.go +++ b/internal/cmd/beta/network/update/update.go @@ -30,6 +30,7 @@ const ( ipv6GatewayFlag = "ipv6-gateway" noIpv4GatewayFlag = "no-ipv4-gateway" noIpv6GatewayFlag = "no-ipv6-gateway" + labelFlag = "labels" ) type inputModel struct { @@ -42,6 +43,7 @@ type inputModel struct { IPv6Gateway *string NoIPv4Gateway bool NoIPv6Gateway bool + Labels *map[string]string } func NewCmd(p *print.Printer) *cobra.Command { @@ -136,6 +138,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(ipv6GatewayFlag, "", "The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway") cmd.Flags().Bool(noIpv4GatewayFlag, false, "If set to true, the network doesn't have an IPv4 gateway") cmd.Flags().Bool(noIpv6GatewayFlag, false, "If set to true, the network doesn't have an IPv6 gateway") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network. E.g. '--labels key1=value1,key2=value2,...'") } func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { @@ -156,6 +159,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu IPv6Gateway: flags.FlagToStringPointer(p, cmd, ipv6GatewayFlag), NoIPv4Gateway: flags.FlagToBoolValue(p, cmd, noIpv4GatewayFlag), NoIPv6Gateway: flags.FlagToBoolValue(p, cmd, noIpv6GatewayFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } if p.IsVerbosityDebug() { @@ -174,6 +178,15 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli req := apiClient.PartialUpdateNetwork(ctx, model.ProjectId, model.NetworkId) addressFamily := &iaas.UpdateNetworkAddressFamily{} + var labelsMap *map[string]interface{} + if model.Labels != nil && len(*model.Labels) > 0 { + // convert map[string]string to map[string]interface{} + labelsMap = utils.Ptr(map[string]interface{}{}) + for k, v := range *model.Labels { + (*labelsMap)[k] = v + } + } + if model.IPv6DnsNameServers != nil || model.NoIPv6Gateway || model.IPv6Gateway != nil { addressFamily.Ipv6 = &iaas.UpdateNetworkIPv6Body{ Nameservers: model.IPv6DnsNameServers, @@ -199,7 +212,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } payload := iaas.PartialUpdateNetworkPayload{ - Name: model.Name, + Name: model.Name, + Labels: labelsMap, } if addressFamily.Ipv4 != nil || addressFamily.Ipv6 != nil { diff --git a/internal/cmd/beta/network/update/update_test.go b/internal/cmd/beta/network/update/update_test.go index 99b3e8ba6..7a1b243c5 100644 --- a/internal/cmd/beta/network/update/update_test.go +++ b/internal/cmd/beta/network/update/update_test.go @@ -42,6 +42,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st ipv4GatewayFlag: "10.1.2.3", ipv6DnsNameServersFlag: "2001:4860:4860::8888,2001:4860:4860::8844", ipv6GatewayFlag: "2001:4860:4860::8888", + labelFlag: "key=value", } for _, mod := range mods { mod(flagValues) @@ -61,6 +62,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { IPv4Gateway: utils.Ptr("10.1.2.3"), IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), IPv6Gateway: utils.Ptr("2001:4860:4860::8888"), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), } for _, mod := range mods { mod(model) @@ -80,6 +84,9 @@ func fixtureRequest(mods ...func(request *iaas.ApiPartialUpdateNetworkRequest)) func fixturePayload(mods ...func(payload *iaas.PartialUpdateNetworkPayload)) iaas.PartialUpdateNetworkPayload { payload := iaas.PartialUpdateNetworkPayload{ Name: utils.Ptr("example-network-name"), + Labels: utils.Ptr(map[string]interface{}{ + "key": "value", + }), AddressFamily: &iaas.UpdateNetworkAddressFamily{ Ipv4: &iaas.UpdateNetworkIPv4Body{ Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), @@ -218,6 +225,17 @@ func TestParseInput(t *testing.T) { model.IPv6Gateway = nil }), }, + { + description: "labels missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = nil + }), + isValid: true, + }, } for _, tt := range tests { From f8bb8e9f2f01f04aca982062a6ebd7e4c8e41e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 25 Feb 2025 11:19:44 +0100 Subject: [PATCH 208/619] fix(mariadb): add nil pointer checks for cmd outputs (#628) relates to STACKITCLI-103 --- .../cmd/mariadb/credentials/create/create.go | 14 ++++--- .../mariadb/credentials/create/create_test.go | 37 ++++++++++++++++ .../mariadb/credentials/describe/describe.go | 6 ++- .../credentials/describe/describe_test.go | 35 ++++++++++++++++ .../cmd/mariadb/credentials/list/list_test.go | 42 +++++++++++++++++++ .../cmd/mariadb/instance/create/create.go | 12 ++++-- .../mariadb/instance/create/create_test.go | 37 ++++++++++++++++ .../cmd/mariadb/instance/describe/describe.go | 28 ++++++++----- .../instance/describe/describe_test.go | 35 ++++++++++++++++ internal/cmd/mariadb/instance/list/list.go | 11 ++++- .../cmd/mariadb/instance/list/list_test.go | 42 +++++++++++++++++++ internal/cmd/mariadb/plans/plans.go | 22 +++++----- internal/cmd/mariadb/plans/plans_test.go | 42 +++++++++++++++++++ 13 files changed, 331 insertions(+), 32 deletions(-) diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 8fd77e4c1..880444860 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -79,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create MariaDB credentials: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, model.ShowPassword, instanceLabel, resp) }, } configureFlags(cmd) @@ -123,11 +123,15 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *mariadb.CredentialsResponse) error { - if !model.ShowPassword { +func outputResult(p *print.Printer, outputFormat string, showPassword bool, instanceLabel string, resp *mariadb.CredentialsResponse) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + if !showPassword && resp.HasRaw() && resp.Raw.Credentials != nil { resp.Raw.Credentials.Password = utils.Ptr("hidden") } - switch model.OutputFormat { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -151,7 +155,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res if username := resp.Raw.Credentials.Username; username != nil && *username != "" { p.Outputf("Username: %s\n", *username) } - if !model.ShowPassword { + if !showPassword { p.Outputf("Password: \n") } else { p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) diff --git a/internal/cmd/mariadb/credentials/create/create_test.go b/internal/cmd/mariadb/credentials/create/create_test.go index 9d012577b..d3202e596 100644 --- a/internal/cmd/mariadb/credentials/create/create_test.go +++ b/internal/cmd/mariadb/credentials/create/create_test.go @@ -200,3 +200,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + showPassword bool + instanceLabel string + credentials *mariadb.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty credentials", + args: args{ + credentials: &mariadb.CredentialsResponse{}, + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mariadb/credentials/describe/describe.go b/internal/cmd/mariadb/credentials/describe/describe.go index 8739c7d59..8e3e3f869 100644 --- a/internal/cmd/mariadb/credentials/describe/describe.go +++ b/internal/cmd/mariadb/credentials/describe/describe.go @@ -112,6 +112,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API } func outputResult(p *print.Printer, outputFormat string, credentials *mariadb.CredentialsResponse) error { + if credentials == nil { + return fmt.Errorf("credentials is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(credentials, "", " ") @@ -131,7 +135,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *mariadb.Cr return nil default: table := tables.NewTable() - table.AddRow("ID", *credentials.Id) + table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty if credentials.HasRaw() && credentials.Raw.Credentials != nil { diff --git a/internal/cmd/mariadb/credentials/describe/describe_test.go b/internal/cmd/mariadb/credentials/describe/describe_test.go index 27e96b383..f822d88f4 100644 --- a/internal/cmd/mariadb/credentials/describe/describe_test.go +++ b/internal/cmd/mariadb/credentials/describe/describe_test.go @@ -243,3 +243,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials *mariadb.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty credentials", + args: args{ + credentials: &mariadb.CredentialsResponse{}, + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mariadb/credentials/list/list_test.go b/internal/cmd/mariadb/credentials/list/list_test.go index ab667fbb4..978210a9f 100644 --- a/internal/cmd/mariadb/credentials/list/list_test.go +++ b/internal/cmd/mariadb/credentials/list/list_test.go @@ -207,3 +207,45 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []mariadb.CredentialsListItem + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty credentials slice", + args: args{ + credentials: []mariadb.CredentialsListItem{}, + }, + wantErr: false, + }, + { + name: "set empty credential in credentials slice", + args: args{ + credentials: []mariadb.CredentialsListItem{{}}, + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index 81732c1a6..3a2a4e4fb 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -125,7 +125,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) @@ -251,8 +251,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, resp *mariadb.CreateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -271,7 +275,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) diff --git a/internal/cmd/mariadb/instance/create/create_test.go b/internal/cmd/mariadb/instance/create/create_test.go index 554b7db9a..0e797ff1e 100644 --- a/internal/cmd/mariadb/instance/create/create_test.go +++ b/internal/cmd/mariadb/instance/create/create_test.go @@ -463,3 +463,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + resp *mariadb.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty response", + args: args{ + resp: &mariadb.CreateInstanceResponse{}, + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mariadb/instance/describe/describe.go b/internal/cmd/mariadb/instance/describe/describe.go index 952754762..b3b8013a6 100644 --- a/internal/cmd/mariadb/instance/describe/describe.go +++ b/internal/cmd/mariadb/instance/describe/describe.go @@ -100,6 +100,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API } func outputResult(p *print.Printer, outputFormat string, instance *mariadb.Instance) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -123,18 +127,22 @@ func outputResult(p *print.Printer, outputFormat string, instance *mariadb.Insta table.AddSeparator() table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) - table.AddSeparator() - table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) - table.AddSeparator() + if instance.LastOperation != nil { + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) + table.AddSeparator() + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) + table.AddSeparator() + } table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty - acl := (*instance.Parameters)[aclParameterKey] - aclStr, ok := acl.(string) - if ok { - if aclStr != "" { - table.AddSeparator() - table.AddRow("ACL", aclStr) + if instance.Parameters != nil { + acl := (*instance.Parameters)[aclParameterKey] + aclStr, ok := acl.(string) + if ok { + if aclStr != "" { + table.AddSeparator() + table.AddRow("ACL", aclStr) + } } } err := table.Display(p) diff --git a/internal/cmd/mariadb/instance/describe/describe_test.go b/internal/cmd/mariadb/instance/describe/describe_test.go index f7bb4cfca..555f7bcbf 100644 --- a/internal/cmd/mariadb/instance/describe/describe_test.go +++ b/internal/cmd/mariadb/instance/describe/describe_test.go @@ -216,3 +216,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *mariadb.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty instance", + args: args{ + instance: &mariadb.Instance{}, + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index 37c5afff4..2b2dbe70c 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -152,11 +152,18 @@ func outputResult(p *print.Printer, outputFormat string, instances []mariadb.Ins table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] + + lastOperationType, lastOperationState := "", "" + if instance.LastOperation != nil { + lastOperationType = utils.PtrString(instance.LastOperation.Type) + lastOperationState = utils.PtrString(instance.LastOperation.State) + } + table.AddRow( utils.PtrString(instance.InstanceId), utils.PtrString(instance.Name), - utils.PtrString(instance.LastOperation.Type), - utils.PtrString(instance.LastOperation.State), + lastOperationType, + lastOperationState, ) } err := table.Display(p) diff --git a/internal/cmd/mariadb/instance/list/list_test.go b/internal/cmd/mariadb/instance/list/list_test.go index 82ed3955f..a7b29714f 100644 --- a/internal/cmd/mariadb/instance/list/list_test.go +++ b/internal/cmd/mariadb/instance/list/list_test.go @@ -186,3 +186,45 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instances []mariadb.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty instances slice", + args: args{ + instances: []mariadb.Instance{}, + }, + wantErr: false, + }, + { + name: "set empty instance in instances slice", + args: args{ + instances: []mariadb.Instance{{}}, + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index bd3d31957..e4d3bf021 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -152,17 +152,19 @@ func outputResult(p *print.Printer, outputFormat string, plans []mariadb.Offerin table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { o := plans[i] - for j := range *o.Plans { - plan := (*o.Plans)[j] - table.AddRow( - utils.PtrString(o.Name), - utils.PtrString(o.Version), - utils.PtrString(plan.Id), - utils.PtrString(plan.Name), - utils.PtrString(plan.Description), - ) + if o.Plans != nil { + for j := range *o.Plans { + plan := (*o.Plans)[j] + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + ) + } + table.AddSeparator() } - table.AddSeparator() } table.EnableAutoMergeOnColumns(1, 2) err := table.Display(p) diff --git a/internal/cmd/mariadb/plans/plans_test.go b/internal/cmd/mariadb/plans/plans_test.go index 7c6e4b7d7..3d8f56a28 100644 --- a/internal/cmd/mariadb/plans/plans_test.go +++ b/internal/cmd/mariadb/plans/plans_test.go @@ -186,3 +186,45 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + plans []mariadb.Offering + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty plans slice", + args: args{ + plans: []mariadb.Offering{}, + }, + wantErr: false, + }, + { + name: "set empty plan in plans slice", + args: args{ + plans: []mariadb.Offering{{}}, + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From b5c5cadd94e199c5539df0d3c51089140e6f7a6d Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Tue, 25 Feb 2025 11:31:53 +0100 Subject: [PATCH 209/619] chore(volume): Add nil pointer checks and tests for outputResult functions (#623) Signed-off-by: Alexander Dahmen --- internal/cmd/beta/volume/create/create.go | 3 ++ .../cmd/beta/volume/create/create_test.go | 43 +++++++++++++++++-- internal/cmd/beta/volume/delete/delete.go | 6 ++- internal/cmd/beta/volume/describe/describe.go | 3 ++ .../cmd/beta/volume/describe/describe_test.go | 39 +++++++++++++++-- internal/cmd/beta/volume/list/list_test.go | 41 ++++++++++++++++-- .../performance-class/describe/describe.go | 3 ++ .../describe/describe_test.go | 39 +++++++++++++++-- .../performance-class/list/list_test.go | 41 ++++++++++++++++-- internal/cmd/beta/volume/update/update.go | 9 ++-- .../cmd/beta/volume/update/update_test.go | 42 ++++++++++++++++-- 11 files changed, 242 insertions(+), 27 deletions(-) diff --git a/internal/cmd/beta/volume/create/create.go b/internal/cmd/beta/volume/create/create.go index 38cfdbe4f..a00446f90 100644 --- a/internal/cmd/beta/volume/create/create.go +++ b/internal/cmd/beta/volume/create/create.go @@ -199,6 +199,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, model *inputModel, projectLabel string, volume *iaas.Volume) error { + if volume == nil { + return fmt.Errorf("volume response is empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(volume, "", " ") diff --git a/internal/cmd/beta/volume/create/create_test.go b/internal/cmd/beta/volume/create/create_test.go index c9fecec3a..71f3e1697 100644 --- a/internal/cmd/beta/volume/create/create_test.go +++ b/internal/cmd/beta/volume/create/create_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -284,3 +283,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + volume *iaas.Volume + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "volume as argument", + args: args{ + model: fixtureInputModel(), + volume: &iaas.Volume{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.volume); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/volume/delete/delete.go b/internal/cmd/beta/volume/delete/delete.go index ca52fa148..068c0f2ea 100644 --- a/internal/cmd/beta/volume/delete/delete.go +++ b/internal/cmd/beta/volume/delete/delete.go @@ -56,10 +56,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel := model.VolumeId + volumeName, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { p.Debug(print.ErrorLevel, "get volume name: %v", err) - volumeLabel = model.VolumeId + } else if volumeName != "" { + volumeLabel = volumeName } if !model.AssumeYes { diff --git a/internal/cmd/beta/volume/describe/describe.go b/internal/cmd/beta/volume/describe/describe.go index 4dab40860..b69b32332 100644 --- a/internal/cmd/beta/volume/describe/describe.go +++ b/internal/cmd/beta/volume/describe/describe.go @@ -102,6 +102,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, volume *iaas.Volume) error { + if volume == nil { + return fmt.Errorf("volume response is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(volume, "", " ") diff --git a/internal/cmd/beta/volume/describe/describe_test.go b/internal/cmd/beta/volume/describe/describe_test.go index 8f3fcdd57..3de0f688b 100644 --- a/internal/cmd/beta/volume/describe/describe_test.go +++ b/internal/cmd/beta/volume/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -216,3 +215,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + volume *iaas.Volume + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "volume as argument", + args: args{ + volume: &iaas.Volume{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.volume); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/volume/list/list_test.go b/internal/cmd/beta/volume/list/list_test.go index ea1b60ad3..77cc3808b 100644 --- a/internal/cmd/beta/volume/list/list_test.go +++ b/internal/cmd/beta/volume/list/list_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -202,3 +201,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + volumes []iaas.Volume + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty volume", + args: args{ + volumes: []iaas.Volume{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.volumes); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/volume/performance-class/describe/describe.go b/internal/cmd/beta/volume/performance-class/describe/describe.go index 6ed6c261b..9d8537858 100644 --- a/internal/cmd/beta/volume/performance-class/describe/describe.go +++ b/internal/cmd/beta/volume/performance-class/describe/describe.go @@ -102,6 +102,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, performanceClass *iaas.VolumePerformanceClass) error { + if performanceClass == nil { + return fmt.Errorf("performanceClass response is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(performanceClass, "", " ") diff --git a/internal/cmd/beta/volume/performance-class/describe/describe_test.go b/internal/cmd/beta/volume/performance-class/describe/describe_test.go index 2a43beaf1..90ba0da3c 100644 --- a/internal/cmd/beta/volume/performance-class/describe/describe_test.go +++ b/internal/cmd/beta/volume/performance-class/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -210,3 +209,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + performanceClass *iaas.VolumePerformanceClass + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "volume performance class as argument", + args: args{ + performanceClass: &iaas.VolumePerformanceClass{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.performanceClass); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/volume/performance-class/list/list_test.go b/internal/cmd/beta/volume/performance-class/list/list_test.go index 91c2041bb..9e23bbdfd 100644 --- a/internal/cmd/beta/volume/performance-class/list/list_test.go +++ b/internal/cmd/beta/volume/performance-class/list/list_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -202,3 +201,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + performanceClasses []iaas.VolumePerformanceClass + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty volume", + args: args{ + performanceClasses: []iaas.VolumePerformanceClass{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.performanceClasses); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/volume/update/update.go b/internal/cmd/beta/volume/update/update.go index c8a49a617..ffc5273cb 100644 --- a/internal/cmd/beta/volume/update/update.go +++ b/internal/cmd/beta/volume/update/update.go @@ -90,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update volume: %w", err) } - return outputResult(p, model, volumeLabel, resp) + return outputResult(p, model.OutputFormat, volumeLabel, resp) }, } configureFlags(cmd) @@ -152,8 +152,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.UpdateVolumePayload(payload) } -func outputResult(p *print.Printer, model *inputModel, volumeLabel string, volume *iaas.Volume) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, volumeLabel string, volume *iaas.Volume) error { + if volume == nil { + return fmt.Errorf("volume response is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(volume, "", " ") if err != nil { diff --git a/internal/cmd/beta/volume/update/update_test.go b/internal/cmd/beta/volume/update/update_test.go index 283bfda43..cdfed4017 100644 --- a/internal/cmd/beta/volume/update/update_test.go +++ b/internal/cmd/beta/volume/update/update_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -255,3 +254,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + volumeLabel string + volume *iaas.Volume + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "volume as argument", + args: args{ + volume: &iaas.Volume{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.volumeLabel, tt.args.volume); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From e6cf71b62de90ac9a94d0c07275f839cf323eae5 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Tue, 25 Feb 2025 13:20:44 +0100 Subject: [PATCH 210/619] chore(sqlserverflex): Add nil pointer checks and tests for the outputResult functions (#625) Signed-off-by: Alexander Dahmen --- .../sqlserverflex/database/create/create.go | 11 ++-- .../database/create/create_test.go | 42 +++++++++++++-- .../database/describe/describe.go | 11 ++-- .../database/describe/describe_test.go | 48 +++++++++++++++-- .../sqlserverflex/database/list/list_test.go | 43 +++++++++++++-- .../sqlserverflex/instance/create/create.go | 3 ++ .../instance/create/create_test.go | 43 +++++++++++++-- .../instance/describe/describe.go | 24 +++++---- .../instance/describe/describe_test.go | 39 ++++++++++++-- .../sqlserverflex/instance/list/list_test.go | 41 +++++++++++++-- .../sqlserverflex/instance/update/update.go | 3 ++ .../instance/update/update_test.go | 43 +++++++++++++-- .../sqlserverflex/options/options_test.go | 52 +++++++++++++++++-- .../beta/sqlserverflex/user/create/create.go | 3 ++ .../sqlserverflex/user/create/create_test.go | 43 +++++++++++++-- .../sqlserverflex/user/describe/describe.go | 7 ++- .../user/describe/describe_test.go | 39 ++++++++++++-- .../beta/sqlserverflex/user/list/list_test.go | 41 +++++++++++++-- .../user/reset-password/reset_password.go | 9 ++-- .../reset-password/reset_password_test.go | 41 +++++++++++++-- 20 files changed, 519 insertions(+), 67 deletions(-) diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index 920d06c9b..2c5f6d17c 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -79,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } s.Stop() - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, model.DatabaseName, resp) }, } configureFlags(cmd) @@ -132,8 +132,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, model *inputModel, resp *sqlserverflex.CreateDatabaseResponse) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, databaseName string, resp *sqlserverflex.CreateDatabaseResponse) error { + if resp == nil { + return fmt.Errorf("sqlserverflex response is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -151,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *sqlserverflex.Creat return nil default: - p.Outputf("Created database %q\n", model.DatabaseName) + p.Outputf("Created database %q\n", databaseName) return nil } } diff --git a/internal/cmd/beta/sqlserverflex/database/create/create_test.go b/internal/cmd/beta/sqlserverflex/database/create/create_test.go index eedda7fa7..8720e3c59 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -255,3 +254,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + databaseName string + resp *sqlserverflex.CreateDatabaseResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only sql response as argument", + args: args{ + resp: &sqlserverflex.CreateDatabaseResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.databaseName, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index 750488b50..b69dbe1b9 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -109,10 +109,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, outputFormat string, database *sqlserverflex.GetDatabaseResponse) error { +func outputResult(p *print.Printer, outputFormat string, resp *sqlserverflex.GetDatabaseResponse) error { + if resp == nil || resp.Database == nil { + return fmt.Errorf("database response is empty") + } switch outputFormat { case print.JSONOutputFormat: - details, err := json.MarshalIndent(database, "", " ") + details, err := json.MarshalIndent(resp, "", " ") if err != nil { return fmt.Errorf("marshal SQLServer Flex database: %w", err) } @@ -120,7 +123,7 @@ func outputResult(p *print.Printer, outputFormat string, database *sqlserverflex return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(database, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SQLServer Flex database: %w", err) } @@ -128,7 +131,7 @@ func outputResult(p *print.Printer, outputFormat string, database *sqlserverflex return nil default: - database := database.Database + database := resp.Database table := tables.NewTable() table.AddRow("ID", utils.PtrString(database.Id)) table.AddSeparator() diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go index a48d2e0d8..25cd9ad82 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -237,3 +236,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp *sqlserverflex.GetDatabaseResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty response", + args: args{ + resp: &sqlserverflex.GetDatabaseResponse{}, + }, + wantErr: true, + }, + { + name: "only database as argument", + args: args{ + resp: &sqlserverflex.GetDatabaseResponse{Database: &sqlserverflex.SingleDatabase{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/database/list/list_test.go b/internal/cmd/beta/sqlserverflex/database/list/list_test.go index ae2ea8f27..7ab387622 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list_test.go @@ -4,15 +4,14 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -210,3 +209,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + databases []sqlserverflex.Database + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty database in databases slice", + args: args{ + databases: []sqlserverflex.Database{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.databases); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index c4e7b3877..49d4e2941 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -262,6 +262,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlServerFle } func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *sqlserverflex.CreateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("sqlserverflex response is empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go index 10f6fc84e..0850869bd 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go @@ -5,13 +5,12 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -492,3 +491,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + resp *sqlserverflex.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "sql instance as argument", + args: args{ + model: fixtureInputModel(), + resp: &sqlserverflex.CreateInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index 11a4ac39b..5a1d30b83 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -99,6 +99,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl } func outputResult(p *print.Printer, outputFormat string, instance *sqlserverflex.Instance) error { + if instance == nil { + return fmt.Errorf("instance response is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -130,21 +133,24 @@ func outputResult(p *print.Printer, outputFormat string, instance *sqlserverflex table.AddSeparator() table.AddRow("STATUS", utils.PtrString(instance.Status)) table.AddSeparator() - table.AddRow("STORAGE SIZE (GB)", utils.PtrString(instance.Storage.Size)) - table.AddSeparator() + if instance.Storage != nil { + table.AddRow("STORAGE SIZE (GB)", utils.PtrString(instance.Storage.Size)) + table.AddSeparator() + } table.AddRow("VERSION", utils.PtrString(instance.Version)) table.AddSeparator() table.AddRow("BACKUP SCHEDULE (UTC)", utils.PtrString(instance.BackupSchedule)) table.AddSeparator() table.AddRow("ACL", acls) table.AddSeparator() - table.AddRow("FLAVOR DESCRIPTION", utils.PtrString(instance.Flavor.Description)) - table.AddSeparator() - table.AddRow("CPU", utils.PtrString(instance.Flavor.Cpu)) - table.AddSeparator() - table.AddRow("RAM (GB)", utils.PtrString(instance.Flavor.Memory)) - table.AddSeparator() - + if instance.Flavor != nil { + table.AddRow("FLAVOR DESCRIPTION", utils.PtrString(instance.Flavor.Description)) + table.AddSeparator() + table.AddRow("CPU", utils.PtrString(instance.Flavor.Cpu)) + table.AddSeparator() + table.AddRow("RAM (GB)", utils.PtrString(instance.Flavor.Memory)) + table.AddSeparator() + } err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go index 96e791c40..1a74c51a7 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -216,3 +215,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *sqlserverflex.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "instance as argument", + args: args{ + instance: &sqlserverflex.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go index 12ea57b7d..dc42f591c 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -186,3 +185,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instances []sqlserverflex.InstanceListInstance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty instance in instances slice", + args: args{ + instances: []sqlserverflex.InstanceListInstance{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index f1a53a3e6..b1d0da47b 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -247,6 +247,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlServerFle } func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *sqlserverflex.UpdateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("instance response is empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update_test.go b/internal/cmd/beta/sqlserverflex/instance/update/update_test.go index 65570cbcb..4fd28fae1 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update_test.go @@ -5,13 +5,12 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -486,3 +485,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + instanceLabel string + resp *sqlserverflex.UpdateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "instance as argument", + args: args{ + model: fixtureRequiredInputModel(), + resp: &sqlserverflex.UpdateInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/options/options_test.go b/internal/cmd/beta/sqlserverflex/options/options_test.go index 02aff416b..420bbbd37 100644 --- a/internal/cmd/beta/sqlserverflex/options/options_test.go +++ b/internal/cmd/beta/sqlserverflex/options/options_test.go @@ -5,12 +5,11 @@ import ( "fmt" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/google/go-cmp/cmp" - "github.com/google/uuid" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -502,3 +501,50 @@ func TestBuildAndExecuteRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + flavors *sqlserverflex.ListFlavorsResponse + versions *sqlserverflex.ListVersionsResponse + storages *sqlserverflex.ListStoragesResponse + userRoles *sqlserverflex.ListRolesResponse + dbCollations *sqlserverflex.ListCollationsResponse + dbCompatibilities *sqlserverflex.ListCompatibilityResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty - only model", + args: args{ + model: fixtureInputModelAllFalse(), + }, + wantErr: false, + }, + { + name: "all input set", + args: args{ + model: fixtureInputModelAllTrue(), + flavors: &sqlserverflex.ListFlavorsResponse{Flavors: &[]sqlserverflex.InstanceFlavorEntry{}}, + versions: &sqlserverflex.ListVersionsResponse{Versions: &[]string{}}, + storages: &sqlserverflex.ListStoragesResponse{StorageClasses: &[]string{}}, + userRoles: &sqlserverflex.ListRolesResponse{Roles: &[]string{}}, + dbCollations: &sqlserverflex.ListCollationsResponse{Collations: &[]sqlserverflex.MssqlDatabaseCollation{}}, + dbCompatibilities: &sqlserverflex.ListCompatibilityResponse{Compatibilities: &[]sqlserverflex.MssqlDatabaseCompatibility{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.flavors, tt.args.versions, tt.args.storages, tt.args.userRoles, tt.args.dbCollations, tt.args.dbCompatibilities); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 82740c25a..895471eb7 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -144,6 +144,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl } func outputResult(p *print.Printer, model *inputModel, instanceLabel string, user *sqlserverflex.SingleUser) error { + if user == nil { + return fmt.Errorf("user response is empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") diff --git a/internal/cmd/beta/sqlserverflex/user/create/create_test.go b/internal/cmd/beta/sqlserverflex/user/create/create_test.go index 5d5f52ccd..644fe7776 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -223,3 +222,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + instanceLabel string + user *sqlserverflex.SingleUser + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "user as argument", + args: args{ + model: fixtureInputModel(), + user: &sqlserverflex.SingleUser{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index ec54158df..9769862c4 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get SQLServer Flex user: %w", err) } - return outputResult(p, model.OutputFormat, *resp.Item) + return outputResult(p, model.OutputFormat, resp.Item) }, } @@ -118,7 +118,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, outputFormat string, user sqlserverflex.UserResponseUser) error { +func outputResult(p *print.Printer, outputFormat string, user *sqlserverflex.UserResponseUser) error { + if user == nil { + return fmt.Errorf("user response is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go index 3d5bbb3e5..f33c171ae 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -231,3 +230,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + user *sqlserverflex.UserResponseUser + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only user as argument", + args: args{ + user: &sqlserverflex.UserResponseUser{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/user/list/list_test.go b/internal/cmd/beta/sqlserverflex/user/list/list_test.go index 94ef7a475..e67b012a5 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -203,3 +202,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + users []sqlserverflex.InstanceListUser + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty user in the users slice", + args: args{ + users: []sqlserverflex.InstanceListUser{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index 5cb34aa27..4dfe1ffce 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -87,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("reset SQLServer Flex user password: %w", err) } - return outputResult(p, model, userLabel, instanceLabel, user.Item) + return outputResult(p, model.OutputFormat, userLabel, instanceLabel, user.Item) }, } @@ -133,8 +133,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel string, user *sqlserverflex.SingleUser) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, userLabel, instanceLabel string, user *sqlserverflex.SingleUser) error { + if user == nil { + return fmt.Errorf("single user response is empty") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") if err != nil { diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go index 48d8caa32..d13b3b117 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -231,3 +230,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + userLabel string + instanceLabel string + user *sqlserverflex.SingleUser + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only user as argument", + args: args{ + user: &sqlserverflex.SingleUser{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.userLabel, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From ff37f2af675eb60a138297eea2c13e2abeba9548 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Tue, 25 Feb 2025 13:22:20 +0100 Subject: [PATCH 211/619] chore(load-balancer): Add nil pointer checks and tests for the outputResult functions (#624) Signed-off-by: Alexander Dahmen --- .../cmd/load-balancer/describe/describe.go | 3 + .../load-balancer/describe/describe_test.go | 39 +++++++++- .../generate-payload/generate_payload.go | 10 ++- .../generate-payload/generate_payload_test.go | 76 +++++++++++++++++-- internal/cmd/load-balancer/list/list.go | 4 +- internal/cmd/load-balancer/list/list_test.go | 41 +++++++++- .../observability-credentials/add/add.go | 8 +- .../observability-credentials/add/add_test.go | 49 +++++++++++- .../describe/describe.go | 3 +- .../describe/describe_test.go | 46 ++++++++++- .../list/list_test.go | 41 +++++++++- internal/cmd/load-balancer/quota/quota.go | 3 + .../cmd/load-balancer/quota/quota_test.go | 42 +++++++++- .../target-pool/describe/describe.go | 7 +- .../target-pool/describe/describe_test.go | 43 ++++++++++- 15 files changed, 373 insertions(+), 42 deletions(-) diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index 0a0ae869e..0c759d545 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -99,6 +99,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalance } func outputResult(p *print.Printer, outputFormat string, loadBalancer *loadbalancer.LoadBalancer) error { + if loadBalancer == nil { + return fmt.Errorf("loadbalancer response is empty") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(loadBalancer, "", " ") diff --git a/internal/cmd/load-balancer/describe/describe_test.go b/internal/cmd/load-balancer/describe/describe_test.go index 33960ecca..24720dac8 100644 --- a/internal/cmd/load-balancer/describe/describe_test.go +++ b/internal/cmd/load-balancer/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -206,3 +205,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + loadBalancer *loadbalancer.LoadBalancer + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only loadbalancer as argument", + args: args{ + loadBalancer: &loadbalancer.LoadBalancer{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.loadBalancer); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index 4b13af079..b947aa629 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -213,13 +213,16 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalance } func outputCreateResult(p *print.Printer, filePath *string, payload *loadbalancer.CreateLoadBalancerPayload) error { + if payload == nil { + return fmt.Errorf("loadbalancer payload is empty") + } payloadBytes, err := json.MarshalIndent(*payload, "", " ") if err != nil { return fmt.Errorf("marshal create load balancer payload: %w", err) } if filePath != nil { - err = fileutils.WriteToFile(*filePath, string(payloadBytes)) + err = fileutils.WriteToFile(utils.PtrString(filePath), string(payloadBytes)) if err != nil { return fmt.Errorf("write create load balancer payload to the file: %w", err) } @@ -231,13 +234,16 @@ func outputCreateResult(p *print.Printer, filePath *string, payload *loadbalance } func outputUpdateResult(p *print.Printer, filePath *string, payload *loadbalancer.UpdateLoadBalancerPayload) error { + if payload == nil { + return fmt.Errorf("loadbalancer payload is empty") + } payloadBytes, err := json.MarshalIndent(*payload, "", " ") if err != nil { return fmt.Errorf("marshal update load balancer payload: %w", err) } if filePath != nil { - err = fileutils.WriteToFile(*filePath, string(payloadBytes)) + err = fileutils.WriteToFile(utils.PtrString(filePath), string(payloadBytes)) if err != nil { return fmt.Errorf("write update load balancer payload to the file: %w", err) } diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go index b8f48fc69..e8dd6dd2e 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go @@ -4,14 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -310,3 +308,71 @@ func TestModifyListeners(t *testing.T) { }) } } + +func TestOutputCreateResult(t *testing.T) { + type args struct { + filePath *string + payload *loadbalancer.CreateLoadBalancerPayload + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only loadbalancer payload as argument", + args: args{ + payload: &loadbalancer.CreateLoadBalancerPayload{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputCreateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { + t.Errorf("outputCreateResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOutputUpdateResult(t *testing.T) { + type args struct { + filePath *string + payload *loadbalancer.UpdateLoadBalancerPayload + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "only loadbalancer payload as argument", + args: args{ + payload: &loadbalancer.UpdateLoadBalancerPayload{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputUpdateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { + t.Errorf("outputUpdateResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index ecd1b4212..fa2036c29 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -159,8 +159,8 @@ func outputResult(p *print.Printer, outputFormat string, loadBalancers []loadbal utils.PtrString(l.Name), utils.PtrString(l.Status), externalAdress, - len(*l.Listeners), - len(*l.TargetPools), + len(utils.PtrString(l.Listeners)), + len(utils.PtrString(l.TargetPools)), ) } err := table.Display(p) diff --git a/internal/cmd/load-balancer/list/list_test.go b/internal/cmd/load-balancer/list/list_test.go index 0f035066d..2ad30db36 100644 --- a/internal/cmd/load-balancer/list/list_test.go +++ b/internal/cmd/load-balancer/list/list_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -183,3 +182,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + loadBalancers []loadbalancer.LoadBalancer + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty loadbalancer in loadbalancers slice", + args: args{ + loadBalancers: []loadbalancer.LoadBalancer{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.loadBalancers); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index a188bcdd7..77dfbf48e 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -91,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("add Load Balancer observability credentials: %w", err) } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, projectLabel, resp) }, } configureFlags(cmd) @@ -144,12 +144,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalance return req } -func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *loadbalancer.CreateCredentialsResponse) error { - if resp.Credential == nil { +func outputResult(p *print.Printer, outputFormat, projectLabel string, resp *loadbalancer.CreateCredentialsResponse) error { + if resp == nil || resp.Credential == nil { return fmt.Errorf("nil observability credentials response") } - switch model.OutputFormat { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { diff --git a/internal/cmd/load-balancer/observability-credentials/add/add_test.go b/internal/cmd/load-balancer/observability-credentials/add/add_test.go index 85fc6b7d6..a9cfb8719 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add_test.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -193,3 +192,45 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + projectLabel string + resp *loadbalancer.CreateCredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "credentials response with empty Credential", + args: args{ + resp: &loadbalancer.CreateCredentialsResponse{}, + }, + wantErr: true, + }, + { + name: "only credentials response as argument", + args: args{ + resp: &loadbalancer.CreateCredentialsResponse{Credential: &loadbalancer.CredentialsResponse{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(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.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index 68781a17e..e16b9eb4f 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -115,8 +115,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *loadbalanc return nil default: if credentials == nil || credentials.Credential == nil { - p.Info("No credentials found") - return nil + return fmt.Errorf("credentials response is empty") } table := tables.NewTable() diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go index d916923fd..05f8a8d64 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -211,3 +210,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials *loadbalancer.GetCredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "credentials response with empty Credential", + args: args{ + credentials: &loadbalancer.GetCredentialsResponse{}, + }, + wantErr: true, + }, + { + name: "only credentials as argument", + args: args{ + credentials: &loadbalancer.GetCredentialsResponse{Credential: &loadbalancer.CredentialsResponse{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/load-balancer/observability-credentials/list/list_test.go b/internal/cmd/load-balancer/observability-credentials/list/list_test.go index 736adf134..e37d0b3c2 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list_test.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" lbUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -269,3 +268,37 @@ func TestGetFilterOp(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []loadbalancer.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty credentials response in loadbalancers slice", + args: args{ + credentials: []loadbalancer.CredentialsResponse{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index beecd9db2..fb99fb6f7 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -86,6 +86,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalance } func outputResult(p *print.Printer, outputFormat string, quota *loadbalancer.GetQuotaResponse) error { + if quota == nil { + return fmt.Errorf("quota response is empty") + } switch outputFormat { case print.PrettyOutputFormat: diff --git a/internal/cmd/load-balancer/quota/quota_test.go b/internal/cmd/load-balancer/quota/quota_test.go index 47bc747c9..b6938c379 100644 --- a/internal/cmd/load-balancer/quota/quota_test.go +++ b/internal/cmd/load-balancer/quota/quota_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -163,3 +162,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + quota *loadbalancer.GetQuotaResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + outputFormat: print.PrettyOutputFormat, // default output format is json + }, + wantErr: true, + }, + { + name: "only quota as argument", + args: args{ + outputFormat: print.PrettyOutputFormat, // default output format is json + quota: &loadbalancer.GetQuotaResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.quota); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index 3ffa3af70..70af7ce15 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -120,6 +120,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalance } func outputResult(p *print.Printer, outputFormat string, targetPool loadbalancer.TargetPool, listener *loadbalancer.Listener) error { + if listener == nil { + return fmt.Errorf("listener response is empty") + } output := struct { *loadbalancer.TargetPool Listener *loadbalancer.Listener `json:"attached_listener"` @@ -191,9 +194,9 @@ func outputResultAsTable(p *print.Printer, targetPool loadbalancer.TargetPool, l } table := tables.NewTable() - table.AddRow("NAME", *targetPool.Name) + table.AddRow("NAME", utils.PtrString(targetPool.Name)) table.AddSeparator() - table.AddRow("TARGET PORT", *targetPool.TargetPort) + table.AddRow("TARGET PORT", utils.PtrString(targetPool.TargetPort)) table.AddSeparator() table.AddRow("ATTACHED LISTENER", listenerStr) table.AddSeparator() diff --git a/internal/cmd/load-balancer/target-pool/describe/describe_test.go b/internal/cmd/load-balancer/target-pool/describe/describe_test.go index 9127dc29c..502a965f8 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe_test.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) var projectIdFlag = globalflags.ProjectIdFlag @@ -217,3 +216,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + targetPool loadbalancer.TargetPool + listener *loadbalancer.Listener + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "listener and target pool as argument", + args: args{ + targetPool: loadbalancer.TargetPool{}, + listener: &loadbalancer.Listener{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.targetPool, tt.args.listener); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From f7d974495507cb3e6fe830c294e8363653eb8aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 26 Feb 2025 09:27:53 +0100 Subject: [PATCH 212/619] fix(service-account): add nil pointer checks for cmd outputs (#635) relates to STACKITCLI-114 --- internal/cmd/service-account/create/create.go | 10 +++-- .../cmd/service-account/create/create_test.go | 35 ++++++++++++++++ .../service-account/get-jwks/get_jwks_test.go | 40 ++++++++++++++++++ .../service-account/key/describe/describe.go | 4 ++ .../key/describe/describe_test.go | 33 +++++++++++++++ .../cmd/service-account/key/list/list_test.go | 41 +++++++++++++++++++ .../cmd/service-account/list/list_test.go | 41 +++++++++++++++++++ .../service-account/token/create/create.go | 12 ++++-- .../token/create/create_test.go | 35 ++++++++++++++++ .../service-account/token/list/list_test.go | 41 +++++++++++++++++++ 10 files changed, 285 insertions(+), 7 deletions(-) diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index 390e5a15b..eedf109aa 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -74,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create service account: %w", err) } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, projectLabel, resp) }, } configureFlags(cmd) @@ -119,8 +119,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat, projectLabel string, serviceAccount *serviceaccount.ServiceAccount) error { + if serviceAccount == nil { + return fmt.Errorf("service account is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(serviceAccount, "", " ") if err != nil { diff --git a/internal/cmd/service-account/create/create_test.go b/internal/cmd/service-account/create/create_test.go index 5e8584495..d74e9ad3f 100644 --- a/internal/cmd/service-account/create/create_test.go +++ b/internal/cmd/service-account/create/create_test.go @@ -187,3 +187,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + projectLabel string + serviceAccount *serviceaccount.ServiceAccount + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty service account", + args: args{ + serviceAccount: &serviceaccount.ServiceAccount{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(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.serviceAccount); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/service-account/get-jwks/get_jwks_test.go b/internal/cmd/service-account/get-jwks/get_jwks_test.go index 6ea2ee487..93b049d14 100644 --- a/internal/cmd/service-account/get-jwks/get_jwks_test.go +++ b/internal/cmd/service-account/get-jwks/get_jwks_test.go @@ -137,3 +137,43 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + serviceAccounts []serviceaccount.JWK + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty service accounts slice", + args: args{ + serviceAccounts: []serviceaccount.JWK{}, + }, + wantErr: false, + }, + { + name: "empty service account in service accounts slice", + args: args{ + serviceAccounts: []serviceaccount.JWK{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.serviceAccounts); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/service-account/key/describe/describe.go b/internal/cmd/service-account/key/describe/describe.go index ab7d6c367..61bc9af84 100644 --- a/internal/cmd/service-account/key/describe/describe.go +++ b/internal/cmd/service-account/key/describe/describe.go @@ -115,6 +115,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceacco } func outputResult(p *print.Printer, key *serviceaccount.GetServiceAccountKeyResponse) error { + if key == nil { + return fmt.Errorf("key is nil") + } + marshaledKey, err := json.MarshalIndent(key, "", " ") if err != nil { return fmt.Errorf("marshal service account key: %w", err) diff --git a/internal/cmd/service-account/key/describe/describe_test.go b/internal/cmd/service-account/key/describe/describe_test.go index 8323ed679..18cd60082 100644 --- a/internal/cmd/service-account/key/describe/describe_test.go +++ b/internal/cmd/service-account/key/describe/describe_test.go @@ -229,3 +229,36 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + key *serviceaccount.GetServiceAccountKeyResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty key", + args: args{ + key: &serviceaccount.GetServiceAccountKeyResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.key); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/service-account/key/list/list_test.go b/internal/cmd/service-account/key/list/list_test.go index e6ec4b4e4..46933a70c 100644 --- a/internal/cmd/service-account/key/list/list_test.go +++ b/internal/cmd/service-account/key/list/list_test.go @@ -196,3 +196,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + keys []serviceaccount.ServiceAccountKeyListResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty keys slice", + args: args{ + keys: []serviceaccount.ServiceAccountKeyListResponse{}, + }, + wantErr: false, + }, + { + name: "empty key in keys slice", + args: args{ + keys: []serviceaccount.ServiceAccountKeyListResponse{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.keys); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/service-account/list/list_test.go b/internal/cmd/service-account/list/list_test.go index 92d89b8ce..d212eabc8 100644 --- a/internal/cmd/service-account/list/list_test.go +++ b/internal/cmd/service-account/list/list_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serviceAccounts []serviceaccount.ServiceAccount + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty service accounts slice", + args: args{ + serviceAccounts: []serviceaccount.ServiceAccount{}, + }, + wantErr: false, + }, + { + name: "empty service account in service accounts slice", + args: args{ + serviceAccounts: []serviceaccount.ServiceAccount{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serviceAccounts); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index 19a52faee..8f96b4002 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -78,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create access token: %w", err) } - return outputResult(p, model, token) + return outputResult(p, model.OutputFormat, model.ServiceAccountEmail, token) }, } @@ -142,8 +142,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat, serviceAccountEmail string, token *serviceaccount.AccessToken) error { + if token == nil { + return fmt.Errorf("token is nil") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(token, "", " ") if err != nil { @@ -161,7 +165,7 @@ func outputResult(p *print.Printer, model *inputModel, token *serviceaccount.Acc return nil default: - p.Outputf("Created access token for service account %s. Token ID: %s\n\n", model.ServiceAccountEmail, utils.PtrString(token.Id)) + p.Outputf("Created access token for service account %s. Token ID: %s\n\n", serviceAccountEmail, utils.PtrString(token.Id)) p.Outputf("Valid until: %s\n", utils.PtrString(token.ValidUntil)) p.Outputf("Token: %s\n", utils.PtrString(token.Token)) return nil diff --git a/internal/cmd/service-account/token/create/create_test.go b/internal/cmd/service-account/token/create/create_test.go index 2cc8b55c9..d5d18e3e9 100644 --- a/internal/cmd/service-account/token/create/create_test.go +++ b/internal/cmd/service-account/token/create/create_test.go @@ -193,3 +193,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + serviceAccountEmail string + token *serviceaccount.AccessToken + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty token", + args: args{ + token: &serviceaccount.AccessToken{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.serviceAccountEmail, tt.args.token); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/service-account/token/list/list_test.go b/internal/cmd/service-account/token/list/list_test.go index 3ffed20f5..fc3f5b54b 100644 --- a/internal/cmd/service-account/token/list/list_test.go +++ b/internal/cmd/service-account/token/list/list_test.go @@ -196,3 +196,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + tokensMetadata []serviceaccount.AccessTokenMetadata + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty tokens metadata slice", + args: args{ + tokensMetadata: []serviceaccount.AccessTokenMetadata{}, + }, + wantErr: false, + }, + { + name: "empty token metadata in tokens metadata slice", + args: args{ + tokensMetadata: []serviceaccount.AccessTokenMetadata{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.tokensMetadata); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 3f4d14aeb3ca5ad9153049c36864f9dd2f2ed292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 26 Feb 2025 09:28:08 +0100 Subject: [PATCH 213/619] fix(ske): add nil pointer checks for cmd outputs (#634) relates to STACKITCLI-115 --- internal/cmd/ske/cluster/create/create.go | 18 ++-- .../cmd/ske/cluster/create/create_test.go | 36 +++++++ internal/cmd/ske/cluster/describe/describe.go | 16 +++- .../cmd/ske/cluster/describe/describe_test.go | 34 +++++++ .../generate-payload/generate_payload.go | 4 + .../generate-payload/generate_payload_test.go | 42 +++++++++ internal/cmd/ske/cluster/list/list.go | 17 +++- internal/cmd/ske/cluster/list/list_test.go | 41 ++++++++ internal/cmd/ske/cluster/update/update.go | 18 ++-- .../cmd/ske/cluster/update/update_test.go | 36 +++++++ internal/cmd/ske/describe/describe.go | 8 +- internal/cmd/ske/describe/describe_test.go | 35 +++++++ internal/cmd/ske/kubeconfig/create/create.go | 8 +- .../cmd/ske/kubeconfig/create/create_test.go | 44 +++++++++ internal/cmd/ske/options/options.go | 10 ++ internal/cmd/ske/options/options_test.go | 94 +++++++++++++++++++ 16 files changed, 435 insertions(+), 26 deletions(-) diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 967b1fe37..014e69bc2 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -143,7 +143,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) @@ -197,10 +197,14 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie return req } -func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *ske.Cluster) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, cluster *ske.Cluster) error { + if cluster == nil { + return fmt.Errorf("cluster is nil") + } + + switch outputFormat { case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") + details, err := json.MarshalIndent(cluster, "", " ") if err != nil { return fmt.Errorf("marshal SKE cluster: %w", err) } @@ -208,7 +212,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SKE cluster: %w", err) } @@ -217,10 +221,10 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } - p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name)) + p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, utils.PtrString(cluster.Name)) return nil } } diff --git a/internal/cmd/ske/cluster/create/create_test.go b/internal/cmd/ske/cluster/create/create_test.go index 7e2496c84..6e2e92b3f 100644 --- a/internal/cmd/ske/cluster/create/create_test.go +++ b/internal/cmd/ske/cluster/create/create_test.go @@ -315,3 +315,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + cluster *ske.Cluster + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty cluster", + args: args{ + cluster: &ske.Cluster{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.cluster); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 9740abf39..52fb7af4d 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -97,6 +97,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie } func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) error { + if cluster == nil { + return fmt.Errorf("cluster is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(cluster, "", " ") @@ -123,10 +127,14 @@ func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) e table := tables.NewTable() table.AddRow("NAME", utils.PtrString(cluster.Name)) table.AddSeparator() - table.AddRow("STATE", utils.PtrString(cluster.Status.Aggregated)) - table.AddSeparator() - table.AddRow("VERSION", utils.PtrString(cluster.Kubernetes.Version)) - table.AddSeparator() + if cluster.HasStatus() { + table.AddRow("STATE", utils.PtrString(cluster.Status.Aggregated)) + table.AddSeparator() + } + if cluster.Kubernetes != nil { + table.AddRow("VERSION", utils.PtrString(cluster.Kubernetes.Version)) + table.AddSeparator() + } table.AddRow("ACL", acl) err := table.Display(p) if err != nil { diff --git a/internal/cmd/ske/cluster/describe/describe_test.go b/internal/cmd/ske/cluster/describe/describe_test.go index 335bb39c0..99e644af4 100644 --- a/internal/cmd/ske/cluster/describe/describe_test.go +++ b/internal/cmd/ske/cluster/describe/describe_test.go @@ -206,3 +206,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + cluster *ske.Cluster + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty cluster", + args: args{ + cluster: &ske.Cluster{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.cluster); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload.go b/internal/cmd/ske/cluster/generate-payload/generate_payload.go index 461842528..299b5e9ab 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload.go @@ -134,6 +134,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie } func outputResult(p *print.Printer, filePath *string, payload *ske.CreateOrUpdateClusterPayload) error { + if payload == nil { + return fmt.Errorf("payload is nil") + } + payloadBytes, err := json.MarshalIndent(*payload, "", " ") if err != nil { return fmt.Errorf("marshal payload: %w", err) diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go index 3cf60e949..5516ccf26 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go @@ -208,3 +208,45 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + filePath *string + payload *ske.CreateOrUpdateClusterPayload + } + filePathDummy := "/dummy.txt" + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "missing payload", + args: args{ + filePath: &filePathDummy, + }, + wantErr: true, + }, + { + name: "missing file path", + args: args{ + payload: &ske.CreateOrUpdateClusterPayload{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 0a39805aa..8f6dd8829 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -174,11 +174,22 @@ func outputResult(p *print.Printer, outputFormat string, clusters []ske.Cluster) if c.Extensions != nil && c.Extensions.Argus != nil && *c.Extensions.Argus.Enabled { monitoring = "Enabled" } + statusAggregated, kubernetesVersion := "", "" + if c.HasStatus() { + statusAggregated = utils.PtrString(c.Status.Aggregated) + } + if c.Kubernetes != nil { + kubernetesVersion = utils.PtrString(c.Kubernetes.Version) + } + countNodepools := 0 + if c.Nodepools != nil { + countNodepools = len(*c.Nodepools) + } table.AddRow( utils.PtrString(c.Name), - utils.PtrString(c.Status.Aggregated), - utils.PtrString(c.Kubernetes.Version), - len(*c.Nodepools), + statusAggregated, + kubernetesVersion, + countNodepools, monitoring, ) } diff --git a/internal/cmd/ske/cluster/list/list_test.go b/internal/cmd/ske/cluster/list/list_test.go index 9e9a8c6a3..2959d6be6 100644 --- a/internal/cmd/ske/cluster/list/list_test.go +++ b/internal/cmd/ske/cluster/list/list_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + clusters []ske.Cluster + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty clusters slice", + args: args{ + clusters: []ske.Cluster{}, + }, + wantErr: false, + }, + { + name: "empty cluster in clusters slice", + args: args{ + clusters: []ske.Cluster{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.clusters); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index 48d73784b..c407b7fb8 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -105,7 +105,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, resp) + return outputResult(p, model.OutputFormat, model.Async, model.ClusterName, resp) }, } configureFlags(cmd) @@ -159,10 +159,14 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie return req } -func outputResult(p *print.Printer, model *inputModel, resp *ske.Cluster) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, async bool, clusterName string, cluster *ske.Cluster) error { + if cluster == nil { + return fmt.Errorf("cluster is nil") + } + + switch outputFormat { case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") + details, err := json.MarshalIndent(cluster, "", " ") if err != nil { return fmt.Errorf("marshal SKE cluster: %w", err) } @@ -170,7 +174,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *ske.Cluster) error return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal SKE cluster: %w", err) } @@ -179,10 +183,10 @@ func outputResult(p *print.Printer, model *inputModel, resp *ske.Cluster) error return nil default: operationState := "Updated" - if model.Async { + if async { operationState = "Triggered update of" } - p.Info("%s cluster %q\n", operationState, model.ClusterName) + p.Info("%s cluster %q\n", operationState, clusterName) return nil } } diff --git a/internal/cmd/ske/cluster/update/update_test.go b/internal/cmd/ske/cluster/update/update_test.go index 32a1cfed5..53bce8b78 100644 --- a/internal/cmd/ske/cluster/update/update_test.go +++ b/internal/cmd/ske/cluster/update/update_test.go @@ -295,3 +295,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + clusterName string + cluster *ske.Cluster + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty cluster", + args: args{ + cluster: &ske.Cluster{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.clusterName, tt.args.cluster); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index 025cd78a1..4912b997d 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -87,6 +87,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenab } func outputResult(p *print.Printer, outputFormat string, project *serviceenablement.ServiceStatus, projectId string) error { + if project == nil { + return fmt.Errorf("project is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(project, "", " ") @@ -108,7 +112,9 @@ func outputResult(p *print.Printer, outputFormat string, project *serviceenablem table := tables.NewTable() table.AddRow("ID", projectId) table.AddSeparator() - table.AddRow("STATE", utils.PtrString(project.State)) + if project.HasState() { + table.AddRow("STATE", utils.PtrString(project.State)) + } err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/ske/describe/describe_test.go b/internal/cmd/ske/describe/describe_test.go index fe8e39e71..983e061e5 100644 --- a/internal/cmd/ske/describe/describe_test.go +++ b/internal/cmd/ske/describe/describe_test.go @@ -169,3 +169,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + project *serviceenablement.ServiceStatus + projectId string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty project", + args: args{ + project: &serviceenablement.ServiceStatus{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.project, tt.args.projectId); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index a8fb68437..8677b033c 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -159,7 +159,7 @@ func NewCmd(p *print.Printer) *cobra.Command { p.Outputf("\nSet kubectl context to %s with: kubectl config use-context %s\n", model.ClusterName, model.ClusterName) } - return outputResult(p, model, kubeconfigPath, respKubeconfig, respLogin) + return outputResult(p, model.OutputFormat, model.ClusterName, kubeconfigPath, respKubeconfig, respLogin) }, } configureFlags(cmd) @@ -242,8 +242,8 @@ func buildRequestLogin(ctx context.Context, model *inputModel, apiClient *ske.AP return apiClient.GetLoginKubeconfig(ctx, model.ProjectId, model.ClusterName), nil } -func outputResult(p *print.Printer, model *inputModel, kubeconfigPath string, respKubeconfig *ske.Kubeconfig, respLogin *ske.LoginKubeconfig) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, clusterName, kubeconfigPath string, respKubeconfig *ske.Kubeconfig, respLogin *ske.LoginKubeconfig) error { + switch outputFormat { case print.JSONOutputFormat: var err error var details []byte @@ -277,7 +277,7 @@ func outputResult(p *print.Printer, model *inputModel, kubeconfigPath string, re if respKubeconfig != nil { expiration = fmt.Sprintf(", with expiration date %v (UTC)", utils.ConvertTimePToDateTimeString(respKubeconfig.ExpirationTimestamp)) } - p.Outputf("Updated kubeconfig file for cluster %s in %q%s\n", model.ClusterName, kubeconfigPath, expiration) + p.Outputf("Updated kubeconfig file for cluster %s in %q%s\n", clusterName, kubeconfigPath, expiration) return nil } diff --git a/internal/cmd/ske/kubeconfig/create/create_test.go b/internal/cmd/ske/kubeconfig/create/create_test.go index 85cfe1560..9743067f8 100644 --- a/internal/cmd/ske/kubeconfig/create/create_test.go +++ b/internal/cmd/ske/kubeconfig/create/create_test.go @@ -289,3 +289,47 @@ func TestBuildRequestCreate(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + clusterName string + kubeconfigPath string + respKubeconfig *ske.Kubeconfig + respLogin *ske.LoginKubeconfig + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "missing kubeconfig", + args: args{ + respLogin: &ske.LoginKubeconfig{}, + }, + wantErr: false, + }, + { + name: "missing login", + args: args{ + respKubeconfig: &ske.Kubeconfig{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.clusterName, tt.args.kubeconfigPath, tt.args.respKubeconfig, tt.args.respLogin); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index 82105321c..419721d29 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -136,6 +136,12 @@ func buildRequest(ctx context.Context, apiClient *ske.APIClient) ske.ApiListProv } func outputResult(p *print.Printer, model *inputModel, options *ske.ProviderOptions) error { + if model == nil || model.GlobalFlagModel == nil { + return fmt.Errorf("model is nil") + } else if options == nil { + return fmt.Errorf("options is nil") + } + // filter output based on the flags if !model.AvailabilityZones { options.AvailabilityZones = nil @@ -179,6 +185,10 @@ func outputResult(p *print.Printer, model *inputModel, options *ske.ProviderOpti } func outputResultAsTable(p *print.Printer, options *ske.ProviderOptions) error { + if options == nil { + return fmt.Errorf("options is nil") + } + content := []tables.Table{} if options.AvailabilityZones != nil && len(*options.AvailabilityZones) != 0 { content = append(content, buildAvailabilityZonesTable(options)) diff --git a/internal/cmd/ske/options/options_test.go b/internal/cmd/ske/options/options_test.go index d6045f823..6b1c1ae93 100644 --- a/internal/cmd/ske/options/options_test.go +++ b/internal/cmd/ske/options/options_test.go @@ -186,3 +186,97 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + options *ske.ProviderOptions + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "missing model", + args: args{ + options: &ske.ProviderOptions{}, + }, + wantErr: true, + }, + { + name: "missing options", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + }, + wantErr: true, + }, + { + name: "missing global flags in model", + args: args{ + model: &inputModel{}, + options: &ske.ProviderOptions{}, + }, + wantErr: true, + }, + { + name: "set model and options", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + options: &ske.ProviderOptions{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.options); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOutputResultAsTable(t *testing.T) { + type args struct { + options *ske.ProviderOptions + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty options", + args: args{ + options: &ske.ProviderOptions{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResultAsTable(p, tt.args.options); (err != nil) != tt.wantErr { + t.Errorf("outputResultAsTable() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 3e9181d23942e87ed4cb6f109f094cd5a2d74f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 26 Feb 2025 09:28:22 +0100 Subject: [PATCH 214/619] fix(secrets-manager): add nil pointer checks for cmd outputs (#633) relates to STACKITCLI-113 --- .../secrets-manager/instance/create/create.go | 14 ++++-- .../instance/create/create_test.go | 36 +++++++++++++ .../instance/describe/describe.go | 8 ++- .../instance/describe/describe_test.go | 50 +++++++++++++++++++ .../instance/list/list_test.go | 41 +++++++++++++++ .../cmd/secrets-manager/user/create/create.go | 24 +++++---- .../user/create/create_test.go | 35 +++++++++++++ .../user/describe/describe_test.go | 34 +++++++++++++ .../secrets-manager/user/list/list_test.go | 41 +++++++++++++++ 9 files changed, 267 insertions(+), 16 deletions(-) diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index 3d16d252e..35c02682c 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -94,7 +94,7 @@ If you want to retry configuring the ACLs, you can do it via: } } - return outputResult(p, model, projectLabel, instanceId, resp) + return outputResult(p, model.OutputFormat, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -157,10 +157,14 @@ 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 { +func outputResult(p *print.Printer, outputFormat, projectLabel, instanceId string, instance *secretsmanager.Instance) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + + switch outputFormat { case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") + details, err := json.MarshalIndent(instance, "", " ") if err != nil { return fmt.Errorf("marshal Secrets Manager instance: %w", err) } @@ -168,7 +172,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Secrets Manager instance: %w", err) } diff --git a/internal/cmd/secrets-manager/instance/create/create_test.go b/internal/cmd/secrets-manager/instance/create/create_test.go index 96dc7d994..92b04ba79 100644 --- a/internal/cmd/secrets-manager/instance/create/create_test.go +++ b/internal/cmd/secrets-manager/instance/create/create_test.go @@ -302,3 +302,39 @@ func TestBuildCreateACLRequests(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + projectLabel string + instanceId string + instance *secretsmanager.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty instance", + args: args{ + instance: &secretsmanager.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(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.instanceId, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index e40278256..8551fa8bf 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -111,6 +111,12 @@ func buildListACLsRequest(ctx context.Context, model *inputModel, apiClient *sec } func outputResult(p *print.Printer, outputFormat string, instance *secretsmanager.Instance, aclList *secretsmanager.ListACLsResponse) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } else if aclList == nil { + return fmt.Errorf("aclList is nil") + } + output := struct { *secretsmanager.Instance *secretsmanager.ListACLsResponse @@ -148,7 +154,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *secretsmanage table.AddRow("CREATION DATE", utils.PtrString(instance.CreationStartDate)) table.AddSeparator() // Only show ACL if it's present and not empty - if aclList != nil && aclList.Acls != nil && len(*aclList.Acls) > 0 { + if aclList.Acls != nil && len(*aclList.Acls) > 0 { var cidrs []string for _, acl := range *aclList.Acls { diff --git a/internal/cmd/secrets-manager/instance/describe/describe_test.go b/internal/cmd/secrets-manager/instance/describe/describe_test.go index a6026be25..212c825ab 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe_test.go +++ b/internal/cmd/secrets-manager/instance/describe/describe_test.go @@ -252,3 +252,53 @@ func TestBuildGetACLsRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *secretsmanager.Instance + aclList *secretsmanager.ListACLsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "missing acl", + args: args{ + aclList: &secretsmanager.ListACLsResponse{}, + }, + wantErr: true, + }, + { + name: "missing instance", + args: args{ + instance: &secretsmanager.Instance{}, + }, + wantErr: true, + }, + { + name: "empty instance and empty acl", + args: args{ + instance: &secretsmanager.Instance{}, + aclList: &secretsmanager.ListACLsResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance, tt.args.aclList); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/secrets-manager/instance/list/list_test.go b/internal/cmd/secrets-manager/instance/list/list_test.go index 3de6c45fa..3903b0210 100644 --- a/internal/cmd/secrets-manager/instance/list/list_test.go +++ b/internal/cmd/secrets-manager/instance/list/list_test.go @@ -196,3 +196,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instances []secretsmanager.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty instances slice", + args: args{ + instances: []secretsmanager.Instance{}, + }, + wantErr: false, + }, + { + name: "empty instance in instances slice", + args: args{ + instances: []secretsmanager.Instance{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 33edfbe3a..12a767cf4 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -86,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Secrets Manager user: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, instanceLabel, resp) }, } @@ -137,10 +137,14 @@ 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 { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, user *secretsmanager.User) error { + if user == nil { + return fmt.Errorf("user is nil") + } + + switch outputFormat { case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") + details, err := json.MarshalIndent(user, "", " ") if err != nil { return fmt.Errorf("marshal Secrets Manager user: %w", err) } @@ -148,7 +152,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal Secrets Manager user: %w", err) } @@ -156,11 +160,11 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: - p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) - p.Outputf("Username: %s\n", utils.PtrString(resp.Username)) - p.Outputf("Password: %s\n", utils.PtrString(resp.Password)) - p.Outputf("Description: %s\n", utils.PtrString(resp.Description)) - p.Outputf("Write Access: %s\n", utils.PtrString(resp.Write)) + p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) + p.Outputf("Username: %s\n", utils.PtrString(user.Username)) + p.Outputf("Password: %s\n", utils.PtrString(user.Password)) + p.Outputf("Description: %s\n", utils.PtrString(user.Description)) + p.Outputf("Write Access: %s\n", utils.PtrString(user.Write)) return nil } diff --git a/internal/cmd/secrets-manager/user/create/create_test.go b/internal/cmd/secrets-manager/user/create/create_test.go index 701787089..be5ae1a37 100644 --- a/internal/cmd/secrets-manager/user/create/create_test.go +++ b/internal/cmd/secrets-manager/user/create/create_test.go @@ -225,3 +225,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instanceLabel string + user *secretsmanager.User + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty user", + args: args{ + user: &secretsmanager.User{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/secrets-manager/user/describe/describe_test.go b/internal/cmd/secrets-manager/user/describe/describe_test.go index c34fb0063..46cd4b63e 100644 --- a/internal/cmd/secrets-manager/user/describe/describe_test.go +++ b/internal/cmd/secrets-manager/user/describe/describe_test.go @@ -243,3 +243,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + user secretsmanager.User + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty user", + args: args{ + user: secretsmanager.User{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/secrets-manager/user/list/list_test.go b/internal/cmd/secrets-manager/user/list/list_test.go index 9f996c584..ac4c830a7 100644 --- a/internal/cmd/secrets-manager/user/list/list_test.go +++ b/internal/cmd/secrets-manager/user/list/list_test.go @@ -203,3 +203,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + users []secretsmanager.User + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty users slice", + args: args{ + users: []secretsmanager.User{}, + }, + wantErr: false, + }, + { + name: "empty user in users slice", + args: args{ + users: []secretsmanager.User{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From d9be82ef517726633095f4db2570abde27e20b07 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 3 Mar 2025 07:56:14 +0100 Subject: [PATCH 215/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.6.7 (#640) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 50526fe09..a024e5ba0 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.6 + github.com/jedib0t/go-pretty/v6 v6.6.7 github.com/lmittmann/tint v1.0.7 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.9.1 diff --git a/go.sum b/go.sum index ee472c853..b3dab75f4 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.6 h1:LyezkL+1SuqH2z47e5IMQkYUIcs2BD+MnpdPRiRcN0c= -github.com/jedib0t/go-pretty/v6 v6.6.6/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo= +github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= From 0f71ec90c216be544cb443cc429360cbae5e9933 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 5 Mar 2025 08:15:04 +0100 Subject: [PATCH 216/619] fix(deps): update stackit sdk modules (#637) * fix(deps): update stackit sdk modules * Exclude serviceenablement Signed-off-by: Alexander Dahmen --------- Signed-off-by: Alexander Dahmen Co-authored-by: Renovate Bot Co-authored-by: Alexander Dahmen --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a024e5ba0..d2920fa79 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.20.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.18.0 diff --git a/go.sum b/go.sum index b3dab75f4..c05ccea99 100644 --- a/go.sum +++ b/go.sum @@ -123,8 +123,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0 h1:nSaSvo9o github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0/go.mod h1:LoOkWrUropfVm72oE5aWSC9yRiM3s8Vf3TvC7HtC3b8= github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0 h1:gEoA2oj3OcDg3XI0KSJm8mCjQz9WOZENeSgfTFPK8ow= github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0/go.mod h1:JE8POcTfSxTo+g1MkgVQ+OjT4jWEr08MIY8qx3Hi+Tw= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.20.0 h1:yg8YlMn7Sj3SeF6rxkCLp74N16JH5u6coOEN7GJH67Y= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.20.0/go.mod h1:w10/728sUT49t4WFbV8zI3dvn0u3tGEIq77rRsVm460= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1 h1:ZFFJr54FcYTUBjE+5E3Cx92jTDdHGKT2DTIvvJSRrTc= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1/go.mod h1:9p5IIdOKOM5/DIjbenKrWvz6GlSps4jsPJZkH7QJuRU= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.18.0 h1:7nNjIIcBQRDVnW4NL7+R8DaCKEqxxxsmVsgOVe50ZMU= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.18.0/go.mod h1:UFujBT+JlNvl6JNrY96UpLGqp+lZTD+JWL7siqhGPlw= github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0 h1:P7bxaVzkZPGMWItLynKIvc88Xh6jCnK4dPTTT+L607o= From 9bd08cb78cd5bf5ec0fa1e5d6d46b0421ddafe31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Thu, 6 Mar 2025 11:35:20 +0100 Subject: [PATCH 217/619] RabbitMQ: Nil checks and testcases for output functions (#645) * chore: add nil checks and testcases * fix: integrate review findings --- .../cmd/rabbitmq/credentials/create/create.go | 16 ++++- .../credentials/create/create_test.go | 58 ++++++++++++++++++- .../rabbitmq/credentials/describe/describe.go | 5 +- .../credentials/describe/describe_test.go | 42 +++++++++++++- .../rabbitmq/credentials/list/list_test.go | 44 ++++++++++++-- .../cmd/rabbitmq/instance/create/create.go | 10 ++++ .../rabbitmq/instance/create/create_test.go | 50 ++++++++++++++-- .../rabbitmq/instance/describe/describe.go | 27 +++++---- .../instance/describe/describe_test.go | 49 +++++++++++++++- internal/cmd/rabbitmq/instance/list/list.go | 13 ++++- .../cmd/rabbitmq/instance/list/list_test.go | 44 ++++++++++++-- internal/cmd/rabbitmq/plans/plans.go | 22 +++---- internal/cmd/rabbitmq/plans/plans_test.go | 44 ++++++++++++-- 13 files changed, 374 insertions(+), 50 deletions(-) diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index 1a7cd75ad..bc4e069f4 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -78,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create RabbitMQ credentials: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, *model, instanceLabel, resp) }, } configureFlags(cmd) @@ -122,8 +122,20 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *rabbitmq.CredentialsResponse) error { +func outputResult(p *print.Printer, model inputModel, instanceLabel string, resp *rabbitmq.CredentialsResponse) error { + if model.GlobalFlagModel == nil { + return fmt.Errorf("no global flags available") + } + if resp == nil { + return fmt.Errorf("no response available") + } + if !model.ShowPassword { + if resp.Raw == nil { + resp.Raw = &rabbitmq.RawCredentials{Credentials: &rabbitmq.Credentials{}} + } else if resp.Raw.Credentials == nil { + resp.Raw.Credentials = &rabbitmq.Credentials{} + } resp.Raw.Credentials.Password = utils.Ptr("hidden") } switch model.OutputFormat { diff --git a/internal/cmd/rabbitmq/credentials/create/create_test.go b/internal/cmd/rabbitmq/credentials/create/create_test.go index 494647b00..1c053d029 100644 --- a/internal/cmd/rabbitmq/credentials/create/create_test.go +++ b/internal/cmd/rabbitmq/credentials/create/create_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -200,3 +199,56 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + instanceLabel string + resp *rabbitmq.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + model: inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + instanceLabel: "", + resp: &rabbitmq.CredentialsResponse{}, + }, + wantErr: false, + }, + { + name: "nil response", + args: args{ + model: inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + instanceLabel: "", + }, + wantErr: true, + }, + { + name: "no flags", + args: args{ + model: inputModel{}, + instanceLabel: "", + resp: &rabbitmq.CredentialsResponse{}, + }, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/rabbitmq/credentials/describe/describe.go b/internal/cmd/rabbitmq/credentials/describe/describe.go index 990fcad69..85159848d 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe.go @@ -112,6 +112,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP } func outputResult(p *print.Printer, outputFormat string, credentials *rabbitmq.CredentialsResponse) error { + if credentials == nil { + return fmt.Errorf("no response passed") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(credentials, "", " ") @@ -131,7 +134,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *rabbitmq.C return nil default: table := tables.NewTable() - table.AddRow("ID", *credentials.Id) + table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty if credentials.HasRaw() && credentials.Raw.Credentials != nil { diff --git a/internal/cmd/rabbitmq/credentials/describe/describe_test.go b/internal/cmd/rabbitmq/credentials/describe/describe_test.go index ac88bb829..ef4d23107 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe_test.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -243,3 +242,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + credentials *rabbitmq.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + outputFormat: "", + credentials: &rabbitmq.CredentialsResponse{}, + }, + wantErr: false, + }, + { + name: "empty", + args: args{ + outputFormat: "", + }, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/rabbitmq/credentials/list/list_test.go b/internal/cmd/rabbitmq/credentials/list/list_test.go index 71263bdc0..431a51a08 100644 --- a/internal/cmd/rabbitmq/credentials/list/list_test.go +++ b/internal/cmd/rabbitmq/credentials/list/list_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -207,3 +206,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []rabbitmq.CredentialsListItem + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "non empty list with empty elements", + args: args{ + outputFormat: "", + credentials: []rabbitmq.CredentialsListItem{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index 2810d24e8..3ea8bfda1 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -257,6 +257,16 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient rabbitMQClie } func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *rabbitmq.CreateInstanceResponse) error { + if model == nil { + return fmt.Errorf("no model passed") + } + if model.GlobalFlagModel == nil { + return fmt.Errorf("no globalflags passed") + } + if resp == nil { + return fmt.Errorf("no response passed") + } + switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/rabbitmq/instance/create/create_test.go b/internal/cmd/rabbitmq/instance/create/create_test.go index 0f3b165c6..5faeb3257 100644 --- a/internal/cmd/rabbitmq/instance/create/create_test.go +++ b/internal/cmd/rabbitmq/instance/create/create_test.go @@ -5,13 +5,12 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -488,3 +487,46 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + projectLabel string + instanceId string + resp *rabbitmq.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + model: inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + resp: &rabbitmq.CreateInstanceResponse{}, + }, + wantErr: false, + }, + { + name: "empty", + args: args{ + model: inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + }, + }, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, &tt.args.model, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/rabbitmq/instance/describe/describe.go b/internal/cmd/rabbitmq/instance/describe/describe.go index 2aad472cd..c65f67ed3 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe.go +++ b/internal/cmd/rabbitmq/instance/describe/describe.go @@ -100,6 +100,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP } func outputResult(p *print.Printer, outputFormat string, instance *rabbitmq.Instance) error { + if instance == nil { + return fmt.Errorf("no instance passed") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -123,18 +126,22 @@ func outputResult(p *print.Printer, outputFormat string, instance *rabbitmq.Inst table.AddSeparator() table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) - table.AddSeparator() - table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) - table.AddSeparator() + if lastOperation := instance.LastOperation; lastOperation != nil { + table.AddRow("LAST OPERATION TYPE", utils.PtrString(lastOperation.Type)) + table.AddSeparator() + table.AddRow("LAST OPERATION STATE", utils.PtrString(lastOperation.State)) + table.AddSeparator() + } table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) // Only show ACL if it's present and not empty - acl := (*instance.Parameters)[aclParameterKey] - aclStr, ok := acl.(string) - if ok { - if aclStr != "" { - table.AddSeparator() - table.AddRow("ACL", aclStr) + if parameters := instance.Parameters; parameters != nil { + acl := (*instance.Parameters)[aclParameterKey] + aclStr, ok := acl.(string) + if ok { + if aclStr != "" { + table.AddSeparator() + table.AddRow("ACL", aclStr) + } } } err := table.Display(p) diff --git a/internal/cmd/rabbitmq/instance/describe/describe_test.go b/internal/cmd/rabbitmq/instance/describe/describe_test.go index ff09ef0ae..4b9420995 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe_test.go +++ b/internal/cmd/rabbitmq/instance/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -216,3 +215,47 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + instance *rabbitmq.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{instance: &rabbitmq.Instance{}}, + wantErr: false, + }, + { + name: "nil instance", + args: args{}, + wantErr: true, + }, + { + name: "empty parameters", + args: args{ + outputFormat: "", + instance: &rabbitmq.Instance{ + Parameters: &map[string]interface{}{ + "foo": nil, + }, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index 3ffc1a146..3ade03661 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -152,11 +152,20 @@ func outputResult(p *print.Printer, outputFormat string, instances []rabbitmq.In table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] + var ( + opType, opState string + ) + if lastOperation := instance.LastOperation; lastOperation != nil { + opType = utils.PtrString(lastOperation.Type) + opState = utils.PtrString(lastOperation.State) + } else { + opType, opState = "n/a", "n/a" + } table.AddRow( utils.PtrString(instance.InstanceId), utils.PtrString(instance.Name), - utils.PtrString(instance.LastOperation.Type), - utils.PtrString(instance.LastOperation.State), + opType, + opState, ) } err := table.Display(p) diff --git a/internal/cmd/rabbitmq/instance/list/list_test.go b/internal/cmd/rabbitmq/instance/list/list_test.go index 004e9f436..50bdcf4bd 100644 --- a/internal/cmd/rabbitmq/instance/list/list_test.go +++ b/internal/cmd/rabbitmq/instance/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -186,3 +185,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + instances []rabbitmq.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "slice with empty element", + args: args{ + outputFormat: "", + instances: []rabbitmq.Instance{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index 6156c0724..1b84f3029 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -153,17 +153,19 @@ func outputResult(p *print.Printer, outputFormat string, plans []rabbitmq.Offeri table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { o := plans[i] - for j := range *o.Plans { - plan := (*o.Plans)[j] - table.AddRow( - utils.PtrString(o.Name), - utils.PtrString(o.Version), - utils.PtrString(plan.Id), - utils.PtrString(plan.Name), - utils.PtrString(plan.Description), - ) + if o.Plans != nil { + for j := range *o.Plans { + plan := (*o.Plans)[j] + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + ) + } + table.AddSeparator() } - table.AddSeparator() } table.EnableAutoMergeOnColumns(1, 2) err := table.Display(p) diff --git a/internal/cmd/rabbitmq/plans/plans_test.go b/internal/cmd/rabbitmq/plans/plans_test.go index 8fa1378d7..ab8966a20 100644 --- a/internal/cmd/rabbitmq/plans/plans_test.go +++ b/internal/cmd/rabbitmq/plans/plans_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -186,3 +185,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + plans []rabbitmq.Offering + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "slice with empty element", + args: args{ + outputFormat: "", + plans: []rabbitmq.Offering{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From b82752036b28832e9cc1a7aaa06c02aa41431900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Thu, 6 Mar 2025 11:39:39 +0100 Subject: [PATCH 218/619] Redis: Add nil checks and testcases for output functions (#646) * chore: add nil checks and testcases * chore: Added testcases for nil responses --- .../cmd/redis/credentials/create/create.go | 20 ++++++-- .../redis/credentials/create/create_test.go | 38 ++++++++++++-- .../redis/credentials/describe/describe.go | 5 +- .../credentials/describe/describe_test.go | 39 +++++++++++++-- .../cmd/redis/credentials/list/list_test.go | 44 ++++++++++++++-- internal/cmd/redis/instance/create/create.go | 9 ++++ .../cmd/redis/instance/create/create_test.go | 50 +++++++++++++++++-- .../cmd/redis/instance/describe/describe.go | 29 +++++++---- .../redis/instance/describe/describe_test.go | 50 +++++++++++++++++-- internal/cmd/redis/instance/list/list.go | 10 +++- internal/cmd/redis/instance/list/list_test.go | 43 ++++++++++++++-- internal/cmd/redis/plans/plans.go | 22 ++++---- internal/cmd/redis/plans/plans_test.go | 43 ++++++++++++++-- 13 files changed, 349 insertions(+), 53 deletions(-) diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index 388e269a4..9b2098344 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -79,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Redis credentials: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, *model, instanceLabel, resp) }, } configureFlags(cmd) @@ -123,8 +123,20 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *redis.CredentialsResponse) error { +func outputResult(p *print.Printer, model inputModel, instanceLabel string, resp *redis.CredentialsResponse) error { + if model.GlobalFlagModel == nil { + return fmt.Errorf("no global flags defined") + } + if resp == nil { + return fmt.Errorf("no response defined") + } if !model.ShowPassword { + if resp.Raw == nil { + resp.Raw = &redis.RawCredentials{} + } + if resp.Raw.Credentials == nil { + resp.Raw.Credentials = &redis.Credentials{} + } resp.Raw.Credentials.Password = utils.Ptr("hidden") } @@ -146,11 +158,11 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, *resp.Id) + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) // The username field cannot be set by the user, so we only display it if it's not returned empty if resp.HasRaw() && resp.Raw.Credentials != nil { if username := resp.Raw.Credentials.Username; username != nil && *username != "" { - p.Outputf("Username: %s\n", *username) + p.Outputf("Username: %s\n", utils.PtrString(username)) } if !model.ShowPassword { p.Outputf("Password: \n") diff --git a/internal/cmd/redis/credentials/create/create_test.go b/internal/cmd/redis/credentials/create/create_test.go index bb1ee454a..511b066ad 100644 --- a/internal/cmd/redis/credentials/create/create_test.go +++ b/internal/cmd/redis/credentials/create/create_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -200,3 +199,36 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + instanceLabel string + resp *redis.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, resp: &redis.CredentialsResponse{}}, + wantErr: false, + }, + { + name: "nil response", + args: args{model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}}, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/redis/credentials/describe/describe.go b/internal/cmd/redis/credentials/describe/describe.go index 6d342002f..7a6dc78e4 100644 --- a/internal/cmd/redis/credentials/describe/describe.go +++ b/internal/cmd/redis/credentials/describe/describe.go @@ -112,6 +112,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl } func outputResult(p *print.Printer, outputFormat string, credentials *redis.CredentialsResponse) error { + if credentials == nil { + return fmt.Errorf("no credentials passed") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(credentials, "", " ") @@ -131,7 +134,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *redis.Cred return nil default: table := tables.NewTable() - table.AddRow("ID", *credentials.Id) + table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty if credentials.HasRaw() && credentials.Raw.Credentials != nil { diff --git a/internal/cmd/redis/credentials/describe/describe_test.go b/internal/cmd/redis/credentials/describe/describe_test.go index 909d337f4..c6f837491 100644 --- a/internal/cmd/redis/credentials/describe/describe_test.go +++ b/internal/cmd/redis/credentials/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -243,3 +242,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + credentials *redis.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + credentials: &redis.CredentialsResponse{}, + }, + wantErr: false, + }, + { + name: "nil response", + args: args{}, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/redis/credentials/list/list_test.go b/internal/cmd/redis/credentials/list/list_test.go index d59fc9c80..b771823bf 100644 --- a/internal/cmd/redis/credentials/list/list_test.go +++ b/internal/cmd/redis/credentials/list/list_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -207,3 +206,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []redis.CredentialsListItem + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "slice with empty element", + args: args{ + outputFormat: "", + credentials: []redis.CredentialsListItem{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index 84d8e19ee..87db67741 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -252,6 +252,15 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient redisClient) } func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *redis.CreateInstanceResponse) error { + if model == nil { + return fmt.Errorf("no model passed") + } + if model.GlobalFlagModel == nil { + return fmt.Errorf("no global flags passed") + } + if resp == nil { + return fmt.Errorf("no response defined") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/redis/instance/create/create_test.go b/internal/cmd/redis/instance/create/create_test.go index dd35d51be..59ee4d259 100644 --- a/internal/cmd/redis/instance/create/create_test.go +++ b/internal/cmd/redis/instance/create/create_test.go @@ -5,13 +5,12 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -463,3 +462,46 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + instanceId string + resp *redis.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, + projectLabel: "", + instanceId: testMonitoringInstanceId, + resp: &redis.CreateInstanceResponse{}, + }, + wantErr: false, + }, + { + name: "nil response", + args: args{ + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, + projectLabel: "", + instanceId: testMonitoringInstanceId, + }, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/redis/instance/describe/describe.go b/internal/cmd/redis/instance/describe/describe.go index 5e8737212..f91b4b1e6 100644 --- a/internal/cmd/redis/instance/describe/describe.go +++ b/internal/cmd/redis/instance/describe/describe.go @@ -100,6 +100,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl } func outputResult(p *print.Printer, outputFormat string, instance *redis.Instance) error { + if instance == nil { + return fmt.Errorf("no instance passed") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -123,18 +126,22 @@ func outputResult(p *print.Printer, outputFormat string, instance *redis.Instanc table.AddSeparator() table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) - table.AddSeparator() - table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) - table.AddSeparator() + if lastOperation := instance.LastOperation; lastOperation != nil { + table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) + table.AddSeparator() + table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) + table.AddSeparator() + } table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) - // Only show ACL if it's present and not empty - acl := (*instance.Parameters)[aclParameterKey] - aclStr, ok := acl.(string) - if ok { - if aclStr != "" { - table.AddSeparator() - table.AddRow("ACL", aclStr) + if parameters := instance.Parameters; parameters != nil { + // Only show ACL if it's present and not empty + acl := (*parameters)[aclParameterKey] + aclStr, ok := acl.(string) + if ok { + if aclStr != "" { + table.AddSeparator() + table.AddRow("ACL", aclStr) + } } } err := table.Display(p) diff --git a/internal/cmd/redis/instance/describe/describe_test.go b/internal/cmd/redis/instance/describe/describe_test.go index 188927f28..1e12d6195 100644 --- a/internal/cmd/redis/instance/describe/describe_test.go +++ b/internal/cmd/redis/instance/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -216,3 +215,48 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + instance *redis.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + instance: &redis.Instance{}, + }, + wantErr: false, + }, + { + name: "nil response", + args: args{}, + wantErr: true, + }, + { + name: "nil parameter", + args: args{ + instance: &redis.Instance{ + Parameters: &map[string]interface{}{ + "foo": nil, + }, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index d75ea93b4..4b49c15fa 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -152,11 +152,17 @@ func outputResult(p *print.Printer, outputFormat string, instances []redis.Insta table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { instance := instances[i] + var ( + lastOperationType, lastOperationState string + ) + if lastOperation := instance.LastOperation; lastOperation != nil { + lastOperationType, lastOperationState = utils.PtrString(lastOperation.Type), utils.PtrString(lastOperation.State) + } table.AddRow( utils.PtrString(instance.InstanceId), utils.PtrString(instance.Name), - utils.PtrString(instance.LastOperation.Type), - utils.PtrString(instance.LastOperation.State), + lastOperationType, + lastOperationState, ) } err := table.Display(p) diff --git a/internal/cmd/redis/instance/list/list_test.go b/internal/cmd/redis/instance/list/list_test.go index 692c71222..0338bd8a7 100644 --- a/internal/cmd/redis/instance/list/list_test.go +++ b/internal/cmd/redis/instance/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -186,3 +185,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + instances []redis.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "slice with empty element", + args: args{ + instances: []redis.Instance{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 0f7dbde6b..8ae785da6 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -152,17 +152,19 @@ func outputResult(p *print.Printer, outputFormat string, plans []redis.Offering) table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { o := plans[i] - for j := range *o.Plans { - plan := (*o.Plans)[j] - table.AddRow( - utils.PtrString(o.Name), - utils.PtrString(o.Version), - utils.PtrString(plan.Id), - utils.PtrString(plan.Name), - utils.PtrString(plan.Description), - ) + if o.Plans != nil { + for j := range *o.Plans { + plan := (*o.Plans)[j] + table.AddRow( + utils.PtrString(o.Name), + utils.PtrString(o.Version), + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + ) + } + table.AddSeparator() } - table.AddSeparator() } table.EnableAutoMergeOnColumns(1, 2) err := table.Display(p) diff --git a/internal/cmd/redis/plans/plans_test.go b/internal/cmd/redis/plans/plans_test.go index 7f1a7a909..f850de8a1 100644 --- a/internal/cmd/redis/plans/plans_test.go +++ b/internal/cmd/redis/plans/plans_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -186,3 +185,39 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + plans []redis.Offering + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "slice with empty elements", + args: args{ + plans: []redis.Offering{ + {}, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From ef291d1683ca5b0d719ec0a26ecb999a32685117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Thu, 6 Mar 2025 15:28:55 +0100 Subject: [PATCH 219/619] Feat/stackitcli 117 move iaa s beta commonds to top level (#611) * feat: move IaaS commands from beta to GA * feat: updated documentation * fix: review findings --- README.md | 6 +- docs/stackit.md | 11 +++ ...ity-group.md => stackit_affinity-group.md} | 16 ++--- ...te.md => stackit_affinity-group_create.md} | 10 +-- ...te.md => stackit_affinity-group_delete.md} | 10 +-- ....md => stackit_affinity-group_describe.md} | 10 +-- ...list.md => stackit_affinity-group_list.md} | 12 ++-- docs/stackit_beta.md | 11 --- docs/stackit_beta_image_update.md | 63 ----------------- docs/stackit_beta_network-area.md | 40 ----------- ...stackit_beta_network-area_network-range.md | 37 ---------- docs/stackit_beta_network-area_route.md | 38 ---------- docs/stackit_beta_network-interface.md | 38 ---------- docs/stackit_beta_public-ip.md | 40 ----------- docs/stackit_beta_security-group.md | 39 ----------- docs/stackit_beta_security-group_rule.md | 37 ---------- docs/stackit_beta_server.md | 55 --------------- docs/stackit_beta_server_backup.md | 42 ----------- docs/stackit_beta_server_backup_schedule.md | 38 ---------- docs/stackit_beta_server_command.md | 37 ---------- docs/stackit_beta_server_os-update.md | 39 ----------- .../stackit_beta_server_os-update_schedule.md | 38 ---------- docs/stackit_beta_server_volume.md | 38 ---------- docs/stackit_beta_volume.md | 40 ----------- ...stackit_beta_image.md => stackit_image.md} | 18 ++--- ...mage_create.md => stackit_image_create.md} | 12 ++-- ...mage_delete.md => stackit_image_delete.md} | 10 +-- ..._describe.md => stackit_image_describe.md} | 10 +-- ...ta_image_list.md => stackit_image_list.md} | 14 ++-- docs/stackit_image_update.md | 62 +++++++++++++++++ ...t_beta_key-pair.md => stackit_key-pair.md} | 18 ++--- ...r_create.md => stackit_key-pair_create.md} | 16 ++--- ...r_delete.md => stackit_key-pair_delete.md} | 10 +-- ...scribe.md => stackit_key-pair_describe.md} | 12 ++-- ...-pair_list.md => stackit_key-pair_list.md} | 16 ++--- ...r_update.md => stackit_key-pair_update.md} | 10 +-- docs/stackit_network-area.md | 40 +++++++++++ ...eate.md => stackit_network-area_create.md} | 16 ++--- ...lete.md => stackit_network-area_delete.md} | 10 +-- ...be.md => stackit_network-area_describe.md} | 14 ++-- ...a_list.md => stackit_network-area_list.md} | 16 ++--- docs/stackit_network-area_network-range.md | 37 ++++++++++ ...ckit_network-area_network-range_create.md} | 10 +-- ...ckit_network-area_network-range_delete.md} | 10 +-- ...it_network-area_network-range_describe.md} | 10 +-- ...tackit_network-area_network-range_list.md} | 14 ++-- docs/stackit_network-area_route.md | 38 ++++++++++ ...d => stackit_network-area_route_create.md} | 12 ++-- ...d => stackit_network-area_route_delete.md} | 10 +-- ...=> stackit_network-area_route_describe.md} | 12 ++-- ....md => stackit_network-area_route_list.md} | 14 ++-- ...d => stackit_network-area_route_update.md} | 10 +-- ...date.md => stackit_network-area_update.md} | 10 +-- docs/stackit_network-interface.md | 38 ++++++++++ ...md => stackit_network-interface_create.md} | 12 ++-- ...md => stackit_network-interface_delete.md} | 10 +-- ... => stackit_network-interface_describe.md} | 14 ++-- ...t.md => stackit_network-interface_list.md} | 16 ++--- ...md => stackit_network-interface_update.md} | 14 ++-- ...kit_beta_network.md => stackit_network.md} | 18 ++--- ...rk_create.md => stackit_network_create.md} | 20 +++--- ...rk_delete.md => stackit_network_delete.md} | 10 +-- ...escribe.md => stackit_network_describe.md} | 12 ++-- ...etwork_list.md => stackit_network_list.md} | 16 ++--- ...rk_update.md => stackit_network_update.md} | 16 ++--- docs/stackit_public-ip.md | 40 +++++++++++ ...iate.md => stackit_public-ip_associate.md} | 10 +-- ..._create.md => stackit_public-ip_create.md} | 14 ++-- ..._delete.md => stackit_public-ip_delete.md} | 10 +-- ...cribe.md => stackit_public-ip_describe.md} | 12 ++-- ...e.md => stackit_public-ip_disassociate.md} | 10 +-- ...c-ip_list.md => stackit_public-ip_list.md} | 16 ++--- ..._update.md => stackit_public-ip_update.md} | 12 ++-- ...stackit_beta_quota.md => stackit_quota.md} | 10 +-- ...ta_quota_list.md => stackit_quota_list.md} | 12 ++-- docs/stackit_security-group.md | 39 +++++++++++ ...te.md => stackit_security-group_create.md} | 12 ++-- ...te.md => stackit_security-group_delete.md} | 10 +-- ....md => stackit_security-group_describe.md} | 10 +-- ...list.md => stackit_security-group_list.md} | 12 ++-- docs/stackit_security-group_rule.md | 37 ++++++++++ ... => stackit_security-group_rule_create.md} | 16 ++--- ... => stackit_security-group_rule_delete.md} | 10 +-- ...> stackit_security-group_rule_describe.md} | 12 ++-- ...md => stackit_security-group_rule_list.md} | 14 ++-- ...te.md => stackit_security-group_update.md} | 12 ++-- docs/stackit_server.md | 55 +++++++++++++++ docs/stackit_server_backup.md | 42 +++++++++++ ...ate.md => stackit_server_backup_create.md} | 12 ++-- ...ete.md => stackit_server_backup_delete.md} | 10 +-- ...e.md => stackit_server_backup_describe.md} | 12 ++-- ...le.md => stackit_server_backup_disable.md} | 10 +-- ...ble.md => stackit_server_backup_enable.md} | 10 +-- ..._list.md => stackit_server_backup_list.md} | 12 ++-- ...re.md => stackit_server_backup_restore.md} | 12 ++-- docs/stackit_server_backup_schedule.md | 38 ++++++++++ ... stackit_server_backup_schedule_create.md} | 12 ++-- ... stackit_server_backup_schedule_delete.md} | 10 +-- ...tackit_server_backup_schedule_describe.md} | 12 ++-- ...=> stackit_server_backup_schedule_list.md} | 12 ++-- ... stackit_server_backup_schedule_update.md} | 12 ++-- ...=> stackit_server_backup_volume-backup.md} | 12 ++-- ...kit_server_backup_volume-backup_delete.md} | 10 +-- ...it_server_backup_volume-backup_restore.md} | 10 +-- docs/stackit_server_command.md | 37 ++++++++++ ...te.md => stackit_server_command_create.md} | 12 ++-- ....md => stackit_server_command_describe.md} | 12 ++-- ...list.md => stackit_server_command_list.md} | 12 ++-- ....md => stackit_server_command_template.md} | 12 ++-- ...ackit_server_command_template_describe.md} | 12 ++-- ...> stackit_server_command_template_list.md} | 12 ++-- ...r_console.md => stackit_server_console.md} | 12 ++-- ...ver_create.md => stackit_server_create.md} | 26 +++---- ...locate.md => stackit_server_deallocate.md} | 10 +-- ...ver_delete.md => stackit_server_delete.md} | 10 +-- ...describe.md => stackit_server_describe.md} | 12 ++-- ..._server_list.md => stackit_server_list.md} | 16 ++--- ...ta_server_log.md => stackit_server_log.md} | 14 ++-- ...type.md => stackit_server_machine-type.md} | 12 ++-- ...> stackit_server_machine-type_describe.md} | 12 ++-- ...md => stackit_server_machine-type_list.md} | 14 ++-- ...md => stackit_server_network-interface.md} | 14 ++-- ...tackit_server_network-interface_attach.md} | 12 ++-- ...tackit_server_network-interface_detach.md} | 12 ++-- ... stackit_server_network-interface_list.md} | 14 ++-- docs/stackit_server_os-update.md | 39 +++++++++++ ....md => stackit_server_os-update_create.md} | 12 ++-- ...d => stackit_server_os-update_describe.md} | 12 ++-- ...md => stackit_server_os-update_disable.md} | 10 +-- ....md => stackit_server_os-update_enable.md} | 10 +-- ...st.md => stackit_server_os-update_list.md} | 12 ++-- docs/stackit_server_os-update_schedule.md | 38 ++++++++++ ...ackit_server_os-update_schedule_create.md} | 12 ++-- ...ackit_server_os-update_schedule_delete.md} | 10 +-- ...kit_server_os-update_schedule_describe.md} | 12 ++-- ...stackit_server_os-update_schedule_list.md} | 12 ++-- ...ackit_server_os-update_schedule_update.md} | 10 +-- ...blic-ip.md => stackit_server_public-ip.md} | 12 ++-- ....md => stackit_server_public-ip_attach.md} | 10 +-- ....md => stackit_server_public-ip_detach.md} | 10 +-- ...ver_reboot.md => stackit_server_reboot.md} | 12 ++-- ...ver_rescue.md => stackit_server_rescue.md} | 10 +-- ...ver_resize.md => stackit_server_resize.md} | 10 +-- ...t.md => stackit_server_service-account.md} | 14 ++-- ... stackit_server_service-account_attach.md} | 10 +-- ... stackit_server_service-account_detach.md} | 10 +-- ...=> stackit_server_service-account_list.md} | 14 ++-- ...erver_start.md => stackit_server_start.md} | 10 +-- ..._server_stop.md => stackit_server_stop.md} | 10 +-- ...unrescue.md => stackit_server_unrescue.md} | 10 +-- ...ver_update.md => stackit_server_update.md} | 12 ++-- docs/stackit_server_volume.md | 38 ++++++++++ ...ach.md => stackit_server_volume_attach.md} | 12 ++-- ...e.md => stackit_server_volume_describe.md} | 14 ++-- ...ach.md => stackit_server_volume_detach.md} | 10 +-- ..._list.md => stackit_server_volume_list.md} | 12 ++-- ...ate.md => stackit_server_volume_update.md} | 10 +-- docs/stackit_volume.md | 40 +++++++++++ ...ume_create.md => stackit_volume_create.md} | 16 ++--- ...ume_delete.md => stackit_volume_delete.md} | 10 +-- ...describe.md => stackit_volume_describe.md} | 12 ++-- ..._volume_list.md => stackit_volume_list.md} | 16 ++--- ...md => stackit_volume_performance-class.md} | 12 ++-- ...ckit_volume_performance-class_describe.md} | 12 ++-- ... stackit_volume_performance-class_list.md} | 16 ++--- ...ume_resize.md => stackit_volume_resize.md} | 10 +-- ...ume_update.md => stackit_volume_update.md} | 14 ++-- .../affinity-groups/affinity-groups.go | 8 +-- .../affinity-groups/create/create.go | 2 +- .../affinity-groups/create/create_test.go | 0 .../affinity-groups/delete/delete.go | 2 +- .../affinity-groups/delete/delete_test.go | 0 .../affinity-groups/describe/describe.go | 2 +- .../affinity-groups/describe/describe_test.go | 0 .../{beta => }/affinity-groups/list/list.go | 4 +- .../affinity-groups/list/list_test.go | 0 internal/cmd/beta/beta.go | 22 ------ internal/cmd/beta/server/server.go | 69 ------------------- .../cmd/{beta => }/image/create/create.go | 4 +- .../{beta => }/image/create/create_test.go | 0 .../cmd/{beta => }/image/delete/delete.go | 2 +- .../{beta => }/image/delete/delete_test.go | 0 .../cmd/{beta => }/image/describe/describe.go | 2 +- .../image/describe/describe_test.go | 0 internal/cmd/{beta => }/image/image.go | 10 +-- internal/cmd/{beta => }/image/list/list.go | 6 +- .../cmd/{beta => }/image/list/list_test.go | 0 .../cmd/{beta => }/image/update/update.go | 4 +- .../{beta => }/image/update/update_test.go | 0 .../cmd/{beta => }/key-pair/create/create.go | 8 +-- .../{beta => }/key-pair/create/create_test.go | 0 .../key-pair/create/template/id_ed25519.pub | 0 .../cmd/{beta => }/key-pair/delete/delete.go | 2 +- .../{beta => }/key-pair/delete/delete_test.go | 0 .../{beta => }/key-pair/describe/describe.go | 4 +- .../key-pair/describe/describe_test.go | 0 internal/cmd/{beta => }/key-pair/key-pair.go | 10 +-- internal/cmd/{beta => }/key-pair/list/list.go | 8 +-- .../cmd/{beta => }/key-pair/list/list_test.go | 0 .../cmd/{beta => }/key-pair/update/update.go | 2 +- .../{beta => }/key-pair/update/update_test.go | 0 .../{beta => }/network-area/create/create.go | 8 +-- .../network-area/create/create_test.go | 0 .../{beta => }/network-area/delete/delete.go | 2 +- .../network-area/delete/delete_test.go | 0 .../network-area/describe/describe.go | 6 +- .../network-area/describe/describe_test.go | 0 .../cmd/{beta => }/network-area/list/list.go | 8 +-- .../{beta => }/network-area/list/list_test.go | 0 .../network-range/create/create.go | 2 +- .../network-range/create/create_test.go | 0 .../network-range/delete/delete.go | 2 +- .../network-range/delete/delete_test.go | 0 .../network-range/describe/describe.go | 2 +- .../network-range/describe/describe_test.go | 0 .../network-area/network-range/list/list.go | 6 +- .../network-range/list/list_test.go | 0 .../network-range/network_range.go | 8 +-- .../{beta => }/network-area/network_area.go | 14 ++-- .../network-area/route/create/create.go | 4 +- .../network-area/route/create/create_test.go | 0 .../network-area/route/delete/delete.go | 2 +- .../network-area/route/delete/delete_test.go | 0 .../network-area/route/describe/describe.go | 4 +- .../route/describe/describe_test.go | 0 .../network-area/route/list/list.go | 6 +- .../network-area/route/list/list_test.go | 0 .../{beta => }/network-area/route/routes.go | 10 +-- .../network-area/route/update/update.go | 2 +- .../network-area/route/update/update_test.go | 0 .../{beta => }/network-area/update/update.go | 2 +- .../network-area/update/update_test.go | 0 .../network-interface/create/create.go | 4 +- .../network-interface/create/create_test.go | 0 .../network-interface/delete/delete.go | 2 +- .../network-interface/delete/delete_test.go | 0 .../network-interface/describe/describe.go | 6 +- .../describe/describe_test.go | 0 .../{beta => }/network-interface/list/list.go | 8 +-- .../network-interface/list/list_test.go | 0 .../network-interface/network-interface.go | 10 +-- .../network-interface/update/update.go | 6 +- .../network-interface/update/update_test.go | 0 .../cmd/{beta => }/network/create/create.go | 12 ++-- .../{beta => }/network/create/create_test.go | 0 .../cmd/{beta => }/network/delete/delete.go | 2 +- .../{beta => }/network/delete/delete_test.go | 0 .../{beta => }/network/describe/describe.go | 4 +- .../network/describe/describe_test.go | 0 internal/cmd/{beta => }/network/list/list.go | 8 +-- .../cmd/{beta => }/network/list/list_test.go | 0 internal/cmd/{beta => }/network/network.go | 10 +-- .../cmd/{beta => }/network/update/update.go | 8 +-- .../{beta => }/network/update/update_test.go | 0 .../public-ip/associate/associate.go | 2 +- .../public-ip/associate/associate_test.go | 0 .../cmd/{beta => }/public-ip/create/create.go | 6 +- .../public-ip/create/create_test.go | 0 .../cmd/{beta => }/public-ip/delete/delete.go | 2 +- .../public-ip/delete/delete_test.go | 0 .../{beta => }/public-ip/describe/describe.go | 4 +- .../public-ip/describe/describe_test.go | 0 .../public-ip/disassociate/disassociate.go | 2 +- .../disassociate/disassociate_test.go | 0 .../cmd/{beta => }/public-ip/list/list.go | 8 +-- .../{beta => }/public-ip/list/list_test.go | 0 .../cmd/{beta => }/public-ip/public-ip.go | 14 ++-- .../cmd/{beta => }/public-ip/update/update.go | 4 +- .../public-ip/update/update_test.go | 0 internal/cmd/{beta => }/quota/list/list.go | 2 +- .../cmd/{beta => }/quota/list/list_test.go | 0 internal/cmd/{beta => }/quota/quota.go | 2 +- internal/cmd/root.go | 22 ++++++ .../security-group/create/create.go | 4 +- .../security-group/create/create_test.go | 0 .../security-group/delete/delete.go | 2 +- .../security-group/delete/delete_test.go | 0 .../security-group/describe/describe.go | 2 +- .../security-group/describe/describe_test.go | 0 .../{beta => }/security-group/list/list.go | 4 +- .../security-group/list/list_test.go | 0 .../security-group/rule/create/create.go | 8 +-- .../security-group/rule/create/create_test.go | 0 .../security-group/rule/delete/delete.go | 2 +- .../security-group/rule/delete/delete_test.go | 0 .../security-group/rule/describe/describe.go | 4 +- .../rule/describe/describe_test.go | 0 .../security-group/rule/list/list.go | 6 +- .../security-group/rule/list/list_test.go | 0 .../rule/security_group_rule.go | 8 +-- .../security-group/security_group.go | 12 ++-- .../security-group/update/update.go | 4 +- .../security-group/update/update_test.go | 0 .../cmd/{beta => }/server/backup/backup.go | 18 ++--- .../{beta => }/server/backup/create/create.go | 4 +- .../server/backup/create/create_test.go | 0 .../{beta => }/server/backup/delete/delete.go | 2 +- .../server/backup/delete/delete_test.go | 0 .../server/backup/describe/describe.go | 4 +- .../server/backup/describe/describe_test.go | 0 .../server/backup/disable/disable.go | 2 +- .../server/backup/disable/disable_test.go | 0 .../{beta => }/server/backup/enable/enable.go | 2 +- .../server/backup/enable/enable_test.go | 0 .../cmd/{beta => }/server/backup/list/list.go | 4 +- .../server/backup/list/list_test.go | 0 .../server/backup/restore/restore.go | 4 +- .../server/backup/restore/restore_test.go | 0 .../server/backup/schedule/create/create.go | 4 +- .../backup/schedule/create/create_test.go | 0 .../server/backup/schedule/delete/delete.go | 2 +- .../backup/schedule/delete/delete_test.go | 0 .../backup/schedule/describe/describe.go | 4 +- .../backup/schedule/describe/describe_test.go | 0 .../server/backup/schedule/list/list.go | 4 +- .../server/backup/schedule/list/list_test.go | 0 .../server/backup/schedule/schedule.go | 10 +-- .../server/backup/schedule/update/update.go | 4 +- .../backup/schedule/update/update_test.go | 0 .../backup/volume-backup/delete/delete.go | 2 +- .../volume-backup/delete/delete_test.go | 0 .../backup/volume-backup/restore/restore.go | 2 +- .../volume-backup/restore/restore_test.go | 0 .../backup/volume-backup/volumebackup.go | 4 +- .../cmd/{beta => }/server/command/command.go | 8 +-- .../server/command/create/create.go | 4 +- .../server/command/create/create_test.go | 0 .../server/command/describe/describe.go | 4 +- .../server/command/describe/describe_test.go | 0 .../{beta => }/server/command/list/list.go | 4 +- .../server/command/list/list_test.go | 0 .../command/template/describe/describe.go | 4 +- .../template/describe/describe_test.go | 0 .../server/command/template/list/list.go | 4 +- .../server/command/template/list/list_test.go | 0 .../server/command/template/template.go | 4 +- .../cmd/{beta => }/server/console/console.go | 4 +- .../{beta => }/server/console/console_test.go | 0 .../cmd/{beta => }/server/create/create.go | 18 ++--- .../{beta => }/server/create/create_test.go | 0 .../server/deallocate/deallocate.go | 2 +- .../server/deallocate/deallocate_test.go | 0 .../cmd/{beta => }/server/delete/delete.go | 2 +- .../{beta => }/server/delete/delete_test.go | 0 .../{beta => }/server/describe/describe.go | 4 +- .../server/describe/describe_test.go | 0 internal/cmd/{beta => }/server/list/list.go | 8 +-- .../cmd/{beta => }/server/list/list_test.go | 0 internal/cmd/{beta => }/server/log/log.go | 6 +- .../cmd/{beta => }/server/log/log_test.go | 0 .../server/machine-type/describe/describe.go | 4 +- .../machine-type/describe/describe_test.go | 0 .../server/machine-type/list/list.go | 6 +- .../server/machine-type/list/list_test.go | 0 .../server/machine-type/machine-type.go | 4 +- .../server/network-interface/attach/attach.go | 4 +- .../network-interface/attach/attach_test.go | 0 .../server/network-interface/detach/detach.go | 4 +- .../network-interface/detach/detach_test.go | 0 .../server/network-interface/list/list.go | 6 +- .../network-interface/list/list_test.go | 0 .../network-interface/network-interface.go | 6 +- .../server/os-update/create/create.go | 4 +- .../server/os-update/create/create_test.go | 0 .../server/os-update/describe/describe.go | 4 +- .../os-update/describe/describe_test.go | 0 .../server/os-update/disable/disable.go | 2 +- .../server/os-update/disable/disable_test.go | 0 .../server/os-update/enable/enable.go | 2 +- .../server/os-update/enable/enable_test.go | 0 .../{beta => }/server/os-update/list/list.go | 4 +- .../server/os-update/list/list_test.go | 0 .../{beta => }/server/os-update/os-update.go | 12 ++-- .../os-update/schedule/create/create.go | 4 +- .../os-update/schedule/create/create_test.go | 0 .../os-update/schedule/delete/delete.go | 2 +- .../os-update/schedule/delete/delete_test.go | 0 .../os-update/schedule/describe/describe.go | 4 +- .../schedule/describe/describe_test.go | 0 .../server/os-update/schedule/list/list.go | 4 +- .../os-update/schedule/list/list_test.go | 0 .../server/os-update/schedule/schedule.go | 10 +-- .../os-update/schedule/update/update.go | 2 +- .../os-update/schedule/update/update_test.go | 0 .../server/public-ip/attach/attach.go | 2 +- .../server/public-ip/attach/attach_test.go | 0 .../server/public-ip/detach/detach.go | 2 +- .../server/public-ip/detach/detach_test.go | 0 .../{beta => }/server/public-ip/public_ip.go | 4 +- .../cmd/{beta => }/server/reboot/reboot.go | 4 +- .../{beta => }/server/reboot/reboot_test.go | 0 .../cmd/{beta => }/server/rescue/rescue.go | 2 +- .../{beta => }/server/rescue/rescue_test.go | 0 .../cmd/{beta => }/server/resize/resize.go | 2 +- .../{beta => }/server/resize/resize_test.go | 0 internal/cmd/server/server.go | 69 +++++++++++++++++++ .../server/service-account/attach/attach.go | 2 +- .../service-account/attach/attach_test.go | 0 .../server/service-account/detach/detach.go | 2 +- .../service-account/detach/detach_test.go | 0 .../server/service-account/list/list.go | 6 +- .../server/service-account/list/list_test.go | 0 .../server/service-account/service-account.go | 6 +- internal/cmd/{beta => }/server/start/start.go | 2 +- .../cmd/{beta => }/server/start/start_test.go | 0 internal/cmd/{beta => }/server/stop/stop.go | 2 +- .../cmd/{beta => }/server/stop/stop_test.go | 0 .../{beta => }/server/unrescue/unrescue.go | 2 +- .../server/unrescue/unrescue_test.go | 0 .../cmd/{beta => }/server/update/update.go | 4 +- .../{beta => }/server/update/update_test.go | 0 .../{beta => }/server/volume/attach/attach.go | 4 +- .../server/volume/attach/attach_test.go | 0 .../server/volume/describe/describe.go | 6 +- .../server/volume/describe/describe_test.go | 0 .../{beta => }/server/volume/detach/detach.go | 2 +- .../server/volume/detach/detach_test.go | 0 .../cmd/{beta => }/server/volume/list/list.go | 4 +- .../server/volume/list/list_test.go | 0 .../{beta => }/server/volume/update/update.go | 2 +- .../server/volume/update/update_test.go | 0 .../cmd/{beta => }/server/volume/volume.go | 10 +-- .../cmd/{beta => }/volume/create/create.go | 8 +-- .../{beta => }/volume/create/create_test.go | 0 .../cmd/{beta => }/volume/delete/delete.go | 2 +- .../{beta => }/volume/delete/delete_test.go | 0 .../{beta => }/volume/describe/describe.go | 4 +- .../volume/describe/describe_test.go | 0 internal/cmd/{beta => }/volume/list/list.go | 8 +-- .../cmd/{beta => }/volume/list/list_test.go | 0 .../performance-class/describe/describe.go | 4 +- .../describe/describe_test.go | 0 .../volume/performance-class/list/list.go | 8 +-- .../performance-class/list/list_test.go | 0 .../performance-class/performance_class.go | 4 +- .../cmd/{beta => }/volume/resize/resize.go | 2 +- .../{beta => }/volume/resize/resize_test.go | 0 .../cmd/{beta => }/volume/update/update.go | 6 +- .../{beta => }/volume/update/update_test.go | 0 internal/cmd/{beta => }/volume/volume.go | 14 ++-- 440 files changed, 1931 insertions(+), 1932 deletions(-) rename docs/{stackit_beta_affinity-group.md => stackit_affinity-group.md} (50%) rename docs/{stackit_beta_affinity-group_create.md => stackit_affinity-group_create.md} (73%) rename docs/{stackit_beta_affinity-group_delete.md => stackit_affinity-group_delete.md} (69%) rename docs/{stackit_beta_affinity-group_describe.md => stackit_affinity-group_describe.md} (69%) rename docs/{stackit_beta_affinity-group_list.md => stackit_affinity-group_list.md} (70%) delete mode 100644 docs/stackit_beta_image_update.md delete mode 100644 docs/stackit_beta_network-area.md delete mode 100644 docs/stackit_beta_network-area_network-range.md delete mode 100644 docs/stackit_beta_network-area_route.md delete mode 100644 docs/stackit_beta_network-interface.md delete mode 100644 docs/stackit_beta_public-ip.md delete mode 100644 docs/stackit_beta_security-group.md delete mode 100644 docs/stackit_beta_security-group_rule.md delete mode 100644 docs/stackit_beta_server.md delete mode 100644 docs/stackit_beta_server_backup.md delete mode 100644 docs/stackit_beta_server_backup_schedule.md delete mode 100644 docs/stackit_beta_server_command.md delete mode 100644 docs/stackit_beta_server_os-update.md delete mode 100644 docs/stackit_beta_server_os-update_schedule.md delete mode 100644 docs/stackit_beta_server_volume.md delete mode 100644 docs/stackit_beta_volume.md rename docs/{stackit_beta_image.md => stackit_image.md} (52%) rename docs/{stackit_beta_image_create.md => stackit_image_create.md} (83%) rename docs/{stackit_beta_image_delete.md => stackit_image_delete.md} (74%) rename docs/{stackit_beta_image_describe.md => stackit_image_describe.md} (73%) rename docs/{stackit_beta_image_list.md => stackit_image_list.md} (72%) create mode 100644 docs/stackit_image_update.md rename docs/{stackit_beta_key-pair.md => stackit_key-pair.md} (50%) rename docs/{stackit_beta_key-pair_create.md => stackit_key-pair_create.md} (69%) rename docs/{stackit_beta_key-pair_delete.md => stackit_key-pair_delete.md} (70%) rename docs/{stackit_beta_key-pair_describe.md => stackit_key-pair_describe.md} (69%) rename docs/{stackit_beta_key-pair_list.md => stackit_key-pair_list.md} (68%) rename docs/{stackit_beta_key-pair_update.md => stackit_key-pair_update.md} (72%) create mode 100644 docs/stackit_network-area.md rename docs/{stackit_beta_network-area_create.md => stackit_network-area_create.md} (65%) rename docs/{stackit_beta_network-area_delete.md => stackit_network-area_delete.md} (71%) rename docs/{stackit_beta_network-area_describe.md => stackit_network-area_describe.md} (69%) rename docs/{stackit_beta_network-area_list.md => stackit_network-area_list.md} (67%) create mode 100644 docs/stackit_network-area_network-range.md rename docs/{stackit_beta_network-area_network-range_create.md => stackit_network-area_network-range_create.md} (67%) rename docs/{stackit_beta_network-area_network-range_delete.md => stackit_network-area_network-range_delete.md} (66%) rename docs/{stackit_beta_network-area_network-range_describe.md => stackit_network-area_network-range_describe.md} (66%) rename docs/{stackit_beta_network-area_network-range_list.md => stackit_network-area_network-range_list.md} (64%) create mode 100644 docs/stackit_network-area_route.md rename docs/{stackit_beta_network-area_route_create.md => stackit_network-area_route_create.md} (73%) rename docs/{stackit_beta_network-area_route_delete.md => stackit_network-area_route_delete.md} (68%) rename docs/{stackit_beta_network-area_route_describe.md => stackit_network-area_route_describe.md} (66%) rename docs/{stackit_beta_network-area_route_list.md => stackit_network-area_route_list.md} (66%) rename docs/{stackit_beta_network-area_route_update.md => stackit_network-area_route_update.md} (74%) rename docs/{stackit_beta_network-area_update.md => stackit_network-area_update.md} (79%) create mode 100644 docs/stackit_network-interface.md rename docs/{stackit_beta_network-interface_create.md => stackit_network-interface_create.md} (72%) rename docs/{stackit_beta_network-interface_delete.md => stackit_network-interface_delete.md} (68%) rename docs/{stackit_beta_network-interface_describe.md => stackit_network-interface_describe.md} (63%) rename docs/{stackit_beta_network-interface_list.md => stackit_network-interface_list.md} (66%) rename docs/{stackit_beta_network-interface_update.md => stackit_network-interface_update.md} (71%) rename docs/{stackit_beta_network.md => stackit_network.md} (50%) rename docs/{stackit_beta_network_create.md => stackit_network_create.md} (74%) rename docs/{stackit_beta_network_delete.md => stackit_network_delete.md} (73%) rename docs/{stackit_beta_network_describe.md => stackit_network_describe.md} (69%) rename docs/{stackit_beta_network_list.md => stackit_network_list.md} (69%) rename docs/{stackit_beta_network_update.md => stackit_network_update.md} (75%) create mode 100644 docs/stackit_public-ip.md rename docs/{stackit_beta_public-ip_associate.md => stackit_public-ip_associate.md} (73%) rename docs/{stackit_beta_public-ip_create.md => stackit_public-ip_create.md} (70%) rename docs/{stackit_beta_public-ip_delete.md => stackit_public-ip_delete.md} (72%) rename docs/{stackit_beta_public-ip_describe.md => stackit_public-ip_describe.md} (68%) rename docs/{stackit_beta_public-ip_disassociate.md => stackit_public-ip_disassociate.md} (73%) rename docs/{stackit_beta_public-ip_list.md => stackit_public-ip_list.md} (68%) rename docs/{stackit_beta_public-ip_update.md => stackit_public-ip_update.md} (71%) rename docs/{stackit_beta_quota.md => stackit_quota.md} (72%) rename docs/{stackit_beta_quota_list.md => stackit_quota_list.md} (73%) create mode 100644 docs/stackit_security-group.md rename docs/{stackit_beta_security-group_create.md => stackit_security-group_create.md} (72%) rename docs/{stackit_beta_security-group_delete.md => stackit_security-group_delete.md} (70%) rename docs/{stackit_beta_security-group_describe.md => stackit_security-group_describe.md} (70%) rename docs/{stackit_beta_security-group_list.md => stackit_security-group_list.md} (67%) create mode 100644 docs/stackit_security-group_rule.md rename docs/{stackit_beta_security-group_rule_create.md => stackit_security-group_rule_create.md} (75%) rename docs/{stackit_beta_security-group_rule_delete.md => stackit_security-group_rule_delete.md} (68%) rename docs/{stackit_beta_security-group_rule_describe.md => stackit_security-group_rule_describe.md} (64%) rename docs/{stackit_beta_security-group_rule_list.md => stackit_security-group_rule_list.md} (66%) rename docs/{stackit_beta_security-group_update.md => stackit_security-group_update.md} (71%) create mode 100644 docs/stackit_server.md create mode 100644 docs/stackit_server_backup.md rename docs/{stackit_beta_server_backup_create.md => stackit_server_backup_create.md} (71%) rename docs/{stackit_beta_server_backup_delete.md => stackit_server_backup_delete.md} (69%) rename docs/{stackit_beta_server_backup_describe.md => stackit_server_backup_describe.md} (67%) rename docs/{stackit_beta_server_backup_disable.md => stackit_server_backup_disable.md} (70%) rename docs/{stackit_beta_server_backup_enable.md => stackit_server_backup_enable.md} (70%) rename docs/{stackit_beta_server_backup_list.md => stackit_server_backup_list.md} (69%) rename docs/{stackit_beta_server_backup_restore.md => stackit_server_backup_restore.md} (71%) create mode 100644 docs/stackit_server_backup_schedule.md rename docs/{stackit_beta_server_backup_schedule_create.md => stackit_server_backup_schedule_create.md} (70%) rename docs/{stackit_beta_server_backup_schedule_delete.md => stackit_server_backup_schedule_delete.md} (66%) rename docs/{stackit_beta_server_backup_schedule_describe.md => stackit_server_backup_schedule_describe.md} (63%) rename docs/{stackit_beta_server_backup_schedule_list.md => stackit_server_backup_schedule_list.md} (66%) rename docs/{stackit_beta_server_backup_schedule_update.md => stackit_server_backup_schedule_update.md} (72%) rename docs/{stackit_beta_server_backup_volume-backup.md => stackit_server_backup_volume-backup.md} (54%) rename docs/{stackit_beta_server_backup_volume-backup_delete.md => stackit_server_backup_volume-backup_delete.md} (65%) rename docs/{stackit_beta_server_backup_volume-backup_restore.md => stackit_server_backup_volume-backup_restore.md} (66%) create mode 100644 docs/stackit_server_command.md rename docs/{stackit_beta_server_command_create.md => stackit_server_command_create.md} (69%) rename docs/{stackit_beta_server_command_describe.md => stackit_server_command_describe.md} (66%) rename docs/{stackit_beta_server_command_list.md => stackit_server_command_list.md} (68%) rename docs/{stackit_beta_server_command_template.md => stackit_server_command_template.md} (55%) rename docs/{stackit_beta_server_command_template_describe.md => stackit_server_command_template_describe.md} (63%) rename docs/{stackit_beta_server_command_template_list.md => stackit_server_command_template_list.md} (65%) rename docs/{stackit_beta_server_console.md => stackit_server_console.md} (72%) rename docs/{stackit_beta_server_create.md => stackit_server_create.md} (70%) rename docs/{stackit_beta_server_deallocate.md => stackit_server_deallocate.md} (72%) rename docs/{stackit_beta_server_delete.md => stackit_server_delete.md} (73%) rename docs/{stackit_beta_server_describe.md => stackit_server_describe.md} (70%) rename docs/{stackit_beta_server_list.md => stackit_server_list.md} (70%) rename docs/{stackit_beta_server_log.md => stackit_server_log.md} (72%) rename docs/{stackit_beta_server_machine-type.md => stackit_server_machine-type.md} (58%) rename docs/{stackit_beta_server_machine-type_describe.md => stackit_server_machine-type_describe.md} (63%) rename docs/{stackit_beta_server_machine-type_list.md => stackit_server_machine-type_list.md} (65%) rename docs/{stackit_beta_server_network-interface.md => stackit_server_network-interface.md} (50%) rename docs/{stackit_beta_server_network-interface_attach.md => stackit_server_network-interface_attach.md} (67%) rename docs/{stackit_beta_server_network-interface_detach.md => stackit_server_network-interface_detach.md} (68%) rename docs/{stackit_beta_server_network-interface_list.md => stackit_server_network-interface_list.md} (64%) create mode 100644 docs/stackit_server_os-update.md rename docs/{stackit_beta_server_os-update_create.md => stackit_server_os-update_create.md} (67%) rename docs/{stackit_beta_server_os-update_describe.md => stackit_server_os-update_describe.md} (65%) rename docs/{stackit_beta_server_os-update_disable.md => stackit_server_os-update_disable.md} (68%) rename docs/{stackit_beta_server_os-update_enable.md => stackit_server_os-update_enable.md} (68%) rename docs/{stackit_beta_server_os-update_list.md => stackit_server_os-update_list.md} (67%) create mode 100644 docs/stackit_server_os-update_schedule.md rename docs/{stackit_beta_server_os-update_schedule_create.md => stackit_server_os-update_schedule_create.md} (70%) rename docs/{stackit_beta_server_os-update_schedule_delete.md => stackit_server_os-update_schedule_delete.md} (65%) rename docs/{stackit_beta_server_os-update_schedule_describe.md => stackit_server_os-update_schedule_describe.md} (63%) rename docs/{stackit_beta_server_os-update_schedule_list.md => stackit_server_os-update_schedule_list.md} (65%) rename docs/{stackit_beta_server_os-update_schedule_update.md => stackit_server_os-update_schedule_update.md} (72%) rename docs/{stackit_beta_server_public-ip.md => stackit_server_public-ip.md} (59%) rename docs/{stackit_beta_server_public-ip_attach.md => stackit_server_public-ip_attach.md} (68%) rename docs/{stackit_beta_server_public-ip_detach.md => stackit_server_public-ip_detach.md} (68%) rename docs/{stackit_beta_server_reboot.md => stackit_server_reboot.md} (72%) rename docs/{stackit_beta_server_rescue.md => stackit_server_rescue.md} (74%) rename docs/{stackit_beta_server_resize.md => stackit_server_resize.md} (76%) rename docs/{stackit_beta_server_service-account.md => stackit_server_service-account.md} (51%) rename docs/{stackit_beta_server_service-account_attach.md => stackit_server_service-account_attach.md} (65%) rename docs/{stackit_beta_server_service-account_detach.md => stackit_server_service-account_detach.md} (65%) rename docs/{stackit_beta_server_service-account_list.md => stackit_server_service-account_list.md} (65%) rename docs/{stackit_beta_server_start.md => stackit_server_start.md} (75%) rename docs/{stackit_beta_server_stop.md => stackit_server_stop.md} (73%) rename docs/{stackit_beta_server_unrescue.md => stackit_server_unrescue.md} (72%) rename docs/{stackit_beta_server_update.md => stackit_server_update.md} (72%) create mode 100644 docs/stackit_server_volume.md rename docs/{stackit_beta_server_volume_attach.md => stackit_server_volume_attach.md} (69%) rename docs/{stackit_beta_server_volume_describe.md => stackit_server_volume_describe.md} (66%) rename docs/{stackit_beta_server_volume_detach.md => stackit_server_volume_detach.md} (69%) rename docs/{stackit_beta_server_volume_list.md => stackit_server_volume_list.md} (67%) rename docs/{stackit_beta_server_volume_update.md => stackit_server_volume_update.md} (71%) create mode 100644 docs/stackit_volume.md rename docs/{stackit_beta_volume_create.md => stackit_volume_create.md} (73%) rename docs/{stackit_beta_volume_delete.md => stackit_volume_delete.md} (73%) rename docs/{stackit_beta_volume_describe.md => stackit_volume_describe.md} (70%) rename docs/{stackit_beta_volume_list.md => stackit_volume_list.md} (70%) rename docs/{stackit_beta_volume_performance-class.md => stackit_volume_performance-class.md} (57%) rename docs/{stackit_beta_volume_performance-class_describe.md => stackit_volume_performance-class_describe.md} (61%) rename docs/{stackit_beta_volume_performance-class_list.md => stackit_volume_performance-class_list.md} (63%) rename docs/{stackit_beta_volume_resize.md => stackit_volume_resize.md} (72%) rename docs/{stackit_beta_volume_update.md => stackit_volume_update.md} (70%) rename internal/cmd/{beta => }/affinity-groups/affinity-groups.go (68%) rename internal/cmd/{beta => }/affinity-groups/create/create.go (97%) rename internal/cmd/{beta => }/affinity-groups/create/create_test.go (100%) rename internal/cmd/{beta => }/affinity-groups/delete/delete.go (98%) rename internal/cmd/{beta => }/affinity-groups/delete/delete_test.go (100%) rename internal/cmd/{beta => }/affinity-groups/describe/describe.go (98%) rename internal/cmd/{beta => }/affinity-groups/describe/describe_test.go (100%) rename internal/cmd/{beta => }/affinity-groups/list/list.go (97%) rename internal/cmd/{beta => }/affinity-groups/list/list_test.go (100%) delete mode 100644 internal/cmd/beta/server/server.go rename internal/cmd/{beta => }/image/create/create.go (98%) rename internal/cmd/{beta => }/image/create/create_test.go (100%) rename internal/cmd/{beta => }/image/delete/delete.go (99%) rename internal/cmd/{beta => }/image/delete/delete_test.go (100%) rename internal/cmd/{beta => }/image/describe/describe.go (98%) rename internal/cmd/{beta => }/image/describe/describe_test.go (100%) rename internal/cmd/{beta => }/image/image.go (65%) rename internal/cmd/{beta => }/image/list/list.go (97%) rename internal/cmd/{beta => }/image/list/list_test.go (100%) rename internal/cmd/{beta => }/image/update/update.go (98%) rename internal/cmd/{beta => }/image/update/update_test.go (100%) rename internal/cmd/{beta => }/key-pair/create/create.go (93%) rename internal/cmd/{beta => }/key-pair/create/create_test.go (100%) rename internal/cmd/{beta => }/key-pair/create/template/id_ed25519.pub (100%) rename internal/cmd/{beta => }/key-pair/delete/delete.go (97%) rename internal/cmd/{beta => }/key-pair/delete/delete_test.go (100%) rename internal/cmd/{beta => }/key-pair/describe/describe.go (97%) rename internal/cmd/{beta => }/key-pair/describe/describe_test.go (100%) rename internal/cmd/{beta => }/key-pair/key-pair.go (65%) rename internal/cmd/{beta => }/key-pair/list/list.go (95%) rename internal/cmd/{beta => }/key-pair/list/list_test.go (100%) rename internal/cmd/{beta => }/key-pair/update/update.go (98%) rename internal/cmd/{beta => }/key-pair/update/update_test.go (100%) rename internal/cmd/{beta => }/network-area/create/create.go (90%) rename internal/cmd/{beta => }/network-area/create/create_test.go (100%) rename internal/cmd/{beta => }/network-area/delete/delete.go (98%) rename internal/cmd/{beta => }/network-area/delete/delete_test.go (100%) rename internal/cmd/{beta => }/network-area/describe/describe.go (96%) rename internal/cmd/{beta => }/network-area/describe/describe_test.go (100%) rename internal/cmd/{beta => }/network-area/list/list.go (95%) rename internal/cmd/{beta => }/network-area/list/list_test.go (100%) rename internal/cmd/{beta => }/network-area/network-range/create/create.go (97%) rename internal/cmd/{beta => }/network-area/network-range/create/create_test.go (100%) rename internal/cmd/{beta => }/network-area/network-range/delete/delete.go (97%) rename internal/cmd/{beta => }/network-area/network-range/delete/delete_test.go (100%) rename internal/cmd/{beta => }/network-area/network-range/describe/describe.go (97%) rename internal/cmd/{beta => }/network-area/network-range/describe/describe_test.go (100%) rename internal/cmd/{beta => }/network-area/network-range/list/list.go (94%) rename internal/cmd/{beta => }/network-area/network-range/list/list_test.go (100%) rename internal/cmd/{beta => }/network-area/network-range/network_range.go (69%) rename internal/cmd/{beta => }/network-area/network_area.go (65%) rename internal/cmd/{beta => }/network-area/route/create/create.go (95%) rename internal/cmd/{beta => }/network-area/route/create/create_test.go (100%) rename internal/cmd/{beta => }/network-area/route/delete/delete.go (97%) rename internal/cmd/{beta => }/network-area/route/delete/delete_test.go (100%) rename internal/cmd/{beta => }/network-area/route/describe/describe.go (95%) rename internal/cmd/{beta => }/network-area/route/describe/describe_test.go (100%) rename internal/cmd/{beta => }/network-area/route/list/list.go (94%) rename internal/cmd/{beta => }/network-area/route/list/list_test.go (100%) rename internal/cmd/{beta => }/network-area/route/routes.go (65%) rename internal/cmd/{beta => }/network-area/route/update/update.go (97%) rename internal/cmd/{beta => }/network-area/route/update/update_test.go (100%) rename internal/cmd/{beta => }/network-area/update/update.go (98%) rename internal/cmd/{beta => }/network-area/update/update_test.go (100%) rename internal/cmd/{beta => }/network-interface/create/create.go (97%) rename internal/cmd/{beta => }/network-interface/create/create_test.go (100%) rename internal/cmd/{beta => }/network-interface/delete/delete.go (97%) rename internal/cmd/{beta => }/network-interface/delete/delete_test.go (100%) rename internal/cmd/{beta => }/network-interface/describe/describe.go (95%) rename internal/cmd/{beta => }/network-interface/describe/describe_test.go (100%) rename internal/cmd/{beta => }/network-interface/list/list.go (94%) rename internal/cmd/{beta => }/network-interface/list/list_test.go (100%) rename internal/cmd/{beta => }/network-interface/network-interface.go (65%) rename internal/cmd/{beta => }/network-interface/update/update.go (96%) rename internal/cmd/{beta => }/network-interface/update/update_test.go (100%) rename internal/cmd/{beta => }/network/create/create.go (94%) rename internal/cmd/{beta => }/network/create/create_test.go (100%) rename internal/cmd/{beta => }/network/delete/delete.go (98%) rename internal/cmd/{beta => }/network/delete/delete_test.go (100%) rename internal/cmd/{beta => }/network/describe/describe.go (98%) rename internal/cmd/{beta => }/network/describe/describe_test.go (100%) rename internal/cmd/{beta => }/network/list/list.go (96%) rename internal/cmd/{beta => }/network/list/list_test.go (100%) rename internal/cmd/{beta => }/network/network.go (67%) rename internal/cmd/{beta => }/network/update/update.go (95%) rename internal/cmd/{beta => }/network/update/update_test.go (100%) rename internal/cmd/{beta => }/public-ip/associate/associate.go (98%) rename internal/cmd/{beta => }/public-ip/associate/associate_test.go (100%) rename internal/cmd/{beta => }/public-ip/create/create.go (96%) rename internal/cmd/{beta => }/public-ip/create/create_test.go (100%) rename internal/cmd/{beta => }/public-ip/delete/delete.go (98%) rename internal/cmd/{beta => }/public-ip/delete/delete_test.go (100%) rename internal/cmd/{beta => }/public-ip/describe/describe.go (97%) rename internal/cmd/{beta => }/public-ip/describe/describe_test.go (100%) rename internal/cmd/{beta => }/public-ip/disassociate/disassociate.go (98%) rename internal/cmd/{beta => }/public-ip/disassociate/disassociate_test.go (100%) rename internal/cmd/{beta => }/public-ip/list/list.go (96%) rename internal/cmd/{beta => }/public-ip/list/list_test.go (100%) rename internal/cmd/{beta => }/public-ip/public-ip.go (60%) rename internal/cmd/{beta => }/public-ip/update/update.go (97%) rename internal/cmd/{beta => }/public-ip/update/update_test.go (100%) rename internal/cmd/{beta => }/quota/list/list.go (99%) rename internal/cmd/{beta => }/quota/list/list_test.go (100%) rename internal/cmd/{beta => }/quota/quota.go (89%) rename internal/cmd/{beta => }/security-group/create/create.go (95%) rename internal/cmd/{beta => }/security-group/create/create_test.go (100%) rename internal/cmd/{beta => }/security-group/delete/delete.go (98%) rename internal/cmd/{beta => }/security-group/delete/delete_test.go (100%) rename internal/cmd/{beta => }/security-group/describe/describe.go (98%) rename internal/cmd/{beta => }/security-group/describe/describe_test.go (100%) rename internal/cmd/{beta => }/security-group/list/list.go (95%) rename internal/cmd/{beta => }/security-group/list/list_test.go (100%) rename internal/cmd/{beta => }/security-group/rule/create/create.go (94%) rename internal/cmd/{beta => }/security-group/rule/create/create_test.go (100%) rename internal/cmd/{beta => }/security-group/rule/delete/delete.go (98%) rename internal/cmd/{beta => }/security-group/rule/delete/delete_test.go (100%) rename internal/cmd/{beta => }/security-group/rule/describe/describe.go (96%) rename internal/cmd/{beta => }/security-group/rule/describe/describe_test.go (100%) rename internal/cmd/{beta => }/security-group/rule/list/list.go (95%) rename internal/cmd/{beta => }/security-group/rule/list/list_test.go (100%) rename internal/cmd/{beta => }/security-group/rule/security_group_rule.go (68%) rename internal/cmd/{beta => }/security-group/security_group.go (60%) rename internal/cmd/{beta => }/security-group/update/update.go (97%) rename internal/cmd/{beta => }/security-group/update/update_test.go (100%) rename internal/cmd/{beta => }/server/backup/backup.go (58%) rename internal/cmd/{beta => }/server/backup/create/create.go (96%) rename internal/cmd/{beta => }/server/backup/create/create_test.go (100%) rename internal/cmd/{beta => }/server/backup/delete/delete.go (97%) rename internal/cmd/{beta => }/server/backup/delete/delete_test.go (100%) rename internal/cmd/{beta => }/server/backup/describe/describe.go (97%) rename internal/cmd/{beta => }/server/backup/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/backup/disable/disable.go (98%) rename internal/cmd/{beta => }/server/backup/disable/disable_test.go (100%) rename internal/cmd/{beta => }/server/backup/enable/enable.go (98%) rename internal/cmd/{beta => }/server/backup/enable/enable_test.go (100%) rename internal/cmd/{beta => }/server/backup/list/list.go (97%) rename internal/cmd/{beta => }/server/backup/list/list_test.go (100%) rename internal/cmd/{beta => }/server/backup/restore/restore.go (96%) rename internal/cmd/{beta => }/server/backup/restore/restore_test.go (100%) rename internal/cmd/{beta => }/server/backup/schedule/create/create.go (95%) rename internal/cmd/{beta => }/server/backup/schedule/create/create_test.go (100%) rename internal/cmd/{beta => }/server/backup/schedule/delete/delete.go (98%) rename internal/cmd/{beta => }/server/backup/schedule/delete/delete_test.go (100%) rename internal/cmd/{beta => }/server/backup/schedule/describe/describe.go (96%) rename internal/cmd/{beta => }/server/backup/schedule/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/backup/schedule/list/list.go (97%) rename internal/cmd/{beta => }/server/backup/schedule/list/list_test.go (100%) rename internal/cmd/{beta => }/server/backup/schedule/schedule.go (63%) rename internal/cmd/{beta => }/server/backup/schedule/update/update.go (97%) rename internal/cmd/{beta => }/server/backup/schedule/update/update_test.go (100%) rename internal/cmd/{beta => }/server/backup/volume-backup/delete/delete.go (97%) rename internal/cmd/{beta => }/server/backup/volume-backup/delete/delete_test.go (100%) rename internal/cmd/{beta => }/server/backup/volume-backup/restore/restore.go (97%) rename internal/cmd/{beta => }/server/backup/volume-backup/restore/restore_test.go (100%) rename internal/cmd/{beta => }/server/backup/volume-backup/volumebackup.go (78%) rename internal/cmd/{beta => }/server/command/command.go (69%) rename internal/cmd/{beta => }/server/command/create/create.go (95%) rename internal/cmd/{beta => }/server/command/create/create_test.go (100%) rename internal/cmd/{beta => }/server/command/describe/describe.go (96%) rename internal/cmd/{beta => }/server/command/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/command/list/list.go (97%) rename internal/cmd/{beta => }/server/command/list/list_test.go (100%) rename internal/cmd/{beta => }/server/command/template/describe/describe.go (95%) rename internal/cmd/{beta => }/server/command/template/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/command/template/list/list.go (97%) rename internal/cmd/{beta => }/server/command/template/list/list_test.go (100%) rename internal/cmd/{beta => }/server/command/template/template.go (79%) rename internal/cmd/{beta => }/server/console/console.go (97%) rename internal/cmd/{beta => }/server/console/console_test.go (100%) rename internal/cmd/{beta => }/server/create/create.go (91%) rename internal/cmd/{beta => }/server/create/create_test.go (100%) rename internal/cmd/{beta => }/server/deallocate/deallocate.go (98%) rename internal/cmd/{beta => }/server/deallocate/deallocate_test.go (100%) rename internal/cmd/{beta => }/server/delete/delete.go (98%) rename internal/cmd/{beta => }/server/delete/delete_test.go (100%) rename internal/cmd/{beta => }/server/describe/describe.go (98%) rename internal/cmd/{beta => }/server/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/list/list.go (96%) rename internal/cmd/{beta => }/server/list/list_test.go (100%) rename internal/cmd/{beta => }/server/log/log.go (96%) rename internal/cmd/{beta => }/server/log/log_test.go (100%) rename internal/cmd/{beta => }/server/machine-type/describe/describe.go (96%) rename internal/cmd/{beta => }/server/machine-type/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/machine-type/list/list.go (96%) rename internal/cmd/{beta => }/server/machine-type/list/list_test.go (100%) rename internal/cmd/{beta => }/server/machine-type/machine-type.go (81%) rename internal/cmd/{beta => }/server/network-interface/attach/attach.go (96%) rename internal/cmd/{beta => }/server/network-interface/attach/attach_test.go (100%) rename internal/cmd/{beta => }/server/network-interface/detach/detach.go (96%) rename internal/cmd/{beta => }/server/network-interface/detach/detach_test.go (100%) rename internal/cmd/{beta => }/server/network-interface/list/list.go (95%) rename internal/cmd/{beta => }/server/network-interface/list/list_test.go (100%) rename internal/cmd/{beta => }/server/network-interface/network-interface.go (73%) rename internal/cmd/{beta => }/server/os-update/create/create.go (96%) rename internal/cmd/{beta => }/server/os-update/create/create_test.go (100%) rename internal/cmd/{beta => }/server/os-update/describe/describe.go (96%) rename internal/cmd/{beta => }/server/os-update/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/os-update/disable/disable.go (98%) rename internal/cmd/{beta => }/server/os-update/disable/disable_test.go (100%) rename internal/cmd/{beta => }/server/os-update/enable/enable.go (98%) rename internal/cmd/{beta => }/server/os-update/enable/enable_test.go (100%) rename internal/cmd/{beta => }/server/os-update/list/list.go (97%) rename internal/cmd/{beta => }/server/os-update/list/list_test.go (100%) rename internal/cmd/{beta => }/server/os-update/os-update.go (62%) rename internal/cmd/{beta => }/server/os-update/schedule/create/create.go (96%) rename internal/cmd/{beta => }/server/os-update/schedule/create/create_test.go (100%) rename internal/cmd/{beta => }/server/os-update/schedule/delete/delete.go (97%) rename internal/cmd/{beta => }/server/os-update/schedule/delete/delete_test.go (100%) rename internal/cmd/{beta => }/server/os-update/schedule/describe/describe.go (96%) rename internal/cmd/{beta => }/server/os-update/schedule/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/os-update/schedule/list/list.go (96%) rename internal/cmd/{beta => }/server/os-update/schedule/list/list_test.go (100%) rename internal/cmd/{beta => }/server/os-update/schedule/schedule.go (62%) rename internal/cmd/{beta => }/server/os-update/schedule/update/update.go (98%) rename internal/cmd/{beta => }/server/os-update/schedule/update/update_test.go (100%) rename internal/cmd/{beta => }/server/public-ip/attach/attach.go (98%) rename internal/cmd/{beta => }/server/public-ip/attach/attach_test.go (100%) rename internal/cmd/{beta => }/server/public-ip/detach/detach.go (98%) rename internal/cmd/{beta => }/server/public-ip/detach/detach_test.go (100%) rename internal/cmd/{beta => }/server/public-ip/public_ip.go (80%) rename internal/cmd/{beta => }/server/reboot/reboot.go (97%) rename internal/cmd/{beta => }/server/reboot/reboot_test.go (100%) rename internal/cmd/{beta => }/server/rescue/rescue.go (98%) rename internal/cmd/{beta => }/server/rescue/rescue_test.go (100%) rename internal/cmd/{beta => }/server/resize/resize.go (98%) rename internal/cmd/{beta => }/server/resize/resize_test.go (100%) create mode 100644 internal/cmd/server/server.go rename internal/cmd/{beta => }/server/service-account/attach/attach.go (97%) rename internal/cmd/{beta => }/server/service-account/attach/attach_test.go (100%) rename internal/cmd/{beta => }/server/service-account/detach/detach.go (97%) rename internal/cmd/{beta => }/server/service-account/detach/detach_test.go (100%) rename internal/cmd/{beta => }/server/service-account/list/list.go (95%) rename internal/cmd/{beta => }/server/service-account/list/list_test.go (100%) rename internal/cmd/{beta => }/server/service-account/service-account.go (71%) rename internal/cmd/{beta => }/server/start/start.go (98%) rename internal/cmd/{beta => }/server/start/start_test.go (100%) rename internal/cmd/{beta => }/server/stop/stop.go (98%) rename internal/cmd/{beta => }/server/stop/stop_test.go (100%) rename internal/cmd/{beta => }/server/unrescue/unrescue.go (98%) rename internal/cmd/{beta => }/server/unrescue/unrescue_test.go (100%) rename internal/cmd/{beta => }/server/update/update.go (96%) rename internal/cmd/{beta => }/server/update/update_test.go (100%) rename internal/cmd/{beta => }/server/volume/attach/attach.go (97%) rename internal/cmd/{beta => }/server/volume/attach/attach_test.go (100%) rename internal/cmd/{beta => }/server/volume/describe/describe.go (95%) rename internal/cmd/{beta => }/server/volume/describe/describe_test.go (100%) rename internal/cmd/{beta => }/server/volume/detach/detach.go (98%) rename internal/cmd/{beta => }/server/volume/detach/detach_test.go (100%) rename internal/cmd/{beta => }/server/volume/list/list.go (97%) rename internal/cmd/{beta => }/server/volume/list/list_test.go (100%) rename internal/cmd/{beta => }/server/volume/update/update.go (98%) rename internal/cmd/{beta => }/server/volume/update/update_test.go (100%) rename internal/cmd/{beta => }/server/volume/volume.go (65%) rename internal/cmd/{beta => }/volume/create/create.go (94%) rename internal/cmd/{beta => }/volume/create/create_test.go (100%) rename internal/cmd/{beta => }/volume/delete/delete.go (98%) rename internal/cmd/{beta => }/volume/delete/delete_test.go (100%) rename internal/cmd/{beta => }/volume/describe/describe.go (97%) rename internal/cmd/{beta => }/volume/describe/describe_test.go (100%) rename internal/cmd/{beta => }/volume/list/list.go (96%) rename internal/cmd/{beta => }/volume/list/list_test.go (100%) rename internal/cmd/{beta => }/volume/performance-class/describe/describe.go (96%) rename internal/cmd/{beta => }/volume/performance-class/describe/describe_test.go (100%) rename internal/cmd/{beta => }/volume/performance-class/list/list.go (94%) rename internal/cmd/{beta => }/volume/performance-class/list/list_test.go (100%) rename internal/cmd/{beta => }/volume/performance-class/performance_class.go (80%) rename internal/cmd/{beta => }/volume/resize/resize.go (98%) rename internal/cmd/{beta => }/volume/resize/resize_test.go (100%) rename internal/cmd/{beta => }/volume/update/update.go (94%) rename internal/cmd/{beta => }/volume/update/update_test.go (100%) rename internal/cmd/{beta => }/volume/volume.go (65%) diff --git a/README.md b/README.md index d7f76ff26..236f7f102 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Service | CLI Commands | Status | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | | Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `beta network-area`
`beta network`
`beta volume`
`beta network-interface`
`beta public-ip`
`beta security-group`
`beta key-pair`
`beta image`
`beta quota` | :white_check_mark: (beta)| +| Infrastructure as a Service (IaaS) | `network-area`
`network`
`volume`
`network-interface`
`public-ip`
`security-group`
`key-pair`
`image`
`quota` | :white_check_mark:| | Authorization | `project`, `organization` | :white_check_mark: | | DNS | `dns` | :white_check_mark: | | Kubernetes Engine (SKE) | `ske` | :white_check_mark: | @@ -91,8 +91,8 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Redis | `redis` | :white_check_mark: | | Resource Manager | `project` | :white_check_mark: | | Secrets Manager | `secrets-manager` | :white_check_mark: | -| Server Backup Management | `beta server backup` | :white_check_mark: (beta) | -| Server Command (Run Command) | `beta server command` | :white_check_mark: (beta) | +| Server Backup Management | `server backup` | :white_check_mark: | +| Server Command (Run Command) | `server command` | :white_check_mark: | | Service Account | `service-account` | :white_check_mark: | | SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | diff --git a/docs/stackit.md b/docs/stackit.md index f7ba5cb48..2dc456b83 100644 --- a/docs/stackit.md +++ b/docs/stackit.md @@ -27,24 +27,35 @@ stackit [flags] ### SEE ALSO +* [stackit affinity-group](./stackit_affinity-group.md) - Manage server affinity groups * [stackit auth](./stackit_auth.md) - Authenticates the STACKIT CLI * [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands * [stackit config](./stackit_config.md) - Provides functionality for CLI configuration options * [stackit curl](./stackit_curl.md) - Executes an authenticated HTTP request to an endpoint * [stackit dns](./stackit_dns.md) - Provides functionality for DNS +* [stackit image](./stackit_image.md) - Manage server images +* [stackit key-pair](./stackit_key-pair.md) - Provides functionality for SSH key pairs * [stackit load-balancer](./stackit_load-balancer.md) - Provides functionality for Load Balancer * [stackit logme](./stackit_logme.md) - Provides functionality for LogMe * [stackit mariadb](./stackit_mariadb.md) - Provides functionality for MariaDB * [stackit mongodbflex](./stackit_mongodbflex.md) - Provides functionality for MongoDB Flex +* [stackit network](./stackit_network.md) - Provides functionality for networks +* [stackit network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-interface](./stackit_network-interface.md) - Provides functionality for network interfaces * [stackit object-storage](./stackit_object-storage.md) - Provides functionality for Object Storage * [stackit observability](./stackit_observability.md) - Provides functionality for Observability * [stackit opensearch](./stackit_opensearch.md) - Provides functionality for OpenSearch * [stackit organization](./stackit_organization.md) - Manages organizations * [stackit postgresflex](./stackit_postgresflex.md) - Provides functionality for PostgreSQL Flex * [stackit project](./stackit_project.md) - Manages projects +* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs +* [stackit quota](./stackit_quota.md) - Manage server quotas * [stackit rabbitmq](./stackit_rabbitmq.md) - Provides functionality for RabbitMQ * [stackit redis](./stackit_redis.md) - Provides functionality for Redis * [stackit secrets-manager](./stackit_secrets-manager.md) - Provides functionality for Secrets Manager +* [stackit security-group](./stackit_security-group.md) - Manage security groups +* [stackit server](./stackit_server.md) - Provides functionality for servers * [stackit service-account](./stackit_service-account.md) - Provides functionality for service accounts * [stackit ske](./stackit_ske.md) - Provides functionality for SKE +* [stackit volume](./stackit_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_affinity-group.md b/docs/stackit_affinity-group.md similarity index 50% rename from docs/stackit_beta_affinity-group.md rename to docs/stackit_affinity-group.md index cf63d5263..9603fe20f 100644 --- a/docs/stackit_beta_affinity-group.md +++ b/docs/stackit_affinity-group.md @@ -1,4 +1,4 @@ -## stackit beta affinity-group +## stackit affinity-group Manage server affinity groups @@ -7,13 +7,13 @@ Manage server affinity groups Manage the lifecycle of server affinity groups. ``` -stackit beta affinity-group [flags] +stackit affinity-group [flags] ``` ### Options ``` - -h, --help Help for "stackit beta affinity-group" + -h, --help Help for "stackit affinity-group" ``` ### Options inherited from parent commands @@ -29,9 +29,9 @@ stackit beta affinity-group [flags] ### SEE ALSO -* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta affinity-group create](./stackit_beta_affinity-group_create.md) - Creates an affinity groups -* [stackit beta affinity-group delete](./stackit_beta_affinity-group_delete.md) - Deletes an affinity group -* [stackit beta affinity-group describe](./stackit_beta_affinity-group_describe.md) - Show details of an affinity group -* [stackit beta affinity-group list](./stackit_beta_affinity-group_list.md) - Lists affinity groups +* [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit affinity-group create](./stackit_affinity-group_create.md) - Creates an affinity groups +* [stackit affinity-group delete](./stackit_affinity-group_delete.md) - Deletes an affinity group +* [stackit affinity-group describe](./stackit_affinity-group_describe.md) - Show details of an affinity group +* [stackit affinity-group list](./stackit_affinity-group_list.md) - Lists affinity groups diff --git a/docs/stackit_beta_affinity-group_create.md b/docs/stackit_affinity-group_create.md similarity index 73% rename from docs/stackit_beta_affinity-group_create.md rename to docs/stackit_affinity-group_create.md index 2eab22578..fb63f39cf 100644 --- a/docs/stackit_beta_affinity-group_create.md +++ b/docs/stackit_affinity-group_create.md @@ -1,4 +1,4 @@ -## stackit beta affinity-group create +## stackit affinity-group create Creates an affinity groups @@ -7,20 +7,20 @@ Creates an affinity groups Creates an affinity groups. ``` -stackit beta affinity-group create [flags] +stackit affinity-group create [flags] ``` ### Examples ``` Create an affinity group with name "AFFINITY_GROUP_NAME" and policy "soft-affinity" - $ stackit beta affinity-group create --name AFFINITY_GROUP_NAME --policy soft-affinity + $ stackit affinity-group create --name AFFINITY_GROUP_NAME --policy soft-affinity ``` ### Options ``` - -h, --help Help for "stackit beta affinity-group create" + -h, --help Help for "stackit affinity-group create" --name string The name of the affinity group. --policy string The policy for the affinity group. Valid values for the policy are: "hard-affinity", "hard-anti-affinity", "soft-affinity", "soft-anti-affinity" ``` @@ -38,5 +38,5 @@ stackit beta affinity-group create [flags] ### SEE ALSO -* [stackit beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups +* [stackit affinity-group](./stackit_affinity-group.md) - Manage server affinity groups diff --git a/docs/stackit_beta_affinity-group_delete.md b/docs/stackit_affinity-group_delete.md similarity index 69% rename from docs/stackit_beta_affinity-group_delete.md rename to docs/stackit_affinity-group_delete.md index e4e43be34..4baa73768 100644 --- a/docs/stackit_beta_affinity-group_delete.md +++ b/docs/stackit_affinity-group_delete.md @@ -1,4 +1,4 @@ -## stackit beta affinity-group delete +## stackit affinity-group delete Deletes an affinity group @@ -7,20 +7,20 @@ Deletes an affinity group Deletes an affinity group. ``` -stackit beta affinity-group delete AFFINITY_GROUP [flags] +stackit affinity-group delete AFFINITY_GROUP [flags] ``` ### Examples ``` Delete an affinity group with ID "xxx" - $ stackit beta affinity-group delete xxx + $ stackit affinity-group delete xxx ``` ### Options ``` - -h, --help Help for "stackit beta affinity-group delete" + -h, --help Help for "stackit affinity-group delete" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta affinity-group delete AFFINITY_GROUP [flags] ### SEE ALSO -* [stackit beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups +* [stackit affinity-group](./stackit_affinity-group.md) - Manage server affinity groups diff --git a/docs/stackit_beta_affinity-group_describe.md b/docs/stackit_affinity-group_describe.md similarity index 69% rename from docs/stackit_beta_affinity-group_describe.md rename to docs/stackit_affinity-group_describe.md index 272c9b291..79276bba0 100644 --- a/docs/stackit_beta_affinity-group_describe.md +++ b/docs/stackit_affinity-group_describe.md @@ -1,4 +1,4 @@ -## stackit beta affinity-group describe +## stackit affinity-group describe Show details of an affinity group @@ -7,20 +7,20 @@ Show details of an affinity group Show details of an affinity group. ``` -stackit beta affinity-group describe AFFINITY_GROUP_ID [flags] +stackit affinity-group describe AFFINITY_GROUP_ID [flags] ``` ### Examples ``` Get details about an affinity group with the ID "xxx" - $ stackit beta affinity-group describe xxx + $ stackit affinity-group describe xxx ``` ### Options ``` - -h, --help Help for "stackit beta affinity-group describe" + -h, --help Help for "stackit affinity-group describe" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta affinity-group describe AFFINITY_GROUP_ID [flags] ### SEE ALSO -* [stackit beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups +* [stackit affinity-group](./stackit_affinity-group.md) - Manage server affinity groups diff --git a/docs/stackit_beta_affinity-group_list.md b/docs/stackit_affinity-group_list.md similarity index 70% rename from docs/stackit_beta_affinity-group_list.md rename to docs/stackit_affinity-group_list.md index ac79cb40a..ea96c20ac 100644 --- a/docs/stackit_beta_affinity-group_list.md +++ b/docs/stackit_affinity-group_list.md @@ -1,4 +1,4 @@ -## stackit beta affinity-group list +## stackit affinity-group list Lists affinity groups @@ -7,23 +7,23 @@ Lists affinity groups Lists affinity groups. ``` -stackit beta affinity-group list [flags] +stackit affinity-group list [flags] ``` ### Examples ``` Lists all affinity groups - $ stackit beta affinity-group list + $ stackit affinity-group list Lists up to 10 affinity groups - $ stackit beta affinity-group list --limit=10 + $ stackit affinity-group list --limit=10 ``` ### Options ``` - -h, --help Help for "stackit beta affinity-group list" + -h, --help Help for "stackit affinity-group list" --limit int Limit the output to the first n elements ``` @@ -40,5 +40,5 @@ stackit beta affinity-group list [flags] ### SEE ALSO -* [stackit beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups +* [stackit affinity-group](./stackit_affinity-group.md) - Manage server affinity groups diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 9cbcd94d0..59bbbc485 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -41,16 +41,5 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line -* [stackit beta affinity-group](./stackit_beta_affinity-group.md) - Manage server affinity groups -* [stackit beta image](./stackit_beta_image.md) - Manage server images -* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks -* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces -* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs -* [stackit beta quota](./stackit_beta_quota.md) - Manage server quotas -* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_image_update.md b/docs/stackit_beta_image_update.md deleted file mode 100644 index 760d561de..000000000 --- a/docs/stackit_beta_image_update.md +++ /dev/null @@ -1,63 +0,0 @@ -## stackit beta image update - -Updates an image - -### Synopsis - -Updates an image - -``` -stackit beta image update IMAGE_ID [flags] -``` - -### Examples - -``` - Update the name of an image with ID "xxx" - $ stackit beta image update xxx --name my-new-name - - Update the labels of an image with ID "xxx" - $ stackit beta image update xxx --labels label1=value1,label2=value2 -``` - -### Options - -``` - --boot-menu Enables the BIOS bootmenu. - --cdrom-bus string Sets CDROM bus controller type. - --disk-bus string Sets Disk bus controller type. - --disk-format string The disk format of the image. - -h, --help Help for "stackit beta image update" - --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) - --local-file-path string The path to the local disk image file. - --min-disk-size int Size in Gigabyte. - --min-ram int Size in Megabyte. - --name string The name of the image. - --nic-model string Sets virtual nic model. - --os string Enables OS specific optimizations. - --os-distro string Operating System Distribution. - --os-version string Version of the OS. - --protected Protected VM. - --rescue-bus string Sets the device bus when the image is used as a rescue image. - --rescue-device string Sets the device when the image is used as a rescue image. - --secure-boot Enables Secure Boot. - --uefi Enables UEFI boot. - --video-model string Sets Graphic device model. - --virtio-scsi Enables the use of VirtIO SCSI to provide block device access. By default instances use VirtIO Block. -``` - -### 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 beta image](./stackit_beta_image.md) - Manage server images - diff --git a/docs/stackit_beta_network-area.md b/docs/stackit_beta_network-area.md deleted file mode 100644 index 3cee4fbbb..000000000 --- a/docs/stackit_beta_network-area.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit beta network-area - -Provides functionality for STACKIT Network Area (SNA) - -### Synopsis - -Provides functionality for STACKIT Network Area (SNA). - -``` -stackit beta network-area [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta network-area" -``` - -### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta network-area create](./stackit_beta_network-area_create.md) - Creates a STACKIT Network Area (SNA) -* [stackit beta network-area delete](./stackit_beta_network-area_delete.md) - Deletes a STACKIT Network Area (SNA) -* [stackit beta network-area describe](./stackit_beta_network-area_describe.md) - Shows details of a STACKIT Network Area -* [stackit beta network-area list](./stackit_beta_network-area_list.md) - Lists all STACKIT Network Areas (SNA) of an organization -* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas -* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas -* [stackit beta network-area update](./stackit_beta_network-area_update.md) - Updates a STACKIT Network Area (SNA) - diff --git a/docs/stackit_beta_network-area_network-range.md b/docs/stackit_beta_network-area_network-range.md deleted file mode 100644 index a93af6120..000000000 --- a/docs/stackit_beta_network-area_network-range.md +++ /dev/null @@ -1,37 +0,0 @@ -## stackit beta network-area network-range - -Provides functionality for network ranges in STACKIT Network Areas - -### Synopsis - -Provides functionality for network ranges in STACKIT Network Areas. - -``` -stackit beta network-area network-range [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta network-area network-range" -``` - -### 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 beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) -* [stackit beta network-area network-range create](./stackit_beta_network-area_network-range_create.md) - Creates a network range in a STACKIT Network Area (SNA) -* [stackit beta network-area network-range delete](./stackit_beta_network-area_network-range_delete.md) - Deletes a network range in a STACKIT Network Area (SNA) -* [stackit beta network-area network-range describe](./stackit_beta_network-area_network-range_describe.md) - Shows details of a network range in a STACKIT Network Area (SNA) -* [stackit beta network-area network-range list](./stackit_beta_network-area_network-range_list.md) - Lists all network ranges in a STACKIT Network Area (SNA) - diff --git a/docs/stackit_beta_network-area_route.md b/docs/stackit_beta_network-area_route.md deleted file mode 100644 index d107ddab2..000000000 --- a/docs/stackit_beta_network-area_route.md +++ /dev/null @@ -1,38 +0,0 @@ -## stackit beta network-area route - -Provides functionality for static routes in STACKIT Network Areas - -### Synopsis - -Provides functionality for static routes in STACKIT Network Areas. - -``` -stackit beta network-area route [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta network-area route" -``` - -### 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 beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) -* [stackit beta network-area route create](./stackit_beta_network-area_route_create.md) - Creates a static route in a STACKIT Network Area (SNA) -* [stackit beta network-area route delete](./stackit_beta_network-area_route_delete.md) - Deletes a static route in a STACKIT Network Area (SNA) -* [stackit beta network-area route describe](./stackit_beta_network-area_route_describe.md) - Shows details of a static route in a STACKIT Network Area (SNA) -* [stackit beta network-area route list](./stackit_beta_network-area_route_list.md) - Lists all static routes in a STACKIT Network Area (SNA) -* [stackit beta network-area route update](./stackit_beta_network-area_route_update.md) - Updates a static route in a STACKIT Network Area (SNA) - diff --git a/docs/stackit_beta_network-interface.md b/docs/stackit_beta_network-interface.md deleted file mode 100644 index 920b310a7..000000000 --- a/docs/stackit_beta_network-interface.md +++ /dev/null @@ -1,38 +0,0 @@ -## stackit beta network-interface - -Provides functionality for network interfaces - -### Synopsis - -Provides functionality for network interfaces. - -``` -stackit beta network-interface [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta network-interface" -``` - -### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta network-interface create](./stackit_beta_network-interface_create.md) - Creates a network interface -* [stackit beta network-interface delete](./stackit_beta_network-interface_delete.md) - Deletes a network interface -* [stackit beta network-interface describe](./stackit_beta_network-interface_describe.md) - Describes a network interface -* [stackit beta network-interface list](./stackit_beta_network-interface_list.md) - Lists all network interfaces of a network -* [stackit beta network-interface update](./stackit_beta_network-interface_update.md) - Updates a network interface - diff --git a/docs/stackit_beta_public-ip.md b/docs/stackit_beta_public-ip.md deleted file mode 100644 index 53811f4f4..000000000 --- a/docs/stackit_beta_public-ip.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit beta public-ip - -Provides functionality for public IPs - -### Synopsis - -Provides functionality for public IPs. - -``` -stackit beta public-ip [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta public-ip" -``` - -### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta public-ip associate](./stackit_beta_public-ip_associate.md) - Associates a Public IP with a network interface or a virtual IP -* [stackit beta public-ip create](./stackit_beta_public-ip_create.md) - Creates a Public IP -* [stackit beta public-ip delete](./stackit_beta_public-ip_delete.md) - Deletes a Public IP -* [stackit beta public-ip describe](./stackit_beta_public-ip_describe.md) - Shows details of a Public IP -* [stackit beta public-ip disassociate](./stackit_beta_public-ip_disassociate.md) - Disassociates a Public IP from a network interface or a virtual IP -* [stackit beta public-ip list](./stackit_beta_public-ip_list.md) - Lists all Public IPs of a project -* [stackit beta public-ip update](./stackit_beta_public-ip_update.md) - Updates a Public IP - diff --git a/docs/stackit_beta_security-group.md b/docs/stackit_beta_security-group.md deleted file mode 100644 index 88b2b69ac..000000000 --- a/docs/stackit_beta_security-group.md +++ /dev/null @@ -1,39 +0,0 @@ -## stackit beta security-group - -Manage security groups - -### Synopsis - -Manage the lifecycle of security groups and rules. - -``` -stackit beta security-group [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta security-group" -``` - -### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta security-group create](./stackit_beta_security-group_create.md) - Creates security groups -* [stackit beta security-group delete](./stackit_beta_security-group_delete.md) - Deletes a security group -* [stackit beta security-group describe](./stackit_beta_security-group_describe.md) - Describes security groups -* [stackit beta security-group list](./stackit_beta_security-group_list.md) - Lists security groups -* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules -* [stackit beta security-group update](./stackit_beta_security-group_update.md) - Updates a security group - diff --git a/docs/stackit_beta_security-group_rule.md b/docs/stackit_beta_security-group_rule.md deleted file mode 100644 index 0d53cb64a..000000000 --- a/docs/stackit_beta_security-group_rule.md +++ /dev/null @@ -1,37 +0,0 @@ -## stackit beta security-group rule - -Provides functionality for security group rules - -### Synopsis - -Provides functionality for security group rules. - -``` -stackit beta security-group rule [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta security-group rule" -``` - -### 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 beta security-group](./stackit_beta_security-group.md) - Manage security groups -* [stackit beta security-group rule create](./stackit_beta_security-group_rule_create.md) - Creates a security group rule -* [stackit beta security-group rule delete](./stackit_beta_security-group_rule_delete.md) - Deletes a security group rule -* [stackit beta security-group rule describe](./stackit_beta_security-group_rule_describe.md) - Shows details of a security group rule -* [stackit beta security-group rule list](./stackit_beta_security-group_rule_list.md) - Lists all security group rules in a security group of a project - diff --git a/docs/stackit_beta_server.md b/docs/stackit_beta_server.md deleted file mode 100644 index 8846ca99c..000000000 --- a/docs/stackit_beta_server.md +++ /dev/null @@ -1,55 +0,0 @@ -## stackit beta server - -Provides functionality for servers - -### Synopsis - -Provides functionality for servers. - -``` -stackit beta server [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta server" -``` - -### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups -* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command -* [stackit beta server console](./stackit_beta_server_console.md) - Gets a URL for server remote console -* [stackit beta server create](./stackit_beta_server_create.md) - Creates a server -* [stackit beta server deallocate](./stackit_beta_server_deallocate.md) - Deallocates an existing server -* [stackit beta server delete](./stackit_beta_server_delete.md) - Deletes a server -* [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server -* [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project -* [stackit beta server log](./stackit_beta_server_log.md) - Gets server console log -* [stackit beta server machine-type](./stackit_beta_server_machine-type.md) - Provides functionality for server machine types available inside a project -* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers -* [stackit beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates -* [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers -* [stackit beta server reboot](./stackit_beta_server_reboot.md) - Reboots a server -* [stackit beta server rescue](./stackit_beta_server_rescue.md) - Rescues an existing server -* [stackit beta server resize](./stackit_beta_server_resize.md) - Resizes the server to the given machine type -* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers -* [stackit beta server start](./stackit_beta_server_start.md) - Starts an existing server or allocates the server if deallocated -* [stackit beta server stop](./stackit_beta_server_stop.md) - Stops an existing server -* [stackit beta server unrescue](./stackit_beta_server_unrescue.md) - Unrescues an existing server -* [stackit beta server update](./stackit_beta_server_update.md) - Updates a server -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes - diff --git a/docs/stackit_beta_server_backup.md b/docs/stackit_beta_server_backup.md deleted file mode 100644 index 232ae497b..000000000 --- a/docs/stackit_beta_server_backup.md +++ /dev/null @@ -1,42 +0,0 @@ -## stackit beta server backup - -Provides functionality for server backups - -### Synopsis - -Provides functionality for server backups. - -``` -stackit beta server backup [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta server backup" -``` - -### 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 beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server backup create](./stackit_beta_server_backup_create.md) - Creates a Server Backup. -* [stackit beta server backup delete](./stackit_beta_server_backup_delete.md) - Deletes a Server Backup. -* [stackit beta server backup describe](./stackit_beta_server_backup_describe.md) - Shows details of a Server Backup -* [stackit beta server backup disable](./stackit_beta_server_backup_disable.md) - Disables Server Backup service -* [stackit beta server backup enable](./stackit_beta_server_backup_enable.md) - Enables Server Backup service -* [stackit beta server backup list](./stackit_beta_server_backup_list.md) - Lists all server backups -* [stackit beta server backup restore](./stackit_beta_server_backup_restore.md) - Restores a Server Backup. -* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule -* [stackit beta server backup volume-backup](./stackit_beta_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups - diff --git a/docs/stackit_beta_server_backup_schedule.md b/docs/stackit_beta_server_backup_schedule.md deleted file mode 100644 index 07e666b18..000000000 --- a/docs/stackit_beta_server_backup_schedule.md +++ /dev/null @@ -1,38 +0,0 @@ -## stackit beta server backup schedule - -Provides functionality for Server Backup Schedule - -### Synopsis - -Provides functionality for Server Backup Schedule. - -``` -stackit beta server backup schedule [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta server backup schedule" -``` - -### 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 beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups -* [stackit beta server backup schedule create](./stackit_beta_server_backup_schedule_create.md) - Creates a Server Backup Schedule -* [stackit beta server backup schedule delete](./stackit_beta_server_backup_schedule_delete.md) - Deletes a Server Backup Schedule -* [stackit beta server backup schedule describe](./stackit_beta_server_backup_schedule_describe.md) - Shows details of a Server Backup Schedule -* [stackit beta server backup schedule list](./stackit_beta_server_backup_schedule_list.md) - Lists all server backup schedules -* [stackit beta server backup schedule update](./stackit_beta_server_backup_schedule_update.md) - Updates a Server Backup Schedule - diff --git a/docs/stackit_beta_server_command.md b/docs/stackit_beta_server_command.md deleted file mode 100644 index 8f128f4ec..000000000 --- a/docs/stackit_beta_server_command.md +++ /dev/null @@ -1,37 +0,0 @@ -## stackit beta server command - -Provides functionality for Server Command - -### Synopsis - -Provides functionality for Server Command. - -``` -stackit beta server command [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta server command" -``` - -### 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 beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server command create](./stackit_beta_server_command_create.md) - Creates a Server Command -* [stackit beta server command describe](./stackit_beta_server_command_describe.md) - Shows details of a Server Command -* [stackit beta server command list](./stackit_beta_server_command_list.md) - Lists all server commands -* [stackit beta server command template](./stackit_beta_server_command_template.md) - Provides functionality for Server Command Template - diff --git a/docs/stackit_beta_server_os-update.md b/docs/stackit_beta_server_os-update.md deleted file mode 100644 index 0cf8358b9..000000000 --- a/docs/stackit_beta_server_os-update.md +++ /dev/null @@ -1,39 +0,0 @@ -## stackit beta server os-update - -Provides functionality for managed server updates - -### Synopsis - -Provides functionality for managed server updates. - -``` -stackit beta server os-update [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta server os-update" -``` - -### 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 beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server os-update create](./stackit_beta_server_os-update_create.md) - Creates a Server os-update. -* [stackit beta server os-update describe](./stackit_beta_server_os-update_describe.md) - Shows details of a Server os-update -* [stackit beta server os-update disable](./stackit_beta_server_os-update_disable.md) - Disables server os-update service -* [stackit beta server os-update enable](./stackit_beta_server_os-update_enable.md) - Enables Server os-update service -* [stackit beta server os-update list](./stackit_beta_server_os-update_list.md) - Lists all server os-updates -* [stackit beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule - diff --git a/docs/stackit_beta_server_os-update_schedule.md b/docs/stackit_beta_server_os-update_schedule.md deleted file mode 100644 index 9579ba4b9..000000000 --- a/docs/stackit_beta_server_os-update_schedule.md +++ /dev/null @@ -1,38 +0,0 @@ -## stackit beta server os-update schedule - -Provides functionality for Server os-update Schedule - -### Synopsis - -Provides functionality for Server os-update Schedule. - -``` -stackit beta server os-update schedule [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta server os-update schedule" -``` - -### 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 beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates -* [stackit beta server os-update schedule create](./stackit_beta_server_os-update_schedule_create.md) - Creates a Server os-update Schedule -* [stackit beta server os-update schedule delete](./stackit_beta_server_os-update_schedule_delete.md) - Deletes a Server os-update Schedule -* [stackit beta server os-update schedule describe](./stackit_beta_server_os-update_schedule_describe.md) - Shows details of a Server os-update Schedule -* [stackit beta server os-update schedule list](./stackit_beta_server_os-update_schedule_list.md) - Lists all server os-update schedules -* [stackit beta server os-update schedule update](./stackit_beta_server_os-update_schedule_update.md) - Updates a Server os-update Schedule - diff --git a/docs/stackit_beta_server_volume.md b/docs/stackit_beta_server_volume.md deleted file mode 100644 index 6bd09c8c1..000000000 --- a/docs/stackit_beta_server_volume.md +++ /dev/null @@ -1,38 +0,0 @@ -## stackit beta server volume - -Provides functionality for server volumes - -### Synopsis - -Provides functionality for server volumes. - -``` -stackit beta server volume [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta server volume" -``` - -### 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 beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server volume attach](./stackit_beta_server_volume_attach.md) - Attaches a volume to a server -* [stackit beta server volume describe](./stackit_beta_server_volume_describe.md) - Describes a server volume attachment -* [stackit beta server volume detach](./stackit_beta_server_volume_detach.md) - Detaches a volume from a server -* [stackit beta server volume list](./stackit_beta_server_volume_list.md) - Lists all server volumes -* [stackit beta server volume update](./stackit_beta_server_volume_update.md) - Updates an attached volume of a server - diff --git a/docs/stackit_beta_volume.md b/docs/stackit_beta_volume.md deleted file mode 100644 index 3d3611aa9..000000000 --- a/docs/stackit_beta_volume.md +++ /dev/null @@ -1,40 +0,0 @@ -## stackit beta volume - -Provides functionality for volumes - -### Synopsis - -Provides functionality for volumes. - -``` -stackit beta volume [flags] -``` - -### Options - -``` - -h, --help Help for "stackit beta volume" -``` - -### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta volume create](./stackit_beta_volume_create.md) - Creates a volume -* [stackit beta volume delete](./stackit_beta_volume_delete.md) - Deletes a volume -* [stackit beta volume describe](./stackit_beta_volume_describe.md) - Shows details of a volume -* [stackit beta volume list](./stackit_beta_volume_list.md) - Lists all volumes of a project -* [stackit beta volume performance-class](./stackit_beta_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project -* [stackit beta volume resize](./stackit_beta_volume_resize.md) - Resizes a volume -* [stackit beta volume update](./stackit_beta_volume_update.md) - Updates a volume - diff --git a/docs/stackit_beta_image.md b/docs/stackit_image.md similarity index 52% rename from docs/stackit_beta_image.md rename to docs/stackit_image.md index 2885055ea..4120c26e6 100644 --- a/docs/stackit_beta_image.md +++ b/docs/stackit_image.md @@ -1,4 +1,4 @@ -## stackit beta image +## stackit image Manage server images @@ -7,13 +7,13 @@ Manage server images Manage the lifecycle of server images. ``` -stackit beta image [flags] +stackit image [flags] ``` ### Options ``` - -h, --help Help for "stackit beta image" + -h, --help Help for "stackit image" ``` ### Options inherited from parent commands @@ -29,10 +29,10 @@ stackit beta image [flags] ### SEE ALSO -* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta image create](./stackit_beta_image_create.md) - Creates images -* [stackit beta image delete](./stackit_beta_image_delete.md) - Deletes an image -* [stackit beta image describe](./stackit_beta_image_describe.md) - Describes image -* [stackit beta image list](./stackit_beta_image_list.md) - Lists images -* [stackit beta image update](./stackit_beta_image_update.md) - Updates an image +* [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit image create](./stackit_image_create.md) - Creates images +* [stackit image delete](./stackit_image_delete.md) - Deletes an image +* [stackit image describe](./stackit_image_describe.md) - Describes image +* [stackit image list](./stackit_image_list.md) - Lists images +* [stackit image update](./stackit_image_update.md) - Updates an image diff --git a/docs/stackit_beta_image_create.md b/docs/stackit_image_create.md similarity index 83% rename from docs/stackit_beta_image_create.md rename to docs/stackit_image_create.md index 8044adef0..83c798f6d 100644 --- a/docs/stackit_beta_image_create.md +++ b/docs/stackit_image_create.md @@ -1,4 +1,4 @@ -## stackit beta image create +## stackit image create Creates images @@ -7,17 +7,17 @@ Creates images Creates images. ``` -stackit beta image create [flags] +stackit image create [flags] ``` ### Examples ``` Create an image with name 'my-new-image' from a raw disk image located in '/my/raw/image' - $ stackit beta image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image + $ stackit image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image Create an image with name 'my-new-image' from a qcow2 image read from '/my/qcow2/image' with labels describing its contents - $ stackit beta image create --name my-new-image --disk-format=qcow2 --local-file-path=/my/qcow2/image --labels os=linux,distro=alpine,version=3.12 + $ stackit image create --name my-new-image --disk-format=qcow2 --local-file-path=/my/qcow2/image --labels os=linux,distro=alpine,version=3.12 ``` ### Options @@ -27,7 +27,7 @@ stackit beta image create [flags] --cdrom-bus string Sets CDROM bus controller type. --disk-bus string Sets Disk bus controller type. --disk-format string The disk format of the image. - -h, --help Help for "stackit beta image create" + -h, --help Help for "stackit image create" --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) --local-file-path string The path to the local disk image file. --min-disk-size int Size in Gigabyte. @@ -60,5 +60,5 @@ stackit beta image create [flags] ### SEE ALSO -* [stackit beta image](./stackit_beta_image.md) - Manage server images +* [stackit image](./stackit_image.md) - Manage server images diff --git a/docs/stackit_beta_image_delete.md b/docs/stackit_image_delete.md similarity index 74% rename from docs/stackit_beta_image_delete.md rename to docs/stackit_image_delete.md index 996596864..bbe36d37d 100644 --- a/docs/stackit_beta_image_delete.md +++ b/docs/stackit_image_delete.md @@ -1,4 +1,4 @@ -## stackit beta image delete +## stackit image delete Deletes an image @@ -7,20 +7,20 @@ Deletes an image Deletes an image by its internal ID. ``` -stackit beta image delete IMAGE_ID [flags] +stackit image delete IMAGE_ID [flags] ``` ### Examples ``` Delete an image with ID "xxx" - $ stackit beta image delete xxx + $ stackit image delete xxx ``` ### Options ``` - -h, --help Help for "stackit beta image delete" + -h, --help Help for "stackit image delete" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta image delete IMAGE_ID [flags] ### SEE ALSO -* [stackit beta image](./stackit_beta_image.md) - Manage server images +* [stackit image](./stackit_image.md) - Manage server images diff --git a/docs/stackit_beta_image_describe.md b/docs/stackit_image_describe.md similarity index 73% rename from docs/stackit_beta_image_describe.md rename to docs/stackit_image_describe.md index 6e1059166..35403a150 100644 --- a/docs/stackit_beta_image_describe.md +++ b/docs/stackit_image_describe.md @@ -1,4 +1,4 @@ -## stackit beta image describe +## stackit image describe Describes image @@ -7,20 +7,20 @@ Describes image Describes an image by its internal ID. ``` -stackit beta image describe IMAGE_ID [flags] +stackit image describe IMAGE_ID [flags] ``` ### Examples ``` Describe image "xxx" - $ stackit beta image describe xxx + $ stackit image describe xxx ``` ### Options ``` - -h, --help Help for "stackit beta image describe" + -h, --help Help for "stackit image describe" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta image describe IMAGE_ID [flags] ### SEE ALSO -* [stackit beta image](./stackit_beta_image.md) - Manage server images +* [stackit image](./stackit_image.md) - Manage server images diff --git a/docs/stackit_beta_image_list.md b/docs/stackit_image_list.md similarity index 72% rename from docs/stackit_beta_image_list.md rename to docs/stackit_image_list.md index 19ac93016..eae2a3409 100644 --- a/docs/stackit_beta_image_list.md +++ b/docs/stackit_image_list.md @@ -1,4 +1,4 @@ -## stackit beta image list +## stackit image list Lists images @@ -7,26 +7,26 @@ Lists images Lists images by their internal ID. ``` -stackit beta image list [flags] +stackit image list [flags] ``` ### Examples ``` List all images - $ stackit beta image list + $ stackit image list List images with label - $ stackit beta image list --label-selector ARM64,dev + $ stackit image list --label-selector ARM64,dev List the first 10 images - $ stackit beta image list --limit=10 + $ stackit image list --limit=10 ``` ### Options ``` - -h, --help Help for "stackit beta image list" + -h, --help Help for "stackit image list" --label-selector string Filter by label --limit int Limit the output to the first n elements ``` @@ -44,5 +44,5 @@ stackit beta image list [flags] ### SEE ALSO -* [stackit beta image](./stackit_beta_image.md) - Manage server images +* [stackit image](./stackit_image.md) - Manage server images diff --git a/docs/stackit_image_update.md b/docs/stackit_image_update.md new file mode 100644 index 000000000..3c6acbe62 --- /dev/null +++ b/docs/stackit_image_update.md @@ -0,0 +1,62 @@ +## stackit image update + +Updates an image + +### Synopsis + +Updates an image + +``` +stackit image update IMAGE_ID [flags] +``` + +### Examples + +``` + Update the name of an image with ID "xxx" + $ stackit image update xxx --name my-new-name + + Update the labels of an image with ID "xxx" + $ stackit image update xxx --labels label1=value1,label2=value2 +``` + +### Options + +``` + --boot-menu Enables the BIOS bootmenu. + --cdrom-bus string Sets CDROM bus controller type. + --disk-bus string Sets Disk bus controller type. + --disk-format string The disk format of the image. + -h, --help Help for "stackit image update" + --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) + --min-disk-size int Size in Gigabyte. + --min-ram int Size in Megabyte. + --name string The name of the image. + --nic-model string Sets virtual nic model. + --os string Enables OS specific optimizations. + --os-distro string Operating System Distribution. + --os-version string Version of the OS. + --protected Protected VM. + --rescue-bus string Sets the device bus when the image is used as a rescue image. + --rescue-device string Sets the device when the image is used as a rescue image. + --secure-boot Enables Secure Boot. + --uefi Enables UEFI boot. + --video-model string Sets Graphic device model. + --virtio-scsi Enables the use of VirtIO SCSI to provide block device access. By default instances use VirtIO Block. +``` + +### 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 image](./stackit_image.md) - Manage server images + diff --git a/docs/stackit_beta_key-pair.md b/docs/stackit_key-pair.md similarity index 50% rename from docs/stackit_beta_key-pair.md rename to docs/stackit_key-pair.md index 49b9a7a77..6e3aff7fb 100644 --- a/docs/stackit_beta_key-pair.md +++ b/docs/stackit_key-pair.md @@ -1,4 +1,4 @@ -## stackit beta key-pair +## stackit key-pair Provides functionality for SSH key pairs @@ -7,13 +7,13 @@ Provides functionality for SSH key pairs Provides functionality for SSH key pairs ``` -stackit beta key-pair [flags] +stackit key-pair [flags] ``` ### Options ``` - -h, --help Help for "stackit beta key-pair" + -h, --help Help for "stackit key-pair" ``` ### Options inherited from parent commands @@ -29,10 +29,10 @@ stackit beta key-pair [flags] ### SEE ALSO -* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta key-pair create](./stackit_beta_key-pair_create.md) - Creates a key pair -* [stackit beta key-pair delete](./stackit_beta_key-pair_delete.md) - Deletes a key pair -* [stackit beta key-pair describe](./stackit_beta_key-pair_describe.md) - Describes a key pair -* [stackit beta key-pair list](./stackit_beta_key-pair_list.md) - Lists all key pairs -* [stackit beta key-pair update](./stackit_beta_key-pair_update.md) - Updates a key pair +* [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit key-pair create](./stackit_key-pair_create.md) - Creates a key pair +* [stackit key-pair delete](./stackit_key-pair_delete.md) - Deletes a key pair +* [stackit key-pair describe](./stackit_key-pair_describe.md) - Describes a key pair +* [stackit key-pair list](./stackit_key-pair_list.md) - Lists all key pairs +* [stackit key-pair update](./stackit_key-pair_update.md) - Updates a key pair diff --git a/docs/stackit_beta_key-pair_create.md b/docs/stackit_key-pair_create.md similarity index 69% rename from docs/stackit_beta_key-pair_create.md rename to docs/stackit_key-pair_create.md index 4ddc33586..04fbb9561 100644 --- a/docs/stackit_beta_key-pair_create.md +++ b/docs/stackit_key-pair_create.md @@ -1,4 +1,4 @@ -## stackit beta key-pair create +## stackit key-pair create Creates a key pair @@ -7,29 +7,29 @@ Creates a key pair Creates a key pair. ``` -stackit beta key-pair create [flags] +stackit key-pair create [flags] ``` ### Examples ``` Create a new key pair with public-key "ssh-rsa xxx" - $ stackit beta key-pair create --public-key `ssh-rsa xxx` + $ stackit key-pair create --public-key `ssh-rsa xxx` Create a new key pair with public-key from file "/Users/username/.ssh/id_rsa.pub" - $ stackit beta key-pair create --public-key `@/Users/username/.ssh/id_rsa.pub` + $ stackit key-pair create --public-key `@/Users/username/.ssh/id_rsa.pub` Create a new key pair with name "KEY_PAIR_NAME" and public-key "ssh-rsa yyy" - $ stackit beta key-pair create --name KEY_PAIR_NAME --public-key `ssh-rsa yyy` + $ stackit key-pair create --name KEY_PAIR_NAME --public-key `ssh-rsa yyy` Create a new key pair with public-key "ssh-rsa xxx" and labels "key=value,key1=value1" - $ stackit beta key-pair create --public-key `ssh-rsa xxx` --labels key=value,key1=value1 + $ stackit key-pair create --public-key `ssh-rsa xxx` --labels key=value,key1=value1 ``` ### Options ``` - -h, --help Help for "stackit beta key-pair create" + -h, --help Help for "stackit key-pair create" --labels stringToString Labels are key-value string pairs which can be attached to a key pair. E.g. '--labels key1=value1,key2=value2,...' (default []) --name string Key pair name --public-key string Public key to be imported (format: ssh-rsa|ssh-ed25519) @@ -48,5 +48,5 @@ stackit beta key-pair create [flags] ### SEE ALSO -* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs +* [stackit key-pair](./stackit_key-pair.md) - Provides functionality for SSH key pairs diff --git a/docs/stackit_beta_key-pair_delete.md b/docs/stackit_key-pair_delete.md similarity index 70% rename from docs/stackit_beta_key-pair_delete.md rename to docs/stackit_key-pair_delete.md index b998b9cd9..b9dc10cda 100644 --- a/docs/stackit_beta_key-pair_delete.md +++ b/docs/stackit_key-pair_delete.md @@ -1,4 +1,4 @@ -## stackit beta key-pair delete +## stackit key-pair delete Deletes a key pair @@ -7,20 +7,20 @@ Deletes a key pair Deletes a key pair. ``` -stackit beta key-pair delete KEY_PAIR_NAME [flags] +stackit key-pair delete KEY_PAIR_NAME [flags] ``` ### Examples ``` Delete key pair with name "KEY_PAIR_NAME" - $ stackit beta key-pair delete KEY_PAIR_NAME + $ stackit key-pair delete KEY_PAIR_NAME ``` ### Options ``` - -h, --help Help for "stackit beta key-pair delete" + -h, --help Help for "stackit key-pair delete" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta key-pair delete KEY_PAIR_NAME [flags] ### SEE ALSO -* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs +* [stackit key-pair](./stackit_key-pair.md) - Provides functionality for SSH key pairs diff --git a/docs/stackit_beta_key-pair_describe.md b/docs/stackit_key-pair_describe.md similarity index 69% rename from docs/stackit_beta_key-pair_describe.md rename to docs/stackit_key-pair_describe.md index 5275e8c37..fa68ec225 100644 --- a/docs/stackit_beta_key-pair_describe.md +++ b/docs/stackit_key-pair_describe.md @@ -1,4 +1,4 @@ -## stackit beta key-pair describe +## stackit key-pair describe Describes a key pair @@ -7,23 +7,23 @@ Describes a key pair Describes a key pair. ``` -stackit beta key-pair describe KEY_PAIR_NAME [flags] +stackit key-pair describe KEY_PAIR_NAME [flags] ``` ### Examples ``` Get details about a key pair with name "KEY_PAIR_NAME" - $ stackit beta key-pair describe KEY_PAIR_NAME + $ stackit key-pair describe KEY_PAIR_NAME Get only the SSH public key of a key pair with name "KEY_PAIR_NAME" - $ stackit beta key-pair describe KEY_PAIR_NAME --public-key + $ stackit key-pair describe KEY_PAIR_NAME --public-key ``` ### Options ``` - -h, --help Help for "stackit beta key-pair describe" + -h, --help Help for "stackit key-pair describe" --public-key Show only the public key ``` @@ -40,5 +40,5 @@ stackit beta key-pair describe KEY_PAIR_NAME [flags] ### SEE ALSO -* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs +* [stackit key-pair](./stackit_key-pair.md) - Provides functionality for SSH key pairs diff --git a/docs/stackit_beta_key-pair_list.md b/docs/stackit_key-pair_list.md similarity index 68% rename from docs/stackit_beta_key-pair_list.md rename to docs/stackit_key-pair_list.md index c77f3fee1..f4af20042 100644 --- a/docs/stackit_beta_key-pair_list.md +++ b/docs/stackit_key-pair_list.md @@ -1,4 +1,4 @@ -## stackit beta key-pair list +## stackit key-pair list Lists all key pairs @@ -7,29 +7,29 @@ Lists all key pairs Lists all key pairs. ``` -stackit beta key-pair list [flags] +stackit key-pair list [flags] ``` ### Examples ``` Lists all key pairs - $ stackit beta key-pair list + $ stackit key-pair list Lists all key pairs which contains the label xxx - $ stackit beta key-pair list --label-selector xxx + $ stackit key-pair list --label-selector xxx Lists all key pairs in JSON format - $ stackit beta key-pair list --output-format json + $ stackit key-pair list --output-format json Lists up to 10 key pairs - $ stackit beta key-pair list --limit 10 + $ stackit key-pair list --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta key-pair list" + -h, --help Help for "stackit key-pair list" --label-selector string Filter by label --limit int Number of key pairs to list ``` @@ -47,5 +47,5 @@ stackit beta key-pair list [flags] ### SEE ALSO -* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs +* [stackit key-pair](./stackit_key-pair.md) - Provides functionality for SSH key pairs diff --git a/docs/stackit_beta_key-pair_update.md b/docs/stackit_key-pair_update.md similarity index 72% rename from docs/stackit_beta_key-pair_update.md rename to docs/stackit_key-pair_update.md index 8735cb03c..6c7399dd0 100644 --- a/docs/stackit_beta_key-pair_update.md +++ b/docs/stackit_key-pair_update.md @@ -1,4 +1,4 @@ -## stackit beta key-pair update +## stackit key-pair update Updates a key pair @@ -7,20 +7,20 @@ Updates a key pair Updates a key pair. ``` -stackit beta key-pair update KEY_PAIR_NAME [flags] +stackit key-pair update KEY_PAIR_NAME [flags] ``` ### Examples ``` Update the labels of a key pair with name "KEY_PAIR_NAME" with "key=value,key1=value1" - $ stackit beta key-pair update KEY_PAIR_NAME --labels key=value,key1=value1 + $ stackit key-pair update KEY_PAIR_NAME --labels key=value,key1=value1 ``` ### Options ``` - -h, --help Help for "stackit beta key-pair update" + -h, --help Help for "stackit key-pair update" --labels stringToString Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...' (default []) ``` @@ -37,5 +37,5 @@ stackit beta key-pair update KEY_PAIR_NAME [flags] ### SEE ALSO -* [stackit beta key-pair](./stackit_beta_key-pair.md) - Provides functionality for SSH key pairs +* [stackit key-pair](./stackit_key-pair.md) - Provides functionality for SSH key pairs diff --git a/docs/stackit_network-area.md b/docs/stackit_network-area.md new file mode 100644 index 000000000..d9ba1ecda --- /dev/null +++ b/docs/stackit_network-area.md @@ -0,0 +1,40 @@ +## stackit network-area + +Provides functionality for STACKIT Network Area (SNA) + +### Synopsis + +Provides functionality for STACKIT Network Area (SNA). + +``` +stackit network-area [flags] +``` + +### Options + +``` + -h, --help Help for "stackit network-area" +``` + +### 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](./stackit.md) - Manage STACKIT resources using the command line +* [stackit network-area create](./stackit_network-area_create.md) - Creates a STACKIT Network Area (SNA) +* [stackit network-area delete](./stackit_network-area_delete.md) - Deletes a STACKIT Network Area (SNA) +* [stackit network-area describe](./stackit_network-area_describe.md) - Shows details of a STACKIT Network Area +* [stackit network-area list](./stackit_network-area_list.md) - Lists all STACKIT Network Areas (SNA) of an organization +* [stackit network-area network-range](./stackit_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit network-area route](./stackit_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit network-area update](./stackit_network-area_update.md) - Updates a STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_create.md b/docs/stackit_network-area_create.md similarity index 65% rename from docs/stackit_beta_network-area_create.md rename to docs/stackit_network-area_create.md index 5edf5af6e..7dc278927 100644 --- a/docs/stackit_beta_network-area_create.md +++ b/docs/stackit_network-area_create.md @@ -1,4 +1,4 @@ -## stackit beta network-area create +## stackit network-area create Creates a STACKIT Network Area (SNA) @@ -7,23 +7,23 @@ Creates a STACKIT Network Area (SNA) Creates a STACKIT Network Area (SNA) in an organization. ``` -stackit beta network-area create [flags] +stackit network-area create [flags] ``` ### Examples ``` Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network - $ stackit beta network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" + $ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" Create a network area with name "network-area-2" in organization with ID "xxx" with network ranges, transfer network and DNS name server - $ stackit beta network-area create --name network-area-2 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --dns-name-servers "1.1.1.1" + $ stackit network-area create --name network-area-2 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --dns-name-servers "1.1.1.1" Create a network area with name "network-area-3" in organization with ID "xxx" with network ranges, transfer network and additional options - $ stackit beta network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24 + $ stackit network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24 Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network and labels "key=value,key1=value1" - $ stackit beta network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1 + $ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1 ``` ### Options @@ -31,7 +31,7 @@ stackit beta network-area create [flags] ``` --default-prefix-length int The default prefix length for networks in the network area --dns-name-servers strings List of DNS name server IPs - -h, --help Help for "stackit beta network-area create" + -h, --help Help for "stackit network-area create" --labels stringToString Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...' (default []) --max-prefix-length int The maximum prefix length for networks in the network area --min-prefix-length int The minimum prefix length for networks in the network area @@ -54,5 +54,5 @@ stackit beta network-area create [flags] ### SEE ALSO -* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) diff --git a/docs/stackit_beta_network-area_delete.md b/docs/stackit_network-area_delete.md similarity index 71% rename from docs/stackit_beta_network-area_delete.md rename to docs/stackit_network-area_delete.md index 0d9a2d8ef..f7814d583 100644 --- a/docs/stackit_beta_network-area_delete.md +++ b/docs/stackit_network-area_delete.md @@ -1,4 +1,4 @@ -## stackit beta network-area delete +## stackit network-area delete Deletes a STACKIT Network Area (SNA) @@ -9,20 +9,20 @@ If the SNA is attached to any projects, the deletion will fail ``` -stackit beta network-area delete AREA_ID [flags] +stackit network-area delete AREA_ID [flags] ``` ### Examples ``` Delete network area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area delete xxx --organization-id yyy + $ stackit network-area delete xxx --organization-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta network-area delete" + -h, --help Help for "stackit network-area delete" --organization-id string Organization ID ``` @@ -39,5 +39,5 @@ stackit beta network-area delete AREA_ID [flags] ### SEE ALSO -* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) diff --git a/docs/stackit_beta_network-area_describe.md b/docs/stackit_network-area_describe.md similarity index 69% rename from docs/stackit_beta_network-area_describe.md rename to docs/stackit_network-area_describe.md index 985dd3e51..a5656cfe7 100644 --- a/docs/stackit_beta_network-area_describe.md +++ b/docs/stackit_network-area_describe.md @@ -1,4 +1,4 @@ -## stackit beta network-area describe +## stackit network-area describe Shows details of a STACKIT Network Area @@ -7,26 +7,26 @@ Shows details of a STACKIT Network Area Shows details of a STACKIT Network Area in an organization. ``` -stackit beta network-area describe AREA_ID [flags] +stackit network-area describe AREA_ID [flags] ``` ### Examples ``` Show details of a network area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area describe xxx --organization-id yyy + $ stackit network-area describe xxx --organization-id yyy Show details of a network area with ID "xxx" in organization with ID "yyy" and show attached projects - $ stackit beta network-area describe xxx --organization-id yyy --show-attached-projects + $ stackit network-area describe xxx --organization-id yyy --show-attached-projects Show details of a network area with ID "xxx" in organization with ID "yyy" in JSON format - $ stackit beta network-area describe xxx --organization-id yyy --output-format json + $ stackit network-area describe xxx --organization-id yyy --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta network-area describe" + -h, --help Help for "stackit network-area describe" --organization-id string Organization ID --show-attached-projects Whether to show attached projects. If a network area has several attached projects, their retrieval may take some time and the output may be extensive. ``` @@ -44,5 +44,5 @@ stackit beta network-area describe AREA_ID [flags] ### SEE ALSO -* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) diff --git a/docs/stackit_beta_network-area_list.md b/docs/stackit_network-area_list.md similarity index 67% rename from docs/stackit_beta_network-area_list.md rename to docs/stackit_network-area_list.md index 2cdfb14b5..74fcaf9d7 100644 --- a/docs/stackit_beta_network-area_list.md +++ b/docs/stackit_network-area_list.md @@ -1,4 +1,4 @@ -## stackit beta network-area list +## stackit network-area list Lists all STACKIT Network Areas (SNA) of an organization @@ -7,29 +7,29 @@ Lists all STACKIT Network Areas (SNA) of an organization Lists all STACKIT Network Areas (SNA) of an organization. ``` -stackit beta network-area list [flags] +stackit network-area list [flags] ``` ### Examples ``` Lists all network areas of organization "xxx" - $ stackit beta network-area list --organization-id xxx + $ stackit network-area list --organization-id xxx Lists all network areas of organization "xxx" in JSON format - $ stackit beta network-area list --organization-id xxx --output-format json + $ stackit network-area list --organization-id xxx --output-format json Lists up to 10 network areas of organization "xxx" - $ stackit beta network-area list --organization-id xxx --limit 10 + $ stackit network-area list --organization-id xxx --limit 10 Lists all network areas of organization "xxx" which contains the label yyy - $ stackit beta network-area list --organization-id xxx --label-selector yyy + $ stackit network-area list --organization-id xxx --label-selector yyy ``` ### Options ``` - -h, --help Help for "stackit beta network-area list" + -h, --help Help for "stackit network-area list" --label-selector string Filter by label --limit int Maximum number of entries to list --organization-id string Organization ID @@ -48,5 +48,5 @@ stackit beta network-area list [flags] ### SEE ALSO -* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) diff --git a/docs/stackit_network-area_network-range.md b/docs/stackit_network-area_network-range.md new file mode 100644 index 000000000..4e146f3d7 --- /dev/null +++ b/docs/stackit_network-area_network-range.md @@ -0,0 +1,37 @@ +## stackit network-area network-range + +Provides functionality for network ranges in STACKIT Network Areas + +### Synopsis + +Provides functionality for network ranges in STACKIT Network Areas. + +``` +stackit network-area network-range [flags] +``` + +### Options + +``` + -h, --help Help for "stackit network-area network-range" +``` + +### 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 network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-area network-range create](./stackit_network-area_network-range_create.md) - Creates a network range in a STACKIT Network Area (SNA) +* [stackit network-area network-range delete](./stackit_network-area_network-range_delete.md) - Deletes a network range in a STACKIT Network Area (SNA) +* [stackit network-area network-range describe](./stackit_network-area_network-range_describe.md) - Shows details of a network range in a STACKIT Network Area (SNA) +* [stackit network-area network-range list](./stackit_network-area_network-range_list.md) - Lists all network ranges in a STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_network-range_create.md b/docs/stackit_network-area_network-range_create.md similarity index 67% rename from docs/stackit_beta_network-area_network-range_create.md rename to docs/stackit_network-area_network-range_create.md index 43cd57c8f..c51b7399a 100644 --- a/docs/stackit_beta_network-area_network-range_create.md +++ b/docs/stackit_network-area_network-range_create.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-range create +## stackit network-area network-range create Creates a network range in a STACKIT Network Area (SNA) @@ -7,20 +7,20 @@ Creates a network range in a STACKIT Network Area (SNA) Creates a network range in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-range create [flags] +stackit network-area network-range create [flags] ``` ### Examples ``` Create a network range in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area network-range create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24" + $ stackit network-area network-range create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24" ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-range create" + -h, --help Help for "stackit network-area network-range create" --network-area-id string STACKIT Network Area (SNA) ID --network-range string Network range to create in CIDR notation --organization-id string Organization ID @@ -39,5 +39,5 @@ stackit beta network-area network-range create [flags] ### SEE ALSO -* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit network-area network-range](./stackit_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_network-range_delete.md b/docs/stackit_network-area_network-range_delete.md similarity index 66% rename from docs/stackit_beta_network-area_network-range_delete.md rename to docs/stackit_network-area_network-range_delete.md index f9c6bf043..22626b6bf 100644 --- a/docs/stackit_beta_network-area_network-range_delete.md +++ b/docs/stackit_network-area_network-range_delete.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-range delete +## stackit network-area network-range delete Deletes a network range in a STACKIT Network Area (SNA) @@ -7,20 +7,20 @@ Deletes a network range in a STACKIT Network Area (SNA) Deletes a network range in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-range delete NETWORK_RANGE_ID [flags] +stackit network-area network-range delete NETWORK_RANGE_ID [flags] ``` ### Examples ``` Delete network range with id "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area network-range delete xxx --network-area-id yyy --organization-id zzz + $ stackit network-area network-range delete xxx --network-area-id yyy --organization-id zzz ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-range delete" + -h, --help Help for "stackit network-area network-range delete" --network-area-id string STACKIT Network Area (SNA) ID --organization-id string Organization ID ``` @@ -38,5 +38,5 @@ stackit beta network-area network-range delete NETWORK_RANGE_ID [flags] ### SEE ALSO -* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit network-area network-range](./stackit_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_network-range_describe.md b/docs/stackit_network-area_network-range_describe.md similarity index 66% rename from docs/stackit_beta_network-area_network-range_describe.md rename to docs/stackit_network-area_network-range_describe.md index 021805445..5e1831f7f 100644 --- a/docs/stackit_beta_network-area_network-range_describe.md +++ b/docs/stackit_network-area_network-range_describe.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-range describe +## stackit network-area network-range describe Shows details of a network range in a STACKIT Network Area (SNA) @@ -7,20 +7,20 @@ Shows details of a network range in a STACKIT Network Area (SNA) Shows details of a network range in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-range describe NETWORK_RANGE_ID [flags] +stackit network-area network-range describe NETWORK_RANGE_ID [flags] ``` ### Examples ``` Show details of a network range with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area network-range describe xxx --network-area-id yyy --organization-id zzz + $ stackit network-area network-range describe xxx --network-area-id yyy --organization-id zzz ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-range describe" + -h, --help Help for "stackit network-area network-range describe" --network-area-id string STACKIT Network Area (SNA) ID --organization-id string Organization ID ``` @@ -38,5 +38,5 @@ stackit beta network-area network-range describe NETWORK_RANGE_ID [flags] ### SEE ALSO -* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit network-area network-range](./stackit_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_network-range_list.md b/docs/stackit_network-area_network-range_list.md similarity index 64% rename from docs/stackit_beta_network-area_network-range_list.md rename to docs/stackit_network-area_network-range_list.md index 75a599d51..f66857ce7 100644 --- a/docs/stackit_beta_network-area_network-range_list.md +++ b/docs/stackit_network-area_network-range_list.md @@ -1,4 +1,4 @@ -## stackit beta network-area network-range list +## stackit network-area network-range list Lists all network ranges in a STACKIT Network Area (SNA) @@ -7,26 +7,26 @@ Lists all network ranges in a STACKIT Network Area (SNA) Lists all network ranges in a STACKIT Network Area (SNA). ``` -stackit beta network-area network-range list [flags] +stackit network-area network-range list [flags] ``` ### Examples ``` Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy + $ stackit network-area network-range list --network-area-id xxx --organization-id yyy Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format - $ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --output-format json + $ stackit network-area network-range list --network-area-id xxx --organization-id yyy --output-format json Lists up to 10 network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --limit 10 + $ stackit network-area network-range list --network-area-id xxx --organization-id yyy --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta network-area network-range list" + -h, --help Help for "stackit network-area network-range list" --limit int Maximum number of entries to list --network-area-id string STACKIT Network Area (SNA) ID --organization-id string Organization ID @@ -45,5 +45,5 @@ stackit beta network-area network-range list [flags] ### SEE ALSO -* [stackit beta network-area network-range](./stackit_beta_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit network-area network-range](./stackit_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas diff --git a/docs/stackit_network-area_route.md b/docs/stackit_network-area_route.md new file mode 100644 index 000000000..a5fb3f19d --- /dev/null +++ b/docs/stackit_network-area_route.md @@ -0,0 +1,38 @@ +## stackit network-area route + +Provides functionality for static routes in STACKIT Network Areas + +### Synopsis + +Provides functionality for static routes in STACKIT Network Areas. + +``` +stackit network-area route [flags] +``` + +### Options + +``` + -h, --help Help for "stackit network-area route" +``` + +### 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 network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-area route create](./stackit_network-area_route_create.md) - Creates a static route in a STACKIT Network Area (SNA) +* [stackit network-area route delete](./stackit_network-area_route_delete.md) - Deletes a static route in a STACKIT Network Area (SNA) +* [stackit network-area route describe](./stackit_network-area_route_describe.md) - Shows details of a static route in a STACKIT Network Area (SNA) +* [stackit network-area route list](./stackit_network-area_route_list.md) - Lists all static routes in a STACKIT Network Area (SNA) +* [stackit network-area route update](./stackit_network-area_route_update.md) - Updates a static route in a STACKIT Network Area (SNA) + diff --git a/docs/stackit_beta_network-area_route_create.md b/docs/stackit_network-area_route_create.md similarity index 73% rename from docs/stackit_beta_network-area_route_create.md rename to docs/stackit_network-area_route_create.md index 787e5dff5..79d239fee 100644 --- a/docs/stackit_beta_network-area_route_create.md +++ b/docs/stackit_network-area_route_create.md @@ -1,4 +1,4 @@ -## stackit beta network-area route create +## stackit network-area route create Creates a static route in a STACKIT Network Area (SNA) @@ -9,23 +9,23 @@ This command is currently asynchonous only due to limitations in the waiting fun ``` -stackit beta network-area route create [flags] +stackit network-area route create [flags] ``` ### Examples ``` Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 + $ stackit network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 Create a static route with labels "key:value" and "foo:bar" with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 + $ stackit network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 ``` ### Options ``` - -h, --help Help for "stackit beta network-area route create" + -h, --help Help for "stackit network-area route create" --labels stringToString Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) --network-area-id string STACKIT Network Area ID --next-hop string Next hop IP address. Must be a valid IPv4 @@ -46,5 +46,5 @@ stackit beta network-area route create [flags] ### SEE ALSO -* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit network-area route](./stackit_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_route_delete.md b/docs/stackit_network-area_route_delete.md similarity index 68% rename from docs/stackit_beta_network-area_route_delete.md rename to docs/stackit_network-area_route_delete.md index 9e9eef46c..fc95549b4 100644 --- a/docs/stackit_beta_network-area_route_delete.md +++ b/docs/stackit_network-area_route_delete.md @@ -1,4 +1,4 @@ -## stackit beta network-area route delete +## stackit network-area route delete Deletes a static route in a STACKIT Network Area (SNA) @@ -7,20 +7,20 @@ Deletes a static route in a STACKIT Network Area (SNA) Deletes a static route in a STACKIT Network Area (SNA). ``` -stackit beta network-area route delete ROUTE_ID [flags] +stackit network-area route delete ROUTE_ID [flags] ``` ### Examples ``` Delete a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area route delete xxx --organization-id zzz --network-area-id yyy + $ stackit network-area route delete xxx --organization-id zzz --network-area-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta network-area route delete" + -h, --help Help for "stackit network-area route delete" --network-area-id string STACKIT Network Area ID --organization-id string Organization ID ``` @@ -38,5 +38,5 @@ stackit beta network-area route delete ROUTE_ID [flags] ### SEE ALSO -* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit network-area route](./stackit_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_route_describe.md b/docs/stackit_network-area_route_describe.md similarity index 66% rename from docs/stackit_beta_network-area_route_describe.md rename to docs/stackit_network-area_route_describe.md index 0cc8d9ca4..fbacf05bd 100644 --- a/docs/stackit_beta_network-area_route_describe.md +++ b/docs/stackit_network-area_route_describe.md @@ -1,4 +1,4 @@ -## stackit beta network-area route describe +## stackit network-area route describe Shows details of a static route in a STACKIT Network Area (SNA) @@ -7,23 +7,23 @@ Shows details of a static route in a STACKIT Network Area (SNA) Shows details of a static route in a STACKIT Network Area (SNA). ``` -stackit beta network-area route describe ROUTE_ID [flags] +stackit network-area route describe ROUTE_ID [flags] ``` ### Examples ``` Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area route describe xxx --network-area-id yyy --organization-id zzz + $ stackit network-area route describe xxx --network-area-id yyy --organization-id zzz Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" in JSON format - $ stackit beta network-area route describe xxx --network-area-id yyy --organization-id zzz --output-format json + $ stackit network-area route describe xxx --network-area-id yyy --organization-id zzz --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta network-area route describe" + -h, --help Help for "stackit network-area route describe" --network-area-id string STACKIT Network Area ID --organization-id string Organization ID ``` @@ -41,5 +41,5 @@ stackit beta network-area route describe ROUTE_ID [flags] ### SEE ALSO -* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit network-area route](./stackit_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_route_list.md b/docs/stackit_network-area_route_list.md similarity index 66% rename from docs/stackit_beta_network-area_route_list.md rename to docs/stackit_network-area_route_list.md index e3181ff69..ff0a6ab1e 100644 --- a/docs/stackit_beta_network-area_route_list.md +++ b/docs/stackit_network-area_route_list.md @@ -1,4 +1,4 @@ -## stackit beta network-area route list +## stackit network-area route list Lists all static routes in a STACKIT Network Area (SNA) @@ -7,26 +7,26 @@ Lists all static routes in a STACKIT Network Area (SNA) Lists all static routes in a STACKIT Network Area (SNA). ``` -stackit beta network-area route list [flags] +stackit network-area route list [flags] ``` ### Examples ``` Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area route list --network-area-id xxx --organization-id yyy + $ stackit network-area route list --network-area-id xxx --organization-id yyy Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format - $ stackit beta network-area route list --network-area-id xxx --organization-id yyy --output-format json + $ stackit network-area route list --network-area-id xxx --organization-id yyy --output-format json Lists up to 10 static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit beta network-area route list --network-area-id xxx --organization-id yyy --limit 10 + $ stackit network-area route list --network-area-id xxx --organization-id yyy --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta network-area route list" + -h, --help Help for "stackit network-area route list" --limit int Maximum number of entries to list --network-area-id string STACKIT Network Area ID --organization-id string Organization ID @@ -45,5 +45,5 @@ stackit beta network-area route list [flags] ### SEE ALSO -* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit network-area route](./stackit_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_route_update.md b/docs/stackit_network-area_route_update.md similarity index 74% rename from docs/stackit_beta_network-area_route_update.md rename to docs/stackit_network-area_route_update.md index 4f9fc4e2a..61e54d10f 100644 --- a/docs/stackit_beta_network-area_route_update.md +++ b/docs/stackit_network-area_route_update.md @@ -1,4 +1,4 @@ -## stackit beta network-area route update +## stackit network-area route update Updates a static route in a STACKIT Network Area (SNA) @@ -9,20 +9,20 @@ This command is currently asynchonous only due to limitations in the waiting fun ``` -stackit beta network-area route update ROUTE_ID [flags] +stackit network-area route update ROUTE_ID [flags] ``` ### Examples ``` Updates the label(s) of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" - $ stackit beta network-area route update xxx --labels key=value,foo=bar --organization-id yyy --network-area-id zzz + $ stackit network-area route update xxx --labels key=value,foo=bar --organization-id yyy --network-area-id zzz ``` ### Options ``` - -h, --help Help for "stackit beta network-area route update" + -h, --help Help for "stackit network-area route update" --labels stringToString Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) --network-area-id string STACKIT Network Area ID --organization-id string Organization ID @@ -41,5 +41,5 @@ stackit beta network-area route update ROUTE_ID [flags] ### SEE ALSO -* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas +* [stackit network-area route](./stackit_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas diff --git a/docs/stackit_beta_network-area_update.md b/docs/stackit_network-area_update.md similarity index 79% rename from docs/stackit_beta_network-area_update.md rename to docs/stackit_network-area_update.md index 8c149885e..57b32a662 100644 --- a/docs/stackit_beta_network-area_update.md +++ b/docs/stackit_network-area_update.md @@ -1,4 +1,4 @@ -## stackit beta network-area update +## stackit network-area update Updates a STACKIT Network Area (SNA) @@ -7,14 +7,14 @@ Updates a STACKIT Network Area (SNA) Updates a STACKIT Network Area (SNA) in an organization. ``` -stackit beta network-area update AREA_ID [flags] +stackit network-area update AREA_ID [flags] ``` ### Examples ``` Update network area with ID "xxx" in organization with ID "yyy" with new name "network-area-1-new" - $ stackit beta network-area update xxx --organization-id yyy --name network-area-1-new + $ stackit network-area update xxx --organization-id yyy --name network-area-1-new ``` ### Options @@ -22,7 +22,7 @@ stackit beta network-area update AREA_ID [flags] ``` --default-prefix-length int The default prefix length for networks in the network area --dns-name-servers strings List of DNS name server IPs - -h, --help Help for "stackit beta network-area update" + -h, --help Help for "stackit network-area update" --labels stringToString Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...' (default []) --max-prefix-length int The maximum prefix length for networks in the network area --min-prefix-length int The minimum prefix length for networks in the network area @@ -43,5 +43,5 @@ stackit beta network-area update AREA_ID [flags] ### SEE ALSO -* [stackit beta network-area](./stackit_beta_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) diff --git a/docs/stackit_network-interface.md b/docs/stackit_network-interface.md new file mode 100644 index 000000000..b7be67c0c --- /dev/null +++ b/docs/stackit_network-interface.md @@ -0,0 +1,38 @@ +## stackit network-interface + +Provides functionality for network interfaces + +### Synopsis + +Provides functionality for network interfaces. + +``` +stackit network-interface [flags] +``` + +### Options + +``` + -h, --help Help for "stackit network-interface" +``` + +### 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](./stackit.md) - Manage STACKIT resources using the command line +* [stackit network-interface create](./stackit_network-interface_create.md) - Creates a network interface +* [stackit network-interface delete](./stackit_network-interface_delete.md) - Deletes a network interface +* [stackit network-interface describe](./stackit_network-interface_describe.md) - Describes a network interface +* [stackit network-interface list](./stackit_network-interface_list.md) - Lists all network interfaces of a network +* [stackit network-interface update](./stackit_network-interface_update.md) - Updates a network interface + diff --git a/docs/stackit_beta_network-interface_create.md b/docs/stackit_network-interface_create.md similarity index 72% rename from docs/stackit_beta_network-interface_create.md rename to docs/stackit_network-interface_create.md index 87914073a..5ff3acd27 100644 --- a/docs/stackit_beta_network-interface_create.md +++ b/docs/stackit_network-interface_create.md @@ -1,4 +1,4 @@ -## stackit beta network-interface create +## stackit network-interface create Creates a network interface @@ -7,24 +7,24 @@ Creates a network interface Creates a network interface. ``` -stackit beta network-interface create [flags] +stackit network-interface create [flags] ``` ### Examples ``` Create a network interface for network with ID "xxx" - $ stackit beta network-interface create --network-id xxx + $ stackit network-interface create --network-id xxx Create a network interface with allowed addresses, labels, a name, security groups and nic security enabled for network with ID "xxx" - $ stackit beta network-interface create --network-id xxx --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 --name NAME --security-groups "UUID1,UUID2" --nic-security + $ stackit network-interface create --network-id xxx --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 --name NAME --security-groups "UUID1,UUID2" --nic-security ``` ### Options ``` --allowed-addresses strings List of allowed IPs - -h, --help Help for "stackit beta network-interface create" + -h, --help Help for "stackit network-interface create" -i, --ipv4 string IPv4 address -s, --ipv6 string IPv6 address --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) @@ -47,5 +47,5 @@ stackit beta network-interface create [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces +* [stackit network-interface](./stackit_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network-interface_delete.md b/docs/stackit_network-interface_delete.md similarity index 68% rename from docs/stackit_beta_network-interface_delete.md rename to docs/stackit_network-interface_delete.md index a6047d548..624e0b83f 100644 --- a/docs/stackit_beta_network-interface_delete.md +++ b/docs/stackit_network-interface_delete.md @@ -1,4 +1,4 @@ -## stackit beta network-interface delete +## stackit network-interface delete Deletes a network interface @@ -7,20 +7,20 @@ Deletes a network interface Deletes a network interface. ``` -stackit beta network-interface delete NIC_ID [flags] +stackit network-interface delete NIC_ID [flags] ``` ### Examples ``` Delete network interface with nic id "xxx" and network ID "yyy" - $ stackit beta network-interface delete xxx --network-id yyy + $ stackit network-interface delete xxx --network-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta network-interface delete" + -h, --help Help for "stackit network-interface delete" --network-id string Network ID ``` @@ -37,5 +37,5 @@ stackit beta network-interface delete NIC_ID [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces +* [stackit network-interface](./stackit_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network-interface_describe.md b/docs/stackit_network-interface_describe.md similarity index 63% rename from docs/stackit_beta_network-interface_describe.md rename to docs/stackit_network-interface_describe.md index a5940b7cd..159475be8 100644 --- a/docs/stackit_beta_network-interface_describe.md +++ b/docs/stackit_network-interface_describe.md @@ -1,4 +1,4 @@ -## stackit beta network-interface describe +## stackit network-interface describe Describes a network interface @@ -7,26 +7,26 @@ Describes a network interface Describes a network interface. ``` -stackit beta network-interface describe NIC_ID [flags] +stackit network-interface describe NIC_ID [flags] ``` ### Examples ``` Describes network interface with nic id "xxx" and network ID "yyy" - $ stackit beta network-interface describe xxx --network-id yyy + $ stackit network-interface describe xxx --network-id yyy Describes network interface with nic id "xxx" and network ID "yyy" in JSON format - $ stackit beta network-interface describe xxx --network-id yyy --output-format json + $ stackit network-interface describe xxx --network-id yyy --output-format json Describes network interface with nic id "xxx" and network ID "yyy" in yaml format - $ stackit beta network-interface describe xxx --network-id yyy --output-format yaml + $ stackit network-interface describe xxx --network-id yyy --output-format yaml ``` ### Options ``` - -h, --help Help for "stackit beta network-interface describe" + -h, --help Help for "stackit network-interface describe" --network-id string Network ID ``` @@ -43,5 +43,5 @@ stackit beta network-interface describe NIC_ID [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces +* [stackit network-interface](./stackit_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network-interface_list.md b/docs/stackit_network-interface_list.md similarity index 66% rename from docs/stackit_beta_network-interface_list.md rename to docs/stackit_network-interface_list.md index 4e5272349..f202a6667 100644 --- a/docs/stackit_beta_network-interface_list.md +++ b/docs/stackit_network-interface_list.md @@ -1,4 +1,4 @@ -## stackit beta network-interface list +## stackit network-interface list Lists all network interfaces of a network @@ -7,29 +7,29 @@ Lists all network interfaces of a network Lists all network interfaces of a network. ``` -stackit beta network-interface list [flags] +stackit network-interface list [flags] ``` ### Examples ``` Lists all network interfaces with network ID "xxx" - $ stackit beta network-interface list --network-id xxx + $ stackit network-interface list --network-id xxx Lists all network interfaces with network ID "xxx" which contains the label xxx - $ stackit beta network-interface list --network-id xxx --label-selector xxx + $ stackit network-interface list --network-id xxx --label-selector xxx Lists all network interfaces with network ID "xxx" in JSON format - $ stackit beta network-interface list --network-id xxx --output-format json + $ stackit network-interface list --network-id xxx --output-format json Lists up to 10 network interfaces with network ID "xxx" - $ stackit beta network-interface list --network-id xxx --limit 10 + $ stackit network-interface list --network-id xxx --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta network-interface list" + -h, --help Help for "stackit network-interface list" --label-selector string Filter by label --limit int Maximum number of entries to list --network-id string Network ID @@ -48,5 +48,5 @@ stackit beta network-interface list [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces +* [stackit network-interface](./stackit_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network-interface_update.md b/docs/stackit_network-interface_update.md similarity index 71% rename from docs/stackit_beta_network-interface_update.md rename to docs/stackit_network-interface_update.md index e9c1b6ec7..0c3e2c322 100644 --- a/docs/stackit_beta_network-interface_update.md +++ b/docs/stackit_network-interface_update.md @@ -1,4 +1,4 @@ -## stackit beta network-interface update +## stackit network-interface update Updates a network interface @@ -7,27 +7,27 @@ Updates a network interface Updates a network interface. ``` -stackit beta network-interface update NIC_ID [flags] +stackit network-interface update NIC_ID [flags] ``` ### Examples ``` Updates a network interface with nic id "xxx" and network-id "yyy" to new allowed addresses "1.1.1.1,8.8.8.8,9.9.9.9" and new labels "key=value,key2=value2" - $ stackit beta network-interface update xxx --network-id yyy --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 + $ stackit network-interface update xxx --network-id yyy --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 Updates a network interface with nic id "xxx" and network-id "yyy" with new name "nic-name-new" - $ stackit beta network-interface update xxx --network-id yyy --name nic-name-new + $ stackit network-interface update xxx --network-id yyy --name nic-name-new Updates a network interface with nic id "xxx" and network-id "yyy" to include the security group "zzz" - $ stackit beta network-interface update xxx --network-id yyy --security-groups zzz + $ stackit network-interface update xxx --network-id yyy --security-groups zzz ``` ### Options ``` --allowed-addresses strings List of allowed IPs - -h, --help Help for "stackit beta network-interface update" + -h, --help Help for "stackit network-interface update" --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) -n, --name string Network interface name --network-id string Network ID @@ -48,5 +48,5 @@ stackit beta network-interface update NIC_ID [flags] ### SEE ALSO -* [stackit beta network-interface](./stackit_beta_network-interface.md) - Provides functionality for network interfaces +* [stackit network-interface](./stackit_network-interface.md) - Provides functionality for network interfaces diff --git a/docs/stackit_beta_network.md b/docs/stackit_network.md similarity index 50% rename from docs/stackit_beta_network.md rename to docs/stackit_network.md index 78bf7e4d1..f196fe7b6 100644 --- a/docs/stackit_beta_network.md +++ b/docs/stackit_network.md @@ -1,4 +1,4 @@ -## stackit beta network +## stackit network Provides functionality for networks @@ -7,13 +7,13 @@ Provides functionality for networks Provides functionality for networks. ``` -stackit beta network [flags] +stackit network [flags] ``` ### Options ``` - -h, --help Help for "stackit beta network" + -h, --help Help for "stackit network" ``` ### Options inherited from parent commands @@ -29,10 +29,10 @@ stackit beta network [flags] ### SEE ALSO -* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta network create](./stackit_beta_network_create.md) - Creates a network -* [stackit beta network delete](./stackit_beta_network_delete.md) - Deletes a network -* [stackit beta network describe](./stackit_beta_network_describe.md) - Shows details of a network -* [stackit beta network list](./stackit_beta_network_list.md) - Lists all networks of a project -* [stackit beta network update](./stackit_beta_network_update.md) - Updates a network +* [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit network create](./stackit_network_create.md) - Creates a network +* [stackit network delete](./stackit_network_delete.md) - Deletes a network +* [stackit network describe](./stackit_network_describe.md) - Shows details of a network +* [stackit network list](./stackit_network_list.md) - Lists all networks of a project +* [stackit network update](./stackit_network_update.md) - Updates a network diff --git a/docs/stackit_beta_network_create.md b/docs/stackit_network_create.md similarity index 74% rename from docs/stackit_beta_network_create.md rename to docs/stackit_network_create.md index 9b4c711af..21d9e863c 100644 --- a/docs/stackit_beta_network_create.md +++ b/docs/stackit_network_create.md @@ -1,4 +1,4 @@ -## stackit beta network create +## stackit network create Creates a network @@ -7,35 +7,35 @@ Creates a network Creates a network. ``` -stackit beta network create [flags] +stackit network create [flags] ``` ### Examples ``` Create a network with name "network-1" - $ stackit beta network create --name network-1 + $ stackit network create --name network-1 Create a non-routed network with name "network-1" - $ stackit beta network create --name network-1 --non-routed + $ stackit network create --name network-1 --non-routed Create a network with name "network-1" and no gateway - $ stackit beta network create --name network-1 --no-ipv4-gateway + $ stackit network create --name network-1 --no-ipv4-gateway Create a network with name "network-1" and labels "key=value,key1=value1" - $ stackit beta network create --name network-1 --labels key=value,key1=value1 + $ stackit network create --name network-1 --labels key=value,key1=value1 Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway - $ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3" + $ stackit network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3" Create an IPv6 network with name "network-1" with DNS name servers, a prefix and a gateway - $ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888" + $ stackit network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888" ``` ### Options ``` - -h, --help Help for "stackit beta network create" + -h, --help Help for "stackit network create" --ipv4-dns-name-servers strings List of DNS name servers for IPv4. Nameservers cannot be defined for routed networks --ipv4-gateway string The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway --ipv4-prefix string The IPv4 prefix of the network (CIDR) @@ -64,5 +64,5 @@ stackit beta network create [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks +* [stackit network](./stackit_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_network_delete.md b/docs/stackit_network_delete.md similarity index 73% rename from docs/stackit_beta_network_delete.md rename to docs/stackit_network_delete.md index e3c76d9d7..5fb62e6e3 100644 --- a/docs/stackit_beta_network_delete.md +++ b/docs/stackit_network_delete.md @@ -1,4 +1,4 @@ -## stackit beta network delete +## stackit network delete Deletes a network @@ -9,20 +9,20 @@ If the network is still in use, the deletion will fail ``` -stackit beta network delete NETWORK_ID [flags] +stackit network delete NETWORK_ID [flags] ``` ### Examples ``` Delete network with ID "xxx" - $ stackit beta network delete xxx + $ stackit network delete xxx ``` ### Options ``` - -h, --help Help for "stackit beta network delete" + -h, --help Help for "stackit network delete" ``` ### Options inherited from parent commands @@ -38,5 +38,5 @@ stackit beta network delete NETWORK_ID [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks +* [stackit network](./stackit_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_network_describe.md b/docs/stackit_network_describe.md similarity index 69% rename from docs/stackit_beta_network_describe.md rename to docs/stackit_network_describe.md index cad1ecd51..d7298e4e5 100644 --- a/docs/stackit_beta_network_describe.md +++ b/docs/stackit_network_describe.md @@ -1,4 +1,4 @@ -## stackit beta network describe +## stackit network describe Shows details of a network @@ -7,23 +7,23 @@ Shows details of a network Shows details of a network. ``` -stackit beta network describe NETWORK_ID [flags] +stackit network describe NETWORK_ID [flags] ``` ### Examples ``` Show details of a network with ID "xxx" - $ stackit beta network describe xxx + $ stackit network describe xxx Show details of a network with ID "xxx" in JSON format - $ stackit beta network describe xxx --output-format json + $ stackit network describe xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta network describe" + -h, --help Help for "stackit network describe" ``` ### Options inherited from parent commands @@ -39,5 +39,5 @@ stackit beta network describe NETWORK_ID [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks +* [stackit network](./stackit_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_network_list.md b/docs/stackit_network_list.md similarity index 69% rename from docs/stackit_beta_network_list.md rename to docs/stackit_network_list.md index 0edb4bbec..1b4febd39 100644 --- a/docs/stackit_beta_network_list.md +++ b/docs/stackit_network_list.md @@ -1,4 +1,4 @@ -## stackit beta network list +## stackit network list Lists all networks of a project @@ -7,29 +7,29 @@ Lists all networks of a project Lists all network of a project. ``` -stackit beta network list [flags] +stackit network list [flags] ``` ### Examples ``` Lists all networks - $ stackit beta network list + $ stackit network list Lists all networks in JSON format - $ stackit beta network list --output-format json + $ stackit network list --output-format json Lists up to 10 networks - $ stackit beta network list --limit 10 + $ stackit network list --limit 10 Lists all networks which contains the label xxx - $ tackit beta network list --label-selector xxx + $ stackit network list --label-selector xxx ``` ### Options ``` - -h, --help Help for "stackit beta network list" + -h, --help Help for "stackit network list" --label-selector string Filter by label --limit int Maximum number of entries to list ``` @@ -47,5 +47,5 @@ stackit beta network list [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks +* [stackit network](./stackit_network.md) - Provides functionality for networks diff --git a/docs/stackit_beta_network_update.md b/docs/stackit_network_update.md similarity index 75% rename from docs/stackit_beta_network_update.md rename to docs/stackit_network_update.md index 35b76c078..313ce68fa 100644 --- a/docs/stackit_beta_network_update.md +++ b/docs/stackit_network_update.md @@ -1,4 +1,4 @@ -## stackit beta network update +## stackit network update Updates a network @@ -7,29 +7,29 @@ Updates a network Updates a network. ``` -stackit beta network update NETWORK_ID [flags] +stackit network update NETWORK_ID [flags] ``` ### Examples ``` Update network with ID "xxx" with new name "network-1-new" - $ stackit beta network update xxx --name network-1-new + $ stackit network update xxx --name network-1-new Update network with ID "xxx" with no gateway - $ stackit beta network update --no-ipv4-gateway + $ stackit network update --no-ipv4-gateway Update IPv4 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers - $ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" --ipv4-gateway "10.1.2.3" + $ stackit network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" --ipv4-gateway "10.1.2.3" Update IPv6 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers - $ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888" + $ stackit network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888" ``` ### Options ``` - -h, --help Help for "stackit beta network update" + -h, --help Help for "stackit network update" --ipv4-dns-name-servers strings List of DNS name servers IPv4. Nameservers cannot be defined for routed networks --ipv4-gateway string The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway --ipv6-dns-name-servers strings List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks @@ -53,5 +53,5 @@ stackit beta network update NETWORK_ID [flags] ### SEE ALSO -* [stackit beta network](./stackit_beta_network.md) - Provides functionality for networks +* [stackit network](./stackit_network.md) - Provides functionality for networks diff --git a/docs/stackit_public-ip.md b/docs/stackit_public-ip.md new file mode 100644 index 000000000..99bfd899f --- /dev/null +++ b/docs/stackit_public-ip.md @@ -0,0 +1,40 @@ +## stackit public-ip + +Provides functionality for public IPs + +### Synopsis + +Provides functionality for public IPs. + +``` +stackit public-ip [flags] +``` + +### Options + +``` + -h, --help Help for "stackit public-ip" +``` + +### 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](./stackit.md) - Manage STACKIT resources using the command line +* [stackit public-ip associate](./stackit_public-ip_associate.md) - Associates a Public IP with a network interface or a virtual IP +* [stackit public-ip create](./stackit_public-ip_create.md) - Creates a Public IP +* [stackit public-ip delete](./stackit_public-ip_delete.md) - Deletes a Public IP +* [stackit public-ip describe](./stackit_public-ip_describe.md) - Shows details of a Public IP +* [stackit public-ip disassociate](./stackit_public-ip_disassociate.md) - Disassociates a Public IP from a network interface or a virtual IP +* [stackit public-ip list](./stackit_public-ip_list.md) - Lists all Public IPs of a project +* [stackit public-ip update](./stackit_public-ip_update.md) - Updates a Public IP + diff --git a/docs/stackit_beta_public-ip_associate.md b/docs/stackit_public-ip_associate.md similarity index 73% rename from docs/stackit_beta_public-ip_associate.md rename to docs/stackit_public-ip_associate.md index 0eaf2f6b4..484eabaf8 100644 --- a/docs/stackit_beta_public-ip_associate.md +++ b/docs/stackit_public-ip_associate.md @@ -1,4 +1,4 @@ -## stackit beta public-ip associate +## stackit public-ip associate Associates a Public IP with a network interface or a virtual IP @@ -7,21 +7,21 @@ Associates a Public IP with a network interface or a virtual IP Associates a Public IP with a network interface or a virtual IP. ``` -stackit beta public-ip associate PUBLIC_IP_ID [flags] +stackit public-ip associate PUBLIC_IP_ID [flags] ``` ### Examples ``` Associate public IP with ID "xxx" to a resource (network interface or virtual IP) with ID "yyy" - $ stackit beta public-ip associate xxx --associated-resource-id yyy + $ stackit public-ip associate xxx --associated-resource-id yyy ``` ### Options ``` --associated-resource-id string Associates the public IP with a network interface or virtual IP (ID) - -h, --help Help for "stackit beta public-ip associate" + -h, --help Help for "stackit public-ip associate" ``` ### Options inherited from parent commands @@ -37,5 +37,5 @@ stackit beta public-ip associate PUBLIC_IP_ID [flags] ### SEE ALSO -* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs diff --git a/docs/stackit_beta_public-ip_create.md b/docs/stackit_public-ip_create.md similarity index 70% rename from docs/stackit_beta_public-ip_create.md rename to docs/stackit_public-ip_create.md index 023de706d..9ea017de9 100644 --- a/docs/stackit_beta_public-ip_create.md +++ b/docs/stackit_public-ip_create.md @@ -1,4 +1,4 @@ -## stackit beta public-ip create +## stackit public-ip create Creates a Public IP @@ -7,27 +7,27 @@ Creates a Public IP Creates a Public IP. ``` -stackit beta public-ip create [flags] +stackit public-ip create [flags] ``` ### Examples ``` Create a public IP - $ stackit beta public-ip create + $ stackit public-ip create Create a public IP with associated resource ID "xxx" - $ stackit beta public-ip create --associated-resource-id xxx + $ stackit public-ip create --associated-resource-id xxx Create a public IP with associated resource ID "xxx" and labels - $ stackit beta public-ip create --associated-resource-id xxx --labels key=value,foo=bar + $ stackit public-ip create --associated-resource-id xxx --labels key=value,foo=bar ``` ### Options ``` --associated-resource-id string Associates the public IP with a network interface or virtual IP (ID) - -h, --help Help for "stackit beta public-ip create" + -h, --help Help for "stackit public-ip create" --labels stringToString Labels are key-value string pairs which can be attached to a public IP. E.g. '--labels key1=value1,key2=value2,...' (default []) ``` @@ -44,5 +44,5 @@ stackit beta public-ip create [flags] ### SEE ALSO -* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs diff --git a/docs/stackit_beta_public-ip_delete.md b/docs/stackit_public-ip_delete.md similarity index 72% rename from docs/stackit_beta_public-ip_delete.md rename to docs/stackit_public-ip_delete.md index 265df7727..d5d7c46e2 100644 --- a/docs/stackit_beta_public-ip_delete.md +++ b/docs/stackit_public-ip_delete.md @@ -1,4 +1,4 @@ -## stackit beta public-ip delete +## stackit public-ip delete Deletes a Public IP @@ -9,20 +9,20 @@ If the public IP is still in use, the deletion will fail ``` -stackit beta public-ip delete PUBLIC_IP_ID [flags] +stackit public-ip delete PUBLIC_IP_ID [flags] ``` ### Examples ``` Delete public IP with ID "xxx" - $ stackit beta public-ip delete xxx + $ stackit public-ip delete xxx ``` ### Options ``` - -h, --help Help for "stackit beta public-ip delete" + -h, --help Help for "stackit public-ip delete" ``` ### Options inherited from parent commands @@ -38,5 +38,5 @@ stackit beta public-ip delete PUBLIC_IP_ID [flags] ### SEE ALSO -* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs diff --git a/docs/stackit_beta_public-ip_describe.md b/docs/stackit_public-ip_describe.md similarity index 68% rename from docs/stackit_beta_public-ip_describe.md rename to docs/stackit_public-ip_describe.md index 9925d2602..811d7c4d7 100644 --- a/docs/stackit_beta_public-ip_describe.md +++ b/docs/stackit_public-ip_describe.md @@ -1,4 +1,4 @@ -## stackit beta public-ip describe +## stackit public-ip describe Shows details of a Public IP @@ -7,23 +7,23 @@ Shows details of a Public IP Shows details of a Public IP. ``` -stackit beta public-ip describe PUBLIC_IP_ID [flags] +stackit public-ip describe PUBLIC_IP_ID [flags] ``` ### Examples ``` Show details of a public IP with ID "xxx" - $ stackit beta public-ip describe xxx + $ stackit public-ip describe xxx Show details of a public IP with ID "xxx" in JSON format - $ stackit beta public-ip describe xxx --output-format json + $ stackit public-ip describe xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta public-ip describe" + -h, --help Help for "stackit public-ip describe" ``` ### Options inherited from parent commands @@ -39,5 +39,5 @@ stackit beta public-ip describe PUBLIC_IP_ID [flags] ### SEE ALSO -* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs diff --git a/docs/stackit_beta_public-ip_disassociate.md b/docs/stackit_public-ip_disassociate.md similarity index 73% rename from docs/stackit_beta_public-ip_disassociate.md rename to docs/stackit_public-ip_disassociate.md index d26de87f0..992ca2044 100644 --- a/docs/stackit_beta_public-ip_disassociate.md +++ b/docs/stackit_public-ip_disassociate.md @@ -1,4 +1,4 @@ -## stackit beta public-ip disassociate +## stackit public-ip disassociate Disassociates a Public IP from a network interface or a virtual IP @@ -7,20 +7,20 @@ Disassociates a Public IP from a network interface or a virtual IP Disassociates a Public IP from a network interface or a virtual IP. ``` -stackit beta public-ip disassociate PUBLIC_IP_ID [flags] +stackit public-ip disassociate PUBLIC_IP_ID [flags] ``` ### Examples ``` Disassociate public IP with ID "xxx" from a resource (network interface or virtual IP) - $ stackit beta public-ip disassociate xxx + $ stackit public-ip disassociate xxx ``` ### Options ``` - -h, --help Help for "stackit beta public-ip disassociate" + -h, --help Help for "stackit public-ip disassociate" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta public-ip disassociate PUBLIC_IP_ID [flags] ### SEE ALSO -* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs diff --git a/docs/stackit_beta_public-ip_list.md b/docs/stackit_public-ip_list.md similarity index 68% rename from docs/stackit_beta_public-ip_list.md rename to docs/stackit_public-ip_list.md index 845a82973..513394fa9 100644 --- a/docs/stackit_beta_public-ip_list.md +++ b/docs/stackit_public-ip_list.md @@ -1,4 +1,4 @@ -## stackit beta public-ip list +## stackit public-ip list Lists all Public IPs of a project @@ -7,29 +7,29 @@ Lists all Public IPs of a project Lists all Public IPs of a project. ``` -stackit beta public-ip list [flags] +stackit public-ip list [flags] ``` ### Examples ``` Lists all public IPs - $ stackit beta public-ip list + $ stackit public-ip list Lists all public IPs which contains the label xxx - $ stackit beta public-ip list --label-selector xxx + $ stackit public-ip list --label-selector xxx Lists all public IPs in JSON format - $ stackit beta public-ip list --output-format json + $ stackit public-ip list --output-format json Lists up to 10 public IPs - $ stackit beta public-ip list --limit 10 + $ stackit public-ip list --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta public-ip list" + -h, --help Help for "stackit public-ip list" --label-selector string Filter by label --limit int Maximum number of entries to list ``` @@ -47,5 +47,5 @@ stackit beta public-ip list [flags] ### SEE ALSO -* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs diff --git a/docs/stackit_beta_public-ip_update.md b/docs/stackit_public-ip_update.md similarity index 71% rename from docs/stackit_beta_public-ip_update.md rename to docs/stackit_public-ip_update.md index 4344b32a4..96a625987 100644 --- a/docs/stackit_beta_public-ip_update.md +++ b/docs/stackit_public-ip_update.md @@ -1,4 +1,4 @@ -## stackit beta public-ip update +## stackit public-ip update Updates a Public IP @@ -7,23 +7,23 @@ Updates a Public IP Updates a Public IP. ``` -stackit beta public-ip update PUBLIC_IP_ID [flags] +stackit public-ip update PUBLIC_IP_ID [flags] ``` ### Examples ``` Update public IP with ID "xxx" - $ stackit beta public-ip update xxx + $ stackit public-ip update xxx Update public IP with ID "xxx" with new labels - $ stackit beta public-ip update xxx --labels key=value,foo=bar + $ stackit public-ip update xxx --labels key=value,foo=bar ``` ### Options ``` - -h, --help Help for "stackit beta public-ip update" + -h, --help Help for "stackit public-ip update" --labels stringToString Labels are key-value string pairs which can be attached to a public IP. E.g. '--labels key1=value1,key2=value2,...' (default []) ``` @@ -40,5 +40,5 @@ stackit beta public-ip update PUBLIC_IP_ID [flags] ### SEE ALSO -* [stackit beta public-ip](./stackit_beta_public-ip.md) - Provides functionality for public IPs +* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs diff --git a/docs/stackit_beta_quota.md b/docs/stackit_quota.md similarity index 72% rename from docs/stackit_beta_quota.md rename to docs/stackit_quota.md index 3fa8e4a33..074b95cbc 100644 --- a/docs/stackit_beta_quota.md +++ b/docs/stackit_quota.md @@ -1,4 +1,4 @@ -## stackit beta quota +## stackit quota Manage server quotas @@ -7,13 +7,13 @@ Manage server quotas Manage the lifecycle of server quotas. ``` -stackit beta quota [flags] +stackit quota [flags] ``` ### Options ``` - -h, --help Help for "stackit beta quota" + -h, --help Help for "stackit quota" ``` ### Options inherited from parent commands @@ -29,6 +29,6 @@ stackit beta quota [flags] ### SEE ALSO -* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands -* [stackit beta quota list](./stackit_beta_quota_list.md) - Lists quotas +* [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit quota list](./stackit_quota_list.md) - Lists quotas diff --git a/docs/stackit_beta_quota_list.md b/docs/stackit_quota_list.md similarity index 73% rename from docs/stackit_beta_quota_list.md rename to docs/stackit_quota_list.md index f9a6fa62c..f68113391 100644 --- a/docs/stackit_beta_quota_list.md +++ b/docs/stackit_quota_list.md @@ -1,26 +1,26 @@ -## stackit beta quota list +## stackit quota list Lists quotas ### Synopsis -Lists server quotas. +Lists project quotas. ``` -stackit beta quota list [flags] +stackit quota list [flags] ``` ### Examples ``` List available quotas - $ stackit beta quota list + $ stackit quota list ``` ### Options ``` - -h, --help Help for "stackit beta quota list" + -h, --help Help for "stackit quota list" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta quota list [flags] ### SEE ALSO -* [stackit beta quota](./stackit_beta_quota.md) - Manage server quotas +* [stackit quota](./stackit_quota.md) - Manage server quotas diff --git a/docs/stackit_security-group.md b/docs/stackit_security-group.md new file mode 100644 index 000000000..949333c96 --- /dev/null +++ b/docs/stackit_security-group.md @@ -0,0 +1,39 @@ +## stackit security-group + +Manage security groups + +### Synopsis + +Manage the lifecycle of security groups and rules. + +``` +stackit security-group [flags] +``` + +### Options + +``` + -h, --help Help for "stackit security-group" +``` + +### 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](./stackit.md) - Manage STACKIT resources using the command line +* [stackit security-group create](./stackit_security-group_create.md) - Creates security groups +* [stackit security-group delete](./stackit_security-group_delete.md) - Deletes a security group +* [stackit security-group describe](./stackit_security-group_describe.md) - Describes security groups +* [stackit security-group list](./stackit_security-group_list.md) - Lists security groups +* [stackit security-group rule](./stackit_security-group_rule.md) - Provides functionality for security group rules +* [stackit security-group update](./stackit_security-group_update.md) - Updates a security group + diff --git a/docs/stackit_beta_security-group_create.md b/docs/stackit_security-group_create.md similarity index 72% rename from docs/stackit_beta_security-group_create.md rename to docs/stackit_security-group_create.md index 4c806e71b..c63370118 100644 --- a/docs/stackit_beta_security-group_create.md +++ b/docs/stackit_security-group_create.md @@ -1,4 +1,4 @@ -## stackit beta security-group create +## stackit security-group create Creates security groups @@ -7,24 +7,24 @@ Creates security groups Creates security groups. ``` -stackit beta security-group create [flags] +stackit security-group create [flags] ``` ### Examples ``` Create a named group - $ stackit beta security-group create --name my-new-group + $ stackit security-group create --name my-new-group Create a named group with labels - $ stackit beta security-group create --name my-new-group --labels label1=value1,label2=value2 + $ stackit security-group create --name my-new-group --labels label1=value1,label2=value2 ``` ### Options ``` --description string An optional description of the security group. - -h, --help Help for "stackit beta security-group create" + -h, --help Help for "stackit security-group create" --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) --name string The name of the security group. --stateful Create a stateful or a stateless security group @@ -43,5 +43,5 @@ stackit beta security-group create [flags] ### SEE ALSO -* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups +* [stackit security-group](./stackit_security-group.md) - Manage security groups diff --git a/docs/stackit_beta_security-group_delete.md b/docs/stackit_security-group_delete.md similarity index 70% rename from docs/stackit_beta_security-group_delete.md rename to docs/stackit_security-group_delete.md index ce64513cb..6402e0bd2 100644 --- a/docs/stackit_beta_security-group_delete.md +++ b/docs/stackit_security-group_delete.md @@ -1,4 +1,4 @@ -## stackit beta security-group delete +## stackit security-group delete Deletes a security group @@ -7,20 +7,20 @@ Deletes a security group Deletes a security group by its internal ID. ``` -stackit beta security-group delete GROUP_ID [flags] +stackit security-group delete GROUP_ID [flags] ``` ### Examples ``` Delete a named group with ID "xxx" - $ stackit beta security-group delete xxx + $ stackit security-group delete xxx ``` ### Options ``` - -h, --help Help for "stackit beta security-group delete" + -h, --help Help for "stackit security-group delete" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta security-group delete GROUP_ID [flags] ### SEE ALSO -* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups +* [stackit security-group](./stackit_security-group.md) - Manage security groups diff --git a/docs/stackit_beta_security-group_describe.md b/docs/stackit_security-group_describe.md similarity index 70% rename from docs/stackit_beta_security-group_describe.md rename to docs/stackit_security-group_describe.md index d2a3f9131..2a29d26fc 100644 --- a/docs/stackit_beta_security-group_describe.md +++ b/docs/stackit_security-group_describe.md @@ -1,4 +1,4 @@ -## stackit beta security-group describe +## stackit security-group describe Describes security groups @@ -7,20 +7,20 @@ Describes security groups Describes security groups by its internal ID. ``` -stackit beta security-group describe GROUP_ID [flags] +stackit security-group describe GROUP_ID [flags] ``` ### Examples ``` Describe group "xxx" - $ stackit beta security-group describe xxx + $ stackit security-group describe xxx ``` ### Options ``` - -h, --help Help for "stackit beta security-group describe" + -h, --help Help for "stackit security-group describe" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta security-group describe GROUP_ID [flags] ### SEE ALSO -* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups +* [stackit security-group](./stackit_security-group.md) - Manage security groups diff --git a/docs/stackit_beta_security-group_list.md b/docs/stackit_security-group_list.md similarity index 67% rename from docs/stackit_beta_security-group_list.md rename to docs/stackit_security-group_list.md index c70d22c89..990f01364 100644 --- a/docs/stackit_beta_security-group_list.md +++ b/docs/stackit_security-group_list.md @@ -1,4 +1,4 @@ -## stackit beta security-group list +## stackit security-group list Lists security groups @@ -7,23 +7,23 @@ Lists security groups Lists security groups by its internal ID. ``` -stackit beta security-group list [flags] +stackit security-group list [flags] ``` ### Examples ``` List all groups - $ stackit beta security-group list + $ stackit security-group list List groups with labels - $ stackit beta security-group list --label-selector label1=value1,label2=value2 + $ stackit security-group list --label-selector label1=value1,label2=value2 ``` ### Options ``` - -h, --help Help for "stackit beta security-group list" + -h, --help Help for "stackit security-group list" --label-selector string Filter by label ``` @@ -40,5 +40,5 @@ stackit beta security-group list [flags] ### SEE ALSO -* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups +* [stackit security-group](./stackit_security-group.md) - Manage security groups diff --git a/docs/stackit_security-group_rule.md b/docs/stackit_security-group_rule.md new file mode 100644 index 000000000..558abe544 --- /dev/null +++ b/docs/stackit_security-group_rule.md @@ -0,0 +1,37 @@ +## stackit security-group rule + +Provides functionality for security group rules + +### Synopsis + +Provides functionality for security group rules. + +``` +stackit security-group rule [flags] +``` + +### Options + +``` + -h, --help Help for "stackit security-group rule" +``` + +### 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 security-group](./stackit_security-group.md) - Manage security groups +* [stackit security-group rule create](./stackit_security-group_rule_create.md) - Creates a security group rule +* [stackit security-group rule delete](./stackit_security-group_rule_delete.md) - Deletes a security group rule +* [stackit security-group rule describe](./stackit_security-group_rule_describe.md) - Shows details of a security group rule +* [stackit security-group rule list](./stackit_security-group_rule_list.md) - Lists all security group rules in a security group of a project + diff --git a/docs/stackit_beta_security-group_rule_create.md b/docs/stackit_security-group_rule_create.md similarity index 75% rename from docs/stackit_beta_security-group_rule_create.md rename to docs/stackit_security-group_rule_create.md index 54e40d327..0ad7a823b 100644 --- a/docs/stackit_beta_security-group_rule_create.md +++ b/docs/stackit_security-group_rule_create.md @@ -1,4 +1,4 @@ -## stackit beta security-group rule create +## stackit security-group rule create Creates a security group rule @@ -7,23 +7,23 @@ Creates a security group rule Creates a security group rule. ``` -stackit beta security-group rule create [flags] +stackit security-group rule create [flags] ``` ### Examples ``` Create a security group rule for security group with ID "xxx" with direction "ingress" - $ stackit beta security-group rule create --security-group-id xxx --direction ingress + $ stackit security-group rule create --security-group-id xxx --direction ingress Create a security group rule for security group with ID "xxx" with direction "egress", protocol "icmp" and icmp parameters - $ stackit beta security-group rule create --security-group-id xxx --direction egress --protocol-name icmp --icmp-parameter-code 0 --icmp-parameter-type 8 + $ stackit security-group rule create --security-group-id xxx --direction egress --protocol-name icmp --icmp-parameter-code 0 --icmp-parameter-type 8 Create a security group rule for security group with ID "xxx" with direction "ingress", protocol "tcp" and port range values - $ stackit beta security-group rule create --security-group-id xxx --direction ingress --protocol-name tcp --port-range-max 24 --port-range-min 22 + $ stackit security-group rule create --security-group-id xxx --direction ingress --protocol-name tcp --port-range-max 24 --port-range-min 22 Create a security group rule for security group with ID "xxx" with direction "ingress" and protocol number 1 - $ stackit beta security-group rule create --security-group-id xxx --direction ingress --protocol-number 1 + $ stackit security-group rule create --security-group-id xxx --direction ingress --protocol-number 1 ``` ### Options @@ -32,7 +32,7 @@ stackit beta security-group rule create [flags] --description string The rule description --direction string The direction of the traffic which the rule should match. The possible values are: "ingress", "egress" --ether-type string The ethertype which the rule should match - -h, --help Help for "stackit beta security-group rule create" + -h, --help Help for "stackit security-group rule create" --icmp-parameter-code int ICMP code. Can be set if the protocol is ICMP --icmp-parameter-type int ICMP type. Can be set if the protocol is ICMP --ip-range string The remote IP range which the rule should match @@ -57,5 +57,5 @@ stackit beta security-group rule create [flags] ### SEE ALSO -* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules +* [stackit security-group rule](./stackit_security-group_rule.md) - Provides functionality for security group rules diff --git a/docs/stackit_beta_security-group_rule_delete.md b/docs/stackit_security-group_rule_delete.md similarity index 68% rename from docs/stackit_beta_security-group_rule_delete.md rename to docs/stackit_security-group_rule_delete.md index 9489102a5..003912835 100644 --- a/docs/stackit_beta_security-group_rule_delete.md +++ b/docs/stackit_security-group_rule_delete.md @@ -1,4 +1,4 @@ -## stackit beta security-group rule delete +## stackit security-group rule delete Deletes a security group rule @@ -9,20 +9,20 @@ If the security group rule is still in use, the deletion will fail ``` -stackit beta security-group rule delete SECURITY_GROUP_RULE_ID [flags] +stackit security-group rule delete SECURITY_GROUP_RULE_ID [flags] ``` ### Examples ``` Delete security group rule with ID "xxx" in security group with ID "yyy" - $ stackit beta security-group rule delete xxx --security-group-id yyy + $ stackit security-group rule delete xxx --security-group-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta security-group rule delete" + -h, --help Help for "stackit security-group rule delete" --security-group-id string The security group ID ``` @@ -39,5 +39,5 @@ stackit beta security-group rule delete SECURITY_GROUP_RULE_ID [flags] ### SEE ALSO -* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules +* [stackit security-group rule](./stackit_security-group_rule.md) - Provides functionality for security group rules diff --git a/docs/stackit_beta_security-group_rule_describe.md b/docs/stackit_security-group_rule_describe.md similarity index 64% rename from docs/stackit_beta_security-group_rule_describe.md rename to docs/stackit_security-group_rule_describe.md index d23c66138..66579d57e 100644 --- a/docs/stackit_beta_security-group_rule_describe.md +++ b/docs/stackit_security-group_rule_describe.md @@ -1,4 +1,4 @@ -## stackit beta security-group rule describe +## stackit security-group rule describe Shows details of a security group rule @@ -7,23 +7,23 @@ Shows details of a security group rule Shows details of a security group rule. ``` -stackit beta security-group rule describe SECURITY_GROUP_RULE_ID [flags] +stackit security-group rule describe SECURITY_GROUP_RULE_ID [flags] ``` ### Examples ``` Show details of a security group rule with ID "xxx" in security group with ID "yyy" - $ stackit beta security-group rule describe xxx --security-group-id yyy + $ stackit security-group rule describe xxx --security-group-id yyy Show details of a security group rule with ID "xxx" in security group with ID "yyy" in JSON format - $ stackit beta security-group rule describe xxx --security-group-id yyy --output-format json + $ stackit security-group rule describe xxx --security-group-id yyy --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta security-group rule describe" + -h, --help Help for "stackit security-group rule describe" --security-group-id string The security group ID ``` @@ -40,5 +40,5 @@ stackit beta security-group rule describe SECURITY_GROUP_RULE_ID [flags] ### SEE ALSO -* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules +* [stackit security-group rule](./stackit_security-group_rule.md) - Provides functionality for security group rules diff --git a/docs/stackit_beta_security-group_rule_list.md b/docs/stackit_security-group_rule_list.md similarity index 66% rename from docs/stackit_beta_security-group_rule_list.md rename to docs/stackit_security-group_rule_list.md index c3ef60e01..c1aff833b 100644 --- a/docs/stackit_beta_security-group_rule_list.md +++ b/docs/stackit_security-group_rule_list.md @@ -1,4 +1,4 @@ -## stackit beta security-group rule list +## stackit security-group rule list Lists all security group rules in a security group of a project @@ -7,26 +7,26 @@ Lists all security group rules in a security group of a project Lists all security group rules in a security group of a project. ``` -stackit beta security-group rule list [flags] +stackit security-group rule list [flags] ``` ### Examples ``` Lists all security group rules in security group with ID "xxx" - $ stackit beta security-group rule list --security-group-id xxx + $ stackit security-group rule list --security-group-id xxx Lists all security group rules in security group with ID "xxx" in JSON format - $ stackit beta security-group rule list --security-group-id xxx --output-format json + $ stackit security-group rule list --security-group-id xxx --output-format json Lists up to 10 security group rules in security group with ID "xxx" - $ stackit beta security-group rule list --security-group-id xxx --limit 10 + $ stackit security-group rule list --security-group-id xxx --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta security-group rule list" + -h, --help Help for "stackit security-group rule list" --limit int Maximum number of entries to list --security-group-id string The security group ID ``` @@ -44,5 +44,5 @@ stackit beta security-group rule list [flags] ### SEE ALSO -* [stackit beta security-group rule](./stackit_beta_security-group_rule.md) - Provides functionality for security group rules +* [stackit security-group rule](./stackit_security-group_rule.md) - Provides functionality for security group rules diff --git a/docs/stackit_beta_security-group_update.md b/docs/stackit_security-group_update.md similarity index 71% rename from docs/stackit_beta_security-group_update.md rename to docs/stackit_security-group_update.md index fa3bad995..4dd30f03b 100644 --- a/docs/stackit_beta_security-group_update.md +++ b/docs/stackit_security-group_update.md @@ -1,4 +1,4 @@ -## stackit beta security-group update +## stackit security-group update Updates a security group @@ -7,24 +7,24 @@ Updates a security group Updates a named security group ``` -stackit beta security-group update GROUP_ID [flags] +stackit security-group update GROUP_ID [flags] ``` ### Examples ``` Update the name of group "xxx" - $ stackit beta security-group update xxx --name my-new-name + $ stackit security-group update xxx --name my-new-name Update the labels of group "xxx" - $ stackit beta security-group update xxx --labels label1=value1,label2=value2 + $ stackit security-group update xxx --labels label1=value1,label2=value2 ``` ### Options ``` --description string An optional description of the security group. - -h, --help Help for "stackit beta security-group update" + -h, --help Help for "stackit security-group update" --labels stringToString Labels are key-value string pairs which can be attached to a network-interface. E.g. '--labels key1=value1,key2=value2,...' (default []) --name string The name of the security group. ``` @@ -42,5 +42,5 @@ stackit beta security-group update GROUP_ID [flags] ### SEE ALSO -* [stackit beta security-group](./stackit_beta_security-group.md) - Manage security groups +* [stackit security-group](./stackit_security-group.md) - Manage security groups diff --git a/docs/stackit_server.md b/docs/stackit_server.md new file mode 100644 index 000000000..83bf55541 --- /dev/null +++ b/docs/stackit_server.md @@ -0,0 +1,55 @@ +## stackit server + +Provides functionality for servers + +### Synopsis + +Provides functionality for servers. + +``` +stackit server [flags] +``` + +### Options + +``` + -h, --help Help for "stackit server" +``` + +### 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](./stackit.md) - Manage STACKIT resources using the command line +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups +* [stackit server command](./stackit_server_command.md) - Provides functionality for Server Command +* [stackit server console](./stackit_server_console.md) - Gets a URL for server remote console +* [stackit server create](./stackit_server_create.md) - Creates a server +* [stackit server deallocate](./stackit_server_deallocate.md) - Deallocates an existing server +* [stackit server delete](./stackit_server_delete.md) - Deletes a server +* [stackit server describe](./stackit_server_describe.md) - Shows details of a server +* [stackit server list](./stackit_server_list.md) - Lists all servers of a project +* [stackit server log](./stackit_server_log.md) - Gets server console log +* [stackit server machine-type](./stackit_server_machine-type.md) - Provides functionality for server machine types available inside a project +* [stackit server network-interface](./stackit_server_network-interface.md) - Allows attaching/detaching network interfaces to servers +* [stackit server os-update](./stackit_server_os-update.md) - Provides functionality for managed server updates +* [stackit server public-ip](./stackit_server_public-ip.md) - Allows attaching/detaching public IPs to servers +* [stackit server reboot](./stackit_server_reboot.md) - Reboots a server +* [stackit server rescue](./stackit_server_rescue.md) - Rescues an existing server +* [stackit server resize](./stackit_server_resize.md) - Resizes the server to the given machine type +* [stackit server service-account](./stackit_server_service-account.md) - Allows attaching/detaching service accounts to servers +* [stackit server start](./stackit_server_start.md) - Starts an existing server or allocates the server if deallocated +* [stackit server stop](./stackit_server_stop.md) - Stops an existing server +* [stackit server unrescue](./stackit_server_unrescue.md) - Unrescues an existing server +* [stackit server update](./stackit_server_update.md) - Updates a server +* [stackit server volume](./stackit_server_volume.md) - Provides functionality for server volumes + diff --git a/docs/stackit_server_backup.md b/docs/stackit_server_backup.md new file mode 100644 index 000000000..40ec81ed9 --- /dev/null +++ b/docs/stackit_server_backup.md @@ -0,0 +1,42 @@ +## stackit server backup + +Provides functionality for server backups + +### Synopsis + +Provides functionality for server backups. + +``` +stackit server backup [flags] +``` + +### Options + +``` + -h, --help Help for "stackit server backup" +``` + +### 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 server](./stackit_server.md) - Provides functionality for servers +* [stackit server backup create](./stackit_server_backup_create.md) - Creates a Server Backup. +* [stackit server backup delete](./stackit_server_backup_delete.md) - Deletes a Server Backup. +* [stackit server backup describe](./stackit_server_backup_describe.md) - Shows details of a Server Backup +* [stackit server backup disable](./stackit_server_backup_disable.md) - Disables Server Backup service +* [stackit server backup enable](./stackit_server_backup_enable.md) - Enables Server Backup service +* [stackit server backup list](./stackit_server_backup_list.md) - Lists all server backups +* [stackit server backup restore](./stackit_server_backup_restore.md) - Restores a Server Backup. +* [stackit server backup schedule](./stackit_server_backup_schedule.md) - Provides functionality for Server Backup Schedule +* [stackit server backup volume-backup](./stackit_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups + diff --git a/docs/stackit_beta_server_backup_create.md b/docs/stackit_server_backup_create.md similarity index 71% rename from docs/stackit_beta_server_backup_create.md rename to docs/stackit_server_backup_create.md index a98bbd909..0d77984fb 100644 --- a/docs/stackit_beta_server_backup_create.md +++ b/docs/stackit_server_backup_create.md @@ -1,4 +1,4 @@ -## stackit beta server backup create +## stackit server backup create Creates a Server Backup. @@ -7,23 +7,23 @@ Creates a Server Backup. Creates a Server Backup. Operation always is async. ``` -stackit beta server backup create [flags] +stackit server backup create [flags] ``` ### Examples ``` Create a Server Backup with name "mybackup" - $ stackit beta server backup create --server-id xxx --name=mybackup + $ stackit server backup create --server-id xxx --name=mybackup Create a Server Backup with name "mybackup" and retention period of 5 days - $ stackit beta server backup create --server-id xxx --name=mybackup --retention-period=5 + $ stackit server backup create --server-id xxx --name=mybackup --retention-period=5 ``` ### Options ``` - -h, --help Help for "stackit beta server backup create" + -h, --help Help for "stackit server backup create" -b, --name string Backup name -d, --retention-period int Backup retention period (in days) (default 14) -s, --server-id string Server ID @@ -43,5 +43,5 @@ stackit beta server backup create [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_delete.md b/docs/stackit_server_backup_delete.md similarity index 69% rename from docs/stackit_beta_server_backup_delete.md rename to docs/stackit_server_backup_delete.md index fb5da015b..96e1fca84 100644 --- a/docs/stackit_beta_server_backup_delete.md +++ b/docs/stackit_server_backup_delete.md @@ -1,4 +1,4 @@ -## stackit beta server backup delete +## stackit server backup delete Deletes a Server Backup. @@ -7,20 +7,20 @@ Deletes a Server Backup. Deletes a Server Backup. Operation always is async. ``` -stackit beta server backup delete BACKUP_ID [flags] +stackit server backup delete BACKUP_ID [flags] ``` ### Examples ``` Delete a Server Backup with ID "xxx" for server "zzz" - $ stackit beta server backup delete xxx --server-id=zzz + $ stackit server backup delete xxx --server-id=zzz ``` ### Options ``` - -h, --help Help for "stackit beta server backup delete" + -h, --help Help for "stackit server backup delete" -s, --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server backup delete BACKUP_ID [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_describe.md b/docs/stackit_server_backup_describe.md similarity index 67% rename from docs/stackit_beta_server_backup_describe.md rename to docs/stackit_server_backup_describe.md index bdd5c4ff6..008fc02ee 100644 --- a/docs/stackit_beta_server_backup_describe.md +++ b/docs/stackit_server_backup_describe.md @@ -1,4 +1,4 @@ -## stackit beta server backup describe +## stackit server backup describe Shows details of a Server Backup @@ -7,23 +7,23 @@ Shows details of a Server Backup Shows details of a Server Backup. ``` -stackit beta server backup describe BACKUP_ID [flags] +stackit server backup describe BACKUP_ID [flags] ``` ### Examples ``` Get details of a Server Backup with id "my-backup-id" - $ stackit beta server backup describe my-backup-id + $ stackit server backup describe my-backup-id Get details of a Server Backup with id "my-backup-id" in JSON format - $ stackit beta server backup describe my-backup-id --output-format json + $ stackit server backup describe my-backup-id --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server backup describe" + -h, --help Help for "stackit server backup describe" -s, --server-id string Server ID ``` @@ -40,5 +40,5 @@ stackit beta server backup describe BACKUP_ID [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_disable.md b/docs/stackit_server_backup_disable.md similarity index 70% rename from docs/stackit_beta_server_backup_disable.md rename to docs/stackit_server_backup_disable.md index 21766dd43..3a5d623d1 100644 --- a/docs/stackit_beta_server_backup_disable.md +++ b/docs/stackit_server_backup_disable.md @@ -1,4 +1,4 @@ -## stackit beta server backup disable +## stackit server backup disable Disables Server Backup service @@ -7,20 +7,20 @@ Disables Server Backup service Disables Server Backup service. ``` -stackit beta server backup disable [flags] +stackit server backup disable [flags] ``` ### Examples ``` Disable Server Backup functionality for your server. - $ stackit beta server backup disable --server-id=zzz + $ stackit server backup disable --server-id=zzz ``` ### Options ``` - -h, --help Help for "stackit beta server backup disable" + -h, --help Help for "stackit server backup disable" -s, --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server backup disable [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_enable.md b/docs/stackit_server_backup_enable.md similarity index 70% rename from docs/stackit_beta_server_backup_enable.md rename to docs/stackit_server_backup_enable.md index decc76394..e0268a57f 100644 --- a/docs/stackit_beta_server_backup_enable.md +++ b/docs/stackit_server_backup_enable.md @@ -1,4 +1,4 @@ -## stackit beta server backup enable +## stackit server backup enable Enables Server Backup service @@ -7,20 +7,20 @@ Enables Server Backup service Enables Server Backup service. ``` -stackit beta server backup enable [flags] +stackit server backup enable [flags] ``` ### Examples ``` Enable Server Backup functionality for your server - $ stackit beta server backup enable --server-id=zzz + $ stackit server backup enable --server-id=zzz ``` ### Options ``` - -h, --help Help for "stackit beta server backup enable" + -h, --help Help for "stackit server backup enable" -s, --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server backup enable [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_list.md b/docs/stackit_server_backup_list.md similarity index 69% rename from docs/stackit_beta_server_backup_list.md rename to docs/stackit_server_backup_list.md index 1e573787b..702d4917b 100644 --- a/docs/stackit_beta_server_backup_list.md +++ b/docs/stackit_server_backup_list.md @@ -1,4 +1,4 @@ -## stackit beta server backup list +## stackit server backup list Lists all server backups @@ -7,23 +7,23 @@ Lists all server backups Lists all server backups. ``` -stackit beta server backup list [flags] +stackit server backup list [flags] ``` ### Examples ``` List all backups for a server with ID "xxx" - $ stackit beta server backup list --server-id xxx + $ stackit server backup list --server-id xxx List all backups for a server with ID "xxx" in JSON format - $ stackit beta server backup list --server-id xxx --output-format json + $ stackit server backup list --server-id xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server backup list" + -h, --help Help for "stackit server backup list" --limit int Maximum number of entries to list -s, --server-id string Server ID ``` @@ -41,5 +41,5 @@ stackit beta server backup list [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_beta_server_backup_restore.md b/docs/stackit_server_backup_restore.md similarity index 71% rename from docs/stackit_beta_server_backup_restore.md rename to docs/stackit_server_backup_restore.md index 8402b25c3..1b33b16f6 100644 --- a/docs/stackit_beta_server_backup_restore.md +++ b/docs/stackit_server_backup_restore.md @@ -1,4 +1,4 @@ -## stackit beta server backup restore +## stackit server backup restore Restores a Server Backup. @@ -7,23 +7,23 @@ Restores a Server Backup. Restores a Server Backup. Operation always is async. ``` -stackit beta server backup restore BACKUP_ID [flags] +stackit server backup restore BACKUP_ID [flags] ``` ### Examples ``` Restore a Server Backup with ID "xxx" for server "zzz" - $ stackit beta server backup restore xxx --server-id=zzz + $ stackit server backup restore xxx --server-id=zzz Restore a Server Backup with ID "xxx" for server "zzz" and start the server afterwards - $ stackit beta server backup restore xxx --server-id=zzz --start-server-after-restore + $ stackit server backup restore xxx --server-id=zzz --start-server-after-restore ``` ### Options ``` - -h, --help Help for "stackit beta server backup restore" + -h, --help Help for "stackit server backup restore" -s, --server-id string Server ID -u, --start-server-after-restore Should the server start after the backup restoring. -i, --volume-ids strings Backup volume IDs, as comma separated UUID values. (default []) @@ -42,5 +42,5 @@ stackit beta server backup restore BACKUP_ID [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups diff --git a/docs/stackit_server_backup_schedule.md b/docs/stackit_server_backup_schedule.md new file mode 100644 index 000000000..710c97b18 --- /dev/null +++ b/docs/stackit_server_backup_schedule.md @@ -0,0 +1,38 @@ +## stackit server backup schedule + +Provides functionality for Server Backup Schedule + +### Synopsis + +Provides functionality for Server Backup Schedule. + +``` +stackit server backup schedule [flags] +``` + +### Options + +``` + -h, --help Help for "stackit server backup schedule" +``` + +### 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 server backup](./stackit_server_backup.md) - Provides functionality for server backups +* [stackit server backup schedule create](./stackit_server_backup_schedule_create.md) - Creates a Server Backup Schedule +* [stackit server backup schedule delete](./stackit_server_backup_schedule_delete.md) - Deletes a Server Backup Schedule +* [stackit server backup schedule describe](./stackit_server_backup_schedule_describe.md) - Shows details of a Server Backup Schedule +* [stackit server backup schedule list](./stackit_server_backup_schedule_list.md) - Lists all server backup schedules +* [stackit server backup schedule update](./stackit_server_backup_schedule_update.md) - Updates a Server Backup Schedule + diff --git a/docs/stackit_beta_server_backup_schedule_create.md b/docs/stackit_server_backup_schedule_create.md similarity index 70% rename from docs/stackit_beta_server_backup_schedule_create.md rename to docs/stackit_server_backup_schedule_create.md index c875687ac..8b0460852 100644 --- a/docs/stackit_beta_server_backup_schedule_create.md +++ b/docs/stackit_server_backup_schedule_create.md @@ -1,4 +1,4 @@ -## stackit beta server backup schedule create +## stackit server backup schedule create Creates a Server Backup Schedule @@ -7,17 +7,17 @@ Creates a Server Backup Schedule Creates a Server Backup Schedule. ``` -stackit beta server backup schedule create [flags] +stackit server backup schedule create [flags] ``` ### Examples ``` Create a Server Backup Schedule with name "myschedule" and backup name "mybackup" - $ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule + $ stackit server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule Create a Server Backup Schedule with name "myschedule", backup name "mybackup" and retention period of 5 days - $ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule --backup-retention-period=5 + $ stackit server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule --backup-retention-period=5 ``` ### Options @@ -28,7 +28,7 @@ stackit beta server backup schedule create [flags] -n, --backup-schedule-name string Backup schedule name -i, --backup-volume-ids strings Backup volume IDs, as comma separated UUID values. (default []) -e, --enabled Is the server backup schedule enabled (default true) - -h, --help Help for "stackit beta server backup schedule create" + -h, --help Help for "stackit server backup schedule create" -r, --rrule string Backup RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") -s, --server-id string Server ID ``` @@ -46,5 +46,5 @@ stackit beta server backup schedule create [flags] ### SEE ALSO -* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule +* [stackit server backup schedule](./stackit_server_backup_schedule.md) - Provides functionality for Server Backup Schedule diff --git a/docs/stackit_beta_server_backup_schedule_delete.md b/docs/stackit_server_backup_schedule_delete.md similarity index 66% rename from docs/stackit_beta_server_backup_schedule_delete.md rename to docs/stackit_server_backup_schedule_delete.md index 44610dc7d..e4fbf501f 100644 --- a/docs/stackit_beta_server_backup_schedule_delete.md +++ b/docs/stackit_server_backup_schedule_delete.md @@ -1,4 +1,4 @@ -## stackit beta server backup schedule delete +## stackit server backup schedule delete Deletes a Server Backup Schedule @@ -7,20 +7,20 @@ Deletes a Server Backup Schedule Deletes a Server Backup Schedule. ``` -stackit beta server backup schedule delete SCHEDULE_ID [flags] +stackit server backup schedule delete SCHEDULE_ID [flags] ``` ### Examples ``` Delete a Server Backup Schedule with ID "xxx" for server "zzz" - $ stackit beta server backup schedule delete xxx --server-id=zzz + $ stackit server backup schedule delete xxx --server-id=zzz ``` ### Options ``` - -h, --help Help for "stackit beta server backup schedule delete" + -h, --help Help for "stackit server backup schedule delete" -s, --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server backup schedule delete SCHEDULE_ID [flags] ### SEE ALSO -* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule +* [stackit server backup schedule](./stackit_server_backup_schedule.md) - Provides functionality for Server Backup Schedule diff --git a/docs/stackit_beta_server_backup_schedule_describe.md b/docs/stackit_server_backup_schedule_describe.md similarity index 63% rename from docs/stackit_beta_server_backup_schedule_describe.md rename to docs/stackit_server_backup_schedule_describe.md index 95f8d5047..e90933b67 100644 --- a/docs/stackit_beta_server_backup_schedule_describe.md +++ b/docs/stackit_server_backup_schedule_describe.md @@ -1,4 +1,4 @@ -## stackit beta server backup schedule describe +## stackit server backup schedule describe Shows details of a Server Backup Schedule @@ -7,23 +7,23 @@ Shows details of a Server Backup Schedule Shows details of a Server Backup Schedule. ``` -stackit beta server backup schedule describe BACKUP_SCHEDULE_ID [flags] +stackit server backup schedule describe BACKUP_SCHEDULE_ID [flags] ``` ### Examples ``` Get details of a Server Backup Schedule with id "my-schedule-id" - $ stackit beta server backup schedule describe my-schedule-id + $ stackit server backup schedule describe my-schedule-id Get details of a Server Backup Schedule with id "my-schedule-id" in JSON format - $ stackit beta server backup schedule describe my-schedule-id --output-format json + $ stackit server backup schedule describe my-schedule-id --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server backup schedule describe" + -h, --help Help for "stackit server backup schedule describe" -s, --server-id string Server ID ``` @@ -40,5 +40,5 @@ stackit beta server backup schedule describe BACKUP_SCHEDULE_ID [flags] ### SEE ALSO -* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule +* [stackit server backup schedule](./stackit_server_backup_schedule.md) - Provides functionality for Server Backup Schedule diff --git a/docs/stackit_beta_server_backup_schedule_list.md b/docs/stackit_server_backup_schedule_list.md similarity index 66% rename from docs/stackit_beta_server_backup_schedule_list.md rename to docs/stackit_server_backup_schedule_list.md index 89fa03e20..e5c69b1ad 100644 --- a/docs/stackit_beta_server_backup_schedule_list.md +++ b/docs/stackit_server_backup_schedule_list.md @@ -1,4 +1,4 @@ -## stackit beta server backup schedule list +## stackit server backup schedule list Lists all server backup schedules @@ -7,23 +7,23 @@ Lists all server backup schedules Lists all server backup schedules. ``` -stackit beta server backup schedule list [flags] +stackit server backup schedule list [flags] ``` ### Examples ``` List all backup schedules for a server with ID "xxx" - $ stackit beta server backup schedule list --server-id xxx + $ stackit server backup schedule list --server-id xxx List all backup schedules for a server with ID "xxx" in JSON format - $ stackit beta server backup schedule list --server-id xxx --output-format json + $ stackit server backup schedule list --server-id xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server backup schedule list" + -h, --help Help for "stackit server backup schedule list" --limit int Maximum number of entries to list -s, --server-id string Server ID ``` @@ -41,5 +41,5 @@ stackit beta server backup schedule list [flags] ### SEE ALSO -* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule +* [stackit server backup schedule](./stackit_server_backup_schedule.md) - Provides functionality for Server Backup Schedule diff --git a/docs/stackit_beta_server_backup_schedule_update.md b/docs/stackit_server_backup_schedule_update.md similarity index 72% rename from docs/stackit_beta_server_backup_schedule_update.md rename to docs/stackit_server_backup_schedule_update.md index a9bcec886..522c6e7a7 100644 --- a/docs/stackit_beta_server_backup_schedule_update.md +++ b/docs/stackit_server_backup_schedule_update.md @@ -1,4 +1,4 @@ -## stackit beta server backup schedule update +## stackit server backup schedule update Updates a Server Backup Schedule @@ -7,17 +7,17 @@ Updates a Server Backup Schedule Updates a Server Backup Schedule. ``` -stackit beta server backup schedule update SCHEDULE_ID [flags] +stackit server backup schedule update SCHEDULE_ID [flags] ``` ### Examples ``` Update the retention period of the backup schedule "zzz" of server "xxx" - $ stackit beta server backup schedule update zzz --server-id=xxx --backup-retention-period=20 + $ stackit server backup schedule update zzz --server-id=xxx --backup-retention-period=20 Update the backup name of the backup schedule "zzz" of server "xxx" - $ stackit beta server backup schedule update zzz --server-id=xxx --backup-name=newname + $ stackit server backup schedule update zzz --server-id=xxx --backup-name=newname ``` ### Options @@ -28,7 +28,7 @@ stackit beta server backup schedule update SCHEDULE_ID [flags] -n, --backup-schedule-name string Backup schedule name -i, --backup-volume-ids strings Backup volume IDs, as comma separated UUID values. (default []) -e, --enabled Is the server backup schedule enabled (default true) - -h, --help Help for "stackit beta server backup schedule update" + -h, --help Help for "stackit server backup schedule update" -r, --rrule string Backup RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") -s, --server-id string Server ID ``` @@ -46,5 +46,5 @@ stackit beta server backup schedule update SCHEDULE_ID [flags] ### SEE ALSO -* [stackit beta server backup schedule](./stackit_beta_server_backup_schedule.md) - Provides functionality for Server Backup Schedule +* [stackit server backup schedule](./stackit_server_backup_schedule.md) - Provides functionality for Server Backup Schedule diff --git a/docs/stackit_beta_server_backup_volume-backup.md b/docs/stackit_server_backup_volume-backup.md similarity index 54% rename from docs/stackit_beta_server_backup_volume-backup.md rename to docs/stackit_server_backup_volume-backup.md index 302577f4a..ba8068b93 100644 --- a/docs/stackit_beta_server_backup_volume-backup.md +++ b/docs/stackit_server_backup_volume-backup.md @@ -1,4 +1,4 @@ -## stackit beta server backup volume-backup +## stackit server backup volume-backup Provides functionality for Server Backup Volume Backups @@ -7,13 +7,13 @@ Provides functionality for Server Backup Volume Backups Provides functionality for Server Backup Volume Backups. ``` -stackit beta server backup volume-backup [flags] +stackit server backup volume-backup [flags] ``` ### Options ``` - -h, --help Help for "stackit beta server backup volume-backup" + -h, --help Help for "stackit server backup volume-backup" ``` ### Options inherited from parent commands @@ -29,7 +29,7 @@ stackit beta server backup volume-backup [flags] ### SEE ALSO -* [stackit beta server backup](./stackit_beta_server_backup.md) - Provides functionality for server backups -* [stackit beta server backup volume-backup delete](./stackit_beta_server_backup_volume-backup_delete.md) - Deletes a Server Volume Backup. -* [stackit beta server backup volume-backup restore](./stackit_beta_server_backup_volume-backup_restore.md) - Restore a Server Volume Backup to a volume. +* [stackit server backup](./stackit_server_backup.md) - Provides functionality for server backups +* [stackit server backup volume-backup delete](./stackit_server_backup_volume-backup_delete.md) - Deletes a Server Volume Backup. +* [stackit server backup volume-backup restore](./stackit_server_backup_volume-backup_restore.md) - Restore a Server Volume Backup to a volume. diff --git a/docs/stackit_beta_server_backup_volume-backup_delete.md b/docs/stackit_server_backup_volume-backup_delete.md similarity index 65% rename from docs/stackit_beta_server_backup_volume-backup_delete.md rename to docs/stackit_server_backup_volume-backup_delete.md index 9c4e18a98..9cbbdc727 100644 --- a/docs/stackit_beta_server_backup_volume-backup_delete.md +++ b/docs/stackit_server_backup_volume-backup_delete.md @@ -1,4 +1,4 @@ -## stackit beta server backup volume-backup delete +## stackit server backup volume-backup delete Deletes a Server Volume Backup. @@ -7,21 +7,21 @@ Deletes a Server Volume Backup. Deletes a Server Volume Backup. Operation always is async. ``` -stackit beta server backup volume-backup delete VOLUME_BACKUP_ID [flags] +stackit server backup volume-backup delete VOLUME_BACKUP_ID [flags] ``` ### Examples ``` Delete a Server Volume Backup with ID "xxx" for server "zzz" and backup "bbb" - $ stackit beta server backup volume-backup delete xxx --server-id=zzz --backup-id=bbb + $ stackit server backup volume-backup delete xxx --server-id=zzz --backup-id=bbb ``` ### Options ``` -b, --backup-id string Backup ID - -h, --help Help for "stackit beta server backup volume-backup delete" + -h, --help Help for "stackit server backup volume-backup delete" -s, --server-id string Server ID ``` @@ -38,5 +38,5 @@ stackit beta server backup volume-backup delete VOLUME_BACKUP_ID [flags] ### SEE ALSO -* [stackit beta server backup volume-backup](./stackit_beta_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups +* [stackit server backup volume-backup](./stackit_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups diff --git a/docs/stackit_beta_server_backup_volume-backup_restore.md b/docs/stackit_server_backup_volume-backup_restore.md similarity index 66% rename from docs/stackit_beta_server_backup_volume-backup_restore.md rename to docs/stackit_server_backup_volume-backup_restore.md index 784b7c70e..622d45f6f 100644 --- a/docs/stackit_beta_server_backup_volume-backup_restore.md +++ b/docs/stackit_server_backup_volume-backup_restore.md @@ -1,4 +1,4 @@ -## stackit beta server backup volume-backup restore +## stackit server backup volume-backup restore Restore a Server Volume Backup to a volume. @@ -7,21 +7,21 @@ Restore a Server Volume Backup to a volume. Restore a Server Volume Backup to a volume. Operation always is async. ``` -stackit beta server backup volume-backup restore VOLUME_BACKUP_ID [flags] +stackit server backup volume-backup restore VOLUME_BACKUP_ID [flags] ``` ### Examples ``` Restore a Server Volume Backup with ID "xxx" for server "zzz" and backup "bbb" to volume "rrr" - $ stackit beta server backup volume-backup restore xxx --server-id=zzz --backup-id=bbb --restore-volume-id=rrr + $ stackit server backup volume-backup restore xxx --server-id=zzz --backup-id=bbb --restore-volume-id=rrr ``` ### Options ``` -b, --backup-id string Backup ID - -h, --help Help for "stackit beta server backup volume-backup restore" + -h, --help Help for "stackit server backup volume-backup restore" -r, --restore-volume-id string Restore Volume ID -s, --server-id string Server ID ``` @@ -39,5 +39,5 @@ stackit beta server backup volume-backup restore VOLUME_BACKUP_ID [flags] ### SEE ALSO -* [stackit beta server backup volume-backup](./stackit_beta_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups +* [stackit server backup volume-backup](./stackit_server_backup_volume-backup.md) - Provides functionality for Server Backup Volume Backups diff --git a/docs/stackit_server_command.md b/docs/stackit_server_command.md new file mode 100644 index 000000000..c0640ba60 --- /dev/null +++ b/docs/stackit_server_command.md @@ -0,0 +1,37 @@ +## stackit server command + +Provides functionality for Server Command + +### Synopsis + +Provides functionality for Server Command. + +``` +stackit server command [flags] +``` + +### Options + +``` + -h, --help Help for "stackit server command" +``` + +### 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 server](./stackit_server.md) - Provides functionality for servers +* [stackit server command create](./stackit_server_command_create.md) - Creates a Server Command +* [stackit server command describe](./stackit_server_command_describe.md) - Shows details of a Server Command +* [stackit server command list](./stackit_server_command_list.md) - Lists all server commands +* [stackit server command template](./stackit_server_command_template.md) - Provides functionality for Server Command Template + diff --git a/docs/stackit_beta_server_command_create.md b/docs/stackit_server_command_create.md similarity index 69% rename from docs/stackit_beta_server_command_create.md rename to docs/stackit_server_command_create.md index e91b8e9fa..224e7742f 100644 --- a/docs/stackit_beta_server_command_create.md +++ b/docs/stackit_server_command_create.md @@ -1,4 +1,4 @@ -## stackit beta server command create +## stackit server command create Creates a Server Command @@ -7,23 +7,23 @@ Creates a Server Command Creates a Server Command. ``` -stackit beta server command create [flags] +stackit server command create [flags] ``` ### Examples ``` Create a server command for server with ID "xxx", template name "RunShellScript" and a script from a file (using the @{...} format) - $ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='@{/path/to/script.sh}' + $ stackit server command create --server-id xxx --template-name=RunShellScript --params script='@{/path/to/script.sh}' Create a server command for server with ID "xxx", template name "RunShellScript" and a script provided on the command line - $ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='echo hello' + $ stackit server command create --server-id xxx --template-name=RunShellScript --params script='echo hello' ``` ### Options ``` - -h, --help Help for "stackit beta server command create" + -h, --help Help for "stackit server command create" -r, --params stringToString Params can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) -s, --server-id string Server ID -n, --template-name string Template name @@ -42,5 +42,5 @@ stackit beta server command create [flags] ### SEE ALSO -* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command +* [stackit server command](./stackit_server_command.md) - Provides functionality for Server Command diff --git a/docs/stackit_beta_server_command_describe.md b/docs/stackit_server_command_describe.md similarity index 66% rename from docs/stackit_beta_server_command_describe.md rename to docs/stackit_server_command_describe.md index 3f5407c5e..61af4782c 100644 --- a/docs/stackit_beta_server_command_describe.md +++ b/docs/stackit_server_command_describe.md @@ -1,4 +1,4 @@ -## stackit beta server command describe +## stackit server command describe Shows details of a Server Command @@ -7,23 +7,23 @@ Shows details of a Server Command Shows details of a Server Command. ``` -stackit beta server command describe COMMAND_ID [flags] +stackit server command describe COMMAND_ID [flags] ``` ### Examples ``` Get details of a Server Command with ID "xxx" for server with ID "yyy" - $ stackit beta server command describe xxx --server-id=yyy + $ stackit server command describe xxx --server-id=yyy Get details of a Server Command with ID "xxx" for server with ID "yyy" in JSON format - $ stackit beta server command describe xxx --server-id=yyy --output-format json + $ stackit server command describe xxx --server-id=yyy --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server command describe" + -h, --help Help for "stackit server command describe" -s, --server-id string Server ID ``` @@ -40,5 +40,5 @@ stackit beta server command describe COMMAND_ID [flags] ### SEE ALSO -* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command +* [stackit server command](./stackit_server_command.md) - Provides functionality for Server Command diff --git a/docs/stackit_beta_server_command_list.md b/docs/stackit_server_command_list.md similarity index 68% rename from docs/stackit_beta_server_command_list.md rename to docs/stackit_server_command_list.md index dca46c0eb..6467de601 100644 --- a/docs/stackit_beta_server_command_list.md +++ b/docs/stackit_server_command_list.md @@ -1,4 +1,4 @@ -## stackit beta server command list +## stackit server command list Lists all server commands @@ -7,23 +7,23 @@ Lists all server commands Lists all server commands. ``` -stackit beta server command list [flags] +stackit server command list [flags] ``` ### Examples ``` List all commands for a server with ID "xxx" - $ stackit beta server command list --server-id xxx + $ stackit server command list --server-id xxx List all commands for a server with ID "xxx" in JSON format - $ stackit beta server command list --server-id xxx --output-format json + $ stackit server command list --server-id xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server command list" + -h, --help Help for "stackit server command list" --limit int Maximum number of entries to list -s, --server-id string Server ID ``` @@ -41,5 +41,5 @@ stackit beta server command list [flags] ### SEE ALSO -* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command +* [stackit server command](./stackit_server_command.md) - Provides functionality for Server Command diff --git a/docs/stackit_beta_server_command_template.md b/docs/stackit_server_command_template.md similarity index 55% rename from docs/stackit_beta_server_command_template.md rename to docs/stackit_server_command_template.md index 2f49f653f..92a904fea 100644 --- a/docs/stackit_beta_server_command_template.md +++ b/docs/stackit_server_command_template.md @@ -1,4 +1,4 @@ -## stackit beta server command template +## stackit server command template Provides functionality for Server Command Template @@ -7,13 +7,13 @@ Provides functionality for Server Command Template Provides functionality for Server Command Template. ``` -stackit beta server command template [flags] +stackit server command template [flags] ``` ### Options ``` - -h, --help Help for "stackit beta server command template" + -h, --help Help for "stackit server command template" ``` ### Options inherited from parent commands @@ -29,7 +29,7 @@ stackit beta server command template [flags] ### SEE ALSO -* [stackit beta server command](./stackit_beta_server_command.md) - Provides functionality for Server Command -* [stackit beta server command template describe](./stackit_beta_server_command_template_describe.md) - Shows details of a Server Command Template -* [stackit beta server command template list](./stackit_beta_server_command_template_list.md) - Lists all server command templates +* [stackit server command](./stackit_server_command.md) - Provides functionality for Server Command +* [stackit server command template describe](./stackit_server_command_template_describe.md) - Shows details of a Server Command Template +* [stackit server command template list](./stackit_server_command_template_list.md) - Lists all server command templates diff --git a/docs/stackit_beta_server_command_template_describe.md b/docs/stackit_server_command_template_describe.md similarity index 63% rename from docs/stackit_beta_server_command_template_describe.md rename to docs/stackit_server_command_template_describe.md index beab674f4..86a035a2b 100644 --- a/docs/stackit_beta_server_command_template_describe.md +++ b/docs/stackit_server_command_template_describe.md @@ -1,4 +1,4 @@ -## stackit beta server command template describe +## stackit server command template describe Shows details of a Server Command Template @@ -7,23 +7,23 @@ Shows details of a Server Command Template Shows details of a Server Command Template. ``` -stackit beta server command template describe COMMAND_TEMPLATE_NAME [flags] +stackit server command template describe COMMAND_TEMPLATE_NAME [flags] ``` ### Examples ``` Get details of a Server Command Template with name "RunShellScript" for server with ID "xxx" - $ stackit beta server command template describe RunShellScript --server-id=xxx + $ stackit server command template describe RunShellScript --server-id=xxx Get details of a Server Command Template with name "RunShellScript" for server with ID "xxx" in JSON format - $ stackit beta server command template describe RunShellScript --server-id=xxx --output-format json + $ stackit server command template describe RunShellScript --server-id=xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server command template describe" + -h, --help Help for "stackit server command template describe" -s, --server-id string Server ID ``` @@ -40,5 +40,5 @@ stackit beta server command template describe COMMAND_TEMPLATE_NAME [flags] ### SEE ALSO -* [stackit beta server command template](./stackit_beta_server_command_template.md) - Provides functionality for Server Command Template +* [stackit server command template](./stackit_server_command_template.md) - Provides functionality for Server Command Template diff --git a/docs/stackit_beta_server_command_template_list.md b/docs/stackit_server_command_template_list.md similarity index 65% rename from docs/stackit_beta_server_command_template_list.md rename to docs/stackit_server_command_template_list.md index 730f9ad12..36457e6f1 100644 --- a/docs/stackit_beta_server_command_template_list.md +++ b/docs/stackit_server_command_template_list.md @@ -1,4 +1,4 @@ -## stackit beta server command template list +## stackit server command template list Lists all server command templates @@ -7,23 +7,23 @@ Lists all server command templates Lists all server command templates. ``` -stackit beta server command template list [flags] +stackit server command template list [flags] ``` ### Examples ``` List all command templates - $ stackit beta server command template list + $ stackit server command template list List all commands templates in JSON format - $ stackit beta server command template list --output-format json + $ stackit server command template list --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server command template list" + -h, --help Help for "stackit server command template list" --limit int Maximum number of entries to list ``` @@ -40,5 +40,5 @@ stackit beta server command template list [flags] ### SEE ALSO -* [stackit beta server command template](./stackit_beta_server_command_template.md) - Provides functionality for Server Command Template +* [stackit server command template](./stackit_server_command_template.md) - Provides functionality for Server Command Template diff --git a/docs/stackit_beta_server_console.md b/docs/stackit_server_console.md similarity index 72% rename from docs/stackit_beta_server_console.md rename to docs/stackit_server_console.md index df3143cea..a8f6300a6 100644 --- a/docs/stackit_beta_server_console.md +++ b/docs/stackit_server_console.md @@ -1,4 +1,4 @@ -## stackit beta server console +## stackit server console Gets a URL for server remote console @@ -7,23 +7,23 @@ Gets a URL for server remote console Gets a URL for server remote console. ``` -stackit beta server console SERVER_ID [flags] +stackit server console SERVER_ID [flags] ``` ### Examples ``` Get a URL for the server remote console with server ID "xxx" - $ stackit beta server console xxx + $ stackit server console xxx Get a URL for the server remote console with server ID "xxx" in JSON format - $ stackit beta server console xxx --output-format json + $ stackit server console xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server console" + -h, --help Help for "stackit server console" ``` ### Options inherited from parent commands @@ -39,5 +39,5 @@ stackit beta server console SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_create.md b/docs/stackit_server_create.md similarity index 70% rename from docs/stackit_beta_server_create.md rename to docs/stackit_server_create.md index c98d6895b..23378c5fa 100644 --- a/docs/stackit_beta_server_create.md +++ b/docs/stackit_server_create.md @@ -1,4 +1,4 @@ -## stackit beta server create +## stackit server create Creates a server @@ -7,38 +7,38 @@ Creates a server Creates a server. ``` -stackit beta server create [flags] +stackit server create [flags] ``` ### Examples ``` Create a server from an image with id xxx - $ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx + $ stackit server create --machine-type t1.1 --name server1 --image-id xxx Create a server with labels from an image with id xxx - $ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --labels key=value,foo=bar + $ stackit server create --machine-type t1.1 --name server1 --image-id xxx --labels key=value,foo=bar Create a server with a boot volume - $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 + $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 Create a server with a boot volume from an existing volume - $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type volume + $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type volume Create a server with a keypair - $ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --keypair-name example + $ stackit server create --machine-type t1.1 --name server1 --image-id xxx --keypair-name example Create a server with a network - $ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --network-id yyy + $ stackit server create --machine-type t1.1 --name server1 --image-id xxx --network-id yyy Create a server with a network interface - $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --network-interface-ids yyy + $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --network-interface-ids yyy Create a server with an attached volume - $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --volumes yyy + $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --volumes yyy Create a server with user data (cloud-init) - $ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml") + $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml") ``` ### Options @@ -51,7 +51,7 @@ stackit beta server create [flags] --boot-volume-size int The size of the boot volume in GB. Must be provided when 'boot-volume-source-type' is 'image' --boot-volume-source-id string ID of the source object of boot volume. It can be either an image or volume ID --boot-volume-source-type string Type of the source object of boot volume. It can be either 'image' or 'volume' - -h, --help Help for "stackit beta server create" + -h, --help Help for "stackit server create" --image-id string The image ID to be used for an ephemeral disk on the server. Either 'image-id' or 'boot-volume-...' flags are required --keypair-name string The name of the SSH keypair used during the server creation --labels stringToString Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...' (default []) @@ -78,5 +78,5 @@ stackit beta server create [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_deallocate.md b/docs/stackit_server_deallocate.md similarity index 72% rename from docs/stackit_beta_server_deallocate.md rename to docs/stackit_server_deallocate.md index c083e1f4a..aa4921589 100644 --- a/docs/stackit_beta_server_deallocate.md +++ b/docs/stackit_server_deallocate.md @@ -1,4 +1,4 @@ -## stackit beta server deallocate +## stackit server deallocate Deallocates an existing server @@ -7,20 +7,20 @@ Deallocates an existing server Deallocates an existing server. ``` -stackit beta server deallocate SERVER_ID [flags] +stackit server deallocate SERVER_ID [flags] ``` ### Examples ``` Deallocate an existing server with ID "xxx" - $ stackit beta server deallocate xxx + $ stackit server deallocate xxx ``` ### Options ``` - -h, --help Help for "stackit beta server deallocate" + -h, --help Help for "stackit server deallocate" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta server deallocate SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_delete.md b/docs/stackit_server_delete.md similarity index 73% rename from docs/stackit_beta_server_delete.md rename to docs/stackit_server_delete.md index b25341fde..32cf0bfe5 100644 --- a/docs/stackit_beta_server_delete.md +++ b/docs/stackit_server_delete.md @@ -1,4 +1,4 @@ -## stackit beta server delete +## stackit server delete Deletes a server @@ -9,20 +9,20 @@ If the server is still in use, the deletion will fail ``` -stackit beta server delete SERVER_ID [flags] +stackit server delete SERVER_ID [flags] ``` ### Examples ``` Delete server with ID "xxx" - $ stackit beta server delete xxx + $ stackit server delete xxx ``` ### Options ``` - -h, --help Help for "stackit beta server delete" + -h, --help Help for "stackit server delete" ``` ### Options inherited from parent commands @@ -38,5 +38,5 @@ stackit beta server delete SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_describe.md b/docs/stackit_server_describe.md similarity index 70% rename from docs/stackit_beta_server_describe.md rename to docs/stackit_server_describe.md index 3fb94e9cc..c6507dfbe 100644 --- a/docs/stackit_beta_server_describe.md +++ b/docs/stackit_server_describe.md @@ -1,4 +1,4 @@ -## stackit beta server describe +## stackit server describe Shows details of a server @@ -7,23 +7,23 @@ Shows details of a server Shows details of a server. ``` -stackit beta server describe SERVER_ID [flags] +stackit server describe SERVER_ID [flags] ``` ### Examples ``` Show details of a server with ID "xxx" - $ stackit beta server describe xxx + $ stackit server describe xxx Show details of a server with ID "xxx" in JSON format - $ stackit beta server describe xxx --output-format json + $ stackit server describe xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server describe" + -h, --help Help for "stackit server describe" ``` ### Options inherited from parent commands @@ -39,5 +39,5 @@ stackit beta server describe SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_list.md b/docs/stackit_server_list.md similarity index 70% rename from docs/stackit_beta_server_list.md rename to docs/stackit_server_list.md index ca0092ffb..064850236 100644 --- a/docs/stackit_beta_server_list.md +++ b/docs/stackit_server_list.md @@ -1,4 +1,4 @@ -## stackit beta server list +## stackit server list Lists all servers of a project @@ -7,29 +7,29 @@ Lists all servers of a project Lists all servers of a project. ``` -stackit beta server list [flags] +stackit server list [flags] ``` ### Examples ``` Lists all servers - $ stackit beta server list + $ stackit server list Lists all servers which contains the label xxx - $ stackit beta server list --label-selector xxx + $ stackit server list --label-selector xxx Lists all servers in JSON format - $ stackit beta server list --output-format json + $ stackit server list --output-format json Lists up to 10 servers - $ stackit beta server list --limit 10 + $ stackit server list --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta server list" + -h, --help Help for "stackit server list" --label-selector string Filter by label --limit int Maximum number of entries to list ``` @@ -47,5 +47,5 @@ stackit beta server list [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_log.md b/docs/stackit_server_log.md similarity index 72% rename from docs/stackit_beta_server_log.md rename to docs/stackit_server_log.md index 0c15a8547..c1e1e7975 100644 --- a/docs/stackit_beta_server_log.md +++ b/docs/stackit_server_log.md @@ -1,4 +1,4 @@ -## stackit beta server log +## stackit server log Gets server console log @@ -7,26 +7,26 @@ Gets server console log Gets server console log. ``` -stackit beta server log SERVER_ID [flags] +stackit server log SERVER_ID [flags] ``` ### Examples ``` Get server console log for the server with ID "xxx" - $ stackit beta server log xxx + $ stackit server log xxx Get server console log for the server with ID "xxx" and limit output lines to 1000 - $ stackit beta server log xxx --length 1000 + $ stackit server log xxx --length 1000 Get server console log for the server with ID "xxx" in JSON format - $ stackit beta server log xxx --output-format json + $ stackit server log xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server log" + -h, --help Help for "stackit server log" --length int Maximum number of lines to list (default 2000) ``` @@ -43,5 +43,5 @@ stackit beta server log SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_machine-type.md b/docs/stackit_server_machine-type.md similarity index 58% rename from docs/stackit_beta_server_machine-type.md rename to docs/stackit_server_machine-type.md index 406ff1176..4a7058bd8 100644 --- a/docs/stackit_beta_server_machine-type.md +++ b/docs/stackit_server_machine-type.md @@ -1,4 +1,4 @@ -## stackit beta server machine-type +## stackit server machine-type Provides functionality for server machine types available inside a project @@ -7,13 +7,13 @@ Provides functionality for server machine types available inside a project Provides functionality for server machine types available inside a project. ``` -stackit beta server machine-type [flags] +stackit server machine-type [flags] ``` ### Options ``` - -h, --help Help for "stackit beta server machine-type" + -h, --help Help for "stackit server machine-type" ``` ### Options inherited from parent commands @@ -29,7 +29,7 @@ stackit beta server machine-type [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server machine-type describe](./stackit_beta_server_machine-type_describe.md) - Shows details of a server machine type -* [stackit beta server machine-type list](./stackit_beta_server_machine-type_list.md) - Get list of all machine types available in a project +* [stackit server](./stackit_server.md) - Provides functionality for servers +* [stackit server machine-type describe](./stackit_server_machine-type_describe.md) - Shows details of a server machine type +* [stackit server machine-type list](./stackit_server_machine-type_list.md) - Get list of all machine types available in a project diff --git a/docs/stackit_beta_server_machine-type_describe.md b/docs/stackit_server_machine-type_describe.md similarity index 63% rename from docs/stackit_beta_server_machine-type_describe.md rename to docs/stackit_server_machine-type_describe.md index 81519354a..c79ec2a84 100644 --- a/docs/stackit_beta_server_machine-type_describe.md +++ b/docs/stackit_server_machine-type_describe.md @@ -1,4 +1,4 @@ -## stackit beta server machine-type describe +## stackit server machine-type describe Shows details of a server machine type @@ -7,23 +7,23 @@ Shows details of a server machine type Shows details of a server machine type. ``` -stackit beta server machine-type describe MACHINE_TYPE [flags] +stackit server machine-type describe MACHINE_TYPE [flags] ``` ### Examples ``` Show details of a server machine type with name "xxx" - $ stackit beta server machine-type describe xxx + $ stackit server machine-type describe xxx Show details of a server machine type with name "xxx" in JSON format - $ stackit beta server machine-type describe xxx --output-format json + $ stackit server machine-type describe xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server machine-type describe" + -h, --help Help for "stackit server machine-type describe" ``` ### Options inherited from parent commands @@ -39,5 +39,5 @@ stackit beta server machine-type describe MACHINE_TYPE [flags] ### SEE ALSO -* [stackit beta server machine-type](./stackit_beta_server_machine-type.md) - Provides functionality for server machine types available inside a project +* [stackit server machine-type](./stackit_server_machine-type.md) - Provides functionality for server machine types available inside a project diff --git a/docs/stackit_beta_server_machine-type_list.md b/docs/stackit_server_machine-type_list.md similarity index 65% rename from docs/stackit_beta_server_machine-type_list.md rename to docs/stackit_server_machine-type_list.md index 3a10a8be5..fd2ed7afe 100644 --- a/docs/stackit_beta_server_machine-type_list.md +++ b/docs/stackit_server_machine-type_list.md @@ -1,4 +1,4 @@ -## stackit beta server machine-type list +## stackit server machine-type list Get list of all machine types available in a project @@ -7,26 +7,26 @@ Get list of all machine types available in a project Get list of all machine types available in a project. ``` -stackit beta server machine-type list [flags] +stackit server machine-type list [flags] ``` ### Examples ``` Get list of all machine types - $ stackit beta server machine-type list + $ stackit server machine-type list Get list of all machine types in JSON format - $ stackit beta server machine-type list --output-format json + $ stackit server machine-type list --output-format json List the first 10 machine types - $ stackit beta server machine-type list --limit=10 + $ stackit server machine-type list --limit=10 ``` ### Options ``` - -h, --help Help for "stackit beta server machine-type list" + -h, --help Help for "stackit server machine-type list" --limit int Limit the output to the first n elements ``` @@ -43,5 +43,5 @@ stackit beta server machine-type list [flags] ### SEE ALSO -* [stackit beta server machine-type](./stackit_beta_server_machine-type.md) - Provides functionality for server machine types available inside a project +* [stackit server machine-type](./stackit_server_machine-type.md) - Provides functionality for server machine types available inside a project diff --git a/docs/stackit_beta_server_network-interface.md b/docs/stackit_server_network-interface.md similarity index 50% rename from docs/stackit_beta_server_network-interface.md rename to docs/stackit_server_network-interface.md index d2029b1e6..c198fb69f 100644 --- a/docs/stackit_beta_server_network-interface.md +++ b/docs/stackit_server_network-interface.md @@ -1,4 +1,4 @@ -## stackit beta server network-interface +## stackit server network-interface Allows attaching/detaching network interfaces to servers @@ -7,13 +7,13 @@ Allows attaching/detaching network interfaces to servers Allows attaching/detaching network interfaces to servers. ``` -stackit beta server network-interface [flags] +stackit server network-interface [flags] ``` ### Options ``` - -h, --help Help for "stackit beta server network-interface" + -h, --help Help for "stackit server network-interface" ``` ### Options inherited from parent commands @@ -29,8 +29,8 @@ stackit beta server network-interface [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server network-interface attach](./stackit_beta_server_network-interface_attach.md) - Attaches a network interface to a server -* [stackit beta server network-interface detach](./stackit_beta_server_network-interface_detach.md) - Detaches a network interface from a server -* [stackit beta server network-interface list](./stackit_beta_server_network-interface_list.md) - Lists all attached network interfaces of a server +* [stackit server](./stackit_server.md) - Provides functionality for servers +* [stackit server network-interface attach](./stackit_server_network-interface_attach.md) - Attaches a network interface to a server +* [stackit server network-interface detach](./stackit_server_network-interface_detach.md) - Detaches a network interface from a server +* [stackit server network-interface list](./stackit_server_network-interface_list.md) - Lists all attached network interfaces of a server diff --git a/docs/stackit_beta_server_network-interface_attach.md b/docs/stackit_server_network-interface_attach.md similarity index 67% rename from docs/stackit_beta_server_network-interface_attach.md rename to docs/stackit_server_network-interface_attach.md index af58fe6c8..f20e49cb5 100644 --- a/docs/stackit_beta_server_network-interface_attach.md +++ b/docs/stackit_server_network-interface_attach.md @@ -1,4 +1,4 @@ -## stackit beta server network-interface attach +## stackit server network-interface attach Attaches a network interface to a server @@ -7,24 +7,24 @@ Attaches a network interface to a server Attaches a network interface to a server. ``` -stackit beta server network-interface attach [flags] +stackit server network-interface attach [flags] ``` ### Examples ``` Attach a network interface with ID "xxx" to a server with ID "yyy" - $ stackit beta server network-interface attach --network-interface-id xxx --server-id yyy + $ stackit server network-interface attach --network-interface-id xxx --server-id yyy Create a network interface for network with ID "xxx" and attach it to a server with ID "yyy" - $ stackit beta server network-interface attach --network-id xxx --server-id yyy --create + $ stackit server network-interface attach --network-id xxx --server-id yyy --create ``` ### Options ``` -b, --create If this is set a network interface will be created. (default false) - -h, --help Help for "stackit beta server network-interface attach" + -h, --help Help for "stackit server network-interface attach" --network-id string Network ID --network-interface-id string Network Interface ID --server-id string Server ID @@ -43,5 +43,5 @@ stackit beta server network-interface attach [flags] ### SEE ALSO -* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers +* [stackit server network-interface](./stackit_server_network-interface.md) - Allows attaching/detaching network interfaces to servers diff --git a/docs/stackit_beta_server_network-interface_detach.md b/docs/stackit_server_network-interface_detach.md similarity index 68% rename from docs/stackit_beta_server_network-interface_detach.md rename to docs/stackit_server_network-interface_detach.md index f6859346a..19369455a 100644 --- a/docs/stackit_beta_server_network-interface_detach.md +++ b/docs/stackit_server_network-interface_detach.md @@ -1,4 +1,4 @@ -## stackit beta server network-interface detach +## stackit server network-interface detach Detaches a network interface from a server @@ -7,24 +7,24 @@ Detaches a network interface from a server Detaches a network interface from a server. ``` -stackit beta server network-interface detach [flags] +stackit server network-interface detach [flags] ``` ### Examples ``` Detach a network interface with ID "xxx" from a server with ID "yyy" - $ stackit beta server network-interface detach --network-interface-id xxx --server-id yyy + $ stackit server network-interface detach --network-interface-id xxx --server-id yyy Detach and delete all network interfaces for network with ID "xxx" and detach them from a server with ID "yyy" - $ stackit beta server network-interface detach --network-id xxx --server-id yyy --delete + $ stackit server network-interface detach --network-id xxx --server-id yyy --delete ``` ### Options ``` -b, --delete If this is set all network interfaces will be deleted. (default false) - -h, --help Help for "stackit beta server network-interface detach" + -h, --help Help for "stackit server network-interface detach" --network-id string Network ID --network-interface-id string Network Interface ID --server-id string Server ID @@ -43,5 +43,5 @@ stackit beta server network-interface detach [flags] ### SEE ALSO -* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers +* [stackit server network-interface](./stackit_server_network-interface.md) - Allows attaching/detaching network interfaces to servers diff --git a/docs/stackit_beta_server_network-interface_list.md b/docs/stackit_server_network-interface_list.md similarity index 64% rename from docs/stackit_beta_server_network-interface_list.md rename to docs/stackit_server_network-interface_list.md index a184557eb..42ed2e5b5 100644 --- a/docs/stackit_beta_server_network-interface_list.md +++ b/docs/stackit_server_network-interface_list.md @@ -1,4 +1,4 @@ -## stackit beta server network-interface list +## stackit server network-interface list Lists all attached network interfaces of a server @@ -7,26 +7,26 @@ Lists all attached network interfaces of a server Lists all attached network interfaces of a server. ``` -stackit beta server network-interface list [flags] +stackit server network-interface list [flags] ``` ### Examples ``` Lists all attached network interfaces of server with ID "xxx" - $ stackit beta server network-interface list --server-id xxx + $ stackit server network-interface list --server-id xxx Lists all attached network interfaces of server with ID "xxx" in JSON format - $ stackit beta server network-interface list --server-id xxx --output-format json + $ stackit server network-interface list --server-id xxx --output-format json Lists up to 10 attached network interfaces of server with ID "xxx" - $ stackit beta server network-interface list --server-id xxx --limit 10 + $ stackit server network-interface list --server-id xxx --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta server network-interface list" + -h, --help Help for "stackit server network-interface list" --limit int Maximum number of entries to list --server-id string Server ID ``` @@ -44,5 +44,5 @@ stackit beta server network-interface list [flags] ### SEE ALSO -* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers +* [stackit server network-interface](./stackit_server_network-interface.md) - Allows attaching/detaching network interfaces to servers diff --git a/docs/stackit_server_os-update.md b/docs/stackit_server_os-update.md new file mode 100644 index 000000000..baf0ad8cc --- /dev/null +++ b/docs/stackit_server_os-update.md @@ -0,0 +1,39 @@ +## stackit server os-update + +Provides functionality for managed server updates + +### Synopsis + +Provides functionality for managed server updates. + +``` +stackit server os-update [flags] +``` + +### Options + +``` + -h, --help Help for "stackit server os-update" +``` + +### 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 server](./stackit_server.md) - Provides functionality for servers +* [stackit server os-update create](./stackit_server_os-update_create.md) - Creates a Server os-update. +* [stackit server os-update describe](./stackit_server_os-update_describe.md) - Shows details of a Server os-update +* [stackit server os-update disable](./stackit_server_os-update_disable.md) - Disables server os-update service +* [stackit server os-update enable](./stackit_server_os-update_enable.md) - Enables Server os-update service +* [stackit server os-update list](./stackit_server_os-update_list.md) - Lists all server os-updates +* [stackit server os-update schedule](./stackit_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule + diff --git a/docs/stackit_beta_server_os-update_create.md b/docs/stackit_server_os-update_create.md similarity index 67% rename from docs/stackit_beta_server_os-update_create.md rename to docs/stackit_server_os-update_create.md index fcfa3efb6..f84cb6d77 100644 --- a/docs/stackit_beta_server_os-update_create.md +++ b/docs/stackit_server_os-update_create.md @@ -1,4 +1,4 @@ -## stackit beta server os-update create +## stackit server os-update create Creates a Server os-update. @@ -7,23 +7,23 @@ Creates a Server os-update. Creates a Server os-update. Operation always is async. ``` -stackit beta server os-update create [flags] +stackit server os-update create [flags] ``` ### Examples ``` Create a Server os-update with name "myupdate" - $ stackit beta server os-update create --server-id xxx --name=myupdate + $ stackit server os-update create --server-id xxx --name=myupdate Create a Server os-update with name "myupdate" and maintenance window for 13 o'clock. - $ stackit beta server os-update create --server-id xxx --name=mybupdate --maintenance-window=13 + $ stackit server os-update create --server-id xxx --name=mybupdate --maintenance-window=13 ``` ### Options ``` - -h, --help Help for "stackit beta server os-update create" + -h, --help Help for "stackit server os-update create" -m, --maintenance-window int Maintenance window (in hours, 1-24) (default 23) -s, --server-id string Server ID ``` @@ -41,5 +41,5 @@ stackit beta server os-update create [flags] ### SEE ALSO -* [stackit beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates +* [stackit server os-update](./stackit_server_os-update.md) - Provides functionality for managed server updates diff --git a/docs/stackit_beta_server_os-update_describe.md b/docs/stackit_server_os-update_describe.md similarity index 65% rename from docs/stackit_beta_server_os-update_describe.md rename to docs/stackit_server_os-update_describe.md index a73f04dd7..8302a131f 100644 --- a/docs/stackit_beta_server_os-update_describe.md +++ b/docs/stackit_server_os-update_describe.md @@ -1,4 +1,4 @@ -## stackit beta server os-update describe +## stackit server os-update describe Shows details of a Server os-update @@ -7,23 +7,23 @@ Shows details of a Server os-update Shows details of a Server os-update. ``` -stackit beta server os-update describe UPDATE_ID [flags] +stackit server os-update describe UPDATE_ID [flags] ``` ### Examples ``` Get details of a Server os-update with id "my-os-update-id" - $ stackit beta server os-update describe my-os-update-id + $ stackit server os-update describe my-os-update-id Get details of a Server os-update with id "my-os-update-id" in JSON format - $ stackit beta server os-update describe my-os-update-id --output-format json + $ stackit server os-update describe my-os-update-id --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server os-update describe" + -h, --help Help for "stackit server os-update describe" -s, --server-id string Server ID ``` @@ -40,5 +40,5 @@ stackit beta server os-update describe UPDATE_ID [flags] ### SEE ALSO -* [stackit beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates +* [stackit server os-update](./stackit_server_os-update.md) - Provides functionality for managed server updates diff --git a/docs/stackit_beta_server_os-update_disable.md b/docs/stackit_server_os-update_disable.md similarity index 68% rename from docs/stackit_beta_server_os-update_disable.md rename to docs/stackit_server_os-update_disable.md index 477d42214..5be186b0b 100644 --- a/docs/stackit_beta_server_os-update_disable.md +++ b/docs/stackit_server_os-update_disable.md @@ -1,4 +1,4 @@ -## stackit beta server os-update disable +## stackit server os-update disable Disables server os-update service @@ -7,20 +7,20 @@ Disables server os-update service Disables server os-update service. ``` -stackit beta server os-update disable [flags] +stackit server os-update disable [flags] ``` ### Examples ``` Disable os-update functionality for your server. - $ stackit beta server os-update disable --server-id=zzz + $ stackit server os-update disable --server-id=zzz ``` ### Options ``` - -h, --help Help for "stackit beta server os-update disable" + -h, --help Help for "stackit server os-update disable" -s, --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server os-update disable [flags] ### SEE ALSO -* [stackit beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates +* [stackit server os-update](./stackit_server_os-update.md) - Provides functionality for managed server updates diff --git a/docs/stackit_beta_server_os-update_enable.md b/docs/stackit_server_os-update_enable.md similarity index 68% rename from docs/stackit_beta_server_os-update_enable.md rename to docs/stackit_server_os-update_enable.md index 661ddaf47..fdcc98abe 100644 --- a/docs/stackit_beta_server_os-update_enable.md +++ b/docs/stackit_server_os-update_enable.md @@ -1,4 +1,4 @@ -## stackit beta server os-update enable +## stackit server os-update enable Enables Server os-update service @@ -7,20 +7,20 @@ Enables Server os-update service Enables Server os-update service. ``` -stackit beta server os-update enable [flags] +stackit server os-update enable [flags] ``` ### Examples ``` Enable os-update functionality for your server - $ stackit beta server os-update enable --server-id=zzz + $ stackit server os-update enable --server-id=zzz ``` ### Options ``` - -h, --help Help for "stackit beta server os-update enable" + -h, --help Help for "stackit server os-update enable" -s, --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server os-update enable [flags] ### SEE ALSO -* [stackit beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates +* [stackit server os-update](./stackit_server_os-update.md) - Provides functionality for managed server updates diff --git a/docs/stackit_beta_server_os-update_list.md b/docs/stackit_server_os-update_list.md similarity index 67% rename from docs/stackit_beta_server_os-update_list.md rename to docs/stackit_server_os-update_list.md index 57c46d3df..97ff3bad7 100644 --- a/docs/stackit_beta_server_os-update_list.md +++ b/docs/stackit_server_os-update_list.md @@ -1,4 +1,4 @@ -## stackit beta server os-update list +## stackit server os-update list Lists all server os-updates @@ -7,23 +7,23 @@ Lists all server os-updates Lists all server os-updates. ``` -stackit beta server os-update list [flags] +stackit server os-update list [flags] ``` ### Examples ``` List all os-updates for a server with ID "xxx" - $ stackit beta server os-update list --server-id xxx + $ stackit server os-update list --server-id xxx List all os-updates for a server with ID "xxx" in JSON format - $ stackit beta server os-update list --server-id xxx --output-format json + $ stackit server os-update list --server-id xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server os-update list" + -h, --help Help for "stackit server os-update list" --limit int Maximum number of entries to list -s, --server-id string Server ID ``` @@ -41,5 +41,5 @@ stackit beta server os-update list [flags] ### SEE ALSO -* [stackit beta server os-update](./stackit_beta_server_os-update.md) - Provides functionality for managed server updates +* [stackit server os-update](./stackit_server_os-update.md) - Provides functionality for managed server updates diff --git a/docs/stackit_server_os-update_schedule.md b/docs/stackit_server_os-update_schedule.md new file mode 100644 index 000000000..1cc934797 --- /dev/null +++ b/docs/stackit_server_os-update_schedule.md @@ -0,0 +1,38 @@ +## stackit server os-update schedule + +Provides functionality for Server os-update Schedule + +### Synopsis + +Provides functionality for Server os-update Schedule. + +``` +stackit server os-update schedule [flags] +``` + +### Options + +``` + -h, --help Help for "stackit server os-update schedule" +``` + +### 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 server os-update](./stackit_server_os-update.md) - Provides functionality for managed server updates +* [stackit server os-update schedule create](./stackit_server_os-update_schedule_create.md) - Creates a Server os-update Schedule +* [stackit server os-update schedule delete](./stackit_server_os-update_schedule_delete.md) - Deletes a Server os-update Schedule +* [stackit server os-update schedule describe](./stackit_server_os-update_schedule_describe.md) - Shows details of a Server os-update Schedule +* [stackit server os-update schedule list](./stackit_server_os-update_schedule_list.md) - Lists all server os-update schedules +* [stackit server os-update schedule update](./stackit_server_os-update_schedule_update.md) - Updates a Server os-update Schedule + diff --git a/docs/stackit_beta_server_os-update_schedule_create.md b/docs/stackit_server_os-update_schedule_create.md similarity index 70% rename from docs/stackit_beta_server_os-update_schedule_create.md rename to docs/stackit_server_os-update_schedule_create.md index 529fe2b87..75862ef17 100644 --- a/docs/stackit_beta_server_os-update_schedule_create.md +++ b/docs/stackit_server_os-update_schedule_create.md @@ -1,4 +1,4 @@ -## stackit beta server os-update schedule create +## stackit server os-update schedule create Creates a Server os-update Schedule @@ -7,24 +7,24 @@ Creates a Server os-update Schedule Creates a Server os-update Schedule. ``` -stackit beta server os-update schedule create [flags] +stackit server os-update schedule create [flags] ``` ### Examples ``` Create a Server os-update Schedule with name "myschedule" - $ stackit beta server os-update schedule create --server-id xxx --name=myschedule + $ stackit server os-update schedule create --server-id xxx --name=myschedule Create a Server os-update Schedule with name "myschedule" and maintenance window for 14 o'clock - $ stackit beta server os-update schedule create --server-id xxx --name=myschedule --maintenance-window=14 + $ stackit server os-update schedule create --server-id xxx --name=myschedule --maintenance-window=14 ``` ### Options ``` -e, --enabled Is the server os-update schedule enabled (default true) - -h, --help Help for "stackit beta server os-update schedule create" + -h, --help Help for "stackit server os-update schedule create" -d, --maintenance-window int os-update maintenance window (in hours, 1-24) (default 23) -n, --name string os-update schedule name -r, --rrule string os-update RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") @@ -44,5 +44,5 @@ stackit beta server os-update schedule create [flags] ### SEE ALSO -* [stackit beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule +* [stackit server os-update schedule](./stackit_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule diff --git a/docs/stackit_beta_server_os-update_schedule_delete.md b/docs/stackit_server_os-update_schedule_delete.md similarity index 65% rename from docs/stackit_beta_server_os-update_schedule_delete.md rename to docs/stackit_server_os-update_schedule_delete.md index d2e5e2bc9..c61c8b7ce 100644 --- a/docs/stackit_beta_server_os-update_schedule_delete.md +++ b/docs/stackit_server_os-update_schedule_delete.md @@ -1,4 +1,4 @@ -## stackit beta server os-update schedule delete +## stackit server os-update schedule delete Deletes a Server os-update Schedule @@ -7,20 +7,20 @@ Deletes a Server os-update Schedule Deletes a Server os-update Schedule. ``` -stackit beta server os-update schedule delete SCHEDULE_ID [flags] +stackit server os-update schedule delete SCHEDULE_ID [flags] ``` ### Examples ``` Delete a Server os-update Schedule with ID "xxx" for server "zzz" - $ stackit beta server os-update schedule delete xxx --server-id=zzz + $ stackit server os-update schedule delete xxx --server-id=zzz ``` ### Options ``` - -h, --help Help for "stackit beta server os-update schedule delete" + -h, --help Help for "stackit server os-update schedule delete" -s, --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server os-update schedule delete SCHEDULE_ID [flags] ### SEE ALSO -* [stackit beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule +* [stackit server os-update schedule](./stackit_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule diff --git a/docs/stackit_beta_server_os-update_schedule_describe.md b/docs/stackit_server_os-update_schedule_describe.md similarity index 63% rename from docs/stackit_beta_server_os-update_schedule_describe.md rename to docs/stackit_server_os-update_schedule_describe.md index fc6542fd2..f93d219ac 100644 --- a/docs/stackit_beta_server_os-update_schedule_describe.md +++ b/docs/stackit_server_os-update_schedule_describe.md @@ -1,4 +1,4 @@ -## stackit beta server os-update schedule describe +## stackit server os-update schedule describe Shows details of a Server os-update Schedule @@ -7,23 +7,23 @@ Shows details of a Server os-update Schedule Shows details of a Server os-update Schedule. ``` -stackit beta server os-update schedule describe SCHEDULE_ID [flags] +stackit server os-update schedule describe SCHEDULE_ID [flags] ``` ### Examples ``` Get details of a Server os-update Schedule with id "my-schedule-id" - $ stackit beta server os-update schedule describe my-schedule-id + $ stackit server os-update schedule describe my-schedule-id Get details of a Server os-update Schedule with id "my-schedule-id" in JSON format - $ stackit beta server os-update schedule describe my-schedule-id --output-format json + $ stackit server os-update schedule describe my-schedule-id --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server os-update schedule describe" + -h, --help Help for "stackit server os-update schedule describe" -s, --server-id string Server ID ``` @@ -40,5 +40,5 @@ stackit beta server os-update schedule describe SCHEDULE_ID [flags] ### SEE ALSO -* [stackit beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule +* [stackit server os-update schedule](./stackit_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule diff --git a/docs/stackit_beta_server_os-update_schedule_list.md b/docs/stackit_server_os-update_schedule_list.md similarity index 65% rename from docs/stackit_beta_server_os-update_schedule_list.md rename to docs/stackit_server_os-update_schedule_list.md index 5352184bb..3cf2d1580 100644 --- a/docs/stackit_beta_server_os-update_schedule_list.md +++ b/docs/stackit_server_os-update_schedule_list.md @@ -1,4 +1,4 @@ -## stackit beta server os-update schedule list +## stackit server os-update schedule list Lists all server os-update schedules @@ -7,23 +7,23 @@ Lists all server os-update schedules Lists all server os-update schedules. ``` -stackit beta server os-update schedule list [flags] +stackit server os-update schedule list [flags] ``` ### Examples ``` List all os-update schedules for a server with ID "xxx" - $ stackit beta server os-update schedule list --server-id xxx + $ stackit server os-update schedule list --server-id xxx List all os-update schedules for a server with ID "xxx" in JSON format - $ stackit beta server os-update schedule list --server-id xxx --output-format json + $ stackit server os-update schedule list --server-id xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server os-update schedule list" + -h, --help Help for "stackit server os-update schedule list" --limit int Maximum number of entries to list -s, --server-id string Server ID ``` @@ -41,5 +41,5 @@ stackit beta server os-update schedule list [flags] ### SEE ALSO -* [stackit beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule +* [stackit server os-update schedule](./stackit_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule diff --git a/docs/stackit_beta_server_os-update_schedule_update.md b/docs/stackit_server_os-update_schedule_update.md similarity index 72% rename from docs/stackit_beta_server_os-update_schedule_update.md rename to docs/stackit_server_os-update_schedule_update.md index 4b901269f..8a29cd366 100644 --- a/docs/stackit_beta_server_os-update_schedule_update.md +++ b/docs/stackit_server_os-update_schedule_update.md @@ -1,4 +1,4 @@ -## stackit beta server os-update schedule update +## stackit server os-update schedule update Updates a Server os-update Schedule @@ -7,21 +7,21 @@ Updates a Server os-update Schedule Updates a Server os-update Schedule. ``` -stackit beta server os-update schedule update SCHEDULE_ID [flags] +stackit server os-update schedule update SCHEDULE_ID [flags] ``` ### Examples ``` Update the name of the os-update schedule "zzz" of server "xxx" - $ stackit beta server os-update schedule update zzz --server-id=xxx --name=newname + $ stackit server os-update schedule update zzz --server-id=xxx --name=newname ``` ### Options ``` -e, --enabled Is the server os-update schedule enabled (default true) - -h, --help Help for "stackit beta server os-update schedule update" + -h, --help Help for "stackit server os-update schedule update" -d, --maintenance-window int Maintenance window (in hours, 1-24) (default 23) -n, --name string os-update schedule name -r, --rrule string os-update RRULE (recurrence rule) (default "DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1") @@ -41,5 +41,5 @@ stackit beta server os-update schedule update SCHEDULE_ID [flags] ### SEE ALSO -* [stackit beta server os-update schedule](./stackit_beta_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule +* [stackit server os-update schedule](./stackit_server_os-update_schedule.md) - Provides functionality for Server os-update Schedule diff --git a/docs/stackit_beta_server_public-ip.md b/docs/stackit_server_public-ip.md similarity index 59% rename from docs/stackit_beta_server_public-ip.md rename to docs/stackit_server_public-ip.md index 2572a6214..6ad5bfc99 100644 --- a/docs/stackit_beta_server_public-ip.md +++ b/docs/stackit_server_public-ip.md @@ -1,4 +1,4 @@ -## stackit beta server public-ip +## stackit server public-ip Allows attaching/detaching public IPs to servers @@ -7,13 +7,13 @@ Allows attaching/detaching public IPs to servers Allows attaching/detaching public IPs to servers. ``` -stackit beta server public-ip [flags] +stackit server public-ip [flags] ``` ### Options ``` - -h, --help Help for "stackit beta server public-ip" + -h, --help Help for "stackit server public-ip" ``` ### Options inherited from parent commands @@ -29,7 +29,7 @@ stackit beta server public-ip [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server public-ip attach](./stackit_beta_server_public-ip_attach.md) - Attaches a public IP to a server -* [stackit beta server public-ip detach](./stackit_beta_server_public-ip_detach.md) - Detaches a public IP from a server +* [stackit server](./stackit_server.md) - Provides functionality for servers +* [stackit server public-ip attach](./stackit_server_public-ip_attach.md) - Attaches a public IP to a server +* [stackit server public-ip detach](./stackit_server_public-ip_detach.md) - Detaches a public IP from a server diff --git a/docs/stackit_beta_server_public-ip_attach.md b/docs/stackit_server_public-ip_attach.md similarity index 68% rename from docs/stackit_beta_server_public-ip_attach.md rename to docs/stackit_server_public-ip_attach.md index ce1a537e2..a3cc5172f 100644 --- a/docs/stackit_beta_server_public-ip_attach.md +++ b/docs/stackit_server_public-ip_attach.md @@ -1,4 +1,4 @@ -## stackit beta server public-ip attach +## stackit server public-ip attach Attaches a public IP to a server @@ -7,20 +7,20 @@ Attaches a public IP to a server Attaches a public IP to a server. ``` -stackit beta server public-ip attach PUBLIC_IP_ID [flags] +stackit server public-ip attach PUBLIC_IP_ID [flags] ``` ### Examples ``` Attach a public IP with ID "xxx" to a server with ID "yyy" - $ stackit beta server public-ip attach xxx --server-id yyy + $ stackit server public-ip attach xxx --server-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta server public-ip attach" + -h, --help Help for "stackit server public-ip attach" --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server public-ip attach PUBLIC_IP_ID [flags] ### SEE ALSO -* [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers +* [stackit server public-ip](./stackit_server_public-ip.md) - Allows attaching/detaching public IPs to servers diff --git a/docs/stackit_beta_server_public-ip_detach.md b/docs/stackit_server_public-ip_detach.md similarity index 68% rename from docs/stackit_beta_server_public-ip_detach.md rename to docs/stackit_server_public-ip_detach.md index af84a000a..4881e3c2d 100644 --- a/docs/stackit_beta_server_public-ip_detach.md +++ b/docs/stackit_server_public-ip_detach.md @@ -1,4 +1,4 @@ -## stackit beta server public-ip detach +## stackit server public-ip detach Detaches a public IP from a server @@ -7,20 +7,20 @@ Detaches a public IP from a server Detaches a public IP from a server. ``` -stackit beta server public-ip detach PUBLIC_IP_ID [flags] +stackit server public-ip detach PUBLIC_IP_ID [flags] ``` ### Examples ``` Detaches a public IP with ID "xxx" from a server with ID "yyy" - $ stackit beta server public-ip detach xxx --server-id yyy + $ stackit server public-ip detach xxx --server-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta server public-ip detach" + -h, --help Help for "stackit server public-ip detach" --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server public-ip detach PUBLIC_IP_ID [flags] ### SEE ALSO -* [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers +* [stackit server public-ip](./stackit_server_public-ip.md) - Allows attaching/detaching public IPs to servers diff --git a/docs/stackit_beta_server_reboot.md b/docs/stackit_server_reboot.md similarity index 72% rename from docs/stackit_beta_server_reboot.md rename to docs/stackit_server_reboot.md index e425e2f51..8075a67ba 100644 --- a/docs/stackit_beta_server_reboot.md +++ b/docs/stackit_server_reboot.md @@ -1,4 +1,4 @@ -## stackit beta server reboot +## stackit server reboot Reboots a server @@ -7,24 +7,24 @@ Reboots a server Reboots a server. ``` -stackit beta server reboot SERVER_ID [flags] +stackit server reboot SERVER_ID [flags] ``` ### Examples ``` Perform a soft reboot of a server with ID "xxx" - $ stackit beta server reboot xxx + $ stackit server reboot xxx Perform a hard reboot of a server with ID "xxx" - $ stackit beta server reboot xxx --hard + $ stackit server reboot xxx --hard ``` ### Options ``` -b, --hard Performs a hard reboot. (default false) - -h, --help Help for "stackit beta server reboot" + -h, --help Help for "stackit server reboot" ``` ### Options inherited from parent commands @@ -40,5 +40,5 @@ stackit beta server reboot SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_rescue.md b/docs/stackit_server_rescue.md similarity index 74% rename from docs/stackit_beta_server_rescue.md rename to docs/stackit_server_rescue.md index 06983d133..4aaa5104b 100644 --- a/docs/stackit_beta_server_rescue.md +++ b/docs/stackit_server_rescue.md @@ -1,4 +1,4 @@ -## stackit beta server rescue +## stackit server rescue Rescues an existing server @@ -7,20 +7,20 @@ Rescues an existing server Rescues an existing server. ``` -stackit beta server rescue SERVER_ID [flags] +stackit server rescue SERVER_ID [flags] ``` ### Examples ``` Rescue an existing server with ID "xxx" using image with ID "yyy" as boot volume - $ stackit beta server rescue xxx --image-id yyy + $ stackit server rescue xxx --image-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta server rescue" + -h, --help Help for "stackit server rescue" --image-id string The image ID to be used for a temporary boot volume. ``` @@ -37,5 +37,5 @@ stackit beta server rescue SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_resize.md b/docs/stackit_server_resize.md similarity index 76% rename from docs/stackit_beta_server_resize.md rename to docs/stackit_server_resize.md index 73a94c785..c91335432 100644 --- a/docs/stackit_beta_server_resize.md +++ b/docs/stackit_server_resize.md @@ -1,4 +1,4 @@ -## stackit beta server resize +## stackit server resize Resizes the server to the given machine type @@ -7,20 +7,20 @@ Resizes the server to the given machine type Resizes the server to the given machine type. ``` -stackit beta server resize SERVER_ID [flags] +stackit server resize SERVER_ID [flags] ``` ### Examples ``` Resize a server with ID "xxx" to machine type "yyy" - $ stackit beta server resize xxx --machine-type yyy + $ stackit server resize xxx --machine-type yyy ``` ### Options ``` - -h, --help Help for "stackit beta server resize" + -h, --help Help for "stackit server resize" --machine-type string Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html ``` @@ -37,5 +37,5 @@ stackit beta server resize SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_service-account.md b/docs/stackit_server_service-account.md similarity index 51% rename from docs/stackit_beta_server_service-account.md rename to docs/stackit_server_service-account.md index 08509cf0e..5af599a53 100644 --- a/docs/stackit_beta_server_service-account.md +++ b/docs/stackit_server_service-account.md @@ -1,4 +1,4 @@ -## stackit beta server service-account +## stackit server service-account Allows attaching/detaching service accounts to servers @@ -7,13 +7,13 @@ Allows attaching/detaching service accounts to servers Allows attaching/detaching service accounts to servers ``` -stackit beta server service-account [flags] +stackit server service-account [flags] ``` ### Options ``` - -h, --help Help for "stackit beta server service-account" + -h, --help Help for "stackit server service-account" ``` ### Options inherited from parent commands @@ -29,8 +29,8 @@ stackit beta server service-account [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers -* [stackit beta server service-account attach](./stackit_beta_server_service-account_attach.md) - Attach a service account to a server -* [stackit beta server service-account detach](./stackit_beta_server_service-account_detach.md) - Detach a service account from a server -* [stackit beta server service-account list](./stackit_beta_server_service-account_list.md) - List all attached service accounts for a server +* [stackit server](./stackit_server.md) - Provides functionality for servers +* [stackit server service-account attach](./stackit_server_service-account_attach.md) - Attach a service account to a server +* [stackit server service-account detach](./stackit_server_service-account_detach.md) - Detach a service account from a server +* [stackit server service-account list](./stackit_server_service-account_list.md) - List all attached service accounts for a server diff --git a/docs/stackit_beta_server_service-account_attach.md b/docs/stackit_server_service-account_attach.md similarity index 65% rename from docs/stackit_beta_server_service-account_attach.md rename to docs/stackit_server_service-account_attach.md index 4e0998bf9..0cf08c386 100644 --- a/docs/stackit_beta_server_service-account_attach.md +++ b/docs/stackit_server_service-account_attach.md @@ -1,4 +1,4 @@ -## stackit beta server service-account attach +## stackit server service-account attach Attach a service account to a server @@ -7,20 +7,20 @@ Attach a service account to a server Attach a service account to a server ``` -stackit beta server service-account attach SERVICE_ACCOUNT_EMAIL [flags] +stackit server service-account attach SERVICE_ACCOUNT_EMAIL [flags] ``` ### Examples ``` Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy" - $ stackit beta server service-account attach xxx@sa.stackit.cloud --server-id yyy + $ stackit server service-account attach xxx@sa.stackit.cloud --server-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta server service-account attach" + -h, --help Help for "stackit server service-account attach" -s, --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server service-account attach SERVICE_ACCOUNT_EMAIL [flags] ### SEE ALSO -* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers +* [stackit server service-account](./stackit_server_service-account.md) - Allows attaching/detaching service accounts to servers diff --git a/docs/stackit_beta_server_service-account_detach.md b/docs/stackit_server_service-account_detach.md similarity index 65% rename from docs/stackit_beta_server_service-account_detach.md rename to docs/stackit_server_service-account_detach.md index 7f674e634..87806ced3 100644 --- a/docs/stackit_beta_server_service-account_detach.md +++ b/docs/stackit_server_service-account_detach.md @@ -1,4 +1,4 @@ -## stackit beta server service-account detach +## stackit server service-account detach Detach a service account from a server @@ -7,20 +7,20 @@ Detach a service account from a server Detach a service account from a server ``` -stackit beta server service-account detach SERVICE_ACCOUNT_EMAIL [flags] +stackit server service-account detach SERVICE_ACCOUNT_EMAIL [flags] ``` ### Examples ``` Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy" - $ stackit beta server service-account detach xxx@sa.stackit.cloud --server-id yyy + $ stackit server service-account detach xxx@sa.stackit.cloud --server-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta server service-account detach" + -h, --help Help for "stackit server service-account detach" -s, --server-id string Server id ``` @@ -37,5 +37,5 @@ stackit beta server service-account detach SERVICE_ACCOUNT_EMAIL [flags] ### SEE ALSO -* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers +* [stackit server service-account](./stackit_server_service-account.md) - Allows attaching/detaching service accounts to servers diff --git a/docs/stackit_beta_server_service-account_list.md b/docs/stackit_server_service-account_list.md similarity index 65% rename from docs/stackit_beta_server_service-account_list.md rename to docs/stackit_server_service-account_list.md index a6fa2498c..78349aee3 100644 --- a/docs/stackit_beta_server_service-account_list.md +++ b/docs/stackit_server_service-account_list.md @@ -1,4 +1,4 @@ -## stackit beta server service-account list +## stackit server service-account list List all attached service accounts for a server @@ -7,26 +7,26 @@ List all attached service accounts for a server List all attached service accounts for a server ``` -stackit beta server service-account list [flags] +stackit server service-account list [flags] ``` ### Examples ``` List all attached service accounts for a server with ID "xxx" - $ stackit beta server service-account list --server-id xxx + $ stackit server service-account list --server-id xxx List up to 10 attached service accounts for a server with ID "xxx" - $ stackit beta server service-account list --server-id xxx --limit 10 + $ stackit server service-account list --server-id xxx --limit 10 List all attached service accounts for a server with ID "xxx" in JSON format - $ stackit beta server service-account list --server-id xxx --output-format json + $ stackit server service-account list --server-id xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server service-account list" + -h, --help Help for "stackit server service-account list" --limit int Maximum number of entries to list -s, --server-id string Server ID ``` @@ -44,5 +44,5 @@ stackit beta server service-account list [flags] ### SEE ALSO -* [stackit beta server service-account](./stackit_beta_server_service-account.md) - Allows attaching/detaching service accounts to servers +* [stackit server service-account](./stackit_server_service-account.md) - Allows attaching/detaching service accounts to servers diff --git a/docs/stackit_beta_server_start.md b/docs/stackit_server_start.md similarity index 75% rename from docs/stackit_beta_server_start.md rename to docs/stackit_server_start.md index 06dd1b651..1fa89116d 100644 --- a/docs/stackit_beta_server_start.md +++ b/docs/stackit_server_start.md @@ -1,4 +1,4 @@ -## stackit beta server start +## stackit server start Starts an existing server or allocates the server if deallocated @@ -7,20 +7,20 @@ Starts an existing server or allocates the server if deallocated Starts an existing server or allocates the server if deallocated. ``` -stackit beta server start SERVER_ID [flags] +stackit server start SERVER_ID [flags] ``` ### Examples ``` Start an existing server with ID "xxx" - $ stackit beta server start xxx + $ stackit server start xxx ``` ### Options ``` - -h, --help Help for "stackit beta server start" + -h, --help Help for "stackit server start" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta server start SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_stop.md b/docs/stackit_server_stop.md similarity index 73% rename from docs/stackit_beta_server_stop.md rename to docs/stackit_server_stop.md index 51928947f..41403e1f7 100644 --- a/docs/stackit_beta_server_stop.md +++ b/docs/stackit_server_stop.md @@ -1,4 +1,4 @@ -## stackit beta server stop +## stackit server stop Stops an existing server @@ -7,20 +7,20 @@ Stops an existing server Stops an existing server. ``` -stackit beta server stop SERVER_ID [flags] +stackit server stop SERVER_ID [flags] ``` ### Examples ``` Stop an existing server with ID "xxx" - $ stackit beta server stop xxx + $ stackit server stop xxx ``` ### Options ``` - -h, --help Help for "stackit beta server stop" + -h, --help Help for "stackit server stop" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta server stop SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_unrescue.md b/docs/stackit_server_unrescue.md similarity index 72% rename from docs/stackit_beta_server_unrescue.md rename to docs/stackit_server_unrescue.md index 573ad1a6e..5dc30bab3 100644 --- a/docs/stackit_beta_server_unrescue.md +++ b/docs/stackit_server_unrescue.md @@ -1,4 +1,4 @@ -## stackit beta server unrescue +## stackit server unrescue Unrescues an existing server @@ -7,20 +7,20 @@ Unrescues an existing server Unrescues an existing server. ``` -stackit beta server unrescue SERVER_ID [flags] +stackit server unrescue SERVER_ID [flags] ``` ### Examples ``` Unrescue an existing server with ID "xxx" - $ stackit beta server unrescue xxx + $ stackit server unrescue xxx ``` ### Options ``` - -h, --help Help for "stackit beta server unrescue" + -h, --help Help for "stackit server unrescue" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit beta server unrescue SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_beta_server_update.md b/docs/stackit_server_update.md similarity index 72% rename from docs/stackit_beta_server_update.md rename to docs/stackit_server_update.md index 44b1e3ce4..3aac20259 100644 --- a/docs/stackit_beta_server_update.md +++ b/docs/stackit_server_update.md @@ -1,4 +1,4 @@ -## stackit beta server update +## stackit server update Updates a server @@ -7,23 +7,23 @@ Updates a server Updates a server. ``` -stackit beta server update SERVER_ID [flags] +stackit server update SERVER_ID [flags] ``` ### Examples ``` Update server with ID "xxx" with new name "server-1-new" - $ stackit beta server update xxx --name server-1-new + $ stackit server update xxx --name server-1-new Update server with ID "xxx" with new name "server-1-new" and label(s) - $ stackit beta server update xxx --name server-1-new --labels key=value,foo=bar + $ stackit server update xxx --name server-1-new --labels key=value,foo=bar ``` ### Options ``` - -h, --help Help for "stackit beta server update" + -h, --help Help for "stackit server update" --labels stringToString Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...' (default []) -n, --name string Server name ``` @@ -41,5 +41,5 @@ stackit beta server update SERVER_ID [flags] ### SEE ALSO -* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers +* [stackit server](./stackit_server.md) - Provides functionality for servers diff --git a/docs/stackit_server_volume.md b/docs/stackit_server_volume.md new file mode 100644 index 000000000..74e426604 --- /dev/null +++ b/docs/stackit_server_volume.md @@ -0,0 +1,38 @@ +## stackit server volume + +Provides functionality for server volumes + +### Synopsis + +Provides functionality for server volumes. + +``` +stackit server volume [flags] +``` + +### Options + +``` + -h, --help Help for "stackit server volume" +``` + +### 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 server](./stackit_server.md) - Provides functionality for servers +* [stackit server volume attach](./stackit_server_volume_attach.md) - Attaches a volume to a server +* [stackit server volume describe](./stackit_server_volume_describe.md) - Describes a server volume attachment +* [stackit server volume detach](./stackit_server_volume_detach.md) - Detaches a volume from a server +* [stackit server volume list](./stackit_server_volume_list.md) - Lists all server volumes +* [stackit server volume update](./stackit_server_volume_update.md) - Updates an attached volume of a server + diff --git a/docs/stackit_beta_server_volume_attach.md b/docs/stackit_server_volume_attach.md similarity index 69% rename from docs/stackit_beta_server_volume_attach.md rename to docs/stackit_server_volume_attach.md index 89f6fe054..b7014c6a1 100644 --- a/docs/stackit_beta_server_volume_attach.md +++ b/docs/stackit_server_volume_attach.md @@ -1,4 +1,4 @@ -## stackit beta server volume attach +## stackit server volume attach Attaches a volume to a server @@ -7,24 +7,24 @@ Attaches a volume to a server Attaches a volume to a server. ``` -stackit beta server volume attach VOLUME_ID [flags] +stackit server volume attach VOLUME_ID [flags] ``` ### Examples ``` Attach a volume with ID "xxx" to a server with ID "yyy" - $ stackit beta server volume attach xxx --server-id yyy + $ stackit server volume attach xxx --server-id yyy Attach a volume with ID "xxx" to a server with ID "yyy" and enable deletion on termination - $ stackit beta server volume attach xxx --server-id yyy --delete-on-termination + $ stackit server volume attach xxx --server-id yyy --delete-on-termination ``` ### Options ``` -b, --delete-on-termination Delete the volume during the termination of the server. (default false) - -h, --help Help for "stackit beta server volume attach" + -h, --help Help for "stackit server volume attach" --server-id string Server ID ``` @@ -41,5 +41,5 @@ stackit beta server volume attach VOLUME_ID [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes +* [stackit server volume](./stackit_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_volume_describe.md b/docs/stackit_server_volume_describe.md similarity index 66% rename from docs/stackit_beta_server_volume_describe.md rename to docs/stackit_server_volume_describe.md index df99e10a1..be85d6afc 100644 --- a/docs/stackit_beta_server_volume_describe.md +++ b/docs/stackit_server_volume_describe.md @@ -1,4 +1,4 @@ -## stackit beta server volume describe +## stackit server volume describe Describes a server volume attachment @@ -7,26 +7,26 @@ Describes a server volume attachment Describes a server volume attachment. ``` -stackit beta server volume describe VOLUME_ID [flags] +stackit server volume describe VOLUME_ID [flags] ``` ### Examples ``` Get details of the attachment of volume with ID "xxx" to server with ID "yyy" - $ stackit beta server volume describe xxx --server-id yyy + $ stackit server volume describe xxx --server-id yyy Get details of the attachment of volume with ID "xxx" to server with ID "yyy" in JSON format - $ stackit beta server volume describe xxx --server-id yyy --output-format json + $ stackit server volume describe xxx --server-id yyy --output-format json Get details of the attachment of volume with ID "xxx" to server with ID "yyy" in yaml format - $ stackit beta server volume describe xxx --server-id yyy --output-format yaml + $ stackit server volume describe xxx --server-id yyy --output-format yaml ``` ### Options ``` - -h, --help Help for "stackit beta server volume describe" + -h, --help Help for "stackit server volume describe" --server-id string Server ID ``` @@ -43,5 +43,5 @@ stackit beta server volume describe VOLUME_ID [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes +* [stackit server volume](./stackit_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_volume_detach.md b/docs/stackit_server_volume_detach.md similarity index 69% rename from docs/stackit_beta_server_volume_detach.md rename to docs/stackit_server_volume_detach.md index 45b72bc30..3758a7b35 100644 --- a/docs/stackit_beta_server_volume_detach.md +++ b/docs/stackit_server_volume_detach.md @@ -1,4 +1,4 @@ -## stackit beta server volume detach +## stackit server volume detach Detaches a volume from a server @@ -7,20 +7,20 @@ Detaches a volume from a server Detaches a volume from a server. ``` -stackit beta server volume detach VOLUME_ID [flags] +stackit server volume detach VOLUME_ID [flags] ``` ### Examples ``` Detaches a volume with ID "xxx" from a server with ID "yyy" - $ stackit beta server volume detach xxx --server-id yyy + $ stackit server volume detach xxx --server-id yyy ``` ### Options ``` - -h, --help Help for "stackit beta server volume detach" + -h, --help Help for "stackit server volume detach" --server-id string Server ID ``` @@ -37,5 +37,5 @@ stackit beta server volume detach VOLUME_ID [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes +* [stackit server volume](./stackit_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_volume_list.md b/docs/stackit_server_volume_list.md similarity index 67% rename from docs/stackit_beta_server_volume_list.md rename to docs/stackit_server_volume_list.md index b21e59ca8..97560e090 100644 --- a/docs/stackit_beta_server_volume_list.md +++ b/docs/stackit_server_volume_list.md @@ -1,4 +1,4 @@ -## stackit beta server volume list +## stackit server volume list Lists all server volumes @@ -7,23 +7,23 @@ Lists all server volumes Lists all server volumes. ``` -stackit beta server volume list [flags] +stackit server volume list [flags] ``` ### Examples ``` List all volumes for a server with ID "xxx" - $ stackit beta server volume list --server-id xxx + $ stackit server volume list --server-id xxx List all volumes for a server with ID "xxx" in JSON format - $ stackit beta server volumes list --server-id xxx --output-format json + $ stackit server volumes list --server-id xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta server volume list" + -h, --help Help for "stackit server volume list" -s, --server-id string Server ID ``` @@ -40,5 +40,5 @@ stackit beta server volume list [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes +* [stackit server volume](./stackit_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_beta_server_volume_update.md b/docs/stackit_server_volume_update.md similarity index 71% rename from docs/stackit_beta_server_volume_update.md rename to docs/stackit_server_volume_update.md index 88f94fe6f..70290e948 100644 --- a/docs/stackit_beta_server_volume_update.md +++ b/docs/stackit_server_volume_update.md @@ -1,4 +1,4 @@ -## stackit beta server volume update +## stackit server volume update Updates an attached volume of a server @@ -7,21 +7,21 @@ Updates an attached volume of a server Updates an attached volume of a server. ``` -stackit beta server volume update VOLUME_ID [flags] +stackit server volume update VOLUME_ID [flags] ``` ### Examples ``` Update a volume with ID "xxx" of a server with ID "yyy" and enables delete on termination - $ stackit beta server volume update xxx --server-id yyy --delete-on-termination + $ stackit server volume update xxx --server-id yyy --delete-on-termination ``` ### Options ``` -b, --delete-on-termination Delete the volume during the termination of the server. (default false) - -h, --help Help for "stackit beta server volume update" + -h, --help Help for "stackit server volume update" --server-id string Server ID ``` @@ -38,5 +38,5 @@ stackit beta server volume update VOLUME_ID [flags] ### SEE ALSO -* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes +* [stackit server volume](./stackit_server_volume.md) - Provides functionality for server volumes diff --git a/docs/stackit_volume.md b/docs/stackit_volume.md new file mode 100644 index 000000000..c83878554 --- /dev/null +++ b/docs/stackit_volume.md @@ -0,0 +1,40 @@ +## stackit volume + +Provides functionality for volumes + +### Synopsis + +Provides functionality for volumes. + +``` +stackit volume [flags] +``` + +### Options + +``` + -h, --help Help for "stackit volume" +``` + +### 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](./stackit.md) - Manage STACKIT resources using the command line +* [stackit volume create](./stackit_volume_create.md) - Creates a volume +* [stackit volume delete](./stackit_volume_delete.md) - Deletes a volume +* [stackit volume describe](./stackit_volume_describe.md) - Shows details of a volume +* [stackit volume list](./stackit_volume_list.md) - Lists all volumes of a project +* [stackit volume performance-class](./stackit_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project +* [stackit volume resize](./stackit_volume_resize.md) - Resizes a volume +* [stackit volume update](./stackit_volume_update.md) - Updates a volume + diff --git a/docs/stackit_beta_volume_create.md b/docs/stackit_volume_create.md similarity index 73% rename from docs/stackit_beta_volume_create.md rename to docs/stackit_volume_create.md index e2d41da46..dedf3c595 100644 --- a/docs/stackit_beta_volume_create.md +++ b/docs/stackit_volume_create.md @@ -1,4 +1,4 @@ -## stackit beta volume create +## stackit volume create Creates a volume @@ -7,23 +7,23 @@ Creates a volume Creates a volume. ``` -stackit beta volume create [flags] +stackit volume create [flags] ``` ### Examples ``` Create a volume with availability zone "eu01-1" and size 64 GB - $ stackit beta volume create --availability-zone eu01-1 --size 64 + $ stackit volume create --availability-zone eu01-1 --size 64 Create a volume with availability zone "eu01-1", size 64 GB and labels - $ stackit beta volume create --availability-zone eu01-1 --size 64 --labels key=value,foo=bar + $ stackit volume create --availability-zone eu01-1 --size 64 --labels key=value,foo=bar Create a volume with name "volume-1", from a source image with ID "xxx" - $ stackit beta volume create --availability-zone eu01-1 --name volume-1 --source-id xxx --source-type image + $ stackit volume create --availability-zone eu01-1 --name volume-1 --source-id xxx --source-type image Create a volume with availability zone "eu01-1", performance class "storage_premium_perf1" and size 64 GB - $ stackit beta volume create --availability-zone eu01-1 --performance-class storage_premium_perf1 --size 64 + $ stackit volume create --availability-zone eu01-1 --performance-class storage_premium_perf1 --size 64 ``` ### Options @@ -31,7 +31,7 @@ stackit beta volume create [flags] ``` --availability-zone string Availability zone --description string Volume description - -h, --help Help for "stackit beta volume create" + -h, --help Help for "stackit volume create" --labels stringToString Labels are key-value string pairs which can be attached to a volume. E.g. '--labels key1=value1,key2=value2,...' (default []) -n, --name string Volume name --performance-class string Performance class @@ -53,5 +53,5 @@ stackit beta volume create [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes +* [stackit volume](./stackit_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_delete.md b/docs/stackit_volume_delete.md similarity index 73% rename from docs/stackit_beta_volume_delete.md rename to docs/stackit_volume_delete.md index 8cf666298..165804aa6 100644 --- a/docs/stackit_beta_volume_delete.md +++ b/docs/stackit_volume_delete.md @@ -1,4 +1,4 @@ -## stackit beta volume delete +## stackit volume delete Deletes a volume @@ -9,20 +9,20 @@ If the volume is still in use, the deletion will fail ``` -stackit beta volume delete VOLUME_ID [flags] +stackit volume delete VOLUME_ID [flags] ``` ### Examples ``` Delete volume with ID "xxx" - $ stackit beta volume delete xxx + $ stackit volume delete xxx ``` ### Options ``` - -h, --help Help for "stackit beta volume delete" + -h, --help Help for "stackit volume delete" ``` ### Options inherited from parent commands @@ -38,5 +38,5 @@ stackit beta volume delete VOLUME_ID [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes +* [stackit volume](./stackit_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_describe.md b/docs/stackit_volume_describe.md similarity index 70% rename from docs/stackit_beta_volume_describe.md rename to docs/stackit_volume_describe.md index f6556c1cf..a098db3a7 100644 --- a/docs/stackit_beta_volume_describe.md +++ b/docs/stackit_volume_describe.md @@ -1,4 +1,4 @@ -## stackit beta volume describe +## stackit volume describe Shows details of a volume @@ -7,23 +7,23 @@ Shows details of a volume Shows details of a volume. ``` -stackit beta volume describe VOLUME_ID [flags] +stackit volume describe VOLUME_ID [flags] ``` ### Examples ``` Show details of a volume with ID "xxx" - $ stackit beta volume describe xxx + $ stackit volume describe xxx Show details of a volume with ID "xxx" in JSON format - $ stackit beta volume describe xxx --output-format json + $ stackit volume describe xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta volume describe" + -h, --help Help for "stackit volume describe" ``` ### Options inherited from parent commands @@ -39,5 +39,5 @@ stackit beta volume describe VOLUME_ID [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes +* [stackit volume](./stackit_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_list.md b/docs/stackit_volume_list.md similarity index 70% rename from docs/stackit_beta_volume_list.md rename to docs/stackit_volume_list.md index c6f33ad92..2e59fd0d7 100644 --- a/docs/stackit_beta_volume_list.md +++ b/docs/stackit_volume_list.md @@ -1,4 +1,4 @@ -## stackit beta volume list +## stackit volume list Lists all volumes of a project @@ -7,29 +7,29 @@ Lists all volumes of a project Lists all volumes of a project. ``` -stackit beta volume list [flags] +stackit volume list [flags] ``` ### Examples ``` Lists all volumes - $ stackit beta volume list + $ stackit volume list Lists all volumes which contains the label xxx - $ stackit beta volume list --label-selector xxx + $ stackit volume list --label-selector xxx Lists all volumes in JSON format - $ stackit beta volume list --output-format json + $ stackit volume list --output-format json Lists up to 10 volumes - $ stackit beta volume list --limit 10 + $ stackit volume list --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta volume list" + -h, --help Help for "stackit volume list" --label-selector string Filter by label --limit int Maximum number of entries to list ``` @@ -47,5 +47,5 @@ stackit beta volume list [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes +* [stackit volume](./stackit_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_performance-class.md b/docs/stackit_volume_performance-class.md similarity index 57% rename from docs/stackit_beta_volume_performance-class.md rename to docs/stackit_volume_performance-class.md index 7df645369..f584910ab 100644 --- a/docs/stackit_beta_volume_performance-class.md +++ b/docs/stackit_volume_performance-class.md @@ -1,4 +1,4 @@ -## stackit beta volume performance-class +## stackit volume performance-class Provides functionality for volume performance classes available inside a project @@ -7,13 +7,13 @@ Provides functionality for volume performance classes available inside a project Provides functionality for volume performance classes available inside a project. ``` -stackit beta volume performance-class [flags] +stackit volume performance-class [flags] ``` ### Options ``` - -h, --help Help for "stackit beta volume performance-class" + -h, --help Help for "stackit volume performance-class" ``` ### Options inherited from parent commands @@ -29,7 +29,7 @@ stackit beta volume performance-class [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes -* [stackit beta volume performance-class describe](./stackit_beta_volume_performance-class_describe.md) - Shows details of a volume performance class -* [stackit beta volume performance-class list](./stackit_beta_volume_performance-class_list.md) - Lists all volume performance classes for a project +* [stackit volume](./stackit_volume.md) - Provides functionality for volumes +* [stackit volume performance-class describe](./stackit_volume_performance-class_describe.md) - Shows details of a volume performance class +* [stackit volume performance-class list](./stackit_volume_performance-class_list.md) - Lists all volume performance classes for a project diff --git a/docs/stackit_beta_volume_performance-class_describe.md b/docs/stackit_volume_performance-class_describe.md similarity index 61% rename from docs/stackit_beta_volume_performance-class_describe.md rename to docs/stackit_volume_performance-class_describe.md index ed8fa7942..a7c53a69c 100644 --- a/docs/stackit_beta_volume_performance-class_describe.md +++ b/docs/stackit_volume_performance-class_describe.md @@ -1,4 +1,4 @@ -## stackit beta volume performance-class describe +## stackit volume performance-class describe Shows details of a volume performance class @@ -7,23 +7,23 @@ Shows details of a volume performance class Shows details of a volume performance class. ``` -stackit beta volume performance-class describe VOLUME_PERFORMANCE_CLASS [flags] +stackit volume performance-class describe VOLUME_PERFORMANCE_CLASS [flags] ``` ### Examples ``` Show details of a volume performance class with name "xxx" - $ stackit beta volume performance-class describe xxx + $ stackit volume performance-class describe xxx Show details of a volume performance class with name "xxx" in JSON format - $ stackit beta volume performance-class describe xxx --output-format json + $ stackit volume performance-class describe xxx --output-format json ``` ### Options ``` - -h, --help Help for "stackit beta volume performance-class describe" + -h, --help Help for "stackit volume performance-class describe" ``` ### Options inherited from parent commands @@ -39,5 +39,5 @@ stackit beta volume performance-class describe VOLUME_PERFORMANCE_CLASS [flags] ### SEE ALSO -* [stackit beta volume performance-class](./stackit_beta_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project +* [stackit volume performance-class](./stackit_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project diff --git a/docs/stackit_beta_volume_performance-class_list.md b/docs/stackit_volume_performance-class_list.md similarity index 63% rename from docs/stackit_beta_volume_performance-class_list.md rename to docs/stackit_volume_performance-class_list.md index ed595ca77..e01cd3df4 100644 --- a/docs/stackit_beta_volume_performance-class_list.md +++ b/docs/stackit_volume_performance-class_list.md @@ -1,4 +1,4 @@ -## stackit beta volume performance-class list +## stackit volume performance-class list Lists all volume performance classes for a project @@ -7,29 +7,29 @@ Lists all volume performance classes for a project Lists all volume performance classes for a project. ``` -stackit beta volume performance-class list [flags] +stackit volume performance-class list [flags] ``` ### Examples ``` Lists all volume performance classes - $ stackit beta volume performance-class list + $ stackit volume performance-class list Lists all volume performance classes which contains the label xxx - $ stackit beta volume performance-class list --label-selector xxx + $ stackit volume performance-class list --label-selector xxx Lists all volume performance classes in JSON format - $ stackit beta volume performance-class list --output-format json + $ stackit volume performance-class list --output-format json Lists up to 10 volume performance classes - $ stackit beta volume performance-class list --limit 10 + $ stackit volume performance-class list --limit 10 ``` ### Options ``` - -h, --help Help for "stackit beta volume performance-class list" + -h, --help Help for "stackit volume performance-class list" --label-selector string Filter by label --limit int Maximum number of entries to list ``` @@ -47,5 +47,5 @@ stackit beta volume performance-class list [flags] ### SEE ALSO -* [stackit beta volume performance-class](./stackit_beta_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project +* [stackit volume performance-class](./stackit_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project diff --git a/docs/stackit_beta_volume_resize.md b/docs/stackit_volume_resize.md similarity index 72% rename from docs/stackit_beta_volume_resize.md rename to docs/stackit_volume_resize.md index 4df6abbcf..04286ff44 100644 --- a/docs/stackit_beta_volume_resize.md +++ b/docs/stackit_volume_resize.md @@ -1,4 +1,4 @@ -## stackit beta volume resize +## stackit volume resize Resizes a volume @@ -7,20 +7,20 @@ Resizes a volume Resizes a volume. ``` -stackit beta volume resize VOLUME_ID [flags] +stackit volume resize VOLUME_ID [flags] ``` ### Examples ``` Resize volume with ID "xxx" with new size 10 GB - $ stackit beta volume resize xxx --size 10 + $ stackit volume resize xxx --size 10 ``` ### Options ``` - -h, --help Help for "stackit beta volume resize" + -h, --help Help for "stackit volume resize" --size int Volume size (GB) ``` @@ -37,5 +37,5 @@ stackit beta volume resize VOLUME_ID [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes +* [stackit volume](./stackit_volume.md) - Provides functionality for volumes diff --git a/docs/stackit_beta_volume_update.md b/docs/stackit_volume_update.md similarity index 70% rename from docs/stackit_beta_volume_update.md rename to docs/stackit_volume_update.md index ce82c2fe0..1f28e3b1e 100644 --- a/docs/stackit_beta_volume_update.md +++ b/docs/stackit_volume_update.md @@ -1,4 +1,4 @@ -## stackit beta volume update +## stackit volume update Updates a volume @@ -7,27 +7,27 @@ Updates a volume Updates a volume. ``` -stackit beta volume update VOLUME_ID [flags] +stackit volume update VOLUME_ID [flags] ``` ### Examples ``` Update volume with ID "xxx" with new name "volume-1-new" - $ stackit beta volume update xxx --name volume-1-new + $ stackit volume update xxx --name volume-1-new Update volume with ID "xxx" with new name "volume-1-new" and new description "volume-1-desc-new" - $ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new + $ stackit volume update xxx --name volume-1-new --description volume-1-desc-new Update volume with ID "xxx" with new name "volume-1-new", new description "volume-1-desc-new" and label(s) - $ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new --labels key=value,foo=bar + $ stackit volume update xxx --name volume-1-new --description volume-1-desc-new --labels key=value,foo=bar ``` ### Options ``` --description string Volume description - -h, --help Help for "stackit beta volume update" + -h, --help Help for "stackit volume update" --labels stringToString Labels are key-value string pairs which can be attached to a volume. E.g. '--labels key1=value1,key2=value2,...' (default []) -n, --name string Volume name ``` @@ -45,5 +45,5 @@ stackit beta volume update VOLUME_ID [flags] ### SEE ALSO -* [stackit beta volume](./stackit_beta_volume.md) - Provides functionality for volumes +* [stackit volume](./stackit_volume.md) - Provides functionality for volumes diff --git a/internal/cmd/beta/affinity-groups/affinity-groups.go b/internal/cmd/affinity-groups/affinity-groups.go similarity index 68% rename from internal/cmd/beta/affinity-groups/affinity-groups.go rename to internal/cmd/affinity-groups/affinity-groups.go index f05389de3..57f44f65e 100644 --- a/internal/cmd/beta/affinity-groups/affinity-groups.go +++ b/internal/cmd/affinity-groups/affinity-groups.go @@ -2,10 +2,10 @@ package affinity_groups import ( "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go similarity index 97% rename from internal/cmd/beta/affinity-groups/create/create.go rename to internal/cmd/affinity-groups/create/create.go index fb3a3dae7..ab1f48d3a 100644 --- a/internal/cmd/beta/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create an affinity group with name "AFFINITY_GROUP_NAME" and policy "soft-affinity"`, - "$ stackit beta affinity-group create --name AFFINITY_GROUP_NAME --policy soft-affinity", + "$ stackit affinity-group create --name AFFINITY_GROUP_NAME --policy soft-affinity", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/affinity-groups/create/create_test.go b/internal/cmd/affinity-groups/create/create_test.go similarity index 100% rename from internal/cmd/beta/affinity-groups/create/create_test.go rename to internal/cmd/affinity-groups/create/create_test.go diff --git a/internal/cmd/beta/affinity-groups/delete/delete.go b/internal/cmd/affinity-groups/delete/delete.go similarity index 98% rename from internal/cmd/beta/affinity-groups/delete/delete.go rename to internal/cmd/affinity-groups/delete/delete.go index f48dbd6a6..195b4539d 100644 --- a/internal/cmd/beta/affinity-groups/delete/delete.go +++ b/internal/cmd/affinity-groups/delete/delete.go @@ -35,7 +35,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete an affinity group with ID "xxx"`, - "$ stackit beta affinity-group delete xxx", + "$ stackit affinity-group delete xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/affinity-groups/delete/delete_test.go b/internal/cmd/affinity-groups/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/affinity-groups/delete/delete_test.go rename to internal/cmd/affinity-groups/delete/delete_test.go diff --git a/internal/cmd/beta/affinity-groups/describe/describe.go b/internal/cmd/affinity-groups/describe/describe.go similarity index 98% rename from internal/cmd/beta/affinity-groups/describe/describe.go rename to internal/cmd/affinity-groups/describe/describe.go index 197cf1b37..410937fb1 100644 --- a/internal/cmd/beta/affinity-groups/describe/describe.go +++ b/internal/cmd/affinity-groups/describe/describe.go @@ -36,7 +36,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details about an affinity group with the ID "xxx"`, - "$ stackit beta affinity-group describe xxx", + "$ stackit affinity-group describe xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/affinity-groups/describe/describe_test.go b/internal/cmd/affinity-groups/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/affinity-groups/describe/describe_test.go rename to internal/cmd/affinity-groups/describe/describe_test.go diff --git a/internal/cmd/beta/affinity-groups/list/list.go b/internal/cmd/affinity-groups/list/list.go similarity index 97% rename from internal/cmd/beta/affinity-groups/list/list.go rename to internal/cmd/affinity-groups/list/list.go index 260eb787b..3c270bcdb 100644 --- a/internal/cmd/beta/affinity-groups/list/list.go +++ b/internal/cmd/affinity-groups/list/list.go @@ -36,11 +36,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( "Lists all affinity groups", - "$ stackit beta affinity-group list", + "$ stackit affinity-group list", ), examples.NewExample( "Lists up to 10 affinity groups", - "$ stackit beta affinity-group list --limit=10", + "$ stackit affinity-group list --limit=10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/affinity-groups/list/list_test.go b/internal/cmd/affinity-groups/list/list_test.go similarity index 100% rename from internal/cmd/beta/affinity-groups/list/list_test.go rename to internal/cmd/affinity-groups/list/list_test.go diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index d5b30e94a..ed6873b0e 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,18 +3,7 @@ package beta import ( "fmt" - affinityGroups "github.com/stackitcloud/stackit-cli/internal/cmd/beta/affinity-groups" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image" - keypair "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network" - networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area" - networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface" - publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/quota" - securitygroup "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -47,15 +36,4 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(sqlserverflex.NewCmd(p)) - cmd.AddCommand(server.NewCmd(p)) - cmd.AddCommand(networkArea.NewCmd(p)) - cmd.AddCommand(network.NewCmd(p)) - cmd.AddCommand(volume.NewCmd(p)) - cmd.AddCommand(networkinterface.NewCmd(p)) - cmd.AddCommand(publicip.NewCmd(p)) - cmd.AddCommand(securitygroup.NewCmd(p)) - cmd.AddCommand(keypair.NewCmd(p)) - cmd.AddCommand(image.NewCmd(p)) - cmd.AddCommand(quota.NewCmd(p)) - cmd.AddCommand(affinityGroups.NewCmd(p)) } diff --git a/internal/cmd/beta/server/server.go b/internal/cmd/beta/server/server.go deleted file mode 100644 index 888ed703a..000000000 --- a/internal/cmd/beta/server/server.go +++ /dev/null @@ -1,69 +0,0 @@ -package server - -import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/console" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/deallocate" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/log" - machinetype "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/machine-type" - networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface" - osUpdate "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update" - publicip "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/reboot" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/rescue" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/resize" - serviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/start" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/stop" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/unrescue" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume" - - "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/cobra" -) - -func NewCmd(p *print.Printer) *cobra.Command { - cmd := &cobra.Command{ - Use: "server", - Short: "Provides functionality for servers", - Long: "Provides functionality for servers.", - Args: args.NoArgs, - Run: utils.CmdHelp, - } - addSubcommands(cmd, p) - return cmd -} - -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(backup.NewCmd(p)) - cmd.AddCommand(command.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(publicip.NewCmd(p)) - cmd.AddCommand(serviceaccount.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(volume.NewCmd(p)) - cmd.AddCommand(networkinterface.NewCmd(p)) - cmd.AddCommand(console.NewCmd(p)) - cmd.AddCommand(log.NewCmd(p)) - cmd.AddCommand(start.NewCmd(p)) - cmd.AddCommand(stop.NewCmd(p)) - cmd.AddCommand(reboot.NewCmd(p)) - cmd.AddCommand(deallocate.NewCmd(p)) - cmd.AddCommand(resize.NewCmd(p)) - cmd.AddCommand(rescue.NewCmd(p)) - cmd.AddCommand(unrescue.NewCmd(p)) - cmd.AddCommand(osUpdate.NewCmd(p)) - cmd.AddCommand(machinetype.NewCmd(p)) -} diff --git a/internal/cmd/beta/image/create/create.go b/internal/cmd/image/create/create.go similarity index 98% rename from internal/cmd/beta/image/create/create.go rename to internal/cmd/image/create/create.go index 149aae01e..5fd2e86f2 100644 --- a/internal/cmd/beta/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -90,11 +90,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create an image with name 'my-new-image' from a raw disk image located in '/my/raw/image'`, - `$ stackit beta image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image`, + `$ stackit image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image`, ), examples.NewExample( `Create an image with name 'my-new-image' from a qcow2 image read from '/my/qcow2/image' with labels describing its contents`, - `$ stackit beta image create --name my-new-image --disk-format=qcow2 --local-file-path=/my/qcow2/image --labels os=linux,distro=alpine,version=3.12`, + `$ stackit image create --name my-new-image --disk-format=qcow2 --local-file-path=/my/qcow2/image --labels os=linux,distro=alpine,version=3.12`, ), ), RunE: func(cmd *cobra.Command, _ []string) (err error) { diff --git a/internal/cmd/beta/image/create/create_test.go b/internal/cmd/image/create/create_test.go similarity index 100% rename from internal/cmd/beta/image/create/create_test.go rename to internal/cmd/image/create/create_test.go diff --git a/internal/cmd/beta/image/delete/delete.go b/internal/cmd/image/delete/delete.go similarity index 99% rename from internal/cmd/beta/image/delete/delete.go rename to internal/cmd/image/delete/delete.go index 609ced9ec..57ae4f026 100644 --- a/internal/cmd/beta/image/delete/delete.go +++ b/internal/cmd/image/delete/delete.go @@ -31,7 +31,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Long: "Deletes an image by its internal ID.", Args: args.SingleArg(imageIdArg, utils.ValidateUUID), Example: examples.Build( - examples.NewExample(`Delete an image with ID "xxx"`, `$ stackit beta image delete xxx`), + examples.NewExample(`Delete an image with ID "xxx"`, `$ stackit image delete xxx`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/image/delete/delete_test.go b/internal/cmd/image/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/image/delete/delete_test.go rename to internal/cmd/image/delete/delete_test.go diff --git a/internal/cmd/beta/image/describe/describe.go b/internal/cmd/image/describe/describe.go similarity index 98% rename from internal/cmd/beta/image/describe/describe.go rename to internal/cmd/image/describe/describe.go index 8c8b27023..20ab802fc 100644 --- a/internal/cmd/beta/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -33,7 +33,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Long: "Describes an image by its internal ID.", Args: args.SingleArg(imageIdArg, utils.ValidateUUID), Example: examples.Build( - examples.NewExample(`Describe image "xxx"`, `$ stackit beta image describe xxx`), + examples.NewExample(`Describe image "xxx"`, `$ stackit image describe xxx`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/image/describe/describe_test.go b/internal/cmd/image/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/image/describe/describe_test.go rename to internal/cmd/image/describe/describe_test.go diff --git a/internal/cmd/beta/image/image.go b/internal/cmd/image/image.go similarity index 65% rename from internal/cmd/beta/image/image.go rename to internal/cmd/image/image.go index c84ef1430..899a62ce9 100644 --- a/internal/cmd/beta/image/image.go +++ b/internal/cmd/image/image.go @@ -1,11 +1,11 @@ package image import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/image/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/image/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/image/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/image/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/image/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/image/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" diff --git a/internal/cmd/beta/image/list/list.go b/internal/cmd/image/list/list.go similarity index 97% rename from internal/cmd/beta/image/list/list.go rename to internal/cmd/image/list/list.go index 035771d89..32316eae0 100644 --- a/internal/cmd/beta/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -40,15 +40,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all images`, - `$ stackit beta image list`, + `$ stackit image list`, ), examples.NewExample( `List images with label`, - `$ stackit beta image list --label-selector ARM64,dev`, + `$ stackit image list --label-selector ARM64,dev`, ), examples.NewExample( `List the first 10 images`, - `$ stackit beta image list --limit=10`, + `$ stackit image list --limit=10`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/image/list/list_test.go b/internal/cmd/image/list/list_test.go similarity index 100% rename from internal/cmd/beta/image/list/list_test.go rename to internal/cmd/image/list/list_test.go diff --git a/internal/cmd/beta/image/update/update.go b/internal/cmd/image/update/update.go similarity index 98% rename from internal/cmd/beta/image/update/update.go rename to internal/cmd/image/update/update.go index 9a4603882..8e6a8a2dd 100644 --- a/internal/cmd/beta/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -108,8 +108,8 @@ func NewCmd(p *print.Printer) *cobra.Command { Long: "Updates an image", Args: args.SingleArg(imageIdArg, utils.ValidateUUID), Example: examples.Build( - examples.NewExample(`Update the name of an image with ID "xxx"`, `$ stackit beta image update xxx --name my-new-name`), - examples.NewExample(`Update the labels of an image with ID "xxx"`, `$ stackit beta image update xxx --labels label1=value1,label2=value2`), + examples.NewExample(`Update the name of an image with ID "xxx"`, `$ stackit image update xxx --name my-new-name`), + examples.NewExample(`Update the labels of an image with ID "xxx"`, `$ stackit image update xxx --labels label1=value1,label2=value2`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/image/update/update_test.go b/internal/cmd/image/update/update_test.go similarity index 100% rename from internal/cmd/beta/image/update/update_test.go rename to internal/cmd/image/update/update_test.go diff --git a/internal/cmd/beta/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go similarity index 93% rename from internal/cmd/beta/key-pair/create/create.go rename to internal/cmd/key-pair/create/create.go index a69d75505..0c96810ba 100644 --- a/internal/cmd/beta/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -39,19 +39,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a new key pair with public-key "ssh-rsa xxx"`, - "$ stackit beta key-pair create --public-key `ssh-rsa xxx`", + "$ stackit key-pair create --public-key `ssh-rsa xxx`", ), examples.NewExample( `Create a new key pair with public-key from file "/Users/username/.ssh/id_rsa.pub"`, - "$ stackit beta key-pair create --public-key `@/Users/username/.ssh/id_rsa.pub`", + "$ stackit key-pair create --public-key `@/Users/username/.ssh/id_rsa.pub`", ), examples.NewExample( `Create a new key pair with name "KEY_PAIR_NAME" and public-key "ssh-rsa yyy"`, - "$ stackit beta key-pair create --name KEY_PAIR_NAME --public-key `ssh-rsa yyy`", + "$ stackit key-pair create --name KEY_PAIR_NAME --public-key `ssh-rsa yyy`", ), examples.NewExample( `Create a new key pair with public-key "ssh-rsa xxx" and labels "key=value,key1=value1"`, - "$ stackit beta key-pair create --public-key `ssh-rsa xxx` --labels key=value,key1=value1", + "$ stackit key-pair create --public-key `ssh-rsa xxx` --labels key=value,key1=value1", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/key-pair/create/create_test.go b/internal/cmd/key-pair/create/create_test.go similarity index 100% rename from internal/cmd/beta/key-pair/create/create_test.go rename to internal/cmd/key-pair/create/create_test.go diff --git a/internal/cmd/beta/key-pair/create/template/id_ed25519.pub b/internal/cmd/key-pair/create/template/id_ed25519.pub similarity index 100% rename from internal/cmd/beta/key-pair/create/template/id_ed25519.pub rename to internal/cmd/key-pair/create/template/id_ed25519.pub diff --git a/internal/cmd/beta/key-pair/delete/delete.go b/internal/cmd/key-pair/delete/delete.go similarity index 97% rename from internal/cmd/beta/key-pair/delete/delete.go rename to internal/cmd/key-pair/delete/delete.go index e1144dd5d..ba9b5a9ce 100644 --- a/internal/cmd/beta/key-pair/delete/delete.go +++ b/internal/cmd/key-pair/delete/delete.go @@ -32,7 +32,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete key pair with name "KEY_PAIR_NAME"`, - "$ stackit beta key-pair delete KEY_PAIR_NAME", + "$ stackit key-pair delete KEY_PAIR_NAME", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/key-pair/delete/delete_test.go b/internal/cmd/key-pair/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/key-pair/delete/delete_test.go rename to internal/cmd/key-pair/delete/delete_test.go diff --git a/internal/cmd/beta/key-pair/describe/describe.go b/internal/cmd/key-pair/describe/describe.go similarity index 97% rename from internal/cmd/beta/key-pair/describe/describe.go rename to internal/cmd/key-pair/describe/describe.go index b9efb0907..f4ee01f94 100644 --- a/internal/cmd/beta/key-pair/describe/describe.go +++ b/internal/cmd/key-pair/describe/describe.go @@ -44,11 +44,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details about a key pair with name "KEY_PAIR_NAME"`, - "$ stackit beta key-pair describe KEY_PAIR_NAME", + "$ stackit key-pair describe KEY_PAIR_NAME", ), examples.NewExample( `Get only the SSH public key of a key pair with name "KEY_PAIR_NAME"`, - "$ stackit beta key-pair describe KEY_PAIR_NAME --public-key", + "$ stackit key-pair describe KEY_PAIR_NAME --public-key", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/key-pair/describe/describe_test.go b/internal/cmd/key-pair/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/key-pair/describe/describe_test.go rename to internal/cmd/key-pair/describe/describe_test.go diff --git a/internal/cmd/beta/key-pair/key-pair.go b/internal/cmd/key-pair/key-pair.go similarity index 65% rename from internal/cmd/beta/key-pair/key-pair.go rename to internal/cmd/key-pair/key-pair.go index d8e6f91aa..90bbd648b 100644 --- a/internal/cmd/beta/key-pair/key-pair.go +++ b/internal/cmd/key-pair/key-pair.go @@ -3,11 +3,11 @@ package keypair import ( "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/key-pair/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/update" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) diff --git a/internal/cmd/beta/key-pair/list/list.go b/internal/cmd/key-pair/list/list.go similarity index 95% rename from internal/cmd/beta/key-pair/list/list.go rename to internal/cmd/key-pair/list/list.go index 9a1c9c624..8685edb36 100644 --- a/internal/cmd/beta/key-pair/list/list.go +++ b/internal/cmd/key-pair/list/list.go @@ -42,19 +42,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all key pairs`, - "$ stackit beta key-pair list", + "$ stackit key-pair list", ), examples.NewExample( `Lists all key pairs which contains the label xxx`, - "$ stackit beta key-pair list --label-selector xxx", + "$ stackit key-pair list --label-selector xxx", ), examples.NewExample( `Lists all key pairs in JSON format`, - "$ stackit beta key-pair list --output-format json", + "$ stackit key-pair list --output-format json", ), examples.NewExample( `Lists up to 10 key pairs`, - "$ stackit beta key-pair list --limit 10", + "$ stackit key-pair list --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/key-pair/list/list_test.go b/internal/cmd/key-pair/list/list_test.go similarity index 100% rename from internal/cmd/beta/key-pair/list/list_test.go rename to internal/cmd/key-pair/list/list_test.go diff --git a/internal/cmd/beta/key-pair/update/update.go b/internal/cmd/key-pair/update/update.go similarity index 98% rename from internal/cmd/beta/key-pair/update/update.go rename to internal/cmd/key-pair/update/update.go index 90cf02e07..1a64875b5 100644 --- a/internal/cmd/beta/key-pair/update/update.go +++ b/internal/cmd/key-pair/update/update.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update the labels of a key pair with name "KEY_PAIR_NAME" with "key=value,key1=value1"`, - "$ stackit beta key-pair update KEY_PAIR_NAME --labels key=value,key1=value1", + "$ stackit key-pair update KEY_PAIR_NAME --labels key=value,key1=value1", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/key-pair/update/update_test.go b/internal/cmd/key-pair/update/update_test.go similarity index 100% rename from internal/cmd/beta/key-pair/update/update_test.go rename to internal/cmd/key-pair/update/update_test.go diff --git a/internal/cmd/beta/network-area/create/create.go b/internal/cmd/network-area/create/create.go similarity index 90% rename from internal/cmd/beta/network-area/create/create.go rename to internal/cmd/network-area/create/create.go index 3c348908f..4ce917af7 100644 --- a/internal/cmd/beta/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -54,19 +54,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network`, - `$ stackit beta network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24"`, + `$ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24"`, ), examples.NewExample( `Create a network area with name "network-area-2" in organization with ID "xxx" with network ranges, transfer network and DNS name server`, - `$ stackit beta network-area create --name network-area-2 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --dns-name-servers "1.1.1.1"`, + `$ stackit network-area create --name network-area-2 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --dns-name-servers "1.1.1.1"`, ), examples.NewExample( `Create a network area with name "network-area-3" in organization with ID "xxx" with network ranges, transfer network and additional options`, - `$ stackit beta network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24`, + `$ stackit network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24`, ), examples.NewExample( `Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network and labels "key=value,key1=value1"`, - `$ stackit beta network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1`, + `$ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network-area/create/create_test.go b/internal/cmd/network-area/create/create_test.go similarity index 100% rename from internal/cmd/beta/network-area/create/create_test.go rename to internal/cmd/network-area/create/create_test.go diff --git a/internal/cmd/beta/network-area/delete/delete.go b/internal/cmd/network-area/delete/delete.go similarity index 98% rename from internal/cmd/beta/network-area/delete/delete.go rename to internal/cmd/network-area/delete/delete.go index 3952efc42..d617d8496 100644 --- a/internal/cmd/beta/network-area/delete/delete.go +++ b/internal/cmd/network-area/delete/delete.go @@ -42,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete network area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area delete xxx --organization-id yyy", + "$ stackit network-area delete xxx --organization-id yyy", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/delete/delete_test.go b/internal/cmd/network-area/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/network-area/delete/delete_test.go rename to internal/cmd/network-area/delete/delete_test.go diff --git a/internal/cmd/beta/network-area/describe/describe.go b/internal/cmd/network-area/describe/describe.go similarity index 96% rename from internal/cmd/beta/network-area/describe/describe.go rename to internal/cmd/network-area/describe/describe.go index 22cc7018e..35be06f3c 100644 --- a/internal/cmd/beta/network-area/describe/describe.go +++ b/internal/cmd/network-area/describe/describe.go @@ -43,15 +43,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a network area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area describe xxx --organization-id yyy", + "$ stackit network-area describe xxx --organization-id yyy", ), examples.NewExample( `Show details of a network area with ID "xxx" in organization with ID "yyy" and show attached projects`, - "$ stackit beta network-area describe xxx --organization-id yyy --show-attached-projects", + "$ stackit network-area describe xxx --organization-id yyy --show-attached-projects", ), examples.NewExample( `Show details of a network area with ID "xxx" in organization with ID "yyy" in JSON format`, - "$ stackit beta network-area describe xxx --organization-id yyy --output-format json", + "$ stackit network-area describe xxx --organization-id yyy --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/describe/describe_test.go b/internal/cmd/network-area/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/network-area/describe/describe_test.go rename to internal/cmd/network-area/describe/describe_test.go diff --git a/internal/cmd/beta/network-area/list/list.go b/internal/cmd/network-area/list/list.go similarity index 95% rename from internal/cmd/beta/network-area/list/list.go rename to internal/cmd/network-area/list/list.go index fef600ab3..4e112ae53 100644 --- a/internal/cmd/beta/network-area/list/list.go +++ b/internal/cmd/network-area/list/list.go @@ -43,19 +43,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all network areas of organization "xxx"`, - "$ stackit beta network-area list --organization-id xxx", + "$ stackit network-area list --organization-id xxx", ), examples.NewExample( `Lists all network areas of organization "xxx" in JSON format`, - "$ stackit beta network-area list --organization-id xxx --output-format json", + "$ stackit network-area list --organization-id xxx --output-format json", ), examples.NewExample( `Lists up to 10 network areas of organization "xxx"`, - "$ stackit beta network-area list --organization-id xxx --limit 10", + "$ stackit network-area list --organization-id xxx --limit 10", ), examples.NewExample( `Lists all network areas of organization "xxx" which contains the label yyy`, - "$ stackit beta network-area list --organization-id xxx --label-selector yyy", + "$ stackit network-area list --organization-id xxx --label-selector yyy", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network-area/list/list_test.go b/internal/cmd/network-area/list/list_test.go similarity index 100% rename from internal/cmd/beta/network-area/list/list_test.go rename to internal/cmd/network-area/list/list_test.go diff --git a/internal/cmd/beta/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go similarity index 97% rename from internal/cmd/beta/network-area/network-range/create/create.go rename to internal/cmd/network-area/network-range/create/create.go index 297ee0e7f..98fa25a60 100644 --- a/internal/cmd/beta/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -41,7 +41,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a network range in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - `$ stackit beta network-area network-range create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24"`, + `$ stackit network-area network-range create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24"`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network-area/network-range/create/create_test.go b/internal/cmd/network-area/network-range/create/create_test.go similarity index 100% rename from internal/cmd/beta/network-area/network-range/create/create_test.go rename to internal/cmd/network-area/network-range/create/create_test.go diff --git a/internal/cmd/beta/network-area/network-range/delete/delete.go b/internal/cmd/network-area/network-range/delete/delete.go similarity index 97% rename from internal/cmd/beta/network-area/network-range/delete/delete.go rename to internal/cmd/network-area/network-range/delete/delete.go index b7740dd9e..4b4ab2eda 100644 --- a/internal/cmd/beta/network-area/network-range/delete/delete.go +++ b/internal/cmd/network-area/network-range/delete/delete.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete network range with id "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - `$ stackit beta network-area network-range delete xxx --network-area-id yyy --organization-id zzz`, + `$ stackit network-area network-range delete xxx --network-area-id yyy --organization-id zzz`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/network-range/delete/delete_test.go b/internal/cmd/network-area/network-range/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/network-area/network-range/delete/delete_test.go rename to internal/cmd/network-area/network-range/delete/delete_test.go diff --git a/internal/cmd/beta/network-area/network-range/describe/describe.go b/internal/cmd/network-area/network-range/describe/describe.go similarity index 97% rename from internal/cmd/beta/network-area/network-range/describe/describe.go rename to internal/cmd/network-area/network-range/describe/describe.go index a4c57f7eb..9f35dc145 100644 --- a/internal/cmd/beta/network-area/network-range/describe/describe.go +++ b/internal/cmd/network-area/network-range/describe/describe.go @@ -42,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a network range with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - `$ stackit beta network-area network-range describe xxx --network-area-id yyy --organization-id zzz`, + `$ stackit network-area network-range describe xxx --network-area-id yyy --organization-id zzz`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/network-range/describe/describe_test.go b/internal/cmd/network-area/network-range/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/network-area/network-range/describe/describe_test.go rename to internal/cmd/network-area/network-range/describe/describe_test.go diff --git a/internal/cmd/beta/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go similarity index 94% rename from internal/cmd/beta/network-area/network-range/list/list.go rename to internal/cmd/network-area/network-range/list/list.go index faace6c9c..b9b11d0e2 100644 --- a/internal/cmd/beta/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -43,15 +43,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy", + "$ stackit network-area network-range list --network-area-id xxx --organization-id yyy", ), examples.NewExample( `Lists all network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format`, - "$ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --output-format json", + "$ stackit network-area network-range list --network-area-id xxx --organization-id yyy --output-format json", ), examples.NewExample( `Lists up to 10 network ranges in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area network-range list --network-area-id xxx --organization-id yyy --limit 10", + "$ stackit network-area network-range list --network-area-id xxx --organization-id yyy --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network-area/network-range/list/list_test.go b/internal/cmd/network-area/network-range/list/list_test.go similarity index 100% rename from internal/cmd/beta/network-area/network-range/list/list_test.go rename to internal/cmd/network-area/network-range/list/list_test.go diff --git a/internal/cmd/beta/network-area/network-range/network_range.go b/internal/cmd/network-area/network-range/network_range.go similarity index 69% rename from internal/cmd/beta/network-area/network-range/network_range.go rename to internal/cmd/network-area/network-range/network_range.go index 889cc75a2..71c849f17 100644 --- a/internal/cmd/beta/network-area/network-range/network_range.go +++ b/internal/cmd/network-area/network-range/network_range.go @@ -1,10 +1,10 @@ package networkranges import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/network-area/network_area.go b/internal/cmd/network-area/network_area.go similarity index 65% rename from internal/cmd/beta/network-area/network_area.go rename to internal/cmd/network-area/network_area.go index fd0bdd739..ef12c22a8 100644 --- a/internal/cmd/beta/network-area/network_area.go +++ b/internal/cmd/network-area/network_area.go @@ -1,13 +1,13 @@ package networkarea import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/list" - networkrange "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/network-range" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/list" + networkrange "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go similarity index 95% rename from internal/cmd/beta/network-area/route/create/create.go rename to internal/cmd/network-area/route/create/create.go index d73c337c3..05a881052 100644 --- a/internal/cmd/beta/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -48,11 +48,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", + "$ stackit network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", ), examples.NewExample( `Create a static route with labels "key:value" and "foo:bar" with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", + "$ stackit network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network-area/route/create/create_test.go b/internal/cmd/network-area/route/create/create_test.go similarity index 100% rename from internal/cmd/beta/network-area/route/create/create_test.go rename to internal/cmd/network-area/route/create/create_test.go diff --git a/internal/cmd/beta/network-area/route/delete/delete.go b/internal/cmd/network-area/route/delete/delete.go similarity index 97% rename from internal/cmd/beta/network-area/route/delete/delete.go rename to internal/cmd/network-area/route/delete/delete.go index 0626c67a6..144647440 100644 --- a/internal/cmd/beta/network-area/route/delete/delete.go +++ b/internal/cmd/network-area/route/delete/delete.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - "$ stackit beta network-area route delete xxx --organization-id zzz --network-area-id yyy", + "$ stackit network-area route delete xxx --organization-id zzz --network-area-id yyy", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/route/delete/delete_test.go b/internal/cmd/network-area/route/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/network-area/route/delete/delete_test.go rename to internal/cmd/network-area/route/delete/delete_test.go diff --git a/internal/cmd/beta/network-area/route/describe/describe.go b/internal/cmd/network-area/route/describe/describe.go similarity index 95% rename from internal/cmd/beta/network-area/route/describe/describe.go rename to internal/cmd/network-area/route/describe/describe.go index fa03a07b2..8708f12e1 100644 --- a/internal/cmd/beta/network-area/route/describe/describe.go +++ b/internal/cmd/network-area/route/describe/describe.go @@ -43,11 +43,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - `$ stackit beta network-area route describe xxx --network-area-id yyy --organization-id zzz`, + `$ stackit network-area route describe xxx --network-area-id yyy --organization-id zzz`, ), examples.NewExample( `Show details of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz" in JSON format`, - `$ stackit beta network-area route describe xxx --network-area-id yyy --organization-id zzz --output-format json`, + `$ stackit network-area route describe xxx --network-area-id yyy --organization-id zzz --output-format json`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/route/describe/describe_test.go b/internal/cmd/network-area/route/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/network-area/route/describe/describe_test.go rename to internal/cmd/network-area/route/describe/describe_test.go diff --git a/internal/cmd/beta/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go similarity index 94% rename from internal/cmd/beta/network-area/route/list/list.go rename to internal/cmd/network-area/route/list/list.go index c7e4f46f0..f8bada766 100644 --- a/internal/cmd/beta/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -42,15 +42,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area route list --network-area-id xxx --organization-id yyy", + "$ stackit network-area route list --network-area-id xxx --organization-id yyy", ), examples.NewExample( `Lists all static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" in JSON format`, - "$ stackit beta network-area route list --network-area-id xxx --organization-id yyy --output-format json", + "$ stackit network-area route list --network-area-id xxx --organization-id yyy --output-format json", ), examples.NewExample( `Lists up to 10 static routes in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit beta network-area route list --network-area-id xxx --organization-id yyy --limit 10", + "$ stackit network-area route list --network-area-id xxx --organization-id yyy --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network-area/route/list/list_test.go b/internal/cmd/network-area/route/list/list_test.go similarity index 100% rename from internal/cmd/beta/network-area/route/list/list_test.go rename to internal/cmd/network-area/route/list/list_test.go diff --git a/internal/cmd/beta/network-area/route/routes.go b/internal/cmd/network-area/route/routes.go similarity index 65% rename from internal/cmd/beta/network-area/route/routes.go rename to internal/cmd/network-area/route/routes.go index 1125d4d70..20fa115dd 100644 --- a/internal/cmd/beta/network-area/route/routes.go +++ b/internal/cmd/network-area/route/routes.go @@ -1,11 +1,11 @@ package route import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go similarity index 97% rename from internal/cmd/beta/network-area/route/update/update.go rename to internal/cmd/network-area/route/update/update.go index e378cdcf4..b97c9b44d 100644 --- a/internal/cmd/beta/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -48,7 +48,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Updates the label(s) of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`, - "$ stackit beta network-area route update xxx --labels key=value,foo=bar --organization-id yyy --network-area-id zzz", + "$ stackit network-area route update xxx --labels key=value,foo=bar --organization-id yyy --network-area-id zzz", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/route/update/update_test.go b/internal/cmd/network-area/route/update/update_test.go similarity index 100% rename from internal/cmd/beta/network-area/route/update/update_test.go rename to internal/cmd/network-area/route/update/update_test.go diff --git a/internal/cmd/beta/network-area/update/update.go b/internal/cmd/network-area/update/update.go similarity index 98% rename from internal/cmd/beta/network-area/update/update.go rename to internal/cmd/network-area/update/update.go index 9aab1f1d9..3a0c4f6f7 100644 --- a/internal/cmd/beta/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update network area with ID "xxx" in organization with ID "yyy" with new name "network-area-1-new"`, - "$ stackit beta network-area update xxx --organization-id yyy --name network-area-1-new", + "$ stackit network-area update xxx --organization-id yyy --name network-area-1-new", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-area/update/update_test.go b/internal/cmd/network-area/update/update_test.go similarity index 100% rename from internal/cmd/beta/network-area/update/update_test.go rename to internal/cmd/network-area/update/update_test.go diff --git a/internal/cmd/beta/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go similarity index 97% rename from internal/cmd/beta/network-interface/create/create.go rename to internal/cmd/network-interface/create/create.go index eb6bb301b..a14e57b1e 100644 --- a/internal/cmd/beta/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -58,11 +58,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a network interface for network with ID "xxx"`, - `$ stackit beta network-interface create --network-id xxx`, + `$ stackit network-interface create --network-id xxx`, ), examples.NewExample( `Create a network interface with allowed addresses, labels, a name, security groups and nic security enabled for network with ID "xxx"`, - `$ stackit beta network-interface create --network-id xxx --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 --name NAME --security-groups "UUID1,UUID2" --nic-security`, + `$ stackit network-interface create --network-id xxx --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 --name NAME --security-groups "UUID1,UUID2" --nic-security`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network-interface/create/create_test.go b/internal/cmd/network-interface/create/create_test.go similarity index 100% rename from internal/cmd/beta/network-interface/create/create_test.go rename to internal/cmd/network-interface/create/create_test.go diff --git a/internal/cmd/beta/network-interface/delete/delete.go b/internal/cmd/network-interface/delete/delete.go similarity index 97% rename from internal/cmd/beta/network-interface/delete/delete.go rename to internal/cmd/network-interface/delete/delete.go index 2597e9402..4f2cd3302 100644 --- a/internal/cmd/beta/network-interface/delete/delete.go +++ b/internal/cmd/network-interface/delete/delete.go @@ -36,7 +36,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete network interface with nic id "xxx" and network ID "yyy"`, - `$ stackit beta network-interface delete xxx --network-id yyy`, + `$ stackit network-interface delete xxx --network-id yyy`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-interface/delete/delete_test.go b/internal/cmd/network-interface/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/network-interface/delete/delete_test.go rename to internal/cmd/network-interface/delete/delete_test.go diff --git a/internal/cmd/beta/network-interface/describe/describe.go b/internal/cmd/network-interface/describe/describe.go similarity index 95% rename from internal/cmd/beta/network-interface/describe/describe.go rename to internal/cmd/network-interface/describe/describe.go index a1d741bdf..89b04b9b3 100644 --- a/internal/cmd/beta/network-interface/describe/describe.go +++ b/internal/cmd/network-interface/describe/describe.go @@ -41,15 +41,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Describes network interface with nic id "xxx" and network ID "yyy"`, - `$ stackit beta network-interface describe xxx --network-id yyy`, + `$ stackit network-interface describe xxx --network-id yyy`, ), examples.NewExample( `Describes network interface with nic id "xxx" and network ID "yyy" in JSON format`, - `$ stackit beta network-interface describe xxx --network-id yyy --output-format json`, + `$ stackit network-interface describe xxx --network-id yyy --output-format json`, ), examples.NewExample( `Describes network interface with nic id "xxx" and network ID "yyy" in yaml format`, - `$ stackit beta network-interface describe xxx --network-id yyy --output-format yaml`, + `$ stackit network-interface describe xxx --network-id yyy --output-format yaml`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-interface/describe/describe_test.go b/internal/cmd/network-interface/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/network-interface/describe/describe_test.go rename to internal/cmd/network-interface/describe/describe_test.go diff --git a/internal/cmd/beta/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go similarity index 94% rename from internal/cmd/beta/network-interface/list/list.go rename to internal/cmd/network-interface/list/list.go index b4925b7a5..9ee88cd2f 100644 --- a/internal/cmd/beta/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -42,19 +42,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all network interfaces with network ID "xxx"`, - `$ stackit beta network-interface list --network-id xxx`, + `$ stackit network-interface list --network-id xxx`, ), examples.NewExample( `Lists all network interfaces with network ID "xxx" which contains the label xxx`, - `$ stackit beta network-interface list --network-id xxx --label-selector xxx`, + `$ stackit network-interface list --network-id xxx --label-selector xxx`, ), examples.NewExample( `Lists all network interfaces with network ID "xxx" in JSON format`, - `$ stackit beta network-interface list --network-id xxx --output-format json`, + `$ stackit network-interface list --network-id xxx --output-format json`, ), examples.NewExample( `Lists up to 10 network interfaces with network ID "xxx"`, - `$ stackit beta network-interface list --network-id xxx --limit 10`, + `$ stackit network-interface list --network-id xxx --limit 10`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network-interface/list/list_test.go b/internal/cmd/network-interface/list/list_test.go similarity index 100% rename from internal/cmd/beta/network-interface/list/list_test.go rename to internal/cmd/network-interface/list/list_test.go diff --git a/internal/cmd/beta/network-interface/network-interface.go b/internal/cmd/network-interface/network-interface.go similarity index 65% rename from internal/cmd/beta/network-interface/network-interface.go rename to internal/cmd/network-interface/network-interface.go index b67392d43..cada28596 100644 --- a/internal/cmd/beta/network-interface/network-interface.go +++ b/internal/cmd/network-interface/network-interface.go @@ -2,11 +2,11 @@ package networkinterface import ( "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-interface/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go similarity index 96% rename from internal/cmd/beta/network-interface/update/update.go rename to internal/cmd/network-interface/update/update.go index 9e7c12022..777f2f4b4 100644 --- a/internal/cmd/beta/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -56,15 +56,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Updates a network interface with nic id "xxx" and network-id "yyy" to new allowed addresses "1.1.1.1,8.8.8.8,9.9.9.9" and new labels "key=value,key2=value2"`, - `$ stackit beta network-interface update xxx --network-id yyy --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2`, + `$ stackit network-interface update xxx --network-id yyy --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2`, ), examples.NewExample( `Updates a network interface with nic id "xxx" and network-id "yyy" with new name "nic-name-new"`, - `$ stackit beta network-interface update xxx --network-id yyy --name nic-name-new`, + `$ stackit network-interface update xxx --network-id yyy --name nic-name-new`, ), examples.NewExample( `Updates a network interface with nic id "xxx" and network-id "yyy" to include the security group "zzz"`, - `$ stackit beta network-interface update xxx --network-id yyy --security-groups zzz`, + `$ stackit network-interface update xxx --network-id yyy --security-groups zzz`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network-interface/update/update_test.go b/internal/cmd/network-interface/update/update_test.go similarity index 100% rename from internal/cmd/beta/network-interface/update/update_test.go rename to internal/cmd/network-interface/update/update_test.go diff --git a/internal/cmd/beta/network/create/create.go b/internal/cmd/network/create/create.go similarity index 94% rename from internal/cmd/beta/network/create/create.go rename to internal/cmd/network/create/create.go index 38edf55ac..b89f54f49 100644 --- a/internal/cmd/beta/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -64,27 +64,27 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a network with name "network-1"`, - `$ stackit beta network create --name network-1`, + `$ stackit network create --name network-1`, ), examples.NewExample( `Create a non-routed network with name "network-1"`, - `$ stackit beta network create --name network-1 --non-routed`, + `$ stackit network create --name network-1 --non-routed`, ), examples.NewExample( `Create a network with name "network-1" and no gateway`, - `$ stackit beta network create --name network-1 --no-ipv4-gateway`, + `$ stackit network create --name network-1 --no-ipv4-gateway`, ), examples.NewExample( `Create a network with name "network-1" and labels "key=value,key1=value1"`, - `$ stackit beta network create --name network-1 --labels key=value,key1=value1`, + `$ stackit network create --name network-1 --labels key=value,key1=value1`, ), examples.NewExample( `Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway`, - `$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3"`, + `$ stackit network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3"`, ), examples.NewExample( `Create an IPv6 network with name "network-1" with DNS name servers, a prefix and a gateway`, - `$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"`, + `$ stackit network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network/create/create_test.go b/internal/cmd/network/create/create_test.go similarity index 100% rename from internal/cmd/beta/network/create/create_test.go rename to internal/cmd/network/create/create_test.go diff --git a/internal/cmd/beta/network/delete/delete.go b/internal/cmd/network/delete/delete.go similarity index 98% rename from internal/cmd/beta/network/delete/delete.go rename to internal/cmd/network/delete/delete.go index 17be9f0ed..c1608151e 100644 --- a/internal/cmd/beta/network/delete/delete.go +++ b/internal/cmd/network/delete/delete.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete network with ID "xxx"`, - "$ stackit beta network delete xxx", + "$ stackit network delete xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network/delete/delete_test.go b/internal/cmd/network/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/network/delete/delete_test.go rename to internal/cmd/network/delete/delete_test.go diff --git a/internal/cmd/beta/network/describe/describe.go b/internal/cmd/network/describe/describe.go similarity index 98% rename from internal/cmd/beta/network/describe/describe.go rename to internal/cmd/network/describe/describe.go index e98cd01e6..13eb11133 100644 --- a/internal/cmd/beta/network/describe/describe.go +++ b/internal/cmd/network/describe/describe.go @@ -38,11 +38,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a network with ID "xxx"`, - "$ stackit beta network describe xxx", + "$ stackit network describe xxx", ), examples.NewExample( `Show details of a network with ID "xxx" in JSON format`, - "$ stackit beta network describe xxx --output-format json", + "$ stackit network describe xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network/describe/describe_test.go b/internal/cmd/network/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/network/describe/describe_test.go rename to internal/cmd/network/describe/describe_test.go diff --git a/internal/cmd/beta/network/list/list.go b/internal/cmd/network/list/list.go similarity index 96% rename from internal/cmd/beta/network/list/list.go rename to internal/cmd/network/list/list.go index 7ed81d62c..8b5577685 100644 --- a/internal/cmd/beta/network/list/list.go +++ b/internal/cmd/network/list/list.go @@ -41,19 +41,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all networks`, - "$ stackit beta network list", + "$ stackit network list", ), examples.NewExample( `Lists all networks in JSON format`, - "$ stackit beta network list --output-format json", + "$ stackit network list --output-format json", ), examples.NewExample( `Lists up to 10 networks`, - "$ stackit beta network list --limit 10", + "$ stackit network list --limit 10", ), examples.NewExample( `Lists all networks which contains the label xxx`, - "$ tackit beta network list --label-selector xxx", + "$ stackit network list --label-selector xxx", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/network/list/list_test.go b/internal/cmd/network/list/list_test.go similarity index 100% rename from internal/cmd/beta/network/list/list_test.go rename to internal/cmd/network/list/list_test.go diff --git a/internal/cmd/beta/network/network.go b/internal/cmd/network/network.go similarity index 67% rename from internal/cmd/beta/network/network.go rename to internal/cmd/network/network.go index 30197e2ed..b95a496c7 100644 --- a/internal/cmd/beta/network/network.go +++ b/internal/cmd/network/network.go @@ -1,11 +1,11 @@ package network import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/network/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/network/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/network/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/network/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/network/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/network/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/network/update/update.go b/internal/cmd/network/update/update.go similarity index 95% rename from internal/cmd/beta/network/update/update.go rename to internal/cmd/network/update/update.go index 24c1c5e74..50be6c698 100644 --- a/internal/cmd/beta/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -55,19 +55,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update network with ID "xxx" with new name "network-1-new"`, - `$ stackit beta network update xxx --name network-1-new`, + `$ stackit network update xxx --name network-1-new`, ), examples.NewExample( `Update network with ID "xxx" with no gateway`, - `$ stackit beta network update --no-ipv4-gateway`, + `$ stackit network update --no-ipv4-gateway`, ), examples.NewExample( `Update IPv4 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers`, - `$ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" --ipv4-gateway "10.1.2.3"`, + `$ stackit network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" --ipv4-gateway "10.1.2.3"`, ), examples.NewExample( `Update IPv6 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers`, - `$ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"`, + `$ stackit network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/network/update/update_test.go b/internal/cmd/network/update/update_test.go similarity index 100% rename from internal/cmd/beta/network/update/update_test.go rename to internal/cmd/network/update/update_test.go diff --git a/internal/cmd/beta/public-ip/associate/associate.go b/internal/cmd/public-ip/associate/associate.go similarity index 98% rename from internal/cmd/beta/public-ip/associate/associate.go rename to internal/cmd/public-ip/associate/associate.go index d50bafb8d..9ce91a954 100644 --- a/internal/cmd/beta/public-ip/associate/associate.go +++ b/internal/cmd/public-ip/associate/associate.go @@ -39,7 +39,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Associate public IP with ID "xxx" to a resource (network interface or virtual IP) with ID "yyy"`, - `$ stackit beta public-ip associate xxx --associated-resource-id yyy`, + `$ stackit public-ip associate xxx --associated-resource-id yyy`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/public-ip/associate/associate_test.go b/internal/cmd/public-ip/associate/associate_test.go similarity index 100% rename from internal/cmd/beta/public-ip/associate/associate_test.go rename to internal/cmd/public-ip/associate/associate_test.go diff --git a/internal/cmd/beta/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go similarity index 96% rename from internal/cmd/beta/public-ip/create/create.go rename to internal/cmd/public-ip/create/create.go index 9bc05ab3d..0ba5c6a84 100644 --- a/internal/cmd/beta/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -39,15 +39,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a public IP`, - `$ stackit beta public-ip create`, + `$ stackit public-ip create`, ), examples.NewExample( `Create a public IP with associated resource ID "xxx"`, - `$ stackit beta public-ip create --associated-resource-id xxx`, + `$ stackit public-ip create --associated-resource-id xxx`, ), examples.NewExample( `Create a public IP with associated resource ID "xxx" and labels`, - `$ stackit beta public-ip create --associated-resource-id xxx --labels key=value,foo=bar`, + `$ stackit public-ip create --associated-resource-id xxx --labels key=value,foo=bar`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/public-ip/create/create_test.go b/internal/cmd/public-ip/create/create_test.go similarity index 100% rename from internal/cmd/beta/public-ip/create/create_test.go rename to internal/cmd/public-ip/create/create_test.go diff --git a/internal/cmd/beta/public-ip/delete/delete.go b/internal/cmd/public-ip/delete/delete.go similarity index 98% rename from internal/cmd/beta/public-ip/delete/delete.go rename to internal/cmd/public-ip/delete/delete.go index 0f257d8f0..57a427dd6 100644 --- a/internal/cmd/beta/public-ip/delete/delete.go +++ b/internal/cmd/public-ip/delete/delete.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete public IP with ID "xxx"`, - "$ stackit beta public-ip delete xxx", + "$ stackit public-ip delete xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/public-ip/delete/delete_test.go b/internal/cmd/public-ip/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/public-ip/delete/delete_test.go rename to internal/cmd/public-ip/delete/delete_test.go diff --git a/internal/cmd/beta/public-ip/describe/describe.go b/internal/cmd/public-ip/describe/describe.go similarity index 97% rename from internal/cmd/beta/public-ip/describe/describe.go rename to internal/cmd/public-ip/describe/describe.go index bc532fd6b..820d9ff61 100644 --- a/internal/cmd/beta/public-ip/describe/describe.go +++ b/internal/cmd/public-ip/describe/describe.go @@ -39,11 +39,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a public IP with ID "xxx"`, - "$ stackit beta public-ip describe xxx", + "$ stackit public-ip describe xxx", ), examples.NewExample( `Show details of a public IP with ID "xxx" in JSON format`, - "$ stackit beta public-ip describe xxx --output-format json", + "$ stackit public-ip describe xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/public-ip/describe/describe_test.go b/internal/cmd/public-ip/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/public-ip/describe/describe_test.go rename to internal/cmd/public-ip/describe/describe_test.go diff --git a/internal/cmd/beta/public-ip/disassociate/disassociate.go b/internal/cmd/public-ip/disassociate/disassociate.go similarity index 98% rename from internal/cmd/beta/public-ip/disassociate/disassociate.go rename to internal/cmd/public-ip/disassociate/disassociate.go index eb8872d80..f15bd7efd 100644 --- a/internal/cmd/beta/public-ip/disassociate/disassociate.go +++ b/internal/cmd/public-ip/disassociate/disassociate.go @@ -35,7 +35,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Disassociate public IP with ID "xxx" from a resource (network interface or virtual IP)`, - `$ stackit beta public-ip disassociate xxx`, + `$ stackit public-ip disassociate xxx`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/public-ip/disassociate/disassociate_test.go b/internal/cmd/public-ip/disassociate/disassociate_test.go similarity index 100% rename from internal/cmd/beta/public-ip/disassociate/disassociate_test.go rename to internal/cmd/public-ip/disassociate/disassociate_test.go diff --git a/internal/cmd/beta/public-ip/list/list.go b/internal/cmd/public-ip/list/list.go similarity index 96% rename from internal/cmd/beta/public-ip/list/list.go rename to internal/cmd/public-ip/list/list.go index c071e5069..19c225198 100644 --- a/internal/cmd/beta/public-ip/list/list.go +++ b/internal/cmd/public-ip/list/list.go @@ -41,19 +41,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all public IPs`, - "$ stackit beta public-ip list", + "$ stackit public-ip list", ), examples.NewExample( `Lists all public IPs which contains the label xxx`, - "$ stackit beta public-ip list --label-selector xxx", + "$ stackit public-ip list --label-selector xxx", ), examples.NewExample( `Lists all public IPs in JSON format`, - "$ stackit beta public-ip list --output-format json", + "$ stackit public-ip list --output-format json", ), examples.NewExample( `Lists up to 10 public IPs`, - "$ stackit beta public-ip list --limit 10", + "$ stackit public-ip list --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/public-ip/list/list_test.go b/internal/cmd/public-ip/list/list_test.go similarity index 100% rename from internal/cmd/beta/public-ip/list/list_test.go rename to internal/cmd/public-ip/list/list_test.go diff --git a/internal/cmd/beta/public-ip/public-ip.go b/internal/cmd/public-ip/public-ip.go similarity index 60% rename from internal/cmd/beta/public-ip/public-ip.go rename to internal/cmd/public-ip/public-ip.go index 5c5c8f410..6259759a8 100644 --- a/internal/cmd/beta/public-ip/public-ip.go +++ b/internal/cmd/public-ip/public-ip.go @@ -1,13 +1,13 @@ package publicip import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/associate" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/disassociate" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/public-ip/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/associate" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/disassociate" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go similarity index 97% rename from internal/cmd/beta/public-ip/update/update.go rename to internal/cmd/public-ip/update/update.go index e36d92a70..d3bd1a86c 100644 --- a/internal/cmd/beta/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -42,11 +42,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update public IP with ID "xxx"`, - `$ stackit beta public-ip update xxx`, + `$ stackit public-ip update xxx`, ), examples.NewExample( `Update public IP with ID "xxx" with new labels`, - `$ stackit beta public-ip update xxx --labels key=value,foo=bar`, + `$ stackit public-ip update xxx --labels key=value,foo=bar`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/public-ip/update/update_test.go b/internal/cmd/public-ip/update/update_test.go similarity index 100% rename from internal/cmd/beta/public-ip/update/update_test.go rename to internal/cmd/public-ip/update/update_test.go diff --git a/internal/cmd/beta/quota/list/list.go b/internal/cmd/quota/list/list.go similarity index 99% rename from internal/cmd/beta/quota/list/list.go rename to internal/cmd/quota/list/list.go index 97e9f956b..e18ed94de 100644 --- a/internal/cmd/beta/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -32,7 +32,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List available quotas`, - `$ stackit beta quota list`, + `$ stackit quota list`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/quota/list/list_test.go b/internal/cmd/quota/list/list_test.go similarity index 100% rename from internal/cmd/beta/quota/list/list_test.go rename to internal/cmd/quota/list/list_test.go diff --git a/internal/cmd/beta/quota/quota.go b/internal/cmd/quota/quota.go similarity index 89% rename from internal/cmd/beta/quota/quota.go rename to internal/cmd/quota/quota.go index e4eaf4bd8..bd71be405 100644 --- a/internal/cmd/beta/quota/quota.go +++ b/internal/cmd/quota/quota.go @@ -1,7 +1,7 @@ package quota import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/quota/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/quota/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 4bdf6359a..736c944f5 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -6,26 +6,37 @@ import ( "strings" "time" + affinityGroups "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups" "github.com/stackitcloud/stackit-cli/internal/cmd/auth" "github.com/stackitcloud/stackit-cli/internal/cmd/beta" configCmd "github.com/stackitcloud/stackit-cli/internal/cmd/config" "github.com/stackitcloud/stackit-cli/internal/cmd/curl" "github.com/stackitcloud/stackit-cli/internal/cmd/dns" + "github.com/stackitcloud/stackit-cli/internal/cmd/image" + keypair "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair" loadbalancer "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer" "github.com/stackitcloud/stackit-cli/internal/cmd/logme" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex" + "github.com/stackitcloud/stackit-cli/internal/cmd/network" + networkArea "github.com/stackitcloud/stackit-cli/internal/cmd/network-area" + networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface" objectstorage "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage" "github.com/stackitcloud/stackit-cli/internal/cmd/observability" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch" "github.com/stackitcloud/stackit-cli/internal/cmd/organization" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex" "github.com/stackitcloud/stackit-cli/internal/cmd/project" + publicip "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip" + "github.com/stackitcloud/stackit-cli/internal/cmd/quota" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq" "github.com/stackitcloud/stackit-cli/internal/cmd/redis" secretsmanager "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager" + securitygroup "github.com/stackitcloud/stackit-cli/internal/cmd/security-group" + "github.com/stackitcloud/stackit-cli/internal/cmd/server" serviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/service-account" "github.com/stackitcloud/stackit-cli/internal/cmd/ske" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -164,6 +175,17 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(secretsmanager.NewCmd(p)) cmd.AddCommand(serviceaccount.NewCmd(p)) cmd.AddCommand(ske.NewCmd(p)) + cmd.AddCommand(server.NewCmd(p)) + cmd.AddCommand(networkArea.NewCmd(p)) + cmd.AddCommand(network.NewCmd(p)) + cmd.AddCommand(volume.NewCmd(p)) + cmd.AddCommand(networkinterface.NewCmd(p)) + cmd.AddCommand(publicip.NewCmd(p)) + cmd.AddCommand(securitygroup.NewCmd(p)) + cmd.AddCommand(keypair.NewCmd(p)) + cmd.AddCommand(image.NewCmd(p)) + cmd.AddCommand(quota.NewCmd(p)) + cmd.AddCommand(affinityGroups.NewCmd(p)) } // traverseCommands calls f for c and all of its children. diff --git a/internal/cmd/beta/security-group/create/create.go b/internal/cmd/security-group/create/create.go similarity index 95% rename from internal/cmd/beta/security-group/create/create.go rename to internal/cmd/security-group/create/create.go index af66e0783..24f3da09c 100644 --- a/internal/cmd/beta/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -40,8 +40,8 @@ func NewCmd(p *print.Printer) *cobra.Command { Long: "Creates security groups.", Args: args.NoArgs, Example: examples.Build( - examples.NewExample(`Create a named group`, `$ stackit beta security-group create --name my-new-group`), - examples.NewExample(`Create a named group with labels`, `$ stackit beta security-group create --name my-new-group --labels label1=value1,label2=value2`), + examples.NewExample(`Create a named group`, `$ stackit security-group create --name my-new-group`), + examples.NewExample(`Create a named group with labels`, `$ stackit security-group create --name my-new-group --labels label1=value1,label2=value2`), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/security-group/create/create_test.go b/internal/cmd/security-group/create/create_test.go similarity index 100% rename from internal/cmd/beta/security-group/create/create_test.go rename to internal/cmd/security-group/create/create_test.go diff --git a/internal/cmd/beta/security-group/delete/delete.go b/internal/cmd/security-group/delete/delete.go similarity index 98% rename from internal/cmd/beta/security-group/delete/delete.go rename to internal/cmd/security-group/delete/delete.go index 80f91882c..85781ae13 100644 --- a/internal/cmd/beta/security-group/delete/delete.go +++ b/internal/cmd/security-group/delete/delete.go @@ -31,7 +31,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Long: "Deletes a security group by its internal ID.", Args: args.SingleArg(groupIdArg, utils.ValidateUUID), Example: examples.Build( - examples.NewExample(`Delete a named group with ID "xxx"`, `$ stackit beta security-group delete xxx`), + examples.NewExample(`Delete a named group with ID "xxx"`, `$ stackit security-group delete xxx`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/security-group/delete/delete_test.go b/internal/cmd/security-group/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/security-group/delete/delete_test.go rename to internal/cmd/security-group/delete/delete_test.go diff --git a/internal/cmd/beta/security-group/describe/describe.go b/internal/cmd/security-group/describe/describe.go similarity index 98% rename from internal/cmd/beta/security-group/describe/describe.go rename to internal/cmd/security-group/describe/describe.go index 2ea0084dc..01d86df03 100644 --- a/internal/cmd/beta/security-group/describe/describe.go +++ b/internal/cmd/security-group/describe/describe.go @@ -34,7 +34,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Long: "Describes security groups by its internal ID.", Args: args.SingleArg(groupIdArg, utils.ValidateUUID), Example: examples.Build( - examples.NewExample(`Describe group "xxx"`, `$ stackit beta security-group describe xxx`), + examples.NewExample(`Describe group "xxx"`, `$ stackit security-group describe xxx`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/security-group/describe/describe_test.go b/internal/cmd/security-group/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/security-group/describe/describe_test.go rename to internal/cmd/security-group/describe/describe_test.go diff --git a/internal/cmd/beta/security-group/list/list.go b/internal/cmd/security-group/list/list.go similarity index 95% rename from internal/cmd/beta/security-group/list/list.go rename to internal/cmd/security-group/list/list.go index e9a4e31cf..74a44c943 100644 --- a/internal/cmd/beta/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -37,8 +37,8 @@ func NewCmd(p *print.Printer) *cobra.Command { Long: "Lists security groups by its internal ID.", Args: args.NoArgs, Example: examples.Build( - examples.NewExample(`List all groups`, `$ stackit beta security-group list`), - examples.NewExample(`List groups with labels`, `$ stackit beta security-group list --label-selector label1=value1,label2=value2`), + examples.NewExample(`List all groups`, `$ stackit security-group list`), + examples.NewExample(`List groups with labels`, `$ stackit security-group list --label-selector label1=value1,label2=value2`), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/security-group/list/list_test.go b/internal/cmd/security-group/list/list_test.go similarity index 100% rename from internal/cmd/beta/security-group/list/list_test.go rename to internal/cmd/security-group/list/list_test.go diff --git a/internal/cmd/beta/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go similarity index 94% rename from internal/cmd/beta/security-group/rule/create/create.go rename to internal/cmd/security-group/rule/create/create.go index d5e4ab6d4..a330e98eb 100644 --- a/internal/cmd/beta/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -61,19 +61,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a security group rule for security group with ID "xxx" with direction "ingress"`, - `$ stackit beta security-group rule create --security-group-id xxx --direction ingress`, + `$ stackit security-group rule create --security-group-id xxx --direction ingress`, ), examples.NewExample( `Create a security group rule for security group with ID "xxx" with direction "egress", protocol "icmp" and icmp parameters`, - `$ stackit beta security-group rule create --security-group-id xxx --direction egress --protocol-name icmp --icmp-parameter-code 0 --icmp-parameter-type 8`, + `$ stackit security-group rule create --security-group-id xxx --direction egress --protocol-name icmp --icmp-parameter-code 0 --icmp-parameter-type 8`, ), examples.NewExample( `Create a security group rule for security group with ID "xxx" with direction "ingress", protocol "tcp" and port range values`, - `$ stackit beta security-group rule create --security-group-id xxx --direction ingress --protocol-name tcp --port-range-max 24 --port-range-min 22`, + `$ stackit security-group rule create --security-group-id xxx --direction ingress --protocol-name tcp --port-range-max 24 --port-range-min 22`, ), examples.NewExample( `Create a security group rule for security group with ID "xxx" with direction "ingress" and protocol number 1 `, - `$ stackit beta security-group rule create --security-group-id xxx --direction ingress --protocol-number 1`, + `$ stackit security-group rule create --security-group-id xxx --direction ingress --protocol-number 1`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/security-group/rule/create/create_test.go b/internal/cmd/security-group/rule/create/create_test.go similarity index 100% rename from internal/cmd/beta/security-group/rule/create/create_test.go rename to internal/cmd/security-group/rule/create/create_test.go diff --git a/internal/cmd/beta/security-group/rule/delete/delete.go b/internal/cmd/security-group/rule/delete/delete.go similarity index 98% rename from internal/cmd/beta/security-group/rule/delete/delete.go rename to internal/cmd/security-group/rule/delete/delete.go index 035866bed..247caed8a 100644 --- a/internal/cmd/beta/security-group/rule/delete/delete.go +++ b/internal/cmd/security-group/rule/delete/delete.go @@ -41,7 +41,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete security group rule with ID "xxx" in security group with ID "yyy"`, - "$ stackit beta security-group rule delete xxx --security-group-id yyy", + "$ stackit security-group rule delete xxx --security-group-id yyy", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/security-group/rule/delete/delete_test.go b/internal/cmd/security-group/rule/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/security-group/rule/delete/delete_test.go rename to internal/cmd/security-group/rule/delete/delete_test.go diff --git a/internal/cmd/beta/security-group/rule/describe/describe.go b/internal/cmd/security-group/rule/describe/describe.go similarity index 96% rename from internal/cmd/beta/security-group/rule/describe/describe.go rename to internal/cmd/security-group/rule/describe/describe.go index 2189d736f..8e8bd0508 100644 --- a/internal/cmd/beta/security-group/rule/describe/describe.go +++ b/internal/cmd/security-group/rule/describe/describe.go @@ -41,11 +41,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a security group rule with ID "xxx" in security group with ID "yyy"`, - "$ stackit beta security-group rule describe xxx --security-group-id yyy", + "$ stackit security-group rule describe xxx --security-group-id yyy", ), examples.NewExample( `Show details of a security group rule with ID "xxx" in security group with ID "yyy" in JSON format`, - "$ stackit beta security-group rule describe xxx --security-group-id yyy --output-format json", + "$ stackit security-group rule describe xxx --security-group-id yyy --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/security-group/rule/describe/describe_test.go b/internal/cmd/security-group/rule/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/security-group/rule/describe/describe_test.go rename to internal/cmd/security-group/rule/describe/describe_test.go diff --git a/internal/cmd/beta/security-group/rule/list/list.go b/internal/cmd/security-group/rule/list/list.go similarity index 95% rename from internal/cmd/beta/security-group/rule/list/list.go rename to internal/cmd/security-group/rule/list/list.go index 4e8d63481..84c83ece4 100644 --- a/internal/cmd/beta/security-group/rule/list/list.go +++ b/internal/cmd/security-group/rule/list/list.go @@ -43,15 +43,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all security group rules in security group with ID "xxx"`, - "$ stackit beta security-group rule list --security-group-id xxx", + "$ stackit security-group rule list --security-group-id xxx", ), examples.NewExample( `Lists all security group rules in security group with ID "xxx" in JSON format`, - "$ stackit beta security-group rule list --security-group-id xxx --output-format json", + "$ stackit security-group rule list --security-group-id xxx --output-format json", ), examples.NewExample( `Lists up to 10 security group rules in security group with ID "xxx"`, - "$ stackit beta security-group rule list --security-group-id xxx --limit 10", + "$ stackit security-group rule list --security-group-id xxx --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/security-group/rule/list/list_test.go b/internal/cmd/security-group/rule/list/list_test.go similarity index 100% rename from internal/cmd/beta/security-group/rule/list/list_test.go rename to internal/cmd/security-group/rule/list/list_test.go diff --git a/internal/cmd/beta/security-group/rule/security_group_rule.go b/internal/cmd/security-group/rule/security_group_rule.go similarity index 68% rename from internal/cmd/beta/security-group/rule/security_group_rule.go rename to internal/cmd/security-group/rule/security_group_rule.go index 26b3443f5..c1e133841 100644 --- a/internal/cmd/beta/security-group/rule/security_group_rule.go +++ b/internal/cmd/security-group/rule/security_group_rule.go @@ -1,10 +1,10 @@ package rule import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/security-group/security_group.go b/internal/cmd/security-group/security_group.go similarity index 60% rename from internal/cmd/beta/security-group/security_group.go rename to internal/cmd/security-group/security_group.go index 34e4bb73e..f20679d57 100644 --- a/internal/cmd/beta/security-group/security_group.go +++ b/internal/cmd/security-group/security_group.go @@ -1,12 +1,12 @@ package security_group import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/rule" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/security-group/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule" + "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" diff --git a/internal/cmd/beta/security-group/update/update.go b/internal/cmd/security-group/update/update.go similarity index 97% rename from internal/cmd/beta/security-group/update/update.go rename to internal/cmd/security-group/update/update.go index faec421f5..ddff90e23 100644 --- a/internal/cmd/beta/security-group/update/update.go +++ b/internal/cmd/security-group/update/update.go @@ -41,8 +41,8 @@ func NewCmd(p *print.Printer) *cobra.Command { Long: "Updates a named security group", Args: args.SingleArg(groupNameArg, utils.ValidateUUID), Example: examples.Build( - examples.NewExample(`Update the name of group "xxx"`, `$ stackit beta security-group update xxx --name my-new-name`), - examples.NewExample(`Update the labels of group "xxx"`, `$ stackit beta security-group update xxx --labels label1=value1,label2=value2`), + examples.NewExample(`Update the name of group "xxx"`, `$ stackit security-group update xxx --name my-new-name`), + examples.NewExample(`Update the labels of group "xxx"`, `$ stackit security-group update xxx --labels label1=value1,label2=value2`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/security-group/update/update_test.go b/internal/cmd/security-group/update/update_test.go similarity index 100% rename from internal/cmd/beta/security-group/update/update_test.go rename to internal/cmd/security-group/update/update_test.go diff --git a/internal/cmd/beta/server/backup/backup.go b/internal/cmd/server/backup/backup.go similarity index 58% rename from internal/cmd/beta/server/backup/backup.go rename to internal/cmd/server/backup/backup.go index 512f9bd66..8936ae65f 100644 --- a/internal/cmd/beta/server/backup/backup.go +++ b/internal/cmd/server/backup/backup.go @@ -1,15 +1,15 @@ package backup import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/create" - del "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/disable" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/enable" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/restore" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule" - volumebackup "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/volume-backup" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/create" + del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/disable" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/restore" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule" + volumebackup "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go similarity index 96% rename from internal/cmd/beta/server/backup/create/create.go rename to internal/cmd/server/backup/create/create.go index d64d14c0a..aae197772 100644 --- a/internal/cmd/beta/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -48,10 +48,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a Server Backup with name "mybackup"`, - `$ stackit beta server backup create --server-id xxx --name=mybackup`), + `$ stackit server backup create --server-id xxx --name=mybackup`), examples.NewExample( `Create a Server Backup with name "mybackup" and retention period of 5 days`, - `$ stackit beta server backup create --server-id xxx --name=mybackup --retention-period=5`), + `$ stackit server backup create --server-id xxx --name=mybackup --retention-period=5`), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/create/create_test.go b/internal/cmd/server/backup/create/create_test.go similarity index 100% rename from internal/cmd/beta/server/backup/create/create_test.go rename to internal/cmd/server/backup/create/create_test.go diff --git a/internal/cmd/beta/server/backup/delete/delete.go b/internal/cmd/server/backup/delete/delete.go similarity index 97% rename from internal/cmd/beta/server/backup/delete/delete.go rename to internal/cmd/server/backup/delete/delete.go index e8d92c351..821e62f74 100644 --- a/internal/cmd/beta/server/backup/delete/delete.go +++ b/internal/cmd/server/backup/delete/delete.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete a Server Backup with ID "xxx" for server "zzz"`, - "$ stackit beta server backup delete xxx --server-id=zzz"), + "$ stackit server backup delete xxx --server-id=zzz"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/delete/delete_test.go b/internal/cmd/server/backup/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/server/backup/delete/delete_test.go rename to internal/cmd/server/backup/delete/delete_test.go diff --git a/internal/cmd/beta/server/backup/describe/describe.go b/internal/cmd/server/backup/describe/describe.go similarity index 97% rename from internal/cmd/beta/server/backup/describe/describe.go rename to internal/cmd/server/backup/describe/describe.go index 2f55048cd..318b11b01 100644 --- a/internal/cmd/beta/server/backup/describe/describe.go +++ b/internal/cmd/server/backup/describe/describe.go @@ -41,10 +41,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details of a Server Backup with id "my-backup-id"`, - "$ stackit beta server backup describe my-backup-id"), + "$ stackit server backup describe my-backup-id"), examples.NewExample( `Get details of a Server Backup with id "my-backup-id" in JSON format`, - "$ stackit beta server backup describe my-backup-id --output-format json"), + "$ stackit server backup describe my-backup-id --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/describe/describe_test.go b/internal/cmd/server/backup/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/backup/describe/describe_test.go rename to internal/cmd/server/backup/describe/describe_test.go diff --git a/internal/cmd/beta/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go similarity index 98% rename from internal/cmd/beta/server/backup/disable/disable.go rename to internal/cmd/server/backup/disable/disable.go index 1d1ff797b..fc2219dca 100644 --- a/internal/cmd/beta/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Disable Server Backup functionality for your server.`, - "$ stackit beta server backup disable --server-id=zzz"), + "$ stackit server backup disable --server-id=zzz"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/disable/disable_test.go b/internal/cmd/server/backup/disable/disable_test.go similarity index 100% rename from internal/cmd/beta/server/backup/disable/disable_test.go rename to internal/cmd/server/backup/disable/disable_test.go diff --git a/internal/cmd/beta/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go similarity index 98% rename from internal/cmd/beta/server/backup/enable/enable.go rename to internal/cmd/server/backup/enable/enable.go index c6e6bc01c..3eea44927 100644 --- a/internal/cmd/beta/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Enable Server Backup functionality for your server`, - "$ stackit beta server backup enable --server-id=zzz"), + "$ stackit server backup enable --server-id=zzz"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/enable/enable_test.go b/internal/cmd/server/backup/enable/enable_test.go similarity index 100% rename from internal/cmd/beta/server/backup/enable/enable_test.go rename to internal/cmd/server/backup/enable/enable_test.go diff --git a/internal/cmd/beta/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go similarity index 97% rename from internal/cmd/beta/server/backup/list/list.go rename to internal/cmd/server/backup/list/list.go index fa060a413..8e90413ae 100644 --- a/internal/cmd/beta/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -41,10 +41,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all backups for a server with ID "xxx"`, - "$ stackit beta server backup list --server-id xxx"), + "$ stackit server backup list --server-id xxx"), examples.NewExample( `List all backups for a server with ID "xxx" in JSON format`, - "$ stackit beta server backup list --server-id xxx --output-format json"), + "$ stackit server backup list --server-id xxx --output-format json"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/list/list_test.go b/internal/cmd/server/backup/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/backup/list/list_test.go rename to internal/cmd/server/backup/list/list_test.go diff --git a/internal/cmd/beta/server/backup/restore/restore.go b/internal/cmd/server/backup/restore/restore.go similarity index 96% rename from internal/cmd/beta/server/backup/restore/restore.go rename to internal/cmd/server/backup/restore/restore.go index cfb9be8bd..215d12e9f 100644 --- a/internal/cmd/beta/server/backup/restore/restore.go +++ b/internal/cmd/server/backup/restore/restore.go @@ -43,10 +43,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Restore a Server Backup with ID "xxx" for server "zzz"`, - "$ stackit beta server backup restore xxx --server-id=zzz"), + "$ stackit server backup restore xxx --server-id=zzz"), examples.NewExample( `Restore a Server Backup with ID "xxx" for server "zzz" and start the server afterwards`, - "$ stackit beta server backup restore xxx --server-id=zzz --start-server-after-restore"), + "$ stackit server backup restore xxx --server-id=zzz --start-server-after-restore"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/restore/restore_test.go b/internal/cmd/server/backup/restore/restore_test.go similarity index 100% rename from internal/cmd/beta/server/backup/restore/restore_test.go rename to internal/cmd/server/backup/restore/restore_test.go diff --git a/internal/cmd/beta/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go similarity index 95% rename from internal/cmd/beta/server/backup/schedule/create/create.go rename to internal/cmd/server/backup/schedule/create/create.go index 19b789291..db22b2366 100644 --- a/internal/cmd/beta/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -56,10 +56,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a Server Backup Schedule with name "myschedule" and backup name "mybackup"`, - `$ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule`), + `$ stackit server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule`), examples.NewExample( `Create a Server Backup Schedule with name "myschedule", backup name "mybackup" and retention period of 5 days`, - `$ stackit beta server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule --backup-retention-period=5`), + `$ stackit server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule --backup-retention-period=5`), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/schedule/create/create_test.go b/internal/cmd/server/backup/schedule/create/create_test.go similarity index 100% rename from internal/cmd/beta/server/backup/schedule/create/create_test.go rename to internal/cmd/server/backup/schedule/create/create_test.go diff --git a/internal/cmd/beta/server/backup/schedule/delete/delete.go b/internal/cmd/server/backup/schedule/delete/delete.go similarity index 98% rename from internal/cmd/beta/server/backup/schedule/delete/delete.go rename to internal/cmd/server/backup/schedule/delete/delete.go index 1417aba8e..add739884 100644 --- a/internal/cmd/beta/server/backup/schedule/delete/delete.go +++ b/internal/cmd/server/backup/schedule/delete/delete.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete a Server Backup Schedule with ID "xxx" for server "zzz"`, - "$ stackit beta server backup schedule delete xxx --server-id=zzz"), + "$ stackit server backup schedule delete xxx --server-id=zzz"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/schedule/delete/delete_test.go b/internal/cmd/server/backup/schedule/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/server/backup/schedule/delete/delete_test.go rename to internal/cmd/server/backup/schedule/delete/delete_test.go diff --git a/internal/cmd/beta/server/backup/schedule/describe/describe.go b/internal/cmd/server/backup/schedule/describe/describe.go similarity index 96% rename from internal/cmd/beta/server/backup/schedule/describe/describe.go rename to internal/cmd/server/backup/schedule/describe/describe.go index 4fd94511d..bd3ca9f71 100644 --- a/internal/cmd/beta/server/backup/schedule/describe/describe.go +++ b/internal/cmd/server/backup/schedule/describe/describe.go @@ -40,10 +40,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details of a Server Backup Schedule with id "my-schedule-id"`, - "$ stackit beta server backup schedule describe my-schedule-id"), + "$ stackit server backup schedule describe my-schedule-id"), examples.NewExample( `Get details of a Server Backup Schedule with id "my-schedule-id" in JSON format`, - "$ stackit beta server backup schedule describe my-schedule-id --output-format json"), + "$ stackit server backup schedule describe my-schedule-id --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/schedule/describe/describe_test.go b/internal/cmd/server/backup/schedule/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/backup/schedule/describe/describe_test.go rename to internal/cmd/server/backup/schedule/describe/describe_test.go diff --git a/internal/cmd/beta/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go similarity index 97% rename from internal/cmd/beta/server/backup/schedule/list/list.go rename to internal/cmd/server/backup/schedule/list/list.go index ff8ba067d..a1c60d4bc 100644 --- a/internal/cmd/beta/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -41,10 +41,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all backup schedules for a server with ID "xxx"`, - "$ stackit beta server backup schedule list --server-id xxx"), + "$ stackit server backup schedule list --server-id xxx"), examples.NewExample( `List all backup schedules for a server with ID "xxx" in JSON format`, - "$ stackit beta server backup schedule list --server-id xxx --output-format json"), + "$ stackit server backup schedule list --server-id xxx --output-format json"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/schedule/list/list_test.go b/internal/cmd/server/backup/schedule/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/backup/schedule/list/list_test.go rename to internal/cmd/server/backup/schedule/list/list_test.go diff --git a/internal/cmd/beta/server/backup/schedule/schedule.go b/internal/cmd/server/backup/schedule/schedule.go similarity index 63% rename from internal/cmd/beta/server/backup/schedule/schedule.go rename to internal/cmd/server/backup/schedule/schedule.go index 73f026c5b..423486fde 100644 --- a/internal/cmd/beta/server/backup/schedule/schedule.go +++ b/internal/cmd/server/backup/schedule/schedule.go @@ -1,11 +1,11 @@ package schedule import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/create" - del "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/schedule/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/create" + del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/backup/schedule/update/update.go b/internal/cmd/server/backup/schedule/update/update.go similarity index 97% rename from internal/cmd/beta/server/backup/schedule/update/update.go rename to internal/cmd/server/backup/schedule/update/update.go index 7c278c270..aa9793faa 100644 --- a/internal/cmd/beta/server/backup/schedule/update/update.go +++ b/internal/cmd/server/backup/schedule/update/update.go @@ -56,10 +56,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update the retention period of the backup schedule "zzz" of server "xxx"`, - "$ stackit beta server backup schedule update zzz --server-id=xxx --backup-retention-period=20"), + "$ stackit server backup schedule update zzz --server-id=xxx --backup-retention-period=20"), examples.NewExample( `Update the backup name of the backup schedule "zzz" of server "xxx"`, - "$ stackit beta server backup schedule update zzz --server-id=xxx --backup-name=newname"), + "$ stackit server backup schedule update zzz --server-id=xxx --backup-name=newname"), ), Args: args.SingleArg(scheduleIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/backup/schedule/update/update_test.go b/internal/cmd/server/backup/schedule/update/update_test.go similarity index 100% rename from internal/cmd/beta/server/backup/schedule/update/update_test.go rename to internal/cmd/server/backup/schedule/update/update_test.go diff --git a/internal/cmd/beta/server/backup/volume-backup/delete/delete.go b/internal/cmd/server/backup/volume-backup/delete/delete.go similarity index 97% rename from internal/cmd/beta/server/backup/volume-backup/delete/delete.go rename to internal/cmd/server/backup/volume-backup/delete/delete.go index 1d996b80a..6653c9718 100644 --- a/internal/cmd/beta/server/backup/volume-backup/delete/delete.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete.go @@ -39,7 +39,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete a Server Volume Backup with ID "xxx" for server "zzz" and backup "bbb"`, - "$ stackit beta server backup volume-backup delete xxx --server-id=zzz --backup-id=bbb"), + "$ stackit server backup volume-backup delete xxx --server-id=zzz --backup-id=bbb"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/volume-backup/delete/delete_test.go b/internal/cmd/server/backup/volume-backup/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/server/backup/volume-backup/delete/delete_test.go rename to internal/cmd/server/backup/volume-backup/delete/delete_test.go diff --git a/internal/cmd/beta/server/backup/volume-backup/restore/restore.go b/internal/cmd/server/backup/volume-backup/restore/restore.go similarity index 97% rename from internal/cmd/beta/server/backup/volume-backup/restore/restore.go rename to internal/cmd/server/backup/volume-backup/restore/restore.go index 110eca832..bf76ef7c9 100644 --- a/internal/cmd/beta/server/backup/volume-backup/restore/restore.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore.go @@ -41,7 +41,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Restore a Server Volume Backup with ID "xxx" for server "zzz" and backup "bbb" to volume "rrr"`, - "$ stackit beta server backup volume-backup restore xxx --server-id=zzz --backup-id=bbb --restore-volume-id=rrr"), + "$ stackit server backup volume-backup restore xxx --server-id=zzz --backup-id=bbb --restore-volume-id=rrr"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/backup/volume-backup/restore/restore_test.go b/internal/cmd/server/backup/volume-backup/restore/restore_test.go similarity index 100% rename from internal/cmd/beta/server/backup/volume-backup/restore/restore_test.go rename to internal/cmd/server/backup/volume-backup/restore/restore_test.go diff --git a/internal/cmd/beta/server/backup/volume-backup/volumebackup.go b/internal/cmd/server/backup/volume-backup/volumebackup.go similarity index 78% rename from internal/cmd/beta/server/backup/volume-backup/volumebackup.go rename to internal/cmd/server/backup/volume-backup/volumebackup.go index 17d8840ee..7a4024eb4 100644 --- a/internal/cmd/beta/server/backup/volume-backup/volumebackup.go +++ b/internal/cmd/server/backup/volume-backup/volumebackup.go @@ -1,8 +1,8 @@ package volumebackup import ( - del "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/volume-backup/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/backup/volume-backup/restore" + del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup/restore" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/command/command.go b/internal/cmd/server/command/command.go similarity index 69% rename from internal/cmd/beta/server/command/command.go rename to internal/cmd/server/command/command.go index 6d51137f2..9347fb111 100644 --- a/internal/cmd/beta/server/command/command.go +++ b/internal/cmd/server/command/command.go @@ -1,10 +1,10 @@ package command import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/template" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/command/create/create.go b/internal/cmd/server/command/create/create.go similarity index 95% rename from internal/cmd/beta/server/command/create/create.go rename to internal/cmd/server/command/create/create.go index 1ca0577f9..cc258aa81 100644 --- a/internal/cmd/beta/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -44,10 +44,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a server command for server with ID "xxx", template name "RunShellScript" and a script from a file (using the @{...} format)`, - `$ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='@{/path/to/script.sh}'`), + `$ stackit server command create --server-id xxx --template-name=RunShellScript --params script='@{/path/to/script.sh}'`), examples.NewExample( `Create a server command for server with ID "xxx", template name "RunShellScript" and a script provided on the command line`, - `$ stackit beta server command create --server-id xxx --template-name=RunShellScript --params script='echo hello'`), + `$ stackit server command create --server-id xxx --template-name=RunShellScript --params script='echo hello'`), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/command/create/create_test.go b/internal/cmd/server/command/create/create_test.go similarity index 100% rename from internal/cmd/beta/server/command/create/create_test.go rename to internal/cmd/server/command/create/create_test.go diff --git a/internal/cmd/beta/server/command/describe/describe.go b/internal/cmd/server/command/describe/describe.go similarity index 96% rename from internal/cmd/beta/server/command/describe/describe.go rename to internal/cmd/server/command/describe/describe.go index cfc1f067f..dfd6beba4 100644 --- a/internal/cmd/beta/server/command/describe/describe.go +++ b/internal/cmd/server/command/describe/describe.go @@ -39,10 +39,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details of a Server Command with ID "xxx" for server with ID "yyy"`, - "$ stackit beta server command describe xxx --server-id=yyy"), + "$ stackit server command describe xxx --server-id=yyy"), examples.NewExample( `Get details of a Server Command with ID "xxx" for server with ID "yyy" in JSON format`, - "$ stackit beta server command describe xxx --server-id=yyy --output-format json"), + "$ stackit server command describe xxx --server-id=yyy --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/command/describe/describe_test.go b/internal/cmd/server/command/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/command/describe/describe_test.go rename to internal/cmd/server/command/describe/describe_test.go diff --git a/internal/cmd/beta/server/command/list/list.go b/internal/cmd/server/command/list/list.go similarity index 97% rename from internal/cmd/beta/server/command/list/list.go rename to internal/cmd/server/command/list/list.go index 8db186da9..3ee9fd364 100644 --- a/internal/cmd/beta/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -41,10 +41,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all commands for a server with ID "xxx"`, - "$ stackit beta server command list --server-id xxx"), + "$ stackit server command list --server-id xxx"), examples.NewExample( `List all commands for a server with ID "xxx" in JSON format`, - "$ stackit beta server command list --server-id xxx --output-format json"), + "$ stackit server command list --server-id xxx --output-format json"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/command/list/list_test.go b/internal/cmd/server/command/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/command/list/list_test.go rename to internal/cmd/server/command/list/list_test.go diff --git a/internal/cmd/beta/server/command/template/describe/describe.go b/internal/cmd/server/command/template/describe/describe.go similarity index 95% rename from internal/cmd/beta/server/command/template/describe/describe.go rename to internal/cmd/server/command/template/describe/describe.go index fd60b8c46..d549e8752 100644 --- a/internal/cmd/beta/server/command/template/describe/describe.go +++ b/internal/cmd/server/command/template/describe/describe.go @@ -39,10 +39,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details of a Server Command Template with name "RunShellScript" for server with ID "xxx"`, - "$ stackit beta server command template describe RunShellScript --server-id=xxx"), + "$ stackit server command template describe RunShellScript --server-id=xxx"), examples.NewExample( `Get details of a Server Command Template with name "RunShellScript" for server with ID "xxx" in JSON format`, - "$ stackit beta server command template describe RunShellScript --server-id=xxx --output-format json"), + "$ stackit server command template describe RunShellScript --server-id=xxx --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/command/template/describe/describe_test.go b/internal/cmd/server/command/template/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/command/template/describe/describe_test.go rename to internal/cmd/server/command/template/describe/describe_test.go diff --git a/internal/cmd/beta/server/command/template/list/list.go b/internal/cmd/server/command/template/list/list.go similarity index 97% rename from internal/cmd/beta/server/command/template/list/list.go rename to internal/cmd/server/command/template/list/list.go index 8be97f03b..079c4f5f7 100644 --- a/internal/cmd/beta/server/command/template/list/list.go +++ b/internal/cmd/server/command/template/list/list.go @@ -37,10 +37,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all command templates`, - "$ stackit beta server command template list"), + "$ stackit server command template list"), examples.NewExample( `List all commands templates in JSON format`, - "$ stackit beta server command template list --output-format json"), + "$ stackit server command template list --output-format json"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/command/template/list/list_test.go b/internal/cmd/server/command/template/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/command/template/list/list_test.go rename to internal/cmd/server/command/template/list/list_test.go diff --git a/internal/cmd/beta/server/command/template/template.go b/internal/cmd/server/command/template/template.go similarity index 79% rename from internal/cmd/beta/server/command/template/template.go rename to internal/cmd/server/command/template/template.go index a1f0d7b20..03f9b13da 100644 --- a/internal/cmd/beta/server/command/template/template.go +++ b/internal/cmd/server/command/template/template.go @@ -1,8 +1,8 @@ package template import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/template/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/command/template/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/console/console.go b/internal/cmd/server/console/console.go similarity index 97% rename from internal/cmd/beta/server/console/console.go rename to internal/cmd/server/console/console.go index 026c942cb..3c6f08ab8 100644 --- a/internal/cmd/beta/server/console/console.go +++ b/internal/cmd/server/console/console.go @@ -38,11 +38,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get a URL for the server remote console with server ID "xxx"`, - "$ stackit beta server console xxx", + "$ stackit server console xxx", ), examples.NewExample( `Get a URL for the server remote console with server ID "xxx" in JSON format`, - "$ stackit beta server console xxx --output-format json", + "$ stackit server console xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/console/console_test.go b/internal/cmd/server/console/console_test.go similarity index 100% rename from internal/cmd/beta/server/console/console_test.go rename to internal/cmd/server/console/console_test.go diff --git a/internal/cmd/beta/server/create/create.go b/internal/cmd/server/create/create.go similarity index 91% rename from internal/cmd/beta/server/create/create.go rename to internal/cmd/server/create/create.go index fb0cb24f6..461f58ce3 100644 --- a/internal/cmd/beta/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -74,39 +74,39 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a server from an image with id xxx`, - `$ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx`, + `$ stackit server create --machine-type t1.1 --name server1 --image-id xxx`, ), examples.NewExample( `Create a server with labels from an image with id xxx`, - `$ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --labels key=value,foo=bar`, + `$ stackit server create --machine-type t1.1 --name server1 --image-id xxx --labels key=value,foo=bar`, ), examples.NewExample( `Create a server with a boot volume`, - `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64`, + `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64`, ), examples.NewExample( `Create a server with a boot volume from an existing volume`, - `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type volume`, + `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type volume`, ), examples.NewExample( `Create a server with a keypair`, - `$ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --keypair-name example`, + `$ stackit server create --machine-type t1.1 --name server1 --image-id xxx --keypair-name example`, ), examples.NewExample( `Create a server with a network`, - `$ stackit beta server create --machine-type t1.1 --name server1 --image-id xxx --network-id yyy`, + `$ stackit server create --machine-type t1.1 --name server1 --image-id xxx --network-id yyy`, ), examples.NewExample( `Create a server with a network interface`, - `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --network-interface-ids yyy`, + `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --network-interface-ids yyy`, ), examples.NewExample( `Create a server with an attached volume`, - `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --volumes yyy`, + `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --volumes yyy`, ), examples.NewExample( `Create a server with user data (cloud-init)`, - `$ stackit beta server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml")`, + `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml")`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/server/create/create_test.go b/internal/cmd/server/create/create_test.go similarity index 100% rename from internal/cmd/beta/server/create/create_test.go rename to internal/cmd/server/create/create_test.go diff --git a/internal/cmd/beta/server/deallocate/deallocate.go b/internal/cmd/server/deallocate/deallocate.go similarity index 98% rename from internal/cmd/beta/server/deallocate/deallocate.go rename to internal/cmd/server/deallocate/deallocate.go index 3cb27fb0b..53a01de69 100644 --- a/internal/cmd/beta/server/deallocate/deallocate.go +++ b/internal/cmd/server/deallocate/deallocate.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Deallocate an existing server with ID "xxx"`, - "$ stackit beta server deallocate xxx", + "$ stackit server deallocate xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/deallocate/deallocate_test.go b/internal/cmd/server/deallocate/deallocate_test.go similarity index 100% rename from internal/cmd/beta/server/deallocate/deallocate_test.go rename to internal/cmd/server/deallocate/deallocate_test.go diff --git a/internal/cmd/beta/server/delete/delete.go b/internal/cmd/server/delete/delete.go similarity index 98% rename from internal/cmd/beta/server/delete/delete.go rename to internal/cmd/server/delete/delete.go index eaf994419..77ad35479 100644 --- a/internal/cmd/beta/server/delete/delete.go +++ b/internal/cmd/server/delete/delete.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete server with ID "xxx"`, - "$ stackit beta server delete xxx", + "$ stackit server delete xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/delete/delete_test.go b/internal/cmd/server/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/server/delete/delete_test.go rename to internal/cmd/server/delete/delete_test.go diff --git a/internal/cmd/beta/server/describe/describe.go b/internal/cmd/server/describe/describe.go similarity index 98% rename from internal/cmd/beta/server/describe/describe.go rename to internal/cmd/server/describe/describe.go index ab87b4ba5..0e3e5dae4 100644 --- a/internal/cmd/beta/server/describe/describe.go +++ b/internal/cmd/server/describe/describe.go @@ -38,11 +38,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a server with ID "xxx"`, - "$ stackit beta server describe xxx", + "$ stackit server describe xxx", ), examples.NewExample( `Show details of a server with ID "xxx" in JSON format`, - "$ stackit beta server describe xxx --output-format json", + "$ stackit server describe xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/describe/describe_test.go b/internal/cmd/server/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/describe/describe_test.go rename to internal/cmd/server/describe/describe_test.go diff --git a/internal/cmd/beta/server/list/list.go b/internal/cmd/server/list/list.go similarity index 96% rename from internal/cmd/beta/server/list/list.go rename to internal/cmd/server/list/list.go index b6a20939c..db72cdb26 100644 --- a/internal/cmd/beta/server/list/list.go +++ b/internal/cmd/server/list/list.go @@ -41,19 +41,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all servers`, - "$ stackit beta server list", + "$ stackit server list", ), examples.NewExample( `Lists all servers which contains the label xxx`, - "$ stackit beta server list --label-selector xxx", + "$ stackit server list --label-selector xxx", ), examples.NewExample( `Lists all servers in JSON format`, - "$ stackit beta server list --output-format json", + "$ stackit server list --output-format json", ), examples.NewExample( `Lists up to 10 servers`, - "$ stackit beta server list --limit 10", + "$ stackit server list --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/server/list/list_test.go b/internal/cmd/server/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/list/list_test.go rename to internal/cmd/server/list/list_test.go diff --git a/internal/cmd/beta/server/log/log.go b/internal/cmd/server/log/log.go similarity index 96% rename from internal/cmd/beta/server/log/log.go rename to internal/cmd/server/log/log.go index 3aaa51ed7..974b149a3 100644 --- a/internal/cmd/beta/server/log/log.go +++ b/internal/cmd/server/log/log.go @@ -43,15 +43,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get server console log for the server with ID "xxx"`, - "$ stackit beta server log xxx", + "$ stackit server log xxx", ), examples.NewExample( `Get server console log for the server with ID "xxx" and limit output lines to 1000`, - "$ stackit beta server log xxx --length 1000", + "$ stackit server log xxx --length 1000", ), examples.NewExample( `Get server console log for the server with ID "xxx" in JSON format`, - "$ stackit beta server log xxx --output-format json", + "$ stackit server log xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/log/log_test.go b/internal/cmd/server/log/log_test.go similarity index 100% rename from internal/cmd/beta/server/log/log_test.go rename to internal/cmd/server/log/log_test.go diff --git a/internal/cmd/beta/server/machine-type/describe/describe.go b/internal/cmd/server/machine-type/describe/describe.go similarity index 96% rename from internal/cmd/beta/server/machine-type/describe/describe.go rename to internal/cmd/server/machine-type/describe/describe.go index 365a07205..8c5d99e38 100644 --- a/internal/cmd/beta/server/machine-type/describe/describe.go +++ b/internal/cmd/server/machine-type/describe/describe.go @@ -38,11 +38,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a server machine type with name "xxx"`, - "$ stackit beta server machine-type describe xxx", + "$ stackit server machine-type describe xxx", ), examples.NewExample( `Show details of a server machine type with name "xxx" in JSON format`, - "$ stackit beta server machine-type describe xxx --output-format json", + "$ stackit server machine-type describe xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/machine-type/describe/describe_test.go b/internal/cmd/server/machine-type/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/machine-type/describe/describe_test.go rename to internal/cmd/server/machine-type/describe/describe_test.go diff --git a/internal/cmd/beta/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go similarity index 96% rename from internal/cmd/beta/server/machine-type/list/list.go rename to internal/cmd/server/machine-type/list/list.go index a8511e53a..e04f3e9f8 100644 --- a/internal/cmd/beta/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -39,15 +39,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get list of all machine types`, - "$ stackit beta server machine-type list", + "$ stackit server machine-type list", ), examples.NewExample( `Get list of all machine types in JSON format`, - "$ stackit beta server machine-type list --output-format json", + "$ stackit server machine-type list --output-format json", ), examples.NewExample( `List the first 10 machine types`, - `$ stackit beta server machine-type list --limit=10`, + `$ stackit server machine-type list --limit=10`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/server/machine-type/list/list_test.go b/internal/cmd/server/machine-type/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/machine-type/list/list_test.go rename to internal/cmd/server/machine-type/list/list_test.go diff --git a/internal/cmd/beta/server/machine-type/machine-type.go b/internal/cmd/server/machine-type/machine-type.go similarity index 81% rename from internal/cmd/beta/server/machine-type/machine-type.go rename to internal/cmd/server/machine-type/machine-type.go index 8878cc29f..51c33d236 100644 --- a/internal/cmd/beta/server/machine-type/machine-type.go +++ b/internal/cmd/server/machine-type/machine-type.go @@ -1,8 +1,8 @@ package machinetype import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/machine-type/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/machine-type/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/machine-type/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/machine-type/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/network-interface/attach/attach.go b/internal/cmd/server/network-interface/attach/attach.go similarity index 96% rename from internal/cmd/beta/server/network-interface/attach/attach.go rename to internal/cmd/server/network-interface/attach/attach.go index ecbf6bd41..b2f987f27 100644 --- a/internal/cmd/beta/server/network-interface/attach/attach.go +++ b/internal/cmd/server/network-interface/attach/attach.go @@ -44,11 +44,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Attach a network interface with ID "xxx" to a server with ID "yyy"`, - `$ stackit beta server network-interface attach --network-interface-id xxx --server-id yyy`, + `$ stackit server network-interface attach --network-interface-id xxx --server-id yyy`, ), examples.NewExample( `Create a network interface for network with ID "xxx" and attach it to a server with ID "yyy"`, - `$ stackit beta server network-interface attach --network-id xxx --server-id yyy --create`, + `$ stackit server network-interface attach --network-id xxx --server-id yyy --create`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/server/network-interface/attach/attach_test.go b/internal/cmd/server/network-interface/attach/attach_test.go similarity index 100% rename from internal/cmd/beta/server/network-interface/attach/attach_test.go rename to internal/cmd/server/network-interface/attach/attach_test.go diff --git a/internal/cmd/beta/server/network-interface/detach/detach.go b/internal/cmd/server/network-interface/detach/detach.go similarity index 96% rename from internal/cmd/beta/server/network-interface/detach/detach.go rename to internal/cmd/server/network-interface/detach/detach.go index 993c4426c..f0c735cb1 100644 --- a/internal/cmd/beta/server/network-interface/detach/detach.go +++ b/internal/cmd/server/network-interface/detach/detach.go @@ -44,11 +44,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Detach a network interface with ID "xxx" from a server with ID "yyy"`, - `$ stackit beta server network-interface detach --network-interface-id xxx --server-id yyy`, + `$ stackit server network-interface detach --network-interface-id xxx --server-id yyy`, ), examples.NewExample( `Detach and delete all network interfaces for network with ID "xxx" and detach them from a server with ID "yyy"`, - `$ stackit beta server network-interface detach --network-id xxx --server-id yyy --delete`, + `$ stackit server network-interface detach --network-id xxx --server-id yyy --delete`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/server/network-interface/detach/detach_test.go b/internal/cmd/server/network-interface/detach/detach_test.go similarity index 100% rename from internal/cmd/beta/server/network-interface/detach/detach_test.go rename to internal/cmd/server/network-interface/detach/detach_test.go diff --git a/internal/cmd/beta/server/network-interface/list/list.go b/internal/cmd/server/network-interface/list/list.go similarity index 95% rename from internal/cmd/beta/server/network-interface/list/list.go rename to internal/cmd/server/network-interface/list/list.go index de6fd5100..eb3210cf4 100644 --- a/internal/cmd/beta/server/network-interface/list/list.go +++ b/internal/cmd/server/network-interface/list/list.go @@ -40,15 +40,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all attached network interfaces of server with ID "xxx"`, - "$ stackit beta server network-interface list --server-id xxx", + "$ stackit server network-interface list --server-id xxx", ), examples.NewExample( `Lists all attached network interfaces of server with ID "xxx" in JSON format`, - "$ stackit beta server network-interface list --server-id xxx --output-format json", + "$ stackit server network-interface list --server-id xxx --output-format json", ), examples.NewExample( `Lists up to 10 attached network interfaces of server with ID "xxx"`, - "$ stackit beta server network-interface list --server-id xxx --limit 10", + "$ stackit server network-interface list --server-id xxx --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/server/network-interface/list/list_test.go b/internal/cmd/server/network-interface/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/network-interface/list/list_test.go rename to internal/cmd/server/network-interface/list/list_test.go diff --git a/internal/cmd/beta/server/network-interface/network-interface.go b/internal/cmd/server/network-interface/network-interface.go similarity index 73% rename from internal/cmd/beta/server/network-interface/network-interface.go rename to internal/cmd/server/network-interface/network-interface.go index 88fc744dd..703e48eba 100644 --- a/internal/cmd/beta/server/network-interface/network-interface.go +++ b/internal/cmd/server/network-interface/network-interface.go @@ -1,9 +1,9 @@ package networkinterface import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface/attach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface/detach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/network-interface/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/detach" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go similarity index 96% rename from internal/cmd/beta/server/os-update/create/create.go rename to internal/cmd/server/os-update/create/create.go index ac00b378e..9c4a1cbf9 100644 --- a/internal/cmd/beta/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -43,10 +43,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a Server os-update with name "myupdate"`, - `$ stackit beta server os-update create --server-id xxx --name=myupdate`), + `$ stackit server os-update create --server-id xxx --name=myupdate`), examples.NewExample( `Create a Server os-update with name "myupdate" and maintenance window for 13 o'clock.`, - `$ stackit beta server os-update create --server-id xxx --name=mybupdate --maintenance-window=13`), + `$ stackit server os-update create --server-id xxx --name=mybupdate --maintenance-window=13`), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/create/create_test.go b/internal/cmd/server/os-update/create/create_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/create/create_test.go rename to internal/cmd/server/os-update/create/create_test.go diff --git a/internal/cmd/beta/server/os-update/describe/describe.go b/internal/cmd/server/os-update/describe/describe.go similarity index 96% rename from internal/cmd/beta/server/os-update/describe/describe.go rename to internal/cmd/server/os-update/describe/describe.go index ac3a588d7..f2f768651 100644 --- a/internal/cmd/beta/server/os-update/describe/describe.go +++ b/internal/cmd/server/os-update/describe/describe.go @@ -39,10 +39,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details of a Server os-update with id "my-os-update-id"`, - "$ stackit beta server os-update describe my-os-update-id"), + "$ stackit server os-update describe my-os-update-id"), examples.NewExample( `Get details of a Server os-update with id "my-os-update-id" in JSON format`, - "$ stackit beta server os-update describe my-os-update-id --output-format json"), + "$ stackit server os-update describe my-os-update-id --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/describe/describe_test.go b/internal/cmd/server/os-update/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/describe/describe_test.go rename to internal/cmd/server/os-update/describe/describe_test.go diff --git a/internal/cmd/beta/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go similarity index 98% rename from internal/cmd/beta/server/os-update/disable/disable.go rename to internal/cmd/server/os-update/disable/disable.go index cfd937ec1..a55ab7e9d 100644 --- a/internal/cmd/beta/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -36,7 +36,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Disable os-update functionality for your server.`, - "$ stackit beta server os-update disable --server-id=zzz"), + "$ stackit server os-update disable --server-id=zzz"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/disable/disable_test.go b/internal/cmd/server/os-update/disable/disable_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/disable/disable_test.go rename to internal/cmd/server/os-update/disable/disable_test.go diff --git a/internal/cmd/beta/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go similarity index 98% rename from internal/cmd/beta/server/os-update/enable/enable.go rename to internal/cmd/server/os-update/enable/enable.go index 9cb96b806..0dc7cb0f6 100644 --- a/internal/cmd/beta/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Enable os-update functionality for your server`, - "$ stackit beta server os-update enable --server-id=zzz"), + "$ stackit server os-update enable --server-id=zzz"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/enable/enable_test.go b/internal/cmd/server/os-update/enable/enable_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/enable/enable_test.go rename to internal/cmd/server/os-update/enable/enable_test.go diff --git a/internal/cmd/beta/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go similarity index 97% rename from internal/cmd/beta/server/os-update/list/list.go rename to internal/cmd/server/os-update/list/list.go index 6da7e4fcc..af4f15030 100644 --- a/internal/cmd/beta/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -43,10 +43,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all os-updates for a server with ID "xxx"`, - "$ stackit beta server os-update list --server-id xxx"), + "$ stackit server os-update list --server-id xxx"), examples.NewExample( `List all os-updates for a server with ID "xxx" in JSON format`, - "$ stackit beta server os-update list --server-id xxx --output-format json"), + "$ stackit server os-update list --server-id xxx --output-format json"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/list/list_test.go b/internal/cmd/server/os-update/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/list/list_test.go rename to internal/cmd/server/os-update/list/list_test.go diff --git a/internal/cmd/beta/server/os-update/os-update.go b/internal/cmd/server/os-update/os-update.go similarity index 62% rename from internal/cmd/beta/server/os-update/os-update.go rename to internal/cmd/server/os-update/os-update.go index b4100b3d6..a9d3ec8fc 100644 --- a/internal/cmd/beta/server/os-update/os-update.go +++ b/internal/cmd/server/os-update/os-update.go @@ -1,12 +1,12 @@ package osupdate import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/disable" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/enable" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/disable" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go similarity index 96% rename from internal/cmd/beta/server/os-update/schedule/create/create.go rename to internal/cmd/server/os-update/schedule/create/create.go index f36756391..e61003a95 100644 --- a/internal/cmd/beta/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -52,10 +52,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a Server os-update Schedule with name "myschedule"`, - `$ stackit beta server os-update schedule create --server-id xxx --name=myschedule`), + `$ stackit server os-update schedule create --server-id xxx --name=myschedule`), examples.NewExample( `Create a Server os-update Schedule with name "myschedule" and maintenance window for 14 o'clock`, - `$ stackit beta server os-update schedule create --server-id xxx --name=myschedule --maintenance-window=14`), + `$ stackit server os-update schedule create --server-id xxx --name=myschedule --maintenance-window=14`), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/schedule/create/create_test.go b/internal/cmd/server/os-update/schedule/create/create_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/schedule/create/create_test.go rename to internal/cmd/server/os-update/schedule/create/create_test.go diff --git a/internal/cmd/beta/server/os-update/schedule/delete/delete.go b/internal/cmd/server/os-update/schedule/delete/delete.go similarity index 97% rename from internal/cmd/beta/server/os-update/schedule/delete/delete.go rename to internal/cmd/server/os-update/schedule/delete/delete.go index d19482752..3c9813a98 100644 --- a/internal/cmd/beta/server/os-update/schedule/delete/delete.go +++ b/internal/cmd/server/os-update/schedule/delete/delete.go @@ -36,7 +36,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete a Server os-update Schedule with ID "xxx" for server "zzz"`, - "$ stackit beta server os-update schedule delete xxx --server-id=zzz"), + "$ stackit server os-update schedule delete xxx --server-id=zzz"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/schedule/delete/delete_test.go b/internal/cmd/server/os-update/schedule/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/schedule/delete/delete_test.go rename to internal/cmd/server/os-update/schedule/delete/delete_test.go diff --git a/internal/cmd/beta/server/os-update/schedule/describe/describe.go b/internal/cmd/server/os-update/schedule/describe/describe.go similarity index 96% rename from internal/cmd/beta/server/os-update/schedule/describe/describe.go rename to internal/cmd/server/os-update/schedule/describe/describe.go index efacb1fbe..98aa50f37 100644 --- a/internal/cmd/beta/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/server/os-update/schedule/describe/describe.go @@ -39,10 +39,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details of a Server os-update Schedule with id "my-schedule-id"`, - "$ stackit beta server os-update schedule describe my-schedule-id"), + "$ stackit server os-update schedule describe my-schedule-id"), examples.NewExample( `Get details of a Server os-update Schedule with id "my-schedule-id" in JSON format`, - "$ stackit beta server os-update schedule describe my-schedule-id --output-format json"), + "$ stackit server os-update schedule describe my-schedule-id --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/schedule/describe/describe_test.go b/internal/cmd/server/os-update/schedule/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/schedule/describe/describe_test.go rename to internal/cmd/server/os-update/schedule/describe/describe_test.go diff --git a/internal/cmd/beta/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go similarity index 96% rename from internal/cmd/beta/server/os-update/schedule/list/list.go rename to internal/cmd/server/os-update/schedule/list/list.go index ad46f0de2..339f23fea 100644 --- a/internal/cmd/beta/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -41,10 +41,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all os-update schedules for a server with ID "xxx"`, - "$ stackit beta server os-update schedule list --server-id xxx"), + "$ stackit server os-update schedule list --server-id xxx"), examples.NewExample( `List all os-update schedules for a server with ID "xxx" in JSON format`, - "$ stackit beta server os-update schedule list --server-id xxx --output-format json"), + "$ stackit server os-update schedule list --server-id xxx --output-format json"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/os-update/schedule/list/list_test.go b/internal/cmd/server/os-update/schedule/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/schedule/list/list_test.go rename to internal/cmd/server/os-update/schedule/list/list_test.go diff --git a/internal/cmd/beta/server/os-update/schedule/schedule.go b/internal/cmd/server/os-update/schedule/schedule.go similarity index 62% rename from internal/cmd/beta/server/os-update/schedule/schedule.go rename to internal/cmd/server/os-update/schedule/schedule.go index 60c9e503c..9f051ced0 100644 --- a/internal/cmd/beta/server/os-update/schedule/schedule.go +++ b/internal/cmd/server/os-update/schedule/schedule.go @@ -1,11 +1,11 @@ package schedule import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/create" - del "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/os-update/schedule/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/create" + del "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/os-update/schedule/update/update.go b/internal/cmd/server/os-update/schedule/update/update.go similarity index 98% rename from internal/cmd/beta/server/os-update/schedule/update/update.go rename to internal/cmd/server/os-update/schedule/update/update.go index cea340336..25f110415 100644 --- a/internal/cmd/beta/server/os-update/schedule/update/update.go +++ b/internal/cmd/server/os-update/schedule/update/update.go @@ -51,7 +51,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update the name of the os-update schedule "zzz" of server "xxx"`, - "$ stackit beta server os-update schedule update zzz --server-id=xxx --name=newname"), + "$ stackit server os-update schedule update zzz --server-id=xxx --name=newname"), ), Args: args.SingleArg(scheduleIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/os-update/schedule/update/update_test.go b/internal/cmd/server/os-update/schedule/update/update_test.go similarity index 100% rename from internal/cmd/beta/server/os-update/schedule/update/update_test.go rename to internal/cmd/server/os-update/schedule/update/update_test.go diff --git a/internal/cmd/beta/server/public-ip/attach/attach.go b/internal/cmd/server/public-ip/attach/attach.go similarity index 98% rename from internal/cmd/beta/server/public-ip/attach/attach.go rename to internal/cmd/server/public-ip/attach/attach.go index ff6e6c05d..848a913b4 100644 --- a/internal/cmd/beta/server/public-ip/attach/attach.go +++ b/internal/cmd/server/public-ip/attach/attach.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Attach a public IP with ID "xxx" to a server with ID "yyy"`, - `$ stackit beta server public-ip attach xxx --server-id yyy`, + `$ stackit server public-ip attach xxx --server-id yyy`, )), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/public-ip/attach/attach_test.go b/internal/cmd/server/public-ip/attach/attach_test.go similarity index 100% rename from internal/cmd/beta/server/public-ip/attach/attach_test.go rename to internal/cmd/server/public-ip/attach/attach_test.go diff --git a/internal/cmd/beta/server/public-ip/detach/detach.go b/internal/cmd/server/public-ip/detach/detach.go similarity index 98% rename from internal/cmd/beta/server/public-ip/detach/detach.go rename to internal/cmd/server/public-ip/detach/detach.go index a5c0d366e..809b76759 100644 --- a/internal/cmd/beta/server/public-ip/detach/detach.go +++ b/internal/cmd/server/public-ip/detach/detach.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Detaches a public IP with ID "xxx" from a server with ID "yyy"`, - `$ stackit beta server public-ip detach xxx --server-id yyy`, + `$ stackit server public-ip detach xxx --server-id yyy`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/public-ip/detach/detach_test.go b/internal/cmd/server/public-ip/detach/detach_test.go similarity index 100% rename from internal/cmd/beta/server/public-ip/detach/detach_test.go rename to internal/cmd/server/public-ip/detach/detach_test.go diff --git a/internal/cmd/beta/server/public-ip/public_ip.go b/internal/cmd/server/public-ip/public_ip.go similarity index 80% rename from internal/cmd/beta/server/public-ip/public_ip.go rename to internal/cmd/server/public-ip/public_ip.go index 662d00aa5..0bfafbcbd 100644 --- a/internal/cmd/beta/server/public-ip/public_ip.go +++ b/internal/cmd/server/public-ip/public_ip.go @@ -1,8 +1,8 @@ package publicip import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip/attach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/public-ip/detach" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/public-ip/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/public-ip/detach" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/reboot/reboot.go b/internal/cmd/server/reboot/reboot.go similarity index 97% rename from internal/cmd/beta/server/reboot/reboot.go rename to internal/cmd/server/reboot/reboot.go index 2c32ac2c4..80aed47b3 100644 --- a/internal/cmd/beta/server/reboot/reboot.go +++ b/internal/cmd/server/reboot/reboot.go @@ -41,11 +41,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Perform a soft reboot of a server with ID "xxx"`, - "$ stackit beta server reboot xxx", + "$ stackit server reboot xxx", ), examples.NewExample( `Perform a hard reboot of a server with ID "xxx"`, - "$ stackit beta server reboot xxx --hard", + "$ stackit server reboot xxx --hard", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/reboot/reboot_test.go b/internal/cmd/server/reboot/reboot_test.go similarity index 100% rename from internal/cmd/beta/server/reboot/reboot_test.go rename to internal/cmd/server/reboot/reboot_test.go diff --git a/internal/cmd/beta/server/rescue/rescue.go b/internal/cmd/server/rescue/rescue.go similarity index 98% rename from internal/cmd/beta/server/rescue/rescue.go rename to internal/cmd/server/rescue/rescue.go index 69f4be349..81eabcab2 100644 --- a/internal/cmd/beta/server/rescue/rescue.go +++ b/internal/cmd/server/rescue/rescue.go @@ -41,7 +41,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Rescue an existing server with ID "xxx" using image with ID "yyy" as boot volume`, - "$ stackit beta server rescue xxx --image-id yyy", + "$ stackit server rescue xxx --image-id yyy", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/rescue/rescue_test.go b/internal/cmd/server/rescue/rescue_test.go similarity index 100% rename from internal/cmd/beta/server/rescue/rescue_test.go rename to internal/cmd/server/rescue/rescue_test.go diff --git a/internal/cmd/beta/server/resize/resize.go b/internal/cmd/server/resize/resize.go similarity index 98% rename from internal/cmd/beta/server/resize/resize.go rename to internal/cmd/server/resize/resize.go index 6cd7da807..d0112b723 100644 --- a/internal/cmd/beta/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -41,7 +41,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Resize a server with ID "xxx" to machine type "yyy"`, - "$ stackit beta server resize xxx --machine-type yyy", + "$ stackit server resize xxx --machine-type yyy", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/resize/resize_test.go b/internal/cmd/server/resize/resize_test.go similarity index 100% rename from internal/cmd/beta/server/resize/resize_test.go rename to internal/cmd/server/resize/resize_test.go diff --git a/internal/cmd/server/server.go b/internal/cmd/server/server.go new file mode 100644 index 000000000..209b19e1b --- /dev/null +++ b/internal/cmd/server/server.go @@ -0,0 +1,69 @@ +package server + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/command" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/console" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/deallocate" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/log" + machinetype "github.com/stackitcloud/stackit-cli/internal/cmd/server/machine-type" + networkinterface "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface" + osUpdate "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update" + publicip "github.com/stackitcloud/stackit-cli/internal/cmd/server/public-ip" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/reboot" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/rescue" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/resize" + serviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/start" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/stop" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/unrescue" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "server", + Short: "Provides functionality for servers", + Long: "Provides functionality for servers.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(backup.NewCmd(p)) + cmd.AddCommand(command.NewCmd(p)) + cmd.AddCommand(create.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(publicip.NewCmd(p)) + cmd.AddCommand(serviceaccount.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) + cmd.AddCommand(volume.NewCmd(p)) + cmd.AddCommand(networkinterface.NewCmd(p)) + cmd.AddCommand(console.NewCmd(p)) + cmd.AddCommand(log.NewCmd(p)) + cmd.AddCommand(start.NewCmd(p)) + cmd.AddCommand(stop.NewCmd(p)) + cmd.AddCommand(reboot.NewCmd(p)) + cmd.AddCommand(deallocate.NewCmd(p)) + cmd.AddCommand(resize.NewCmd(p)) + cmd.AddCommand(rescue.NewCmd(p)) + cmd.AddCommand(unrescue.NewCmd(p)) + cmd.AddCommand(osUpdate.NewCmd(p)) + cmd.AddCommand(machinetype.NewCmd(p)) +} diff --git a/internal/cmd/beta/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go similarity index 97% rename from internal/cmd/beta/server/service-account/attach/attach.go rename to internal/cmd/server/service-account/attach/attach.go index cb822440d..49f7a1aa4 100644 --- a/internal/cmd/beta/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy"`, - "$ stackit beta server service-account attach xxx@sa.stackit.cloud --server-id yyy", + "$ stackit server service-account attach xxx@sa.stackit.cloud --server-id yyy", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/service-account/attach/attach_test.go b/internal/cmd/server/service-account/attach/attach_test.go similarity index 100% rename from internal/cmd/beta/server/service-account/attach/attach_test.go rename to internal/cmd/server/service-account/attach/attach_test.go diff --git a/internal/cmd/beta/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go similarity index 97% rename from internal/cmd/beta/server/service-account/detach/detach.go rename to internal/cmd/server/service-account/detach/detach.go index e6ed7df88..aa3983c58 100644 --- a/internal/cmd/beta/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy"`, - "$ stackit beta server service-account detach xxx@sa.stackit.cloud --server-id yyy", + "$ stackit server service-account detach xxx@sa.stackit.cloud --server-id yyy", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/service-account/detach/detach_test.go b/internal/cmd/server/service-account/detach/detach_test.go similarity index 100% rename from internal/cmd/beta/server/service-account/detach/detach_test.go rename to internal/cmd/server/service-account/detach/detach_test.go diff --git a/internal/cmd/beta/server/service-account/list/list.go b/internal/cmd/server/service-account/list/list.go similarity index 95% rename from internal/cmd/beta/server/service-account/list/list.go rename to internal/cmd/server/service-account/list/list.go index 0b5120e7d..d9288a246 100644 --- a/internal/cmd/beta/server/service-account/list/list.go +++ b/internal/cmd/server/service-account/list/list.go @@ -39,15 +39,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all attached service accounts for a server with ID "xxx"`, - "$ stackit beta server service-account list --server-id xxx", + "$ stackit server service-account list --server-id xxx", ), examples.NewExample( `List up to 10 attached service accounts for a server with ID "xxx"`, - "$ stackit beta server service-account list --server-id xxx --limit 10", + "$ stackit server service-account list --server-id xxx --limit 10", ), examples.NewExample( `List all attached service accounts for a server with ID "xxx" in JSON format`, - "$ stackit beta server service-account list --server-id xxx --output-format json", + "$ stackit server service-account list --server-id xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/server/service-account/list/list_test.go b/internal/cmd/server/service-account/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/service-account/list/list_test.go rename to internal/cmd/server/service-account/list/list_test.go diff --git a/internal/cmd/beta/server/service-account/service-account.go b/internal/cmd/server/service-account/service-account.go similarity index 71% rename from internal/cmd/beta/server/service-account/service-account.go rename to internal/cmd/server/service-account/service-account.go index e0907d4f1..0739d29a7 100644 --- a/internal/cmd/beta/server/service-account/service-account.go +++ b/internal/cmd/server/service-account/service-account.go @@ -3,9 +3,9 @@ package serviceaccount import ( "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/attach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/detach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/service-account/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/detach" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/list" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/server/start/start.go b/internal/cmd/server/start/start.go similarity index 98% rename from internal/cmd/beta/server/start/start.go rename to internal/cmd/server/start/start.go index e9f908703..7daec696f 100644 --- a/internal/cmd/beta/server/start/start.go +++ b/internal/cmd/server/start/start.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Start an existing server with ID "xxx"`, - "$ stackit beta server start xxx", + "$ stackit server start xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/start/start_test.go b/internal/cmd/server/start/start_test.go similarity index 100% rename from internal/cmd/beta/server/start/start_test.go rename to internal/cmd/server/start/start_test.go diff --git a/internal/cmd/beta/server/stop/stop.go b/internal/cmd/server/stop/stop.go similarity index 98% rename from internal/cmd/beta/server/stop/stop.go rename to internal/cmd/server/stop/stop.go index 53952101f..1201c778b 100644 --- a/internal/cmd/beta/server/stop/stop.go +++ b/internal/cmd/server/stop/stop.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Stop an existing server with ID "xxx"`, - "$ stackit beta server stop xxx", + "$ stackit server stop xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/stop/stop_test.go b/internal/cmd/server/stop/stop_test.go similarity index 100% rename from internal/cmd/beta/server/stop/stop_test.go rename to internal/cmd/server/stop/stop_test.go diff --git a/internal/cmd/beta/server/unrescue/unrescue.go b/internal/cmd/server/unrescue/unrescue.go similarity index 98% rename from internal/cmd/beta/server/unrescue/unrescue.go rename to internal/cmd/server/unrescue/unrescue.go index 647a15e85..5fc2d7c42 100644 --- a/internal/cmd/beta/server/unrescue/unrescue.go +++ b/internal/cmd/server/unrescue/unrescue.go @@ -37,7 +37,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Unrescue an existing server with ID "xxx"`, - "$ stackit beta server unrescue xxx", + "$ stackit server unrescue xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/unrescue/unrescue_test.go b/internal/cmd/server/unrescue/unrescue_test.go similarity index 100% rename from internal/cmd/beta/server/unrescue/unrescue_test.go rename to internal/cmd/server/unrescue/unrescue_test.go diff --git a/internal/cmd/beta/server/update/update.go b/internal/cmd/server/update/update.go similarity index 96% rename from internal/cmd/beta/server/update/update.go rename to internal/cmd/server/update/update.go index 223942890..d7e06d95a 100644 --- a/internal/cmd/beta/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -43,11 +43,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update server with ID "xxx" with new name "server-1-new"`, - `$ stackit beta server update xxx --name server-1-new`, + `$ stackit server update xxx --name server-1-new`, ), examples.NewExample( `Update server with ID "xxx" with new name "server-1-new" and label(s)`, - `$ stackit beta server update xxx --name server-1-new --labels key=value,foo=bar`, + `$ stackit server update xxx --name server-1-new --labels key=value,foo=bar`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/update/update_test.go b/internal/cmd/server/update/update_test.go similarity index 100% rename from internal/cmd/beta/server/update/update_test.go rename to internal/cmd/server/update/update_test.go diff --git a/internal/cmd/beta/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go similarity index 97% rename from internal/cmd/beta/server/volume/attach/attach.go rename to internal/cmd/server/volume/attach/attach.go index 5a5f3b484..61eab4ba0 100644 --- a/internal/cmd/beta/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -44,11 +44,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Attach a volume with ID "xxx" to a server with ID "yyy"`, - `$ stackit beta server volume attach xxx --server-id yyy`, + `$ stackit server volume attach xxx --server-id yyy`, ), examples.NewExample( `Attach a volume with ID "xxx" to a server with ID "yyy" and enable deletion on termination`, - `$ stackit beta server volume attach xxx --server-id yyy --delete-on-termination`, + `$ stackit server volume attach xxx --server-id yyy --delete-on-termination`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/volume/attach/attach_test.go b/internal/cmd/server/volume/attach/attach_test.go similarity index 100% rename from internal/cmd/beta/server/volume/attach/attach_test.go rename to internal/cmd/server/volume/attach/attach_test.go diff --git a/internal/cmd/beta/server/volume/describe/describe.go b/internal/cmd/server/volume/describe/describe.go similarity index 95% rename from internal/cmd/beta/server/volume/describe/describe.go rename to internal/cmd/server/volume/describe/describe.go index 8ec3b488a..9336183a5 100644 --- a/internal/cmd/beta/server/volume/describe/describe.go +++ b/internal/cmd/server/volume/describe/describe.go @@ -40,15 +40,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Get details of the attachment of volume with ID "xxx" to server with ID "yyy"`, - `$ stackit beta server volume describe xxx --server-id yyy`, + `$ stackit server volume describe xxx --server-id yyy`, ), examples.NewExample( `Get details of the attachment of volume with ID "xxx" to server with ID "yyy" in JSON format`, - `$ stackit beta server volume describe xxx --server-id yyy --output-format json`, + `$ stackit server volume describe xxx --server-id yyy --output-format json`, ), examples.NewExample( `Get details of the attachment of volume with ID "xxx" to server with ID "yyy" in yaml format`, - `$ stackit beta server volume describe xxx --server-id yyy --output-format yaml`, + `$ stackit server volume describe xxx --server-id yyy --output-format yaml`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/volume/describe/describe_test.go b/internal/cmd/server/volume/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/server/volume/describe/describe_test.go rename to internal/cmd/server/volume/describe/describe_test.go diff --git a/internal/cmd/beta/server/volume/detach/detach.go b/internal/cmd/server/volume/detach/detach.go similarity index 98% rename from internal/cmd/beta/server/volume/detach/detach.go rename to internal/cmd/server/volume/detach/detach.go index 858d749e5..826f1881c 100644 --- a/internal/cmd/beta/server/volume/detach/detach.go +++ b/internal/cmd/server/volume/detach/detach.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Detaches a volume with ID "xxx" from a server with ID "yyy"`, - `$ stackit beta server volume detach xxx --server-id yyy`, + `$ stackit server volume detach xxx --server-id yyy`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/volume/detach/detach_test.go b/internal/cmd/server/volume/detach/detach_test.go similarity index 100% rename from internal/cmd/beta/server/volume/detach/detach_test.go rename to internal/cmd/server/volume/detach/detach_test.go diff --git a/internal/cmd/beta/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go similarity index 97% rename from internal/cmd/beta/server/volume/list/list.go rename to internal/cmd/server/volume/list/list.go index 54bde7194..dd7509d7f 100644 --- a/internal/cmd/beta/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -38,10 +38,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `List all volumes for a server with ID "xxx"`, - "$ stackit beta server volume list --server-id xxx"), + "$ stackit server volume list --server-id xxx"), examples.NewExample( `List all volumes for a server with ID "xxx" in JSON format`, - "$ stackit beta server volumes list --server-id xxx --output-format json"), + "$ stackit server volumes list --server-id xxx --output-format json"), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() diff --git a/internal/cmd/beta/server/volume/list/list_test.go b/internal/cmd/server/volume/list/list_test.go similarity index 100% rename from internal/cmd/beta/server/volume/list/list_test.go rename to internal/cmd/server/volume/list/list_test.go diff --git a/internal/cmd/beta/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go similarity index 98% rename from internal/cmd/beta/server/volume/update/update.go rename to internal/cmd/server/volume/update/update.go index 7b90de143..5722808ef 100644 --- a/internal/cmd/beta/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -44,7 +44,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update a volume with ID "xxx" of a server with ID "yyy" and enables delete on termination`, - `$ stackit beta server volume update xxx --server-id yyy --delete-on-termination`, + `$ stackit server volume update xxx --server-id yyy --delete-on-termination`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/server/volume/update/update_test.go b/internal/cmd/server/volume/update/update_test.go similarity index 100% rename from internal/cmd/beta/server/volume/update/update_test.go rename to internal/cmd/server/volume/update/update_test.go diff --git a/internal/cmd/beta/server/volume/volume.go b/internal/cmd/server/volume/volume.go similarity index 65% rename from internal/cmd/beta/server/volume/volume.go rename to internal/cmd/server/volume/volume.go index 77714f625..c851bbcd7 100644 --- a/internal/cmd/beta/server/volume/volume.go +++ b/internal/cmd/server/volume/volume.go @@ -1,11 +1,11 @@ package volume import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/attach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/detach" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/server/volume/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/attach" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/detach" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/volume/create/create.go b/internal/cmd/volume/create/create.go similarity index 94% rename from internal/cmd/beta/volume/create/create.go rename to internal/cmd/volume/create/create.go index a00446f90..90b20d813 100644 --- a/internal/cmd/beta/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -54,19 +54,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a volume with availability zone "eu01-1" and size 64 GB`, - `$ stackit beta volume create --availability-zone eu01-1 --size 64`, + `$ stackit volume create --availability-zone eu01-1 --size 64`, ), examples.NewExample( `Create a volume with availability zone "eu01-1", size 64 GB and labels`, - `$ stackit beta volume create --availability-zone eu01-1 --size 64 --labels key=value,foo=bar`, + `$ stackit volume create --availability-zone eu01-1 --size 64 --labels key=value,foo=bar`, ), examples.NewExample( `Create a volume with name "volume-1", from a source image with ID "xxx"`, - `$ stackit beta volume create --availability-zone eu01-1 --name volume-1 --source-id xxx --source-type image`, + `$ stackit volume create --availability-zone eu01-1 --name volume-1 --source-id xxx --source-type image`, ), examples.NewExample( `Create a volume with availability zone "eu01-1", performance class "storage_premium_perf1" and size 64 GB`, - `$ stackit beta volume create --availability-zone eu01-1 --performance-class storage_premium_perf1 --size 64`, + `$ stackit volume create --availability-zone eu01-1 --performance-class storage_premium_perf1 --size 64`, ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/volume/create/create_test.go b/internal/cmd/volume/create/create_test.go similarity index 100% rename from internal/cmd/beta/volume/create/create_test.go rename to internal/cmd/volume/create/create_test.go diff --git a/internal/cmd/beta/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go similarity index 98% rename from internal/cmd/beta/volume/delete/delete.go rename to internal/cmd/volume/delete/delete.go index 068c0f2ea..d07a9e8f5 100644 --- a/internal/cmd/beta/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -40,7 +40,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Delete volume with ID "xxx"`, - "$ stackit beta volume delete xxx", + "$ stackit volume delete xxx", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/volume/delete/delete_test.go b/internal/cmd/volume/delete/delete_test.go similarity index 100% rename from internal/cmd/beta/volume/delete/delete_test.go rename to internal/cmd/volume/delete/delete_test.go diff --git a/internal/cmd/beta/volume/describe/describe.go b/internal/cmd/volume/describe/describe.go similarity index 97% rename from internal/cmd/beta/volume/describe/describe.go rename to internal/cmd/volume/describe/describe.go index b69b32332..e77073ea2 100644 --- a/internal/cmd/beta/volume/describe/describe.go +++ b/internal/cmd/volume/describe/describe.go @@ -39,11 +39,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a volume with ID "xxx"`, - "$ stackit beta volume describe xxx", + "$ stackit volume describe xxx", ), examples.NewExample( `Show details of a volume with ID "xxx" in JSON format`, - "$ stackit beta volume describe xxx --output-format json", + "$ stackit volume describe xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/volume/describe/describe_test.go b/internal/cmd/volume/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/volume/describe/describe_test.go rename to internal/cmd/volume/describe/describe_test.go diff --git a/internal/cmd/beta/volume/list/list.go b/internal/cmd/volume/list/list.go similarity index 96% rename from internal/cmd/beta/volume/list/list.go rename to internal/cmd/volume/list/list.go index f283037a3..02c643014 100644 --- a/internal/cmd/beta/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -40,19 +40,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all volumes`, - "$ stackit beta volume list", + "$ stackit volume list", ), examples.NewExample( `Lists all volumes which contains the label xxx`, - "$ stackit beta volume list --label-selector xxx", + "$ stackit volume list --label-selector xxx", ), examples.NewExample( `Lists all volumes in JSON format`, - "$ stackit beta volume list --output-format json", + "$ stackit volume list --output-format json", ), examples.NewExample( `Lists up to 10 volumes`, - "$ stackit beta volume list --limit 10", + "$ stackit volume list --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/volume/list/list_test.go b/internal/cmd/volume/list/list_test.go similarity index 100% rename from internal/cmd/beta/volume/list/list_test.go rename to internal/cmd/volume/list/list_test.go diff --git a/internal/cmd/beta/volume/performance-class/describe/describe.go b/internal/cmd/volume/performance-class/describe/describe.go similarity index 96% rename from internal/cmd/beta/volume/performance-class/describe/describe.go rename to internal/cmd/volume/performance-class/describe/describe.go index 9d8537858..ade26f34a 100644 --- a/internal/cmd/beta/volume/performance-class/describe/describe.go +++ b/internal/cmd/volume/performance-class/describe/describe.go @@ -39,11 +39,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Show details of a volume performance class with name "xxx"`, - "$ stackit beta volume performance-class describe xxx", + "$ stackit volume performance-class describe xxx", ), examples.NewExample( `Show details of a volume performance class with name "xxx" in JSON format`, - "$ stackit beta volume performance-class describe xxx --output-format json", + "$ stackit volume performance-class describe xxx --output-format json", ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/volume/performance-class/describe/describe_test.go b/internal/cmd/volume/performance-class/describe/describe_test.go similarity index 100% rename from internal/cmd/beta/volume/performance-class/describe/describe_test.go rename to internal/cmd/volume/performance-class/describe/describe_test.go diff --git a/internal/cmd/beta/volume/performance-class/list/list.go b/internal/cmd/volume/performance-class/list/list.go similarity index 94% rename from internal/cmd/beta/volume/performance-class/list/list.go rename to internal/cmd/volume/performance-class/list/list.go index 9e51bd0d6..4449a5f3e 100644 --- a/internal/cmd/beta/volume/performance-class/list/list.go +++ b/internal/cmd/volume/performance-class/list/list.go @@ -41,19 +41,19 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Lists all volume performance classes`, - "$ stackit beta volume performance-class list", + "$ stackit volume performance-class list", ), examples.NewExample( `Lists all volume performance classes which contains the label xxx`, - "$ stackit beta volume performance-class list --label-selector xxx", + "$ stackit volume performance-class list --label-selector xxx", ), examples.NewExample( `Lists all volume performance classes in JSON format`, - "$ stackit beta volume performance-class list --output-format json", + "$ stackit volume performance-class list --output-format json", ), examples.NewExample( `Lists up to 10 volume performance classes`, - "$ stackit beta volume performance-class list --limit 10", + "$ stackit volume performance-class list --limit 10", ), ), RunE: func(cmd *cobra.Command, _ []string) error { diff --git a/internal/cmd/beta/volume/performance-class/list/list_test.go b/internal/cmd/volume/performance-class/list/list_test.go similarity index 100% rename from internal/cmd/beta/volume/performance-class/list/list_test.go rename to internal/cmd/volume/performance-class/list/list_test.go diff --git a/internal/cmd/beta/volume/performance-class/performance_class.go b/internal/cmd/volume/performance-class/performance_class.go similarity index 80% rename from internal/cmd/beta/volume/performance-class/performance_class.go rename to internal/cmd/volume/performance-class/performance_class.go index 8df1e19fe..4f159606e 100644 --- a/internal/cmd/beta/volume/performance-class/performance_class.go +++ b/internal/cmd/volume/performance-class/performance_class.go @@ -1,8 +1,8 @@ package performanceclass import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/performance-class/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/performance-class/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/performance-class/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/performance-class/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/beta/volume/resize/resize.go b/internal/cmd/volume/resize/resize.go similarity index 98% rename from internal/cmd/beta/volume/resize/resize.go rename to internal/cmd/volume/resize/resize.go index fdcd882a2..7f966a2e3 100644 --- a/internal/cmd/beta/volume/resize/resize.go +++ b/internal/cmd/volume/resize/resize.go @@ -39,7 +39,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Resize volume with ID "xxx" with new size 10 GB`, - `$ stackit beta volume resize xxx --size 10`, + `$ stackit volume resize xxx --size 10`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/volume/resize/resize_test.go b/internal/cmd/volume/resize/resize_test.go similarity index 100% rename from internal/cmd/beta/volume/resize/resize_test.go rename to internal/cmd/volume/resize/resize_test.go diff --git a/internal/cmd/beta/volume/update/update.go b/internal/cmd/volume/update/update.go similarity index 94% rename from internal/cmd/beta/volume/update/update.go rename to internal/cmd/volume/update/update.go index ffc5273cb..f7afad38a 100644 --- a/internal/cmd/beta/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -45,15 +45,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Update volume with ID "xxx" with new name "volume-1-new"`, - `$ stackit beta volume update xxx --name volume-1-new`, + `$ stackit volume update xxx --name volume-1-new`, ), examples.NewExample( `Update volume with ID "xxx" with new name "volume-1-new" and new description "volume-1-desc-new"`, - `$ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new`, + `$ stackit volume update xxx --name volume-1-new --description volume-1-desc-new`, ), examples.NewExample( `Update volume with ID "xxx" with new name "volume-1-new", new description "volume-1-desc-new" and label(s)`, - `$ stackit beta volume update xxx --name volume-1-new --description volume-1-desc-new --labels key=value,foo=bar`, + `$ stackit volume update xxx --name volume-1-new --description volume-1-desc-new --labels key=value,foo=bar`, ), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/beta/volume/update/update_test.go b/internal/cmd/volume/update/update_test.go similarity index 100% rename from internal/cmd/beta/volume/update/update_test.go rename to internal/cmd/volume/update/update_test.go diff --git a/internal/cmd/beta/volume/volume.go b/internal/cmd/volume/volume.go similarity index 65% rename from internal/cmd/beta/volume/volume.go rename to internal/cmd/volume/volume.go index 5b03326bf..fe334cb6f 100644 --- a/internal/cmd/beta/volume/volume.go +++ b/internal/cmd/volume/volume.go @@ -1,13 +1,13 @@ package volume import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/list" - performanceclass "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/performance-class" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/resize" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/volume/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/list" + performanceclass "github.com/stackitcloud/stackit-cli/internal/cmd/volume/performance-class" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/resize" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" From ab5ae06c117570404c55dd8e34519fdf49582922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Mon, 10 Mar 2025 09:55:37 +0100 Subject: [PATCH 220/619] chore (postgresflex): Fix potential nil pointer and add test cases (#626) * fix: testcase and fixes for nil pointer exceptions in output functions * fix: integrate review findings --- .../postgresflex/backup/describe/describe.go | 11 ++-- .../backup/describe/describe_test.go | 40 ++++++++++++- internal/cmd/postgresflex/backup/list/list.go | 2 +- .../cmd/postgresflex/backup/list/list_test.go | 53 ++++++++++++++++- .../cmd/postgresflex/instance/clone/clone.go | 11 ++-- .../postgresflex/instance/clone/clone_test.go | 39 +++++++++++-- .../postgresflex/instance/create/create.go | 11 ++-- .../instance/create/create_test.go | 42 ++++++++++++-- .../instance/describe/describe.go | 25 +++++--- .../instance/describe/describe_test.go | 58 ++++++++++++++++++- .../postgresflex/instance/list/list_test.go | 49 ++++++++++++++-- .../postgresflex/instance/update/update.go | 12 ++-- .../instance/update/update_test.go | 45 ++++++++++++-- internal/cmd/postgresflex/options/options.go | 9 ++- .../cmd/postgresflex/options/options_test.go | 51 +++++++++++++++- .../cmd/postgresflex/user/create/create.go | 26 +++++---- .../postgresflex/user/create/create_test.go | 45 ++++++++++++-- .../user/describe/describe_test.go | 37 +++++++++++- .../cmd/postgresflex/user/list/list_test.go | 36 ++++++++++-- .../user/reset-password/reset_password.go | 17 ++++-- .../reset-password/reset_password_test.go | 38 +++++++++++- internal/pkg/utils/utils.go | 9 +++ 22 files changed, 580 insertions(+), 86 deletions(-) diff --git a/internal/cmd/postgresflex/backup/describe/describe.go b/internal/cmd/postgresflex/backup/describe/describe.go index 80cae356a..32cee719f 100644 --- a/internal/cmd/postgresflex/backup/describe/describe.go +++ b/internal/cmd/postgresflex/backup/describe/describe.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe backup for PostgreSQL Flex instance: %w", err) } - return outputResult(p, cmd, model.OutputFormat, *resp.Item) + return outputResult(p, model.OutputFormat, *resp.Item) }, } configureFlags(cmd) @@ -106,8 +106,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle return req } -func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, backup postgresflex.Backup) error { - backupStartTime, err := time.Parse(time.RFC3339, *backup.StartTime) +func outputResult(p *print.Printer, outputFormat string, backup postgresflex.Backup) error { + if backup.StartTime == nil || *backup.StartTime == "" { + return fmt.Errorf("start time not defined") + } + backupStartTime, err := time.Parse(time.RFC3339, utils.PtrString(backup.StartTime)) if err != nil { return fmt.Errorf("parse backup start time: %w", err) } @@ -119,7 +122,7 @@ func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, bac if err != nil { return fmt.Errorf("marshal backup for PostgreSQL Flex backup: %w", err) } - cmd.Println(string(details)) + p.Outputln(string(details)) return nil case print.YAMLOutputFormat: diff --git a/internal/cmd/postgresflex/backup/describe/describe_test.go b/internal/cmd/postgresflex/backup/describe/describe_test.go index c2aab7317..e3f8dd6f1 100644 --- a/internal/cmd/postgresflex/backup/describe/describe_test.go +++ b/internal/cmd/postgresflex/backup/describe/describe_test.go @@ -3,12 +3,14 @@ package describe import ( "context" "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -235,3 +237,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + backup postgresflex.Backup + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, true}, + {"standard", args{outputFormat: "", backup: postgresflex.Backup{StartTime: utils.Ptr(time.Now().Format(time.RFC3339))}}, false}, + {"complete", args{outputFormat: "", backup: postgresflex.Backup{ + EndTime: utils.Ptr(time.Now().Format(time.RFC3339)), + Id: utils.Ptr("id"), + Labels: &[]string{"foo", "bar", "baz"}, + Name: utils.Ptr("name"), + Options: &map[string]string{"test1": "test1", "test2": "test2"}, + Size: utils.Ptr(int64(42)), + StartTime: utils.Ptr(time.Now().Format(time.RFC3339)), + }}, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.backup); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index a8416f602..0b7ab5234 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -157,7 +157,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []postgresflex. for i := range backups { backup := backups[i] - backupStartTime, err := time.Parse(time.RFC3339, *backup.StartTime) + backupStartTime, err := time.Parse(time.RFC3339, utils.PtrString(backup.StartTime)) if err != nil { return fmt.Errorf("parse backup start time: %w", err) } diff --git a/internal/cmd/postgresflex/backup/list/list_test.go b/internal/cmd/postgresflex/backup/list/list_test.go index 242bc9563..302aed436 100644 --- a/internal/cmd/postgresflex/backup/list/list_test.go +++ b/internal/cmd/postgresflex/backup/list/list_test.go @@ -3,13 +3,14 @@ package list import ( "context" "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -205,3 +206,49 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + backups []postgresflex.Backup + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, false}, + {"standard", args{outputFormat: "", backups: []postgresflex.Backup{}}, false}, + {"complete", args{outputFormat: "", backups: []postgresflex.Backup{ + { + EndTime: utils.Ptr(time.Now().Format(time.RFC3339)), + Id: utils.Ptr("id"), + Labels: &[]string{"foo", "bar", "baz"}, + Name: utils.Ptr("name"), + Options: &map[string]string{"test1": "test1", "test2": "test2"}, + Size: utils.Ptr(int64(42)), + StartTime: utils.Ptr(time.Now().Format(time.RFC3339)), + }, + { + EndTime: utils.Ptr(time.Now().Format(time.RFC3339)), + Id: utils.Ptr("id"), + Labels: &[]string{"foo", "bar", "baz"}, + Name: utils.Ptr("name"), + Options: &map[string]string{"test1": "test1", "test2": "test2"}, + Size: utils.Ptr(int64(42)), + StartTime: utils.Ptr(time.Now().Format(time.RFC3339)), + }, + }, + }, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.backups); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index 4ca79de4b..56dde3809 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -108,7 +108,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, instanceLabel, instanceId, resp) + return outputResult(p, model.OutputFormat, model.Async, instanceLabel, instanceId, resp) }, } configureFlags(cmd) @@ -205,8 +205,11 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, async bool, instanceLabel, instanceId string, resp *postgresflex.CloneInstanceResponse) error { + if resp == nil { + return fmt.Errorf("response not set") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -225,7 +228,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel, instanceId return nil default: operationState := "Cloned" - if model.Async { + if async { operationState = "Triggered cloning of" } p.Info("%s instance from instance %q. New Instance ID: %s\n", operationState, instanceLabel, instanceId) diff --git a/internal/cmd/postgresflex/instance/clone/clone_test.go b/internal/cmd/postgresflex/instance/clone/clone_test.go index 47906de21..dfb8e6e67 100644 --- a/internal/cmd/postgresflex/instance/clone/clone_test.go +++ b/internal/cmd/postgresflex/instance/clone/clone_test.go @@ -6,13 +6,12 @@ import ( "testing" "time" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -529,3 +528,35 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + OutputFormat string + instanceLabel string + instanceId string + async bool + resp *postgresflex.CloneInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, true}, + {"standard", args{ + instanceLabel: "foo", + instanceId: "bar", + resp: &postgresflex.CloneInstanceResponse{InstanceId: utils.Ptr("id")}, + }, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.OutputFormat, tt.args.async, tt.args.instanceLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 062107375..41217ffa5 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -133,7 +133,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, instanceId, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -273,8 +273,11 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel, instanceId string, resp *postgresflex.CreateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("no response passed") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -293,7 +296,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) diff --git a/internal/cmd/postgresflex/instance/create/create_test.go b/internal/cmd/postgresflex/instance/create/create_test.go index 8b9bb9450..401665161 100644 --- a/internal/cmd/postgresflex/instance/create/create_test.go +++ b/internal/cmd/postgresflex/instance/create/create_test.go @@ -5,13 +5,12 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -521,3 +520,38 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + instanceId string + resp *postgresflex.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, true}, + {"standard", args{ + outputFormat: "", + async: false, + projectLabel: "label", + instanceId: "4711", + resp: &postgresflex.CreateInstanceResponse{Id: utils.Ptr("id")}, + }, + false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/instance/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index c65ebfda1..7e99a129a 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -102,6 +101,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle } func outputResult(p *print.Printer, outputFormat string, instance *postgresflex.Instance) error { + if instance == nil { + return fmt.Errorf("no response passed") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -122,11 +124,10 @@ func outputResult(p *print.Printer, outputFormat string, instance *postgresflex. default: acls := "" if instance.HasAcl() && instance.Acl.HasItems() { - aclsArray := *instance.Acl.Items - acls = strings.Join(aclsArray, ",") + acls = utils.JoinStringPtr(instance.Acl.Items, ",") } - instanceType, err := postgresflexUtils.GetInstanceType(*instance.Replicas) + instanceType, err := postgresflexUtils.GetInstanceType(utils.PtrValue(instance.Replicas)) if err != nil { // Should never happen instanceType = "" @@ -139,21 +140,27 @@ func outputResult(p *print.Printer, outputFormat string, instance *postgresflex. table.AddSeparator() table.AddRow("STATUS", cases.Title(language.English).String(utils.PtrString(instance.Status))) table.AddSeparator() - table.AddRow("STORAGE SIZE (GB)", utils.PtrString(instance.Storage.Size)) + if instance.Storage != nil { + table.AddRow("STORAGE SIZE (GB)", utils.PtrString(instance.Storage.Size)) + } table.AddSeparator() table.AddRow("VERSION", utils.PtrString(instance.Version)) table.AddSeparator() table.AddRow("ACL", acls) table.AddSeparator() - table.AddRow("FLAVOR DESCRIPTION", utils.PtrString(instance.Flavor.Description)) + if instance.Flavor != nil { + table.AddRow("FLAVOR DESCRIPTION", utils.PtrString(instance.Flavor.Description)) + } table.AddSeparator() table.AddRow("TYPE", instanceType) table.AddSeparator() table.AddRow("REPLICAS", utils.PtrString(instance.Replicas)) table.AddSeparator() - table.AddRow("CPU", utils.PtrString(instance.Flavor.Cpu)) - table.AddSeparator() - table.AddRow("RAM (GB)", utils.PtrString(instance.Flavor.Memory)) + if instance.Flavor != nil { + table.AddRow("CPU", utils.PtrString(instance.Flavor.Cpu)) + table.AddSeparator() + table.AddRow("RAM (GB)", utils.PtrString(instance.Flavor.Memory)) + } table.AddSeparator() table.AddRow("BACKUP SCHEDULE (UTC)", utils.PtrString(instance.BackupSchedule)) table.AddSeparator() diff --git a/internal/cmd/postgresflex/instance/describe/describe_test.go b/internal/cmd/postgresflex/instance/describe/describe_test.go index b71920a5b..825e481f1 100644 --- a/internal/cmd/postgresflex/instance/describe/describe_test.go +++ b/internal/cmd/postgresflex/instance/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -216,3 +215,56 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + instance *postgresflex.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, true}, + {"standard", args{ + outputFormat: "", + instance: &postgresflex.Instance{}, + }, false}, + {"complete", args{ + outputFormat: "", + instance: &postgresflex.Instance{ + Acl: &postgresflex.ACL{ + Items: &[]string{}, + }, + BackupSchedule: new(string), + Flavor: &postgresflex.Flavor{ + Cpu: new(int64), + Description: new(string), + Id: new(string), + Memory: new(int64), + }, + Id: new(string), + Name: new(string), + Options: &map[string]string{}, + Replicas: new(int64), + Status: new(string), + Storage: &postgresflex.Storage{ + Class: new(string), + Size: new(int64), + }, + Version: new(string), + }, + }, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/instance/list/list_test.go b/internal/cmd/postgresflex/instance/list/list_test.go index 0060c7645..11d835caf 100644 --- a/internal/cmd/postgresflex/instance/list/list_test.go +++ b/internal/cmd/postgresflex/instance/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -186,3 +185,45 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + instances []postgresflex.InstanceListInstance + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, false}, + {"standard", args{"", []postgresflex.InstanceListInstance{}}, false}, + {"complete", args{"", []postgresflex.InstanceListInstance{ + { + Id: new(string), + Name: new(string), + Status: new(string), + }, + { + Id: new(string), + Name: new(string), + Status: new(string), + }, + { + Id: new(string), + Name: new(string), + Status: new(string), + }, + }}, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index c5f1857f6..c52b2efc3 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -118,7 +118,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, model.Async, instanceLabel, resp) }, } configureFlags(cmd) @@ -307,8 +307,12 @@ 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 { +func outputResult(p *print.Printer, outputFormat string, async bool, instanceLabel string, resp *postgresflex.PartialUpdateInstanceResponse) error { + if resp == nil { + return fmt.Errorf("no response passed") + } + + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -327,7 +331,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: operationState := "Updated" - if model.Async { + if async { operationState = "Triggered update of" } p.Info("%s instance %q\n", operationState, instanceLabel) diff --git a/internal/cmd/postgresflex/instance/update/update_test.go b/internal/cmd/postgresflex/instance/update/update_test.go index 5ac0a472f..edc536024 100644 --- a/internal/cmd/postgresflex/instance/update/update_test.go +++ b/internal/cmd/postgresflex/instance/update/update_test.go @@ -5,13 +5,12 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -590,3 +589,41 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + instanceLabel string + resp *postgresflex.PartialUpdateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty model", args{}, true}, + {"empty response", args{outputFormat: ""}, true}, + {"standard", args{ + outputFormat: "", + instanceLabel: "test", + resp: &postgresflex.PartialUpdateInstanceResponse{}, + }, false}, + {"complet", args{ + outputFormat: "", + instanceLabel: "test", + resp: &postgresflex.PartialUpdateInstanceResponse{ + Item: &postgresflex.Instance{}, + }, + }, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, true, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index d21067aa1..a8ac9a614 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -166,14 +166,17 @@ func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputM } } - return outputResult(p, model, flavors, versions, storages) + return outputResult(p, *model, flavors, versions, storages) } -func outputResult(p *print.Printer, model *inputModel, flavors *postgresflex.ListFlavorsResponse, versions *postgresflex.ListVersionsResponse, storages *postgresflex.ListStoragesResponse) error { +func outputResult(p *print.Printer, model inputModel, flavors *postgresflex.ListFlavorsResponse, versions *postgresflex.ListVersionsResponse, storages *postgresflex.ListStoragesResponse) error { options := &options{} if flavors != nil { options.Flavors = flavors.Flavors } + if model.GlobalFlagModel == nil { + return fmt.Errorf("no global model defined") + } if versions != nil { options.Versions = versions.Versions } @@ -205,7 +208,7 @@ func outputResult(p *print.Printer, model *inputModel, flavors *postgresflex.Lis } } -func outputResultAsTable(p *print.Printer, model *inputModel, options *options) error { +func outputResultAsTable(p *print.Printer, model inputModel, options *options) error { content := []tables.Table{} if model.Flavors && len(*options.Flavors) != 0 { content = append(content, buildFlavorsTable(*options.Flavors)) diff --git a/internal/cmd/postgresflex/options/options_test.go b/internal/cmd/postgresflex/options/options_test.go index 1a4866a3b..5eebac304 100644 --- a/internal/cmd/postgresflex/options/options_test.go +++ b/internal/cmd/postgresflex/options/options_test.go @@ -5,11 +5,10 @@ import ( "fmt" "testing" + "github.com/google/go-cmp/cmp" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/google/go-cmp/cmp" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -322,3 +321,51 @@ func TestBuildAndExecuteRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + flavors *postgresflex.ListFlavorsResponse + versions *postgresflex.ListVersionsResponse + storages *postgresflex.ListStoragesResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}}, false}, + {"standard", args{ + model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, + flavors: &postgresflex.ListFlavorsResponse{}, + versions: &postgresflex.ListVersionsResponse{}, + storages: &postgresflex.ListStoragesResponse{}, + }, false}, + { + "complete", + args{ + model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}, Flavors: false, Versions: false, Storages: false, FlavorId: new(string)}, + flavors: &postgresflex.ListFlavorsResponse{ + Flavors: &[]postgresflex.Flavor{}, + }, + versions: &postgresflex.ListVersionsResponse{ + Versions: &[]string{}, + }, + storages: &postgresflex.ListStoragesResponse{ + StorageClasses: &[]string{}, + StorageRange: &postgresflex.StorageRange{}, + }, + }, + false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.flavors, tt.args.versions, tt.args.storages); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 4638da73d..44a518d79 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -90,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create PostgreSQL Flex user: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, instanceLabel, resp) }, } @@ -143,8 +143,11 @@ 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 { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, resp *postgresflex.CreateUserResponse) error { + if resp == nil { + return fmt.Errorf("no response passed") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -162,14 +165,15 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res return nil default: - user := resp.Item - p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) - p.Outputf("Username: %s\n", utils.PtrString(user.Username)) - p.Outputf("Password: %s\n", utils.PtrString(user.Password)) - p.Outputf("Roles: %v\n", utils.PtrString(user.Roles)) - p.Outputf("Host: %s\n", utils.PtrString(user.Host)) - p.Outputf("Port: %s\n", utils.PtrString(user.Port)) - p.Outputf("URI: %s\n", utils.PtrString(user.Uri)) + if user := resp.Item; user != nil { + p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) + p.Outputf("Username: %s\n", utils.PtrString(user.Username)) + p.Outputf("Password: %s\n", utils.PtrString(user.Password)) + p.Outputf("Roles: %v\n", utils.PtrString(user.Roles)) + p.Outputf("Host: %s\n", utils.PtrString(user.Host)) + p.Outputf("Port: %s\n", utils.PtrString(user.Port)) + p.Outputf("URI: %s\n", utils.PtrString(user.Uri)) + } return nil } diff --git a/internal/cmd/postgresflex/user/create/create_test.go b/internal/cmd/postgresflex/user/create/create_test.go index d90533633..ab5a43277 100644 --- a/internal/cmd/postgresflex/user/create/create_test.go +++ b/internal/cmd/postgresflex/user/create/create_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -230,3 +229,41 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + instanceLabel string + resp *postgresflex.CreateUserResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, true}, + {"standard", args{resp: &postgresflex.CreateUserResponse{}}, false}, + {"complete", args{resp: &postgresflex.CreateUserResponse{ + Item: &postgresflex.User{ + Database: new(string), + Host: new(string), + Id: new(string), + Password: new(string), + Port: new(int64), + Roles: &[]string{}, + Uri: new(string), + Username: new(string), + }, + }}, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/user/describe/describe_test.go b/internal/cmd/postgresflex/user/describe/describe_test.go index 967c5c640..c3dadb008 100644 --- a/internal/cmd/postgresflex/user/describe/describe_test.go +++ b/internal/cmd/postgresflex/user/describe/describe_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -237,3 +236,35 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + user postgresflex.UserResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"basic", args{}, false}, + {"standard", args{user: postgresflex.UserResponse{}}, false}, + {"complete", args{user: postgresflex.UserResponse{ + Host: new(string), + Id: new(string), + Port: new(int64), + Roles: &[]string{}, + Username: new(string), + }}, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/user/list/list_test.go b/internal/cmd/postgresflex/user/list/list_test.go index 671b7e383..fb042f6c9 100644 --- a/internal/cmd/postgresflex/user/list/list_test.go +++ b/internal/cmd/postgresflex/user/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -203,3 +202,32 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + users []postgresflex.ListUsersResponseItem + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, false}, + {"standard", args{users: []postgresflex.ListUsersResponseItem{{}}}, false}, + {"complete", args{users: []postgresflex.ListUsersResponseItem{{ + Id: new(string), + Username: new(string), + }}}, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index 60abaf04a..14163d879 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -86,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("reset PostgreSQL Flex user password: %w", err) } - return outputResult(p, model, userLabel, instanceLabel, user) + return outputResult(p, model.OutputFormat, userLabel, instanceLabel, user) }, } @@ -132,8 +132,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle return req } -func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel string, user *postgresflex.ResetUserResponse) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat, userLabel, instanceLabel string, user *postgresflex.ResetUserResponse) error { + if user == nil { + return fmt.Errorf("no response passed") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(user, "", " ") if err != nil { @@ -152,9 +155,11 @@ func outputResult(p *print.Printer, model *inputModel, userLabel, instanceLabel return nil default: p.Outputf("Reset password for user %q of instance %q\n\n", userLabel, instanceLabel) - p.Outputf("Username: %s\n", utils.PtrString(user.Item.Username)) - p.Outputf("New password: %s\n", utils.PtrString(user.Item.Password)) - p.Outputf("New URI: %s\n", utils.PtrString(user.Item.Uri)) + if item := user.Item; item != nil { + p.Outputf("Username: %s\n", utils.PtrString(item.Username)) + p.Outputf("New password: %s\n", utils.PtrString(item.Password)) + p.Outputf("New URI: %s\n", utils.PtrString(item.Uri)) + } return nil } } diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go index f147797a0..d984f0271 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go @@ -4,12 +4,11 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -237,3 +236,36 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + userLabel string + instanceLabel string + user *postgresflex.ResetUserResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, true}, + {"standard", args{user: &postgresflex.ResetUserResponse{}}, false}, + {"complete", args{ + userLabel: "userLabel", + instanceLabel: "instanceLabel", + user: &postgresflex.ResetUserResponse{ + Item: &postgresflex.User{}, + }}, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.userLabel, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index e8fea5884..a8b2a31b3 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -27,6 +27,15 @@ func PtrString[T any](t *T) string { return "" } +// PtrValue returns the dereferenced value if the pointer is not nil. Otherwise +// the types zero element is returned +func PtrValue[T any](t *T) (r T) { + if t != nil { + return *t + } + return r +} + // Int64Ptr returns a pointer to an int64 // Needed because the Ptr function only returns pointer to int func Int64Ptr(i int64) *int64 { From 9f1881e49e58ea3d664e0cd88c3098525e55c7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Mon, 10 Mar 2025 09:55:54 +0100 Subject: [PATCH 221/619] chore(project): Add nil pointer checks and tests for the outputResult functions (#622) * fix: fix potential nil-pointer exceptions and add testcase * fix: add review findings --- internal/cmd/project/create/create.go | 10 +++- internal/cmd/project/create/create_test.go | 32 ++++++++-- internal/cmd/project/describe/describe.go | 7 ++- .../cmd/project/describe/describe_test.go | 39 +++++++++++- internal/cmd/project/list/list.go | 7 ++- internal/cmd/project/list/list_test.go | 59 +++++++++++++++++-- internal/cmd/project/member/list/list.go | 11 ++-- internal/cmd/project/member/list/list_test.go | 48 +++++++++++++-- internal/cmd/project/role/list/list_test.go | 41 +++++++++++-- 9 files changed, 226 insertions(+), 28 deletions(-) diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index 19d20beed..99f62fadd 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -95,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create project: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, *model, resp) }, } configureFlags(cmd) @@ -212,7 +212,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *resourceman return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *resourcemanager.Project) error { +func outputResult(p *print.Printer, model inputModel, resp *resourcemanager.Project) error { + if resp == nil { + return fmt.Errorf("response is empty") + } + if model.GlobalFlagModel == nil { + return fmt.Errorf("globalflags are empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/project/create/create_test.go b/internal/cmd/project/create/create_test.go index 43fa09b92..8c977d3c6 100644 --- a/internal/cmd/project/create/create_test.go +++ b/internal/cmd/project/create/create_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" "github.com/zalando/go-keyring" ) @@ -359,3 +358,28 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + resp *resourcemanager.Project + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}}, true}, + {"base", args{inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, &resourcemanager.Project{}}, false}, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index 62b997b64..26162f859 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -119,6 +119,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *resourceman } func outputResult(p *print.Printer, outputFormat string, project *resourcemanager.GetProjectResponse) error { + if project == nil { + return fmt.Errorf("response not set") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(project, "", " ") @@ -146,7 +149,9 @@ func outputResult(p *print.Printer, outputFormat string, project *resourcemanage table.AddSeparator() table.AddRow("STATE", utils.PtrString(project.LifecycleState)) table.AddSeparator() - table.AddRow("PARENT ID", utils.PtrString(project.Parent.Id)) + if project.Parent != nil { + table.AddRow("PARENT ID", utils.PtrString(project.Parent.Id)) + } err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/project/describe/describe_test.go b/internal/cmd/project/describe/describe_test.go index 8d8cd7490..3c2e5f658 100644 --- a/internal/cmd/project/describe/describe_test.go +++ b/internal/cmd/project/describe/describe_test.go @@ -3,13 +3,14 @@ package describe import ( "context" "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" ) @@ -214,3 +215,35 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + project *resourcemanager.GetProjectResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, true}, + {"base", args{"", &resourcemanager.GetProjectResponse{}}, false}, + {"complete", args{"", &resourcemanager.GetProjectResponse{ + ProjectId: utils.Ptr("4711"), + Name: utils.Ptr("name"), + CreationTime: utils.Ptr(time.Now()), + LifecycleState: utils.Ptr(resourcemanager.LIFECYCLESTATE_CREATING), + Parent: &resourcemanager.Parent{Id: utils.Ptr("parent id")}, + }, + }, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.project); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 99afb9b1f..9051dc145 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -242,11 +242,16 @@ func outputResult(p *print.Printer, outputFormat string, projects []resourcemana table.SetHeader("ID", "NAME", "STATE", "PARENT ID") for i := range projects { p := projects[i] + + var parentId *string + if p.Parent != nil { + parentId = p.Parent.Id + } table.AddRow( utils.PtrString(p.ProjectId), utils.PtrString(p.Name), utils.PtrString(p.LifecycleState), - utils.PtrString(p.Parent.Id), + utils.PtrString(parentId), ) } diff --git a/internal/cmd/project/list/list_test.go b/internal/cmd/project/list/list_test.go index 2f5bc9e98..7c6e73cee 100644 --- a/internal/cmd/project/list/list_test.go +++ b/internal/cmd/project/list/list_test.go @@ -9,17 +9,16 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/zalando/go-keyring" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" + "github.com/zalando/go-keyring" ) type testCtxKey struct{} @@ -495,3 +494,53 @@ func TestFetchProjects(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + projects []resourcemanager.Project + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, false}, + {"base", args{"", []resourcemanager.Project{{}}}, false}, + {"complete", args{"", []resourcemanager.Project{ + { + ContainerId: utils.Ptr("container-id1"), + CreationTime: utils.Ptr(time.Now()), + Labels: &map[string]string{"foo": "bar"}, + LifecycleState: utils.Ptr(resourcemanager.LIFECYCLESTATE_CREATING), + Name: utils.Ptr("some name"), + Parent: &resourcemanager.Parent{ + Id: utils.Ptr("parent-id"), + }, + ProjectId: utils.Ptr("project-id1"), + }, + { + ContainerId: utils.Ptr("container-id2"), + CreationTime: utils.Ptr(time.Now()), + Labels: &map[string]string{"foo": "bar"}, + LifecycleState: utils.Ptr(resourcemanager.LIFECYCLESTATE_CREATING), + Name: utils.Ptr("some name"), + Parent: &resourcemanager.Parent{ + Id: utils.Ptr("parent-id"), + }, + ProjectId: utils.Ptr("project-id2"), + }, + }}, false}, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.projects); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index 1d5056303..861423dc5 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -89,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { members = members[:*model.Limit] } - return outputResult(p, model, members) + return outputResult(p, *model, members) }, } configureFlags(cmd) @@ -145,13 +145,16 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *authorizati return req } -func outputResult(p *print.Printer, model *inputModel, members []authorization.Member) error { +func outputResult(p *print.Printer, model inputModel, members []authorization.Member) error { + if model.GlobalFlagModel == nil { + return fmt.Errorf("globalflags are empty") + } sortFn := func(i, j int) bool { switch model.SortBy { case "subject": - return *members[i].Subject < *members[j].Subject + return utils.PtrString(members[i].Subject) < utils.PtrString(members[j].Subject) case "role": - return *members[i].Role < *members[j].Role + return utils.PtrString(members[i].Role) < utils.PtrString(members[j].Role) default: return false } diff --git a/internal/cmd/project/member/list/list_test.go b/internal/cmd/project/member/list/list_test.go index 1e4050d4e..4aecdee12 100644 --- a/internal/cmd/project/member/list/list_test.go +++ b/internal/cmd/project/member/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -209,3 +208,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + members []authorization.Member + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}}, false}, + {"base", args{inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + Subject: utils.Ptr("subject"), + Limit: nil, + SortBy: "", + }, nil}, false}, + {"complete", args{inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + Subject: utils.Ptr("subject"), + Limit: nil, + SortBy: "", + }, + []authorization.Member{ + {Role: utils.Ptr("role1"), Subject: utils.Ptr("subject1")}, + {Role: utils.Ptr("role2"), Subject: utils.Ptr("subject2")}, + {Role: utils.Ptr("role3"), Subject: utils.Ptr("subject3")}, + }}, + false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.members); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/project/role/list/list_test.go b/internal/cmd/project/role/list/list_test.go index 59c8f9855..4e8744528 100644 --- a/internal/cmd/project/role/list/list_test.go +++ b/internal/cmd/project/role/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -172,3 +171,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputRolesResult(t *testing.T) { + type args struct { + outputFormat string + roles []authorization.Role + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, false}, + {"standard", args{"", nil}, false}, + {"complete", args{"", []authorization.Role{ + { + Description: utils.Ptr("description"), + Id: utils.Ptr("id"), + Name: utils.Ptr("name"), + Permissions: &[]authorization.Permission{ + {Description: utils.Ptr("description"), Name: utils.Ptr("name")}, + }, + }, + }}, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputRolesResult(p, tt.args.outputFormat, tt.args.roles); (err != nil) != tt.wantErr { + t.Errorf("outputRolesResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From dcb09fab51c529da510927c361203d8a7e7d47f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 11 Mar 2025 13:55:56 +0100 Subject: [PATCH 222/619] feat(sqlserverflex): region adjustment (#639) relates to STACKITCLI-121 --- go.mod | 2 +- go.sum | 4 +- .../sqlserverflex/database/create/create.go | 2 +- .../database/create/create_test.go | 19 ++++---- .../sqlserverflex/database/delete/delete.go | 2 +- .../database/delete/delete_test.go | 17 +++---- .../database/describe/describe.go | 2 +- .../database/describe/describe_test.go | 17 +++---- .../beta/sqlserverflex/database/list/list.go | 2 +- .../sqlserverflex/database/list/list_test.go | 19 ++++---- .../sqlserverflex/instance/create/create.go | 25 ++++++---- .../instance/create/create_test.go | 46 ++++++++++-------- .../sqlserverflex/instance/delete/delete.go | 6 +-- .../instance/delete/delete_test.go | 15 +++--- .../instance/describe/describe.go | 2 +- .../instance/describe/describe_test.go | 15 +++--- .../beta/sqlserverflex/instance/list/list.go | 2 +- .../sqlserverflex/instance/list/list_test.go | 17 +++---- .../sqlserverflex/instance/update/update.go | 29 ++++++----- .../instance/update/update_test.go | 48 +++++++++++-------- .../cmd/beta/sqlserverflex/options/options.go | 35 ++++++++------ .../sqlserverflex/options/options_test.go | 17 ++++--- .../beta/sqlserverflex/user/create/create.go | 4 +- .../sqlserverflex/user/create/create_test.go | 21 ++++---- .../beta/sqlserverflex/user/delete/delete.go | 6 +-- .../sqlserverflex/user/delete/delete_test.go | 17 +++---- .../sqlserverflex/user/describe/describe.go | 2 +- .../user/describe/describe_test.go | 17 +++---- .../cmd/beta/sqlserverflex/user/list/list.go | 4 +- .../beta/sqlserverflex/user/list/list_test.go | 19 ++++---- .../user/reset-password/reset_password.go | 6 +-- .../reset-password/reset_password_test.go | 17 +++---- .../pkg/services/sqlserverflex/utils/utils.go | 19 +++++--- .../sqlserverflex/utils/utils_test.go | 16 ++++--- 34 files changed, 273 insertions(+), 218 deletions(-) diff --git a/go.mod b/go.mod index d2920fa79..0751f1c64 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.23.0 golang.org/x/oauth2 v0.26.0 diff --git a/go.sum b/go.sum index c05ccea99..d501c8640 100644 --- a/go.sum +++ b/go.sum @@ -161,8 +161,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0 h1:QG+r github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0/go.mod h1:16dOVT052cMuHhUJ3NIcPuY7TrpCr9QlxmvvfjLZubA= github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0 h1:3KUVls8zXsbT2tOYRSHyp3/l0Kpjl4f3INmQKYTe65Y= github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0/go.mod h1:63IvXpBJTIVONAnGPSDo0sRJ+6n6tzO918OLqfYBxto= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.10.0 h1:STq6VaVUeHLeXzl1r5E4+MK5lcNVtdKjjP7N0XOowY4= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.10.0/go.mod h1:hdeLDwSCOmGIYtY4DGN15kjL44DQvo/txHXtTEvZidA= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0 h1:RYJO0rZea9+sxVfaJDWRo2zgfKNgiUcA5c0nbvZURiU= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0/go.mod h1:d2ICXCS2h3IMsZW0OanWkEH2XdLiY/XRKx2TcR940nw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index 2c5f6d17c..fe137c435 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -121,7 +121,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiCreateDatabaseRequest { - req := apiClient.CreateDatabase(ctx, model.ProjectId, model.InstanceId) + req := apiClient.CreateDatabase(ctx, model.ProjectId, model.InstanceId, model.Region) payload := sqlserverflex.CreateDatabasePayload{ Name: &model.DatabaseName, Options: &sqlserverflex.DatabaseDocumentationCreateDatabaseRequestOptions{ diff --git a/internal/cmd/beta/sqlserverflex/database/create/create_test.go b/internal/cmd/beta/sqlserverflex/database/create/create_test.go index 8720e3c59..ada824cb6 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create_test.go @@ -12,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,6 +20,7 @@ var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testDatabaseName = "my-database" var testOwner = "owner" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,9 +34,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - ownerFlag: testOwner, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + ownerFlag: testOwner, } for _, mod := range mods { mod(flagValues) @@ -50,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, DatabaseName: testDatabaseName, InstanceId: testInstanceId, @@ -62,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiCreateDatabaseRequest)) sqlserverflex.ApiCreateDatabaseRequest { - request := testClient.CreateDatabase(testCtx, testProjectId, testInstanceId) + request := testClient.CreateDatabase(testCtx, testProjectId, testInstanceId, testRegion) payload := sqlserverflex.CreateDatabasePayload{ Name: &testDatabaseName, Options: &sqlserverflex.DatabaseDocumentationCreateDatabaseRequestOptions{ @@ -113,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -121,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete.go b/internal/cmd/beta/sqlserverflex/database/delete/delete.go index 6f6426bea..d47633cf3 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete.go @@ -116,6 +116,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiDeleteDatabaseRequest { - req := apiClient.DeleteDatabase(ctx, model.ProjectId, model.InstanceId, model.DatabaseName) + req := apiClient.DeleteDatabase(ctx, model.ProjectId, model.InstanceId, model.DatabaseName, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go index ede474f38..315341040 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/google/uuid" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,6 +20,7 @@ var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testDatabaseName = "my-database" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +34,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, DatabaseName: testDatabaseName, @@ -60,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiDeleteDatabaseRequest)) sqlserverflex.ApiDeleteDatabaseRequest { - request := testClient.DeleteDatabase(testCtx, testProjectId, testInstanceId, testDatabaseName) + request := testClient.DeleteDatabase(testCtx, testProjectId, testInstanceId, testDatabaseName, testRegion) for _, mod := range mods { mod(&request) } @@ -104,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index b69dbe1b9..ed2caecf7 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -105,7 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiGetDatabaseRequest { - req := apiClient.GetDatabase(ctx, model.ProjectId, model.InstanceId, model.DatabaseName) + req := apiClient.GetDatabase(ctx, model.ProjectId, model.InstanceId, model.DatabaseName, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go index 25cd9ad82..b55faf4a2 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go @@ -12,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -21,6 +19,7 @@ var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testDatabaseName = "my-database" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,8 +33,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -47,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, DatabaseName: testDatabaseName, @@ -59,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiGetDatabaseRequest)) sqlserverflex.ApiGetDatabaseRequest { - request := testClient.GetDatabase(testCtx, testProjectId, testInstanceId, testDatabaseName) + request := testClient.GetDatabase(testCtx, testProjectId, testInstanceId, testDatabaseName, testRegion) for _, mod := range mods { mod(&request) } @@ -103,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index 195dc860b..6d660f8a1 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -132,7 +132,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiListDatabasesRequest { - req := apiClient.ListDatabases(ctx, model.ProjectId, model.InstanceId) + req := apiClient.ListDatabases(ctx, model.ProjectId, model.InstanceId, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/database/list/list_test.go b/internal/cmd/beta/sqlserverflex/database/list/list_test.go index 7ab387622..1b10b22a8 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list_test.go @@ -14,20 +14,20 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -39,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -51,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiListDatabasesRequest)) sqlserverflex.ApiListDatabasesRequest { - request := testClient.ListDatabases(testCtx, testProjectId, testInstanceId) + request := testClient.ListDatabases(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -79,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 49d4e2941..6436d545f 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -24,6 +24,17 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/wait" ) +// enforce implementation of interfaces +var ( + _ sqlServerFlexClient = &sqlserverflex.APIClient{} +) + +type sqlServerFlexClient interface { + CreateInstance(ctx context.Context, projectId string, region string) sqlserverflex.ApiCreateInstanceRequest + ListFlavorsExecute(ctx context.Context, projectId string, region string) (*sqlserverflex.ListFlavorsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, flavorId string, region string) (*sqlserverflex.ListStoragesResponse, error) +} + const ( instanceNameFlag = "name" aclFlag = "acl" @@ -114,7 +125,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SQLServer Flex instance creation: %w", err) } @@ -195,19 +206,13 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -type sqlServerFlexClient interface { - CreateInstance(ctx context.Context, projectId string) sqlserverflex.ApiCreateInstanceRequest - ListFlavorsExecute(ctx context.Context, projectId string) (*sqlserverflex.ListFlavorsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*sqlserverflex.ListStoragesResponse, error) -} - func buildRequest(ctx context.Context, model *inputModel, apiClient sqlServerFlexClient) (sqlserverflex.ApiCreateInstanceRequest, error) { - req := apiClient.CreateInstance(ctx, model.ProjectId) + req := apiClient.CreateInstance(ctx, model.ProjectId, model.Region) var flavorId *string var err error - flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return req, fmt.Errorf("get SQLServer Flex flavors: %w", err) } @@ -229,7 +234,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlServerFle flavorId = model.FlavorId } - storages, err := apiClient.ListStoragesExecute(ctx, model.ProjectId, *flavorId) + storages, err := apiClient.ListStoragesExecute(ctx, model.ProjectId, *flavorId, model.Region) if err != nil { return req, fmt.Errorf("get SQLServer Flex storages: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go index 0850869bd..eaf4a5463 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go @@ -14,12 +14,16 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} +var testRegion = "eu01" + +// enforce implementation of interfaces +var ( + _ sqlServerFlexClient = &sqlServerFlexClientMocked{} +) type sqlServerFlexClientMocked struct { listFlavorsFails bool @@ -28,18 +32,18 @@ type sqlServerFlexClientMocked struct { listStoragesResp *sqlserverflex.ListStoragesResponse } -func (c *sqlServerFlexClientMocked) CreateInstance(ctx context.Context, projectId string) sqlserverflex.ApiCreateInstanceRequest { - return testClient.CreateInstance(ctx, projectId) +func (c *sqlServerFlexClientMocked) CreateInstance(ctx context.Context, projectId, region string) sqlserverflex.ApiCreateInstanceRequest { + return testClient.CreateInstance(ctx, projectId, region) } -func (c *sqlServerFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*sqlserverflex.ListStoragesResponse, error) { +func (c *sqlServerFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*sqlserverflex.ListStoragesResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list storages failed") } return c.listStoragesResp, nil } -func (c *sqlServerFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*sqlserverflex.ListFlavorsResponse, error) { +func (c *sqlServerFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*sqlserverflex.ListFlavorsResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") } @@ -51,16 +55,17 @@ var testFlavorId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceNameFlag: "example-name", - aclFlag: "0.0.0.0/0", - backupScheduleFlag: "0 0/6 * * *", - flavorIdFlag: testFlavorId, - storageClassFlag: "storage-class", // Non-default - storageSizeFlag: "10", - versionFlag: "6.0", - editionFlag: "developer", - retentionDaysFlag: "32", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceNameFlag: "example-name", + aclFlag: "0.0.0.0/0", + backupScheduleFlag: "0 0/6 * * *", + flavorIdFlag: testFlavorId, + storageClassFlag: "storage-class", // Non-default + storageSizeFlag: "10", + versionFlag: "6.0", + editionFlag: "developer", + retentionDaysFlag: "32", } for _, mod := range mods { mod(flagValues) @@ -72,6 +77,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceName: utils.Ptr("example-name"), @@ -91,7 +97,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiCreateInstanceRequest)) sqlserverflex.ApiCreateInstanceRequest { - request := testClient.CreateInstance(testCtx, testProjectId) + request := testClient.CreateInstance(testCtx, testProjectId, testRegion) request = request.CreateInstancePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -157,21 +163,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go index a735efa15..c0456b08d 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -77,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SQLServer Flex instance deletion: %w", err) } @@ -121,6 +121,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiDeleteInstanceRequest { - req := apiClient.DeleteInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.DeleteInstance(ctx, model.ProjectId, model.InstanceId, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go index f96593f63..753379175 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go @@ -13,14 +13,13 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,7 +33,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -46,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -57,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiDeleteInstanceRequest)) sqlserverflex.ApiDeleteInstanceRequest { - request := testClient.DeleteInstance(testCtx, testProjectId, testInstanceId) + request := testClient.DeleteInstance(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -101,7 +102,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +118,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index 5a1d30b83..c5d8e68e1 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -94,7 +94,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiGetInstanceRequest { - req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go index 1a74c51a7..29edcede2 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go @@ -12,14 +12,13 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -33,7 +32,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -45,6 +45,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -56,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiGetInstanceRequest)) sqlserverflex.ApiGetInstanceRequest { - request := testClient.GetInstance(testCtx, testProjectId, testInstanceId) + request := testClient.GetInstance(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -100,7 +101,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -108,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -116,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 855273e5f..18666a7d5 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -125,7 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiListInstancesRequest { - req := apiClient.ListInstances(ctx, model.ProjectId) + req := apiClient.ListInstances(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go index dc42f591c..094774724 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go @@ -14,18 +14,18 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -37,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -48,7 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiListInstancesRequest)) sqlserverflex.ApiListInstancesRequest { - request := testClient.ListInstances(testCtx, testProjectId) + request := testClient.ListInstances(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -76,21 +77,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index b1d0da47b..39c5989dc 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -23,6 +23,18 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/wait" ) +// enforce implementation of interfaces +var ( + _ sqlServerFlexClient = &sqlserverflex.APIClient{} +) + +type sqlServerFlexClient interface { + PartialUpdateInstance(ctx context.Context, projectId, instanceId string, region string) sqlserverflex.ApiPartialUpdateInstanceRequest + GetInstanceExecute(ctx context.Context, projectId, instanceId string, region string) (*sqlserverflex.GetInstanceResponse, error) + ListFlavorsExecute(ctx context.Context, projectId string, region string) (*sqlserverflex.ListFlavorsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, flavorId string, region string) (*sqlserverflex.ListStoragesResponse, error) +} + const ( instanceIdArg = "INSTANCE_ID" @@ -76,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -105,7 +117,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SQLServer Flex instance update: %w", err) } @@ -182,20 +194,13 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -type sqlServerFlexClient interface { - PartialUpdateInstance(ctx context.Context, projectId, instanceId string) sqlserverflex.ApiPartialUpdateInstanceRequest - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*sqlserverflex.GetInstanceResponse, error) - ListFlavorsExecute(ctx context.Context, projectId string) (*sqlserverflex.ListFlavorsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*sqlserverflex.ListStoragesResponse, error) -} - func buildRequest(ctx context.Context, model *inputModel, apiClient sqlServerFlexClient) (sqlserverflex.ApiPartialUpdateInstanceRequest, error) { - req := apiClient.PartialUpdateInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.PartialUpdateInstance(ctx, model.ProjectId, model.InstanceId, model.Region) var flavorId *string var err error - flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return req, fmt.Errorf("get SQLServer Flex flavors: %w", err) } @@ -204,7 +209,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlServerFle ram := model.RAM cpu := model.CPU if model.RAM == nil || model.CPU == nil { - currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId) + currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId, model.Region) if err != nil { return req, fmt.Errorf("get SQLServer Flex instance: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update_test.go b/internal/cmd/beta/sqlserverflex/instance/update/update_test.go index 4fd28fae1..4c9c92dd5 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update_test.go @@ -14,12 +14,16 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} +var testRegion = "eu01" + +// enforce implementation of interfaces +var ( + _ sqlServerFlexClient = &sqlServerFlexClientMocked{} +) type sqlServerFlexClientMocked struct { listFlavorsFails bool @@ -30,25 +34,25 @@ type sqlServerFlexClientMocked struct { getInstanceResp *sqlserverflex.GetInstanceResponse } -func (c *sqlServerFlexClientMocked) PartialUpdateInstance(ctx context.Context, projectId, instanceId string) sqlserverflex.ApiPartialUpdateInstanceRequest { - return testClient.PartialUpdateInstance(ctx, projectId, instanceId) +func (c *sqlServerFlexClientMocked) PartialUpdateInstance(ctx context.Context, projectId, instanceId, region string) sqlserverflex.ApiPartialUpdateInstanceRequest { + return testClient.PartialUpdateInstance(ctx, projectId, instanceId, region) } -func (c *sqlServerFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*sqlserverflex.GetInstanceResponse, error) { +func (c *sqlServerFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*sqlserverflex.GetInstanceResponse, error) { if c.getInstanceFails { return nil, fmt.Errorf("get instance failed") } return c.getInstanceResp, nil } -func (c *sqlServerFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*sqlserverflex.ListStoragesResponse, error) { +func (c *sqlServerFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*sqlserverflex.ListStoragesResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list storages failed") } return c.listStoragesResp, nil } -func (c *sqlServerFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*sqlserverflex.ListFlavorsResponse, error) { +func (c *sqlServerFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*sqlserverflex.ListFlavorsResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") } @@ -71,7 +75,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureRequiredFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -81,12 +86,13 @@ func fixtureRequiredFlagValues(mods ...func(flagValues map[string]string)) map[s func fixtureStandardFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - flavorIdFlag: testFlavorId, - instanceNameFlag: "example-name", - aclFlag: "0.0.0.0/0", - backupScheduleFlag: "0 0 * * *", - versionFlag: "5.0", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + flavorIdFlag: testFlavorId, + instanceNameFlag: "example-name", + aclFlag: "0.0.0.0/0", + backupScheduleFlag: "0 0 * * *", + versionFlag: "5.0", } for _, mod := range mods { mod(flagValues) @@ -98,6 +104,7 @@ func fixtureRequiredInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -112,6 +119,7 @@ func fixtureStandardInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -128,7 +136,7 @@ func fixtureStandardInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiPartialUpdateInstanceRequest)) sqlserverflex.ApiPartialUpdateInstanceRequest { - request := testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId) + request := testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId, testRegion) request = request.PartialUpdateInstancePayload(sqlserverflex.PartialUpdateInstancePayload{}) for _, mod := range mods { mod(&request) @@ -196,7 +204,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -204,7 +212,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -212,7 +220,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -368,7 +376,7 @@ func TestBuildRequest(t *testing.T) { }, }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId, testRegion). PartialUpdateInstancePayload(sqlserverflex.PartialUpdateInstancePayload{ FlavorId: utils.Ptr(testFlavorId), }), @@ -389,7 +397,7 @@ func TestBuildRequest(t *testing.T) { }, }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId, testRegion). PartialUpdateInstancePayload(sqlserverflex.PartialUpdateInstancePayload{ FlavorId: utils.Ptr(testFlavorId), }), diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index 8d8e2c681..a4b815a44 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -18,6 +18,20 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) +// enforce implementation of interfaces +var ( + _ sqlServerFlexOptionsClient = &sqlserverflex.APIClient{} +) + +type sqlServerFlexOptionsClient interface { + ListFlavorsExecute(ctx context.Context, projectId string, region string) (*sqlserverflex.ListFlavorsResponse, error) + ListVersionsExecute(ctx context.Context, projectId string, region string) (*sqlserverflex.ListVersionsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, flavorId string, region string) (*sqlserverflex.ListStoragesResponse, error) + ListRolesExecute(ctx context.Context, projectId string, instanceId string, region string) (*sqlserverflex.ListRolesResponse, error) + ListCollationsExecute(ctx context.Context, projectId string, instanceId string, region string) (*sqlserverflex.ListCollationsResponse, error) + ListCompatibilityExecute(ctx context.Context, projectId string, instanceId string, region string) (*sqlserverflex.ListCompatibilityResponse, error) +} + const ( flavorsFlag = "flavors" versionsFlag = "versions" @@ -187,15 +201,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -type sqlServerFlexOptionsClient interface { - ListFlavorsExecute(ctx context.Context, projectId string) (*sqlserverflex.ListFlavorsResponse, error) - ListVersionsExecute(ctx context.Context, projectId string) (*sqlserverflex.ListVersionsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*sqlserverflex.ListStoragesResponse, error) - ListRolesExecute(ctx context.Context, projectId string, instanceId string) (*sqlserverflex.ListRolesResponse, error) - ListCollationsExecute(ctx context.Context, projectId string, instanceId string) (*sqlserverflex.ListCollationsResponse, error) - ListCompatibilityExecute(ctx context.Context, projectId string, instanceId string) (*sqlserverflex.ListCompatibilityResponse, error) -} - func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputModel, apiClient sqlServerFlexOptionsClient) error { var flavors *sqlserverflex.ListFlavorsResponse var versions *sqlserverflex.ListVersionsResponse @@ -206,37 +211,37 @@ func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputM var err error if model.Flavors { - flavors, err = apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err = apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("get SQL Server Flex flavors: %w", err) } } if model.Versions { - versions, err = apiClient.ListVersionsExecute(ctx, model.ProjectId) + versions, err = apiClient.ListVersionsExecute(ctx, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("get SQL Server Flex versions: %w", err) } } if model.Storages { - storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *model.FlavorId) + storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *model.FlavorId, model.Region) if err != nil { return fmt.Errorf("get SQL Server Flex storages: %w", err) } } if model.UserRoles { - userRoles, err = apiClient.ListRolesExecute(ctx, model.ProjectId, *model.InstanceId) + userRoles, err = apiClient.ListRolesExecute(ctx, model.ProjectId, *model.InstanceId, model.Region) if err != nil { return fmt.Errorf("get SQL Server Flex user roles: %w", err) } } if model.DBCollations { - dbCollations, err = apiClient.ListCollationsExecute(ctx, model.ProjectId, *model.InstanceId) + dbCollations, err = apiClient.ListCollationsExecute(ctx, model.ProjectId, *model.InstanceId, model.Region) if err != nil { return fmt.Errorf("get SQL Server Flex DB collations: %w", err) } } if model.DBCompatibilities { - dbCompatibilities, err = apiClient.ListCompatibilityExecute(ctx, model.ProjectId, *model.InstanceId) + dbCompatibilities, err = apiClient.ListCompatibilityExecute(ctx, model.ProjectId, *model.InstanceId, model.Region) if err != nil { return fmt.Errorf("get SQL Server Flex DB compatibilities: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/options/options_test.go b/internal/cmd/beta/sqlserverflex/options/options_test.go index 420bbbd37..5e76ad539 100644 --- a/internal/cmd/beta/sqlserverflex/options/options_test.go +++ b/internal/cmd/beta/sqlserverflex/options/options_test.go @@ -18,6 +18,11 @@ type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testInstanceId = uuid.NewString() +// enforce implementation of interfaces +var ( + _ sqlServerFlexOptionsClient = &sqlServerFlexClientMocked{} +) + type sqlServerFlexClientMocked struct { listFlavorsFails bool listVersionsFails bool @@ -34,7 +39,7 @@ type sqlServerFlexClientMocked struct { listDBCompatibilitiesCalled bool } -func (c *sqlServerFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*sqlserverflex.ListFlavorsResponse, error) { +func (c *sqlServerFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*sqlserverflex.ListFlavorsResponse, error) { c.listFlavorsCalled = true if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") @@ -44,7 +49,7 @@ func (c *sqlServerFlexClientMocked) ListFlavorsExecute(_ context.Context, _ stri }), nil } -func (c *sqlServerFlexClientMocked) ListVersionsExecute(_ context.Context, _ string) (*sqlserverflex.ListVersionsResponse, error) { +func (c *sqlServerFlexClientMocked) ListVersionsExecute(_ context.Context, _, _ string) (*sqlserverflex.ListVersionsResponse, error) { c.listVersionsCalled = true if c.listVersionsFails { return nil, fmt.Errorf("list versions failed") @@ -54,7 +59,7 @@ func (c *sqlServerFlexClientMocked) ListVersionsExecute(_ context.Context, _ str }), nil } -func (c *sqlServerFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*sqlserverflex.ListStoragesResponse, error) { +func (c *sqlServerFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*sqlserverflex.ListStoragesResponse, error) { c.listStoragesCalled = true if c.listStoragesFails { return nil, fmt.Errorf("list storages failed") @@ -68,7 +73,7 @@ func (c *sqlServerFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ }), nil } -func (c *sqlServerFlexClientMocked) ListRolesExecute(_ context.Context, _, _ string) (*sqlserverflex.ListRolesResponse, error) { +func (c *sqlServerFlexClientMocked) ListRolesExecute(_ context.Context, _, _, _ string) (*sqlserverflex.ListRolesResponse, error) { c.listUserRolesCalled = true if c.listUserRolesFails { return nil, fmt.Errorf("list roles failed") @@ -78,7 +83,7 @@ func (c *sqlServerFlexClientMocked) ListRolesExecute(_ context.Context, _, _ str }), nil } -func (c *sqlServerFlexClientMocked) ListCollationsExecute(_ context.Context, _, _ string) (*sqlserverflex.ListCollationsResponse, error) { +func (c *sqlServerFlexClientMocked) ListCollationsExecute(_ context.Context, _, _, _ string) (*sqlserverflex.ListCollationsResponse, error) { c.listDBCollationsCalled = true if c.listDBCollationsFails { return nil, fmt.Errorf("list collations failed") @@ -88,7 +93,7 @@ func (c *sqlServerFlexClientMocked) ListCollationsExecute(_ context.Context, _, }), nil } -func (c *sqlServerFlexClientMocked) ListCompatibilityExecute(_ context.Context, _, _ string) (*sqlserverflex.ListCompatibilityResponse, error) { +func (c *sqlServerFlexClientMocked) ListCompatibilityExecute(_ context.Context, _, _, _ string) (*sqlserverflex.ListCompatibilityResponse, error) { c.listDBCompatibilitiesCalled = true if c.listDBCompatibilitiesFails { return nil, fmt.Errorf("list compatibilities failed") diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 895471eb7..2e4f04896 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -134,7 +134,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiCreateUserRequest { - req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId) + req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId, model.Region) req = req.CreateUserPayload(sqlserverflex.CreateUserPayload{ Username: model.Username, diff --git a/internal/cmd/beta/sqlserverflex/user/create/create_test.go b/internal/cmd/beta/sqlserverflex/user/create/create_test.go index 644fe7776..8db8d6db2 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create_test.go @@ -14,21 +14,21 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - usernameFlag: "johndoe", - rolesFlag: "read", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + usernameFlag: "johndoe", + rolesFlag: "read", } for _, mod := range mods { mod(flagValues) @@ -40,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -53,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiCreateUserRequest)) sqlserverflex.ApiCreateUserRequest { - request := testClient.CreateUser(testCtx, testProjectId, testInstanceId) + request := testClient.CreateUser(testCtx, testProjectId, testInstanceId, testRegion) request = request.CreateUserPayload(sqlserverflex.CreateUserPayload{ Username: utils.Ptr("johndoe"), Roles: utils.Ptr([]string{"read"}), @@ -104,21 +105,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete.go b/internal/cmd/beta/sqlserverflex/user/delete/delete.go index 98d609579..b85272ba3 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete.go @@ -57,13 +57,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - userLabel, err := sqlserverflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) + userLabel, err := sqlserverflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId @@ -126,6 +126,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiDeleteUserRequest { - req := apiClient.DeleteUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.DeleteUser(ctx, model.ProjectId, model.InstanceId, model.UserId, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go index fcc8a26d6..79053edf7 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,6 +20,7 @@ var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testUserId = "my-user-id" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +34,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -60,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiDeleteUserRequest)) sqlserverflex.ApiDeleteUserRequest { - request := testClient.DeleteUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.DeleteUser(testCtx, testProjectId, testInstanceId, testUserId, testRegion) for _, mod := range mods { mod(&request) } @@ -104,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index 9769862c4..e9822bdd0 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -114,7 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiGetUserRequest { - req := apiClient.GetUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.GetUser(ctx, model.ProjectId, model.InstanceId, model.UserId, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go index f33c171ae..c0d6be049 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go @@ -12,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -21,6 +19,7 @@ var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testUserId = "my-user-id" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,8 +33,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -47,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -59,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiGetUserRequest)) sqlserverflex.ApiGetUserRequest { - request := testClient.GetUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.GetUser(testCtx, testProjectId, testInstanceId, testUserId, testRegion) for _, mod := range mods { mod(&request) } @@ -103,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index e2600d2fa..c4fcd2152 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get SQLServer Flex users: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) + instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId @@ -133,7 +133,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiListUsersRequest { - req := apiClient.ListUsers(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.ListUsers(ctx, model.ProjectId, *model.InstanceId, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/user/list/list_test.go b/internal/cmd/beta/sqlserverflex/user/list/list_test.go index e67b012a5..cc3dabc34 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list_test.go @@ -14,20 +14,20 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -39,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: utils.Ptr(testInstanceId), @@ -51,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiListUsersRequest)) sqlserverflex.ApiListUsersRequest { - request := testClient.ListUsers(testCtx, testProjectId, testInstanceId) + request := testClient.ListUsers(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -79,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index 4dfe1ffce..182a9e147 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -60,13 +60,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - userLabel, err := sqlserverflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) + userLabel, err := sqlserverflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId @@ -129,7 +129,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiResetUserRequest { - req := apiClient.ResetUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.ResetUser(ctx, model.ProjectId, model.InstanceId, model.UserId, model.Region) return req } diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go index d13b3b117..8eda0631f 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go @@ -12,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -21,6 +19,7 @@ var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testUserId = "my-user-id" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,8 +33,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -47,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -59,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *sqlserverflex.ApiResetUserRequest)) sqlserverflex.ApiResetUserRequest { - request := testClient.ResetUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.ResetUser(testCtx, testProjectId, testInstanceId, testUserId, testRegion) for _, mod := range mods { mod(&request) } @@ -103,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/pkg/services/sqlserverflex/utils/utils.go b/internal/pkg/services/sqlserverflex/utils/utils.go index 11a88fc77..768507175 100644 --- a/internal/pkg/services/sqlserverflex/utils/utils.go +++ b/internal/pkg/services/sqlserverflex/utils/utils.go @@ -14,10 +14,15 @@ const ( ServiceCmd = "beta sqlserverflex" ) +// enforce implementation of interfaces +var ( + _ SQLServerFlexClient = &sqlserverflex.APIClient{} +) + type SQLServerFlexClient interface { - ListVersionsExecute(ctx context.Context, projectId string) (*sqlserverflex.ListVersionsResponse, error) - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*sqlserverflex.GetInstanceResponse, error) - GetUserExecute(ctx context.Context, projectId, instanceId, userId string) (*sqlserverflex.GetUserResponse, error) + ListVersionsExecute(ctx context.Context, projectId string, region string) (*sqlserverflex.ListVersionsResponse, error) + GetInstanceExecute(ctx context.Context, projectId, instanceId string, region string) (*sqlserverflex.GetInstanceResponse, error) + GetUserExecute(ctx context.Context, projectId, instanceId, userId string, region string) (*sqlserverflex.GetUserResponse, error) } func ValidateFlavorId(flavorId string, flavors *[]sqlserverflex.InstanceFlavorEntry) error { @@ -85,16 +90,16 @@ func LoadFlavorId(cpu, ram int64, flavors *[]sqlserverflex.InstanceFlavorEntry) } } -func GetInstanceName(ctx context.Context, apiClient SQLServerFlexClient, projectId, instanceId string) (string, error) { - resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId) +func GetInstanceName(ctx context.Context, apiClient SQLServerFlexClient, projectId, instanceId, region string) (string, error) { + resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId, region) if err != nil { return "", fmt.Errorf("get SQLServer Flex instance: %w", err) } return *resp.Item.Name, nil } -func GetUserName(ctx context.Context, apiClient SQLServerFlexClient, projectId, instanceId, userId string) (string, error) { - resp, err := apiClient.GetUserExecute(ctx, projectId, instanceId, userId) +func GetUserName(ctx context.Context, apiClient SQLServerFlexClient, projectId, instanceId, userId, region string) (string, error) { + resp, err := apiClient.GetUserExecute(ctx, projectId, instanceId, userId, region) if err != nil { return "", fmt.Errorf("get SQLServer Flex user: %w", err) } diff --git a/internal/pkg/services/sqlserverflex/utils/utils_test.go b/internal/pkg/services/sqlserverflex/utils/utils_test.go index 953965121..00c73e376 100644 --- a/internal/pkg/services/sqlserverflex/utils/utils_test.go +++ b/internal/pkg/services/sqlserverflex/utils/utils_test.go @@ -16,11 +16,15 @@ var ( testProjectId = uuid.NewString() testInstanceId = uuid.NewString() testUserId = uuid.NewString() + + // enforce implementation of interfaces + _ SQLServerFlexClient = &sqlServerFlexClientMocked{} ) const ( testInstanceName = "instance" testUserName = "user" + testRegion = "eu01" ) type sqlServerFlexClientMocked struct { @@ -34,28 +38,28 @@ type sqlServerFlexClientMocked struct { listRestoreJobsResp *sqlserverflex.ListRestoreJobsResponse } -func (m *sqlServerFlexClientMocked) ListVersionsExecute(_ context.Context, _ string) (*sqlserverflex.ListVersionsResponse, error) { +func (m *sqlServerFlexClientMocked) ListVersionsExecute(_ context.Context, _, _ string) (*sqlserverflex.ListVersionsResponse, error) { if m.listVersionsFails { return nil, fmt.Errorf("could not list versions") } return m.listVersionsResp, nil } -func (m *sqlServerFlexClientMocked) ListRestoreJobsExecute(_ context.Context, _, _ string) (*sqlserverflex.ListRestoreJobsResponse, error) { +func (m *sqlServerFlexClientMocked) ListRestoreJobsExecute(_ context.Context, _, _, _ string) (*sqlserverflex.ListRestoreJobsResponse, error) { if m.listRestoreJobsFails { return nil, fmt.Errorf("could not list versions") } return m.listRestoreJobsResp, nil } -func (m *sqlServerFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*sqlserverflex.GetInstanceResponse, error) { +func (m *sqlServerFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*sqlserverflex.GetInstanceResponse, error) { if m.getInstanceFails { return nil, fmt.Errorf("could not get instance") } return m.getInstanceResp, nil } -func (m *sqlServerFlexClientMocked) GetUserExecute(_ context.Context, _, _, _ string) (*sqlserverflex.GetUserResponse, error) { +func (m *sqlServerFlexClientMocked) GetUserExecute(_ context.Context, _, _, _, _ string) (*sqlserverflex.GetUserResponse, error) { if m.getUserFails { return nil, fmt.Errorf("could not get user") } @@ -405,7 +409,7 @@ func TestGetInstanceName(t *testing.T) { getInstanceResp: tt.getInstanceResp, } - output, err := GetInstanceName(context.Background(), client, testProjectId, testInstanceId) + output, err := GetInstanceName(context.Background(), client, testProjectId, testInstanceId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -455,7 +459,7 @@ func TestGetUserName(t *testing.T) { getUserResp: tt.getUserResp, } - output, err := GetUserName(context.Background(), client, testProjectId, testInstanceId, testUserId) + output, err := GetUserName(context.Background(), client, testProjectId, testInstanceId, testUserId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") From 8e7e4aa4ddc680cb32e916f791a56f6a75e7f775 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 14 Mar 2025 07:03:37 +0100 Subject: [PATCH 223/619] feat(postgresql): Region adjustment (#648) Signed-off-by: Alexander Dahmen --- go.mod | 2 +- go.sum | 4 +- .../postgresflex/backup/describe/describe.go | 2 +- .../backup/describe/describe_test.go | 17 +++--- internal/cmd/postgresflex/backup/list/list.go | 4 +- .../cmd/postgresflex/backup/list/list_test.go | 19 +++---- .../backup/update-schedule/update_schedule.go | 4 +- .../update-schedule/update_schedule_test.go | 22 ++++---- .../cmd/postgresflex/instance/clone/clone.go | 16 +++--- .../postgresflex/instance/clone/clone_test.go | 39 +++++++------- .../postgresflex/instance/create/create.go | 16 +++--- .../instance/create/create_test.go | 39 +++++++------- .../postgresflex/instance/delete/delete.go | 18 +++---- .../instance/delete/delete_test.go | 23 ++++---- .../instance/describe/describe.go | 2 +- .../instance/describe/describe_test.go | 15 +++--- .../cmd/postgresflex/instance/list/list.go | 2 +- .../postgresflex/instance/list/list_test.go | 17 +++--- .../postgresflex/instance/update/update.go | 22 ++++---- .../instance/update/update_test.go | 53 ++++++++++--------- internal/cmd/postgresflex/options/options.go | 12 ++--- .../cmd/postgresflex/options/options_test.go | 6 +-- .../cmd/postgresflex/user/create/create.go | 4 +- .../postgresflex/user/create/create_test.go | 21 ++++---- .../cmd/postgresflex/user/delete/delete.go | 6 +-- .../postgresflex/user/delete/delete_test.go | 17 +++--- .../postgresflex/user/describe/describe.go | 2 +- .../user/describe/describe_test.go | 17 +++--- internal/cmd/postgresflex/user/list/list.go | 4 +- .../cmd/postgresflex/user/list/list_test.go | 19 +++---- .../user/reset-password/reset_password.go | 6 +-- .../reset-password/reset_password_test.go | 17 +++--- .../cmd/postgresflex/user/update/update.go | 6 +-- .../postgresflex/user/update/update_test.go | 19 +++---- .../pkg/services/postgresflex/utils/utils.go | 22 ++++---- .../services/postgresflex/utils/utils_test.go | 15 +++--- 36 files changed, 275 insertions(+), 254 deletions(-) diff --git a/go.mod b/go.mod index 0751f1c64..37c11f601 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.18.0 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0 diff --git a/go.sum b/go.sum index d501c8640..1c461e0c3 100644 --- a/go.sum +++ b/go.sum @@ -139,8 +139,8 @@ github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.0 h1:Hn4BwKCz github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.0/go.mod h1:PxfwA6YFtxwOajB4iTp1Eq7G02qUC3HdQPJvHGjQ1hk= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0 h1:y83IhdbQv8EHovWPTqeulGgyZKJ39AQW1klo0g7a7og= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0/go.mod h1:Gk3hWaQDCJGgaixjGkUmoIr74VNWwdAakiUrvizpOWQ= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.18.0 h1:cwdmiwbSml70kE9xV9C25t9WggDT98NdSfWD9w/r4wU= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v0.18.0/go.mod h1:wNPezvzJUgUj+C50EqyMAj5PSkhawT+2Zsdh01WQpAM= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.1 h1:vUi9//CyfS6UMv0hftYMamimjJLco5lxT/KW9y4QPqM= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.1/go.mod h1:7TqfCUZRW7sjv8qOrLV5IvS6jqvY9Uxka165zdjYwD4= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.0 h1:zEJXwsuasmYH8dONZrCsZzcann/+6HZDKUPhN3mOmY0= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.0/go.mod h1:SaL9BCTeWcEmU9JiKgNihEXKnFKDTn91L9ehgvauWuM= github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0 h1:UDIRWwiZ2/2ukmn60wPo83PUSuWPaXqbuRzkRTjRQNQ= diff --git a/internal/cmd/postgresflex/backup/describe/describe.go b/internal/cmd/postgresflex/backup/describe/describe.go index 32cee719f..dbb8fe4ce 100644 --- a/internal/cmd/postgresflex/backup/describe/describe.go +++ b/internal/cmd/postgresflex/backup/describe/describe.go @@ -102,7 +102,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiGetBackupRequest { - req := apiClient.GetBackup(ctx, model.ProjectId, model.InstanceId, model.BackupId) + req := apiClient.GetBackup(ctx, model.ProjectId, model.Region, model.InstanceId, model.BackupId) return req } diff --git a/internal/cmd/postgresflex/backup/describe/describe_test.go b/internal/cmd/postgresflex/backup/describe/describe_test.go index e3f8dd6f1..5c3479254 100644 --- a/internal/cmd/postgresflex/backup/describe/describe_test.go +++ b/internal/cmd/postgresflex/backup/describe/describe_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -23,6 +21,7 @@ var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testBackupId = "backupID" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -36,8 +35,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -49,6 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -61,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiGetBackupRequest)) postgresflex.ApiGetBackupRequest { - request := testClient.GetBackup(testCtx, testProjectId, testInstanceId, testBackupId) + request := testClient.GetBackup(testCtx, testProjectId, testRegion, testInstanceId, testBackupId) for _, mod := range mods { mod(&request) } @@ -105,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index 0b7ab5234..7e1d6c398 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -68,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, *model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId @@ -129,7 +129,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiListBackupsRequest { - req := apiClient.ListBackups(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.ListBackups(ctx, model.ProjectId, model.Region, *model.InstanceId) return req } diff --git a/internal/cmd/postgresflex/backup/list/list_test.go b/internal/cmd/postgresflex/backup/list/list_test.go index 302aed436..f34d184cf 100644 --- a/internal/cmd/postgresflex/backup/list/list_test.go +++ b/internal/cmd/postgresflex/backup/list/list_test.go @@ -14,20 +14,20 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -39,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: utils.Ptr(testInstanceId), @@ -51,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiListBackupsRequest)) postgresflex.ApiListBackupsRequest { - request := testClient.ListBackups(testCtx, testProjectId, testInstanceId) + request := testClient.ListBackups(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -79,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go index 9db444846..9d5ff6626 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go @@ -54,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, *model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId @@ -105,7 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiUpdateBackupScheduleRequest { - req := apiClient.UpdateBackupSchedule(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.UpdateBackupSchedule(ctx, model.ProjectId, model.Region, *model.InstanceId) req = req.UpdateBackupSchedulePayload(postgresflex.UpdateBackupSchedulePayload{ BackupSchedule: model.BackupSchedule, }) diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule_test.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule_test.go index 0f28528cb..446f96226 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule_test.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,12 +20,14 @@ var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testSchedule = "0 0 * * *" +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - scheduleFlag: testSchedule, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + scheduleFlag: testSchedule, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -39,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: utils.Ptr(testInstanceId), @@ -61,7 +62,7 @@ func fixturePayload(mods ...func(payload *postgresflex.UpdateBackupSchedulePaylo } func fixtureRequest(mods ...func(request *postgresflex.ApiUpdateBackupScheduleRequest)) postgresflex.ApiUpdateBackupScheduleRequest { - request := testClient.UpdateBackupSchedule(testCtx, testProjectId, testInstanceId) + request := testClient.UpdateBackupSchedule(testCtx, testProjectId, testRegion, testInstanceId) request = request.UpdateBackupSchedulePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -91,21 +92,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -200,10 +201,11 @@ func TestBuildRequest(t *testing.T) { model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, }, InstanceId: utils.Ptr(testInstanceId), }, - expectedRequest: testClient.UpdateBackupSchedule(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.UpdateBackupSchedule(testCtx, testProjectId, testRegion, testInstanceId). UpdateBackupSchedulePayload(postgresflex.UpdateBackupSchedulePayload{}), }, } diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index 56dde3809..1d753cfeb 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -101,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Cloning instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance cloning: %w", err) } @@ -162,17 +162,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } type PostgreSQLFlexClient interface { - CloneInstance(ctx context.Context, projectId, instanceId string) postgresflex.ApiCloneInstanceRequest - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*postgresflex.InstanceResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*postgresflex.ListStoragesResponse, error) + CloneInstance(ctx context.Context, projectId, region, instanceId string) postgresflex.ApiCloneInstanceRequest + GetInstanceExecute(ctx context.Context, projectId, region, instanceId string) (*postgresflex.InstanceResponse, error) + ListStoragesExecute(ctx context.Context, projectId, region, flavorId string) (*postgresflex.ListStoragesResponse, error) } func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFlexClient) (postgresflex.ApiCloneInstanceRequest, error) { - req := apiClient.CloneInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.CloneInstance(ctx, model.ProjectId, model.Region, model.InstanceId) var storages *postgresflex.ListStoragesResponse if model.StorageClass != nil || model.StorageSize != nil { - currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId) + currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.Region, model.InstanceId) if err != nil { return req, fmt.Errorf("get PostgreSQL Flex instance: %w", err) } @@ -180,7 +180,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl currentInstanceStorageClass := currentInstance.Item.Storage.Class currentInstanceStorageSize := currentInstance.Item.Storage.Size - storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *validationFlavorId) + storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, model.Region, *validationFlavorId) if err != nil { return req, fmt.Errorf("get PostgreSQL Flex storages: %w", err) } diff --git a/internal/cmd/postgresflex/instance/clone/clone_test.go b/internal/cmd/postgresflex/instance/clone/clone_test.go index dfb8e6e67..eed05d8d3 100644 --- a/internal/cmd/postgresflex/instance/clone/clone_test.go +++ b/internal/cmd/postgresflex/instance/clone/clone_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -29,18 +27,18 @@ type postgresFlexClientMocked struct { getInstanceResp *postgresflex.InstanceResponse } -func (c *postgresFlexClientMocked) CloneInstance(ctx context.Context, projectId, instanceId string) postgresflex.ApiCloneInstanceRequest { - return testClient.CloneInstance(ctx, projectId, instanceId) +func (c *postgresFlexClientMocked) CloneInstance(ctx context.Context, projectId, region, instanceId string) postgresflex.ApiCloneInstanceRequest { + return testClient.CloneInstance(ctx, projectId, region, instanceId) } -func (c *postgresFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*postgresflex.InstanceResponse, error) { +func (c *postgresFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*postgresflex.InstanceResponse, error) { if c.getInstanceFails { return nil, fmt.Errorf("get instance failed") } return c.getInstanceResp, nil } -func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*postgresflex.ListStoragesResponse, error) { +func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*postgresflex.ListStoragesResponse, error) { if c.listStoragesFails { return nil, fmt.Errorf("list storages failed") } @@ -53,6 +51,7 @@ var testRecoveryTimestamp = "2024-03-08T09:28:00+00:00" var testFlavorId = uuid.NewString() var testStorageClass = "premium-perf4-stackit" var testStorageSize = int64(10) +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -66,8 +65,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureRequiredFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - recoveryTimestampFlag: testRecoveryTimestamp, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + recoveryTimestampFlag: testRecoveryTimestamp, } for _, mod := range mods { mod(flagValues) @@ -77,10 +77,11 @@ func fixtureRequiredFlagValues(mods ...func(flagValues map[string]string)) map[s func fixtureStandardFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - recoveryTimestampFlag: testRecoveryTimestamp, - storageClassFlag: "class", - storageSizeFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + recoveryTimestampFlag: testRecoveryTimestamp, + storageClassFlag: "class", + storageSizeFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -98,6 +99,7 @@ func fixtureRequiredInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -119,6 +121,7 @@ func fixtureStandardInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -133,7 +136,7 @@ func fixtureStandardInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiCloneInstanceRequest)) postgresflex.ApiCloneInstanceRequest { - request := testClient.CloneInstance(testCtx, testProjectId, testInstanceId) + request := testClient.CloneInstance(testCtx, testProjectId, testRegion, testInstanceId) request = request.CloneInstancePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -230,7 +233,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -238,7 +241,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -246,7 +249,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -397,7 +400,7 @@ func TestBuildRequest(t *testing.T) { Max: utils.Ptr(int64(100)), }, }, - expectedRequest: testClient.CloneInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.CloneInstance(testCtx, testProjectId, testRegion, testInstanceId). CloneInstancePayload(postgresflex.CloneInstancePayload{ Class: utils.Ptr("class"), Timestamp: utils.Ptr(recoveryTimestampString), @@ -428,7 +431,7 @@ func TestBuildRequest(t *testing.T) { Max: utils.Ptr(int64(100)), }, }, - expectedRequest: testClient.CloneInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.CloneInstance(testCtx, testProjectId, testRegion, testInstanceId). CloneInstancePayload(postgresflex.CloneInstancePayload{ Class: utils.Ptr("class"), Size: utils.Ptr(int64(10)), diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 41217ffa5..191d982f5 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -104,7 +104,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Fill in version, if needed if model.Version == nil { - version, err := postgresflexUtils.GetLatestPostgreSQLVersion(ctx, apiClient, model.ProjectId) + version, err := postgresflexUtils.GetLatestPostgreSQLVersion(ctx, apiClient, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("get latest PostgreSQL version: %w", err) } @@ -126,7 +126,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance creation: %w", err) } @@ -208,18 +208,18 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } type PostgreSQLFlexClient interface { - CreateInstance(ctx context.Context, projectId string) postgresflex.ApiCreateInstanceRequest - ListFlavorsExecute(ctx context.Context, projectId string) (*postgresflex.ListFlavorsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*postgresflex.ListStoragesResponse, error) + CreateInstance(ctx context.Context, projectId, region string) postgresflex.ApiCreateInstanceRequest + ListFlavorsExecute(ctx context.Context, projectId, region string) (*postgresflex.ListFlavorsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, region, flavorId string) (*postgresflex.ListStoragesResponse, error) } func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFlexClient) (postgresflex.ApiCreateInstanceRequest, error) { - req := apiClient.CreateInstance(ctx, model.ProjectId) + req := apiClient.CreateInstance(ctx, model.ProjectId, model.Region) var flavorId *string var err error - flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return req, fmt.Errorf("get PostgreSQL Flex flavors: %w", err) } @@ -241,7 +241,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl flavorId = model.FlavorId } - storages, err := apiClient.ListStoragesExecute(ctx, model.ProjectId, *flavorId) + storages, err := apiClient.ListStoragesExecute(ctx, model.ProjectId, model.Region, *flavorId) if err != nil { return req, fmt.Errorf("get PostgreSQL Flex storages: %w", err) } diff --git a/internal/cmd/postgresflex/instance/create/create_test.go b/internal/cmd/postgresflex/instance/create/create_test.go index 401665161..6adbfb09b 100644 --- a/internal/cmd/postgresflex/instance/create/create_test.go +++ b/internal/cmd/postgresflex/instance/create/create_test.go @@ -14,12 +14,11 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &postgresflex.APIClient{} +var testRegion = "eu01" type postgresFlexClientMocked struct { listFlavorsFails bool @@ -28,18 +27,18 @@ type postgresFlexClientMocked struct { listStoragesResp *postgresflex.ListStoragesResponse } -func (c *postgresFlexClientMocked) CreateInstance(ctx context.Context, projectId string) postgresflex.ApiCreateInstanceRequest { - return testClient.CreateInstance(ctx, projectId) +func (c *postgresFlexClientMocked) CreateInstance(ctx context.Context, projectId, region string) postgresflex.ApiCreateInstanceRequest { + return testClient.CreateInstance(ctx, projectId, region) } -func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*postgresflex.ListStoragesResponse, error) { +func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*postgresflex.ListStoragesResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list storages failed") } return c.listStoragesResp, nil } -func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*postgresflex.ListFlavorsResponse, error) { +func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*postgresflex.ListFlavorsResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") } @@ -51,15 +50,16 @@ var testFlavorId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceNameFlag: "example-name", - aclFlag: "0.0.0.0/0", - backupScheduleFlag: "0 0 * * *", - flavorIdFlag: testFlavorId, - storageClassFlag: "premium-perf4-stackit", // Non-default - storageSizeFlag: "10", - versionFlag: "6.0", - typeFlag: "Replica", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceNameFlag: "example-name", + aclFlag: "0.0.0.0/0", + backupScheduleFlag: "0 0 * * *", + flavorIdFlag: testFlavorId, + storageClassFlag: "premium-perf4-stackit", // Non-default + storageSizeFlag: "10", + versionFlag: "6.0", + typeFlag: "Replica", } for _, mod := range mods { mod(flagValues) @@ -71,6 +71,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceName: utils.Ptr("example-name"), @@ -89,7 +90,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiCreateInstanceRequest)) postgresflex.ApiCreateInstanceRequest { - request := testClient.CreateInstance(testCtx, testProjectId) + request := testClient.CreateInstance(testCtx, testProjectId, testRegion) request = request.CreateInstancePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -164,21 +165,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/instance/delete/delete.go b/internal/cmd/postgresflex/instance/delete/delete.go index 97a4ec245..4c9077a6a 100644 --- a/internal/cmd/postgresflex/instance/delete/delete.go +++ b/internal/cmd/postgresflex/instance/delete/delete.go @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -94,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance deletion: %w", err) } @@ -114,7 +114,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Forcing deletion of instance") - _, err = wait.ForceDeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + _, err = wait.ForceDeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance force deletion: %w", err) } @@ -171,23 +171,23 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildDeleteRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiDeleteInstanceRequest { - req := apiClient.DeleteInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.DeleteInstance(ctx, model.ProjectId, model.Region, model.InstanceId) return req } func buildForceDeleteRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiForceDeleteInstanceRequest { - req := apiClient.ForceDeleteInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.ForceDeleteInstance(ctx, model.ProjectId, model.Region, model.InstanceId) return req } type PostgreSQLFlexClient interface { - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*postgresflex.InstanceResponse, error) - ListVersionsExecute(ctx context.Context, projectId string) (*postgresflex.ListVersionsResponse, error) - GetUserExecute(ctx context.Context, projectId, instanceId, userId string) (*postgresflex.GetUserResponse, error) + GetInstanceExecute(ctx context.Context, projectId, region, instanceId string) (*postgresflex.InstanceResponse, error) + ListVersionsExecute(ctx context.Context, projectId, region string) (*postgresflex.ListVersionsResponse, error) + GetUserExecute(ctx context.Context, projectId, region, instanceId, userId string) (*postgresflex.GetUserResponse, error) } func getNextOperations(ctx context.Context, model *inputModel, apiClient PostgreSQLFlexClient) (toDelete, toForceDelete bool, err error) { - instanceStatus, err := postgresflexUtils.GetInstanceStatus(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceStatus, err := postgresflexUtils.GetInstanceStatus(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { return false, false, fmt.Errorf("get PostgreSQL Flex instance status: %w", err) } diff --git a/internal/cmd/postgresflex/instance/delete/delete_test.go b/internal/cmd/postgresflex/instance/delete/delete_test.go index 831180394..23f662a5d 100644 --- a/internal/cmd/postgresflex/instance/delete/delete_test.go +++ b/internal/cmd/postgresflex/instance/delete/delete_test.go @@ -16,32 +16,31 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/wait" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" type postgresFlexClientMocked struct { getInstanceFails bool getInstanceResp *postgresflex.InstanceResponse } -func (c *postgresFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*postgresflex.InstanceResponse, error) { +func (c *postgresFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*postgresflex.InstanceResponse, error) { if c.getInstanceFails { return nil, fmt.Errorf("get instance failed") } return c.getInstanceResp, nil } -func (c *postgresFlexClientMocked) ListVersionsExecute(_ context.Context, _ string) (*postgresflex.ListVersionsResponse, error) { +func (c *postgresFlexClientMocked) ListVersionsExecute(_ context.Context, _, _ string) (*postgresflex.ListVersionsResponse, error) { // Not used in testing return nil, nil } -func (c *postgresFlexClientMocked) GetUserExecute(_ context.Context, _, _, _ string) (*postgresflex.GetUserResponse, error) { +func (c *postgresFlexClientMocked) GetUserExecute(_ context.Context, _, _, _, _ string) (*postgresflex.GetUserResponse, error) { // Not used in testing return nil, nil } @@ -58,7 +57,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -70,6 +70,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -81,7 +82,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureDeleteRequest(mods ...func(request *postgresflex.ApiDeleteInstanceRequest)) postgresflex.ApiDeleteInstanceRequest { - request := testClient.DeleteInstance(testCtx, testProjectId, testInstanceId) + request := testClient.DeleteInstance(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -89,7 +90,7 @@ func fixtureDeleteRequest(mods ...func(request *postgresflex.ApiDeleteInstanceRe } func fixtureForceDeleteRequest(mods ...func(request *postgresflex.ApiForceDeleteInstanceRequest)) postgresflex.ApiForceDeleteInstanceRequest { - request := testClient.ForceDeleteInstance(testCtx, testProjectId, testInstanceId) + request := testClient.ForceDeleteInstance(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -133,7 +134,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -141,7 +142,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -149,7 +150,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/instance/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index 7e99a129a..2d59f5306 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -96,7 +96,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiGetInstanceRequest { - req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.GetInstance(ctx, model.ProjectId, model.Region, model.InstanceId) return req } diff --git a/internal/cmd/postgresflex/instance/describe/describe_test.go b/internal/cmd/postgresflex/instance/describe/describe_test.go index 825e481f1..c6945faa1 100644 --- a/internal/cmd/postgresflex/instance/describe/describe_test.go +++ b/internal/cmd/postgresflex/instance/describe/describe_test.go @@ -12,14 +12,13 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -33,7 +32,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -45,6 +45,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -56,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiGetInstanceRequest)) postgresflex.ApiGetInstanceRequest { - request := testClient.GetInstance(testCtx, testProjectId, testInstanceId) + request := testClient.GetInstance(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -100,7 +101,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -108,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -116,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index aa0e92a03..040a9de6b 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -127,7 +127,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiListInstancesRequest { - req := apiClient.ListInstances(ctx, model.ProjectId) + req := apiClient.ListInstances(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/postgresflex/instance/list/list_test.go b/internal/cmd/postgresflex/instance/list/list_test.go index 11d835caf..09880f92c 100644 --- a/internal/cmd/postgresflex/instance/list/list_test.go +++ b/internal/cmd/postgresflex/instance/list/list_test.go @@ -14,18 +14,18 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -37,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -48,7 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiListInstancesRequest)) postgresflex.ApiListInstancesRequest { - request := testClient.ListInstances(testCtx, testProjectId) + request := testClient.ListInstances(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -76,21 +77,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index c52b2efc3..66022fb1d 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -82,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -111,7 +111,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance update: %w", err) } @@ -199,19 +199,19 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } type PostgreSQLFlexClient interface { - PartialUpdateInstance(ctx context.Context, projectId, instanceId string) postgresflex.ApiPartialUpdateInstanceRequest - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*postgresflex.InstanceResponse, error) - ListFlavorsExecute(ctx context.Context, projectId string) (*postgresflex.ListFlavorsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*postgresflex.ListStoragesResponse, error) + PartialUpdateInstance(ctx context.Context, projectId, region, instanceId string) postgresflex.ApiPartialUpdateInstanceRequest + GetInstanceExecute(ctx context.Context, projectId, region, instanceId string) (*postgresflex.InstanceResponse, error) + ListFlavorsExecute(ctx context.Context, projectId, region string) (*postgresflex.ListFlavorsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, region, flavorId string) (*postgresflex.ListStoragesResponse, error) } func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFlexClient) (postgresflex.ApiPartialUpdateInstanceRequest, error) { - req := apiClient.PartialUpdateInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.PartialUpdateInstance(ctx, model.ProjectId, model.Region, model.InstanceId) var flavorId *string var err error - flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return req, fmt.Errorf("get PostgreSQL Flex flavors: %w", err) } @@ -220,7 +220,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl ram := model.RAM cpu := model.CPU if model.RAM == nil || model.CPU == nil { - currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId) + currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.Region, model.InstanceId) if err != nil { return req, fmt.Errorf("get PostgreSQL Flex instance: %w", err) } @@ -251,13 +251,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl if model.StorageClass != nil || model.StorageSize != nil { validationFlavorId := flavorId if validationFlavorId == nil { - currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId) + currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.Region, model.InstanceId) if err != nil { return req, fmt.Errorf("get PostgreSQL Flex instance: %w", err) } validationFlavorId = currentInstance.Item.Flavor.Id } - storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *validationFlavorId) + storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, model.Region, *validationFlavorId) if err != nil { return req, fmt.Errorf("get PostgreSQL Flex storages: %w", err) } diff --git a/internal/cmd/postgresflex/instance/update/update_test.go b/internal/cmd/postgresflex/instance/update/update_test.go index edc536024..46b157bbe 100644 --- a/internal/cmd/postgresflex/instance/update/update_test.go +++ b/internal/cmd/postgresflex/instance/update/update_test.go @@ -14,12 +14,11 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &postgresflex.APIClient{} +var testRegion = "eu01" type postgresFlexClientMocked struct { listFlavorsFails bool @@ -30,25 +29,25 @@ type postgresFlexClientMocked struct { getInstanceResp *postgresflex.InstanceResponse } -func (c *postgresFlexClientMocked) PartialUpdateInstance(ctx context.Context, projectId, instanceId string) postgresflex.ApiPartialUpdateInstanceRequest { - return testClient.PartialUpdateInstance(ctx, projectId, instanceId) +func (c *postgresFlexClientMocked) PartialUpdateInstance(ctx context.Context, projectId, region, instanceId string) postgresflex.ApiPartialUpdateInstanceRequest { + return testClient.PartialUpdateInstance(ctx, projectId, region, instanceId) } -func (c *postgresFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*postgresflex.InstanceResponse, error) { +func (c *postgresFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*postgresflex.InstanceResponse, error) { if c.getInstanceFails { return nil, fmt.Errorf("get instance failed") } return c.getInstanceResp, nil } -func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*postgresflex.ListStoragesResponse, error) { +func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*postgresflex.ListStoragesResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list storages failed") } return c.listStoragesResp, nil } -func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*postgresflex.ListFlavorsResponse, error) { +func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*postgresflex.ListFlavorsResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") } @@ -71,7 +70,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureRequiredFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -81,15 +81,16 @@ func fixtureRequiredFlagValues(mods ...func(flagValues map[string]string)) map[s func fixtureStandardFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - flavorIdFlag: testFlavorId, - instanceNameFlag: "example-name", - aclFlag: "0.0.0.0/0", - backupScheduleFlag: "0 0 * * *", - storageClassFlag: "class", - storageSizeFlag: "10", - versionFlag: "5.0", - typeFlag: "Single", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + flavorIdFlag: testFlavorId, + instanceNameFlag: "example-name", + aclFlag: "0.0.0.0/0", + backupScheduleFlag: "0 0 * * *", + storageClassFlag: "class", + storageSizeFlag: "10", + versionFlag: "5.0", + typeFlag: "Single", } for _, mod := range mods { mod(flagValues) @@ -101,6 +102,7 @@ func fixtureRequiredInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -115,6 +117,7 @@ func fixtureStandardInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -134,7 +137,7 @@ func fixtureStandardInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiPartialUpdateInstanceRequest)) postgresflex.ApiPartialUpdateInstanceRequest { - request := testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId) + request := testClient.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId) request = request.PartialUpdateInstancePayload(postgresflex.PartialUpdateInstancePayload{}) for _, mod := range mods { mod(&request) @@ -202,7 +205,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -210,7 +213,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -218,7 +221,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -374,7 +377,7 @@ func TestBuildRequest(t *testing.T) { }, }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId). PartialUpdateInstancePayload(postgresflex.PartialUpdateInstancePayload{ FlavorId: utils.Ptr(testFlavorId), }), @@ -395,7 +398,7 @@ func TestBuildRequest(t *testing.T) { }, }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId). PartialUpdateInstancePayload(postgresflex.PartialUpdateInstancePayload{ FlavorId: utils.Ptr(testFlavorId), }), @@ -420,7 +423,7 @@ func TestBuildRequest(t *testing.T) { Max: utils.Ptr(int64(100)), }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId). PartialUpdateInstancePayload(postgresflex.PartialUpdateInstancePayload{ Storage: &postgresflex.Storage{ Class: utils.Ptr("class"), @@ -448,7 +451,7 @@ func TestBuildRequest(t *testing.T) { Max: utils.Ptr(int64(100)), }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId). PartialUpdateInstancePayload(postgresflex.PartialUpdateInstancePayload{ Storage: &postgresflex.Storage{ Class: utils.Ptr("class"), diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index a8ac9a614..8d53c2017 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -136,9 +136,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } type postgresFlexOptionsClient interface { - ListFlavorsExecute(ctx context.Context, projectId string) (*postgresflex.ListFlavorsResponse, error) - ListVersionsExecute(ctx context.Context, projectId string) (*postgresflex.ListVersionsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*postgresflex.ListStoragesResponse, error) + ListFlavorsExecute(ctx context.Context, projectId, region string) (*postgresflex.ListFlavorsResponse, error) + ListVersionsExecute(ctx context.Context, projectId, region string) (*postgresflex.ListVersionsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, region, flavorId string) (*postgresflex.ListStoragesResponse, error) } func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputModel, apiClient postgresFlexOptionsClient) error { @@ -148,19 +148,19 @@ func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputM var err error if model.Flavors { - flavors, err = apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err = apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("get PostgreSQL Flex flavors: %w", err) } } if model.Versions { - versions, err = apiClient.ListVersionsExecute(ctx, model.ProjectId) + versions, err = apiClient.ListVersionsExecute(ctx, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("get PostgreSQL Flex versions: %w", err) } } if model.Storages { - storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *model.FlavorId) + storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, model.Region, *model.FlavorId) if err != nil { return fmt.Errorf("get PostgreSQL Flex storages: %w", err) } diff --git a/internal/cmd/postgresflex/options/options_test.go b/internal/cmd/postgresflex/options/options_test.go index 5eebac304..3854aeaca 100644 --- a/internal/cmd/postgresflex/options/options_test.go +++ b/internal/cmd/postgresflex/options/options_test.go @@ -26,7 +26,7 @@ type postgresFlexClientMocked struct { listStoragesCalled bool } -func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*postgresflex.ListFlavorsResponse, error) { +func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*postgresflex.ListFlavorsResponse, error) { c.listFlavorsCalled = true if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") @@ -36,7 +36,7 @@ func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _ strin }), nil } -func (c *postgresFlexClientMocked) ListVersionsExecute(_ context.Context, _ string) (*postgresflex.ListVersionsResponse, error) { +func (c *postgresFlexClientMocked) ListVersionsExecute(_ context.Context, _, _ string) (*postgresflex.ListVersionsResponse, error) { c.listVersionsCalled = true if c.listVersionsFails { return nil, fmt.Errorf("list versions failed") @@ -46,7 +46,7 @@ func (c *postgresFlexClientMocked) ListVersionsExecute(_ context.Context, _ stri }), nil } -func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*postgresflex.ListStoragesResponse, error) { +func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*postgresflex.ListStoragesResponse, error) { c.listStoragesCalled = true if c.listStoragesFails { return nil, fmt.Errorf("list storages failed") diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 44a518d79..ce2912e3a 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -135,7 +135,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiCreateUserRequest { - req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId) + req := apiClient.CreateUser(ctx, model.ProjectId, model.Region, model.InstanceId) req = req.CreateUserPayload(postgresflex.CreateUserPayload{ Username: model.Username, Roles: model.Roles, diff --git a/internal/cmd/postgresflex/user/create/create_test.go b/internal/cmd/postgresflex/user/create/create_test.go index ab5a43277..6c0fe71ba 100644 --- a/internal/cmd/postgresflex/user/create/create_test.go +++ b/internal/cmd/postgresflex/user/create/create_test.go @@ -14,21 +14,21 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - usernameFlag: "johndoe", - roleFlag: "login", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + usernameFlag: "johndoe", + roleFlag: "login", } for _, mod := range mods { mod(flagValues) @@ -40,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -53,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiCreateUserRequest)) postgresflex.ApiCreateUserRequest { - request := testClient.CreateUser(testCtx, testProjectId, testInstanceId) + request := testClient.CreateUser(testCtx, testProjectId, testRegion, testInstanceId) request = request.CreateUserPayload(postgresflex.CreateUserPayload{ Username: utils.Ptr("johndoe"), Roles: utils.Ptr([]string{"login"}), @@ -87,21 +88,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/user/delete/delete.go b/internal/cmd/postgresflex/user/delete/delete.go index 0ca1f05ac..f9f166291 100644 --- a/internal/cmd/postgresflex/user/delete/delete.go +++ b/internal/cmd/postgresflex/user/delete/delete.go @@ -58,13 +58,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) + userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId, model.UserId) if err != nil { p.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId @@ -127,6 +127,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiDeleteUserRequest { - req := apiClient.DeleteUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.DeleteUser(ctx, model.ProjectId, model.Region, model.InstanceId, model.UserId) return req } diff --git a/internal/cmd/postgresflex/user/delete/delete_test.go b/internal/cmd/postgresflex/user/delete/delete_test.go index f4c38fc32..cd6dfa986 100644 --- a/internal/cmd/postgresflex/user/delete/delete_test.go +++ b/internal/cmd/postgresflex/user/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,6 +20,7 @@ var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testUserId = "12345" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +34,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -60,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiDeleteUserRequest)) postgresflex.ApiDeleteUserRequest { - request := testClient.DeleteUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.DeleteUser(testCtx, testProjectId, testRegion, testInstanceId, testUserId) for _, mod := range mods { mod(&request) } @@ -104,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/user/describe/describe.go b/internal/cmd/postgresflex/user/describe/describe.go index 896154984..cc02a616b 100644 --- a/internal/cmd/postgresflex/user/describe/describe.go +++ b/internal/cmd/postgresflex/user/describe/describe.go @@ -112,7 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiGetUserRequest { - req := apiClient.GetUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.GetUser(ctx, model.ProjectId, model.Region, model.InstanceId, model.UserId) return req } diff --git a/internal/cmd/postgresflex/user/describe/describe_test.go b/internal/cmd/postgresflex/user/describe/describe_test.go index c3dadb008..4ff8819b9 100644 --- a/internal/cmd/postgresflex/user/describe/describe_test.go +++ b/internal/cmd/postgresflex/user/describe/describe_test.go @@ -12,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -21,6 +19,7 @@ var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testUserId = "12345" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,8 +33,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -47,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -59,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiGetUserRequest)) postgresflex.ApiGetUserRequest { - request := testClient.GetUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.GetUser(testCtx, testProjectId, testRegion, testInstanceId, testUserId) for _, mod := range mods { mod(&request) } @@ -103,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index bf540ad4c..0b530674d 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get PostgreSQL Flex users: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, *model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId @@ -133,7 +133,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiListUsersRequest { - req := apiClient.ListUsers(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.ListUsers(ctx, model.ProjectId, model.Region, *model.InstanceId) return req } diff --git a/internal/cmd/postgresflex/user/list/list_test.go b/internal/cmd/postgresflex/user/list/list_test.go index fb042f6c9..ed82bbb26 100644 --- a/internal/cmd/postgresflex/user/list/list_test.go +++ b/internal/cmd/postgresflex/user/list/list_test.go @@ -14,20 +14,20 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -39,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: utils.Ptr(testInstanceId), @@ -51,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiListUsersRequest)) postgresflex.ApiListUsersRequest { - request := testClient.ListUsers(testCtx, testProjectId, testInstanceId) + request := testClient.ListUsers(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -79,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index 14163d879..d2d240585 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -59,13 +59,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) + userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId, model.UserId) if err != nil { p.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId @@ -128,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiResetUserRequest { - req := apiClient.ResetUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.ResetUser(ctx, model.ProjectId, model.Region, model.InstanceId, model.UserId) return req } diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go index d984f0271..8cde43c41 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go @@ -12,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -21,6 +19,7 @@ var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testUserId = "12345" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,8 +33,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -47,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -59,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiResetUserRequest)) postgresflex.ApiResetUserRequest { - request := testClient.ResetUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.ResetUser(testCtx, testProjectId, testRegion, testInstanceId, testUserId) for _, mod := range mods { mod(&request) } @@ -103,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/postgresflex/user/update/update.go b/internal/cmd/postgresflex/user/update/update.go index 7edab64e6..47872ecc5 100644 --- a/internal/cmd/postgresflex/user/update/update.go +++ b/internal/cmd/postgresflex/user/update/update.go @@ -56,13 +56,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { p.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) + userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId, model.UserId) if err != nil { p.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId @@ -135,7 +135,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresflex.APIClient) postgresflex.ApiPartialUpdateUserRequest { - req := apiClient.PartialUpdateUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.PartialUpdateUser(ctx, model.ProjectId, model.Region, model.InstanceId, model.UserId) req = req.PartialUpdateUserPayload(postgresflex.PartialUpdateUserPayload{ Roles: model.Roles, }) diff --git a/internal/cmd/postgresflex/user/update/update_test.go b/internal/cmd/postgresflex/user/update/update_test.go index f50e61f37..fb0fe9cd3 100644 --- a/internal/cmd/postgresflex/user/update/update_test.go +++ b/internal/cmd/postgresflex/user/update/update_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -23,6 +21,7 @@ var testClient = &postgresflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() var testUserId = "12345" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -36,9 +35,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - roleFlag: "login", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + roleFlag: "login", } for _, mod := range mods { mod(flagValues) @@ -50,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -63,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *postgresflex.ApiPartialUpdateUserRequest)) postgresflex.ApiPartialUpdateUserRequest { - request := testClient.PartialUpdateUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.PartialUpdateUser(testCtx, testProjectId, testRegion, testInstanceId, testUserId) request = request.PartialUpdateUserPayload(postgresflex.PartialUpdateUserPayload{ Roles: utils.Ptr([]string{"login"}), }) @@ -105,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/pkg/services/postgresflex/utils/utils.go b/internal/pkg/services/postgresflex/utils/utils.go index 66bc48474..fc1965bdd 100644 --- a/internal/pkg/services/postgresflex/utils/utils.go +++ b/internal/pkg/services/postgresflex/utils/utils.go @@ -19,9 +19,9 @@ var instanceTypeToReplicas = map[string]int64{ } type PostgresFlexClient interface { - ListVersionsExecute(ctx context.Context, projectId string) (*postgresflex.ListVersionsResponse, error) - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*postgresflex.InstanceResponse, error) - GetUserExecute(ctx context.Context, projectId, instanceId, userId string) (*postgresflex.GetUserResponse, error) + ListVersionsExecute(ctx context.Context, projectId, region string) (*postgresflex.ListVersionsResponse, error) + GetInstanceExecute(ctx context.Context, projectId, region, instanceId string) (*postgresflex.InstanceResponse, error) + GetUserExecute(ctx context.Context, projectId, region, instanceId, userId string) (*postgresflex.GetUserResponse, error) } func AvailableInstanceTypes() []string { @@ -119,8 +119,8 @@ func LoadFlavorId(cpu, ram int64, flavors *[]postgresflex.Flavor) (*string, erro } } -func GetLatestPostgreSQLVersion(ctx context.Context, apiClient PostgresFlexClient, projectId string) (string, error) { - resp, err := apiClient.ListVersionsExecute(ctx, projectId) +func GetLatestPostgreSQLVersion(ctx context.Context, apiClient PostgresFlexClient, projectId, region string) (string, error) { + resp, err := apiClient.ListVersionsExecute(ctx, projectId, region) if err != nil { return "", fmt.Errorf("get PostgreSQL versions: %w", err) } @@ -141,24 +141,24 @@ func GetLatestPostgreSQLVersion(ctx context.Context, apiClient PostgresFlexClien return latestVersion, nil } -func GetInstanceName(ctx context.Context, apiClient PostgresFlexClient, projectId, instanceId string) (string, error) { - resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId) +func GetInstanceName(ctx context.Context, apiClient PostgresFlexClient, projectId, region, instanceId string) (string, error) { + resp, err := apiClient.GetInstanceExecute(ctx, projectId, region, instanceId) if err != nil { return "", fmt.Errorf("get PostgreSQL Flex instance: %w", err) } return *resp.Item.Name, nil } -func GetInstanceStatus(ctx context.Context, apiClient PostgresFlexClient, projectId, instanceId string) (string, error) { - resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId) +func GetInstanceStatus(ctx context.Context, apiClient PostgresFlexClient, projectId, region, instanceId string) (string, error) { + resp, err := apiClient.GetInstanceExecute(ctx, projectId, region, instanceId) if err != nil { return "", fmt.Errorf("get PostgreSQL Flex instance: %w", err) } return *resp.Item.Status, nil } -func GetUserName(ctx context.Context, apiClient PostgresFlexClient, projectId, instanceId, userId string) (string, error) { - resp, err := apiClient.GetUserExecute(ctx, projectId, instanceId, userId) +func GetUserName(ctx context.Context, apiClient PostgresFlexClient, projectId, region, instanceId, userId string) (string, error) { + resp, err := apiClient.GetUserExecute(ctx, projectId, region, instanceId, userId) if err != nil { return "", fmt.Errorf("get PostgreSQL Flex user: %w", err) } diff --git a/internal/pkg/services/postgresflex/utils/utils_test.go b/internal/pkg/services/postgresflex/utils/utils_test.go index 250295e79..346debe49 100644 --- a/internal/pkg/services/postgresflex/utils/utils_test.go +++ b/internal/pkg/services/postgresflex/utils/utils_test.go @@ -22,6 +22,7 @@ const ( testInstanceName = "instance" testUserName = "user" testStatus = "running" + testRegion = "eu01" ) type postgresFlexClientMocked struct { @@ -33,21 +34,21 @@ type postgresFlexClientMocked struct { getUserResp *postgresflex.GetUserResponse } -func (m *postgresFlexClientMocked) ListVersionsExecute(_ context.Context, _ string) (*postgresflex.ListVersionsResponse, error) { +func (m *postgresFlexClientMocked) ListVersionsExecute(_ context.Context, _, _ string) (*postgresflex.ListVersionsResponse, error) { if m.listVersionsFails { return nil, fmt.Errorf("could not list versions") } return m.listVersionsResp, nil } -func (m *postgresFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*postgresflex.InstanceResponse, error) { +func (m *postgresFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*postgresflex.InstanceResponse, error) { if m.getInstanceFails { return nil, fmt.Errorf("could not get instance") } return m.getInstanceResp, nil } -func (m *postgresFlexClientMocked) GetUserExecute(_ context.Context, _, _, _ string) (*postgresflex.GetUserResponse, error) { +func (m *postgresFlexClientMocked) GetUserExecute(_ context.Context, _, _, _, _ string) (*postgresflex.GetUserResponse, error) { if m.getUserFails { return nil, fmt.Errorf("could not get user") } @@ -402,7 +403,7 @@ func TestGetLatestPostgreSQLVersion(t *testing.T) { listVersionsResp: tt.listVersionsResp, } - output, err := GetLatestPostgreSQLVersion(context.Background(), client, testProjectId) + output, err := GetLatestPostgreSQLVersion(context.Background(), client, testProjectId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -452,7 +453,7 @@ func TestGetInstanceName(t *testing.T) { getInstanceResp: tt.getInstanceResp, } - output, err := GetInstanceName(context.Background(), client, testProjectId, testInstanceId) + output, err := GetInstanceName(context.Background(), client, testProjectId, testRegion, testInstanceId) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -502,7 +503,7 @@ func TestGetInstanceStatus(t *testing.T) { getInstanceResp: tt.getInstanceResp, } - output, err := GetInstanceStatus(context.Background(), client, testProjectId, testInstanceId) + output, err := GetInstanceStatus(context.Background(), client, testProjectId, testRegion, testInstanceId) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -552,7 +553,7 @@ func TestGetUserName(t *testing.T) { getUserResp: tt.getUserResp, } - output, err := GetUserName(context.Background(), client, testProjectId, testInstanceId, testUserId) + output, err := GetUserName(context.Background(), client, testProjectId, testRegion, testInstanceId, testUserId) if tt.isValid && err != nil { t.Errorf("failed on valid input") From 393d1bd2ce111f8e3ce522491ff4cd33b6e3e6d6 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Tue, 18 Mar 2025 11:30:35 +0100 Subject: [PATCH 224/619] feat(serviceenablement): Region adjustment (#649) Signed-off-by: Alexander Dahmen --- go.mod | 2 +- go.sum | 4 ++-- internal/cmd/ske/cluster/create/create.go | 2 +- internal/cmd/ske/cluster/list/list.go | 2 +- internal/cmd/ske/describe/describe.go | 4 ++-- internal/cmd/ske/describe/describe_test.go | 19 ++++++++++--------- internal/cmd/ske/disable/disable.go | 6 +++--- internal/cmd/ske/disable/disable_test.go | 19 ++++++++++--------- internal/cmd/ske/enable/enable.go | 6 +++--- internal/cmd/ske/enable/enable_test.go | 19 ++++++++++--------- .../service-enablement/utils/utils.go | 6 +++--- .../service-enablement/utils/utils_test.go | 5 +++-- 12 files changed, 49 insertions(+), 45 deletions(-) diff --git a/go.mod b/go.mod index 37c11f601..a6d2b80e1 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0 github.com/zalando/go-keyring v0.2.6 diff --git a/go.sum b/go.sum index 1c461e0c3..a0fa8c1f8 100644 --- a/go.sum +++ b/go.sum @@ -157,8 +157,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 h1:TMUxDh8XG github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0/go.mod h1:giHnHz3kHeLY8Av9MZLsyJlaTXYz+BuGqdP/SKB5Vo0= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0 h1:y+XzJcntHJ7M+IWWvAUkiVFA8op+jZxwHs3ktW2aLoA= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0/go.mod h1:J/Wa67cbDI1wAyxib9PiEbNqGfIoFUH+DSLueVazQx8= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0 h1:QG+rGBHsyXOlJ3ZIeOgExGqu9PoTlGY1rltW/VpG6lw= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.5.0/go.mod h1:16dOVT052cMuHhUJ3NIcPuY7TrpCr9QlxmvvfjLZubA= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.0 h1:Xxd5KUSWRt7FytnNWClLEa0n9GM6e5xAKo835ODSpAM= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.0/go.mod h1:EMqjiq/72WKXSwnJGLpumUJS4Uwlyhg5vtNg7qWoGtc= github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0 h1:3KUVls8zXsbT2tOYRSHyp3/l0Kpjl4f3INmQKYTe65Y= github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0/go.mod h1:63IvXpBJTIVONAnGPSDo0sRJ+6n6tzO918OLqfYBxto= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0 h1:RYJO0rZea9+sxVfaJDWRo2zgfKNgiUcA5c0nbvZURiU= diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 014e69bc2..195b343ca 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -96,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // Check if the project is enabled before trying to create - enabled, err := serviceEnablementUtils.ProjectEnabled(ctx, serviceEnablementApiClient, model.ProjectId) + enabled, err := serviceEnablementUtils.ProjectEnabled(ctx, serviceEnablementApiClient, model.ProjectId, model.Region) if err != nil { return err } diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 8f6dd8829..7b5389454 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -69,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // Check if SKE is enabled for this project - enabled, err := serviceEnablementUtils.ProjectEnabled(ctx, serviceEnablementApiClient, model.ProjectId) + enabled, err := serviceEnablementUtils.ProjectEnabled(ctx, serviceEnablementApiClient, model.ProjectId, model.Region) if err != nil { return err } diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index 4912b997d..6694b04a7 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -81,8 +81,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiGetServiceStatusRequest { - req := apiClient.GetServiceStatus(ctx, model.ProjectId, skeUtils.SKEServiceId) +func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiGetServiceStatusRegionalRequest { + req := apiClient.GetServiceStatusRegional(ctx, model.Region, model.ProjectId, skeUtils.SKEServiceId) return req } diff --git a/internal/cmd/ske/describe/describe_test.go b/internal/cmd/ske/describe/describe_test.go index 983e061e5..839ae512e 100644 --- a/internal/cmd/ske/describe/describe_test.go +++ b/internal/cmd/ske/describe/describe_test.go @@ -15,17 +15,17 @@ import ( "github.com/spf13/cobra" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serviceenablement.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, } @@ -46,8 +47,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *serviceenablement.ApiGetServiceStatusRequest)) serviceenablement.ApiGetServiceStatusRequest { - request := testClient.GetServiceStatus(testCtx, testProjectId, serviceEnablementUtils.SKEServiceId) //nolint:staticcheck //command will be removed in a later update +func fixtureRequest(mods ...func(request *serviceenablement.ApiGetServiceStatusRegionalRequest)) serviceenablement.ApiGetServiceStatusRegionalRequest { + request := testClient.GetServiceStatusRegional(testCtx, testRegion, testProjectId, serviceEnablementUtils.SKEServiceId) //nolint:staticcheck //command will be removed in a later update for _, mod := range mods { mod(&request) } @@ -75,21 +76,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -146,7 +147,7 @@ func TestBuildRequest(t *testing.T) { description string model *inputModel isValid bool - expectedRequest serviceenablement.ApiGetServiceStatusRequest + expectedRequest serviceenablement.ApiGetServiceStatusRegionalRequest }{ { description: "base", diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index 491b06cb7..d00a56715 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Disabling SKE") - _, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) + _, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SKE disabling: %w", err) } @@ -112,7 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiDisableServiceRequest { - req := apiClient.DisableService(ctx, model.ProjectId, utils.SKEServiceId) +func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiDisableServiceRegionalRequest { + req := apiClient.DisableServiceRegional(ctx, model.Region, model.ProjectId, utils.SKEServiceId) return req } diff --git a/internal/cmd/ske/disable/disable_test.go b/internal/cmd/ske/disable/disable_test.go index cc9a528a6..b377dc366 100644 --- a/internal/cmd/ske/disable/disable_test.go +++ b/internal/cmd/ske/disable/disable_test.go @@ -15,17 +15,17 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serviceenablement.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, } @@ -46,8 +47,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *serviceenablement.ApiDisableServiceRequest)) serviceenablement.ApiDisableServiceRequest { - request := testClient.DisableService(testCtx, testProjectId, utils.SKEServiceId) +func fixtureRequest(mods ...func(request *serviceenablement.ApiDisableServiceRegionalRequest)) serviceenablement.ApiDisableServiceRegionalRequest { + request := testClient.DisableServiceRegional(testCtx, testRegion, testProjectId, utils.SKEServiceId) for _, mod := range mods { mod(&request) } @@ -75,21 +76,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -145,7 +146,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest serviceenablement.ApiDisableServiceRequest + expectedRequest serviceenablement.ApiDisableServiceRegionalRequest }{ { description: "base", diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index cdb07134d..9ab8ed7bf 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Enabling SKE") - _, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) + _, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SKE enabling: %w", err) } @@ -112,7 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiEnableServiceRequest { - req := apiClient.EnableService(ctx, model.ProjectId, utils.SKEServiceId) +func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceenablement.APIClient) serviceenablement.ApiEnableServiceRegionalRequest { + req := apiClient.EnableServiceRegional(ctx, model.Region, model.ProjectId, utils.SKEServiceId) return req } diff --git a/internal/cmd/ske/enable/enable_test.go b/internal/cmd/ske/enable/enable_test.go index e0f93b8fc..d46ec2d07 100644 --- a/internal/cmd/ske/enable/enable_test.go +++ b/internal/cmd/ske/enable/enable_test.go @@ -15,17 +15,17 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serviceenablement.APIClient{} var testProjectId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, } @@ -46,8 +47,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *serviceenablement.ApiEnableServiceRequest)) serviceenablement.ApiEnableServiceRequest { - request := testClient.EnableService(testCtx, testProjectId, utils.SKEServiceId) +func fixtureRequest(mods ...func(request *serviceenablement.ApiEnableServiceRegionalRequest)) serviceenablement.ApiEnableServiceRegionalRequest { + request := testClient.EnableServiceRegional(testCtx, testRegion, testProjectId, utils.SKEServiceId) for _, mod := range mods { mod(&request) } @@ -75,21 +76,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -145,7 +146,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest serviceenablement.ApiEnableServiceRequest + expectedRequest serviceenablement.ApiEnableServiceRegionalRequest }{ { description: "base", diff --git a/internal/pkg/services/service-enablement/utils/utils.go b/internal/pkg/services/service-enablement/utils/utils.go index 45e3f819b..a6e29254c 100644 --- a/internal/pkg/services/service-enablement/utils/utils.go +++ b/internal/pkg/services/service-enablement/utils/utils.go @@ -14,11 +14,11 @@ const ( ) type ServiceEnablementClient interface { - GetServiceStatusExecute(ctx context.Context, projectId string, serviceId string) (*serviceenablement.ServiceStatus, error) + GetServiceStatusRegionalExecute(ctx context.Context, region, projectId, serviceId string) (*serviceenablement.ServiceStatus, error) } -func ProjectEnabled(ctx context.Context, apiClient ServiceEnablementClient, projectId string) (bool, error) { - project, err := apiClient.GetServiceStatusExecute(ctx, projectId, SKEServiceId) +func ProjectEnabled(ctx context.Context, apiClient ServiceEnablementClient, projectId, region string) (bool, error) { + project, err := apiClient.GetServiceStatusRegionalExecute(ctx, region, projectId, SKEServiceId) if err != nil { oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped if !ok { diff --git a/internal/pkg/services/service-enablement/utils/utils_test.go b/internal/pkg/services/service-enablement/utils/utils_test.go index 4ade8fa58..3c364847a 100644 --- a/internal/pkg/services/service-enablement/utils/utils_test.go +++ b/internal/pkg/services/service-enablement/utils/utils_test.go @@ -15,6 +15,7 @@ import ( var ( testProjectId = uuid.NewString() + testRegion = "eu01" ) type serviceEnableClientMocked struct { @@ -23,7 +24,7 @@ type serviceEnableClientMocked struct { getServiceStatusResp *serviceenablement.ServiceStatus } -func (m *serviceEnableClientMocked) GetServiceStatusExecute(_ context.Context, _, _ string) (*serviceenablement.ServiceStatus, error) { +func (m *serviceEnableClientMocked) GetServiceStatusRegionalExecute(_ context.Context, _, _, _ string) (*serviceenablement.ServiceStatus, error) { if m.getServiceStatusFails { return nil, fmt.Errorf("could not get service status") } @@ -87,7 +88,7 @@ func TestProjectEnabled(t *testing.T) { getServiceStatusResp: tt.getProjectResp, } - output, err := ProjectEnabled(context.Background(), client, testProjectId) + output, err := ProjectEnabled(context.Background(), client, testRegion, testProjectId) if tt.isValid && err != nil { t.Errorf("failed on valid input") From e2a6274bb0e0bdc26364b3bc9d5bb6bd4cf6a9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 18 Mar 2025 17:17:53 +0100 Subject: [PATCH 225/619] chore(doc): add github issue note and docs link to readme (#655) --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 236f7f102..5cda470a5 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ The STACKIT CLI allows you to manage your STACKIT services and resources as well - Databases such as PostgreSQL Flex, MongoDB Flex and SQLServer Flex This CLI is in a BETA state. More services and functionality will be supported soon. -Your feedback is appreciated! +Your feedback is appreciated! +Feel free to open [GitHub issues](https://github.com/stackitcloud/stackit-cli) to provide feature requests and bug reports. @@ -35,6 +36,10 @@ Your feedback is appreciated! Please refer to our [installation guide](./INSTALLATION.md) for instructions on how to install and get started using the STACKIT CLI. +## Documentation + +There is some [documentation](./docs/stackit.md) available in the markdown format inside the `docs` directory of the repository. + ## Usage A typical command is structured as: From 0ecf9e86b89948c94dc7e853991d45322114b904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 18 Mar 2025 17:45:04 +0100 Subject: [PATCH 226/619] fix(sqlserver): remove region configuration from client (#656) --- internal/pkg/services/sqlserverflex/client/client.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/pkg/services/sqlserverflex/client/client.go b/internal/pkg/services/sqlserverflex/client/client.go index d3789ed5c..2767ae937 100644 --- a/internal/pkg/services/sqlserverflex/client/client.go +++ b/internal/pkg/services/sqlserverflex/client/client.go @@ -21,8 +21,7 @@ func ConfigureClient(p *print.Printer) (*sqlserverflex.APIClient, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions = append(cfgOptions, authCfgOption) customEndpoint := viper.GetString(config.SQLServerFlexCustomEndpointKey) From 5e955969cea046795f5dee2d33152547fe084302 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 19 Mar 2025 14:47:38 +0100 Subject: [PATCH 227/619] fix(deps): update module github.com/goccy/go-yaml to v1.16.0 (#651) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a6d2b80e1..f206199fd 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.15.23 + github.com/goccy/go-yaml v1.16.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index a0fa8c1f8..6457628c4 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/goccy/go-yaml v1.15.23 h1:WS0GAX1uNPDLUvLkNU2vXq6oTnsmfVFocjQ/4qA48qo= -github.com/goccy/go-yaml v1.15.23/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.16.0 h1:d7m1G7A0t+logajVtklHfDYJs2Et9g3gHwdBNNFou0w= +github.com/goccy/go-yaml v1.16.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 8ebf46681a9d460da851a66a7a75e9e5fdad4333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 19 Mar 2025 16:08:23 +0100 Subject: [PATCH 228/619] chore(loadbalancer): regional adjustment (#652) * fix(loadbalancer): show correct number of listeners & targets in list cmd relates to STACKITCLI-127 --- go.mod | 2 +- go.sum | 4 +- internal/cmd/load-balancer/create/create.go | 4 +- .../cmd/load-balancer/create/create_test.go | 26 +++++++----- internal/cmd/load-balancer/delete/delete.go | 4 +- .../cmd/load-balancer/delete/delete_test.go | 16 +++++--- .../cmd/load-balancer/describe/describe.go | 2 +- .../load-balancer/describe/describe_test.go | 18 +++++---- .../generate-payload/generate_payload.go | 2 +- .../generate-payload/generate_payload_test.go | 20 ++++++---- internal/cmd/load-balancer/list/list.go | 18 ++++++--- internal/cmd/load-balancer/list/list_test.go | 25 ++++++++---- .../observability-credentials/add/add.go | 2 +- .../observability-credentials/add/add_test.go | 22 +++++----- .../cleanup/cleanup.go | 6 +-- .../cleanup/cleanup_test.go | 21 +++++----- .../delete/delete.go | 4 +- .../delete/delete_test.go | 19 +++++---- .../describe/describe.go | 2 +- .../describe/describe_test.go | 19 +++++---- .../observability-credentials/list/list.go | 4 +- .../list/list_test.go | 18 +++++---- .../update/update.go | 21 ++++++---- .../update/update_test.go | 40 ++++++++++--------- internal/cmd/load-balancer/quota/quota.go | 2 +- .../cmd/load-balancer/quota/quota_test.go | 16 +++++--- .../target-pool/add-target/add_target.go | 4 +- .../target-pool/add-target/add_target_test.go | 31 +++++++------- .../target-pool/describe/describe.go | 2 +- .../target-pool/describe/describe_test.go | 17 ++++---- .../remove-target/remove_target.go | 6 +-- .../remove-target/remove_target_test.go | 30 +++++++------- internal/cmd/load-balancer/update/update.go | 2 +- .../cmd/load-balancer/update/update_test.go | 18 +++++---- .../services/load-balancer/client/client.go | 3 +- .../pkg/services/load-balancer/utils/utils.go | 33 ++++++++------- .../load-balancer/utils/utils_test.go | 19 ++++----- 37 files changed, 290 insertions(+), 212 deletions(-) diff --git a/go.mod b/go.mod index f206199fd..a5b24e46a 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.18.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.0 diff --git a/go.sum b/go.sum index 6457628c4..7059fa771 100644 --- a/go.sum +++ b/go.sum @@ -125,8 +125,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0 h1:gEoA2oj3OcDg3XI0K github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0/go.mod h1:JE8POcTfSxTo+g1MkgVQ+OjT4jWEr08MIY8qx3Hi+Tw= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1 h1:ZFFJr54FcYTUBjE+5E3Cx92jTDdHGKT2DTIvvJSRrTc= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1/go.mod h1:9p5IIdOKOM5/DIjbenKrWvz6GlSps4jsPJZkH7QJuRU= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.18.0 h1:7nNjIIcBQRDVnW4NL7+R8DaCKEqxxxsmVsgOVe50ZMU= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.18.0/go.mod h1:UFujBT+JlNvl6JNrY96UpLGqp+lZTD+JWL7siqhGPlw= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.0 h1:z2p0OobEAgSE5bQr+KR+4Y1QTvDbSC2a7w2eCV/oSp4= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.0/go.mod h1:x0jgrL+/K2cE4BvcIQByFUf0nOPVZRqq5Z074kjjr64= github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0 h1:P7bxaVzkZPGMWItLynKIvc88Xh6jCnK4dPTTT+L607o= github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0/go.mod h1:os4Kp2+jkMUJ2dZtgU9A91N3EJSw3MMh2slxgK1609g= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0 h1:ks1i+cfD/YPRss//4aq6uvxbLvUwb5QvcUrOPeboLFY= diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index e106d4aa9..a0600f66d 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -95,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Creating load balancer") - _, err = wait.CreateLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, *model.Payload.Name).WaitWithContext(ctx) + _, err = wait.CreateLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *model.Payload.Name).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for load balancer creation: %w", err) } @@ -155,7 +155,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiCreateLoadBalancerRequest { - req := apiClient.CreateLoadBalancer(ctx, model.ProjectId) + req := apiClient.CreateLoadBalancer(ctx, model.ProjectId, model.Region) req = req.CreateLoadBalancerPayload(*model.Payload) req = req.XRequestID(xRequestId) return req diff --git a/internal/cmd/load-balancer/create/create_test.go b/internal/cmd/load-balancer/create/create_test.go index 09dae8cc1..da7bfce83 100644 --- a/internal/cmd/load-balancer/create/create_test.go +++ b/internal/cmd/load-balancer/create/create_test.go @@ -15,14 +15,18 @@ import ( "github.com/google/uuid" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &loadbalancer.APIClient{} -var testProjectId = uuid.NewString() -var testRequestId = xRequestId +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &loadbalancer.APIClient{} + testProjectId = uuid.NewString() + testRequestId = xRequestId +) var testPayload = &loadbalancer.CreateLoadBalancerPayload{ ExternalAddress: utils.Ptr(""), @@ -98,7 +102,8 @@ var testPayload = &loadbalancer.CreateLoadBalancerPayload{ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, payloadFlag: `{ "externalAddress": "", "listeners": [ @@ -180,6 +185,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Payload: testPayload, @@ -191,7 +197,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiCreateLoadBalancerRequest)) loadbalancer.ApiCreateLoadBalancerRequest { - request := testClient.CreateLoadBalancer(testCtx, testProjectId) + request := testClient.CreateLoadBalancer(testCtx, testProjectId, testRegion) request = request.CreateLoadBalancerPayload(*testPayload) request = request.XRequestID(testRequestId) for _, mod := range mods { @@ -226,21 +232,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/delete/delete.go b/internal/cmd/load-balancer/delete/delete.go index ff3f50e80..c2410db74 100644 --- a/internal/cmd/load-balancer/delete/delete.go +++ b/internal/cmd/load-balancer/delete/delete.go @@ -68,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.Async { s := spinner.New(p) s.Start("Deleting load balancer") - _, err = wait.DeleteLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.LoadBalancerName).WaitWithContext(ctx) + _, err = wait.DeleteLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.LoadBalancerName).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for load balancer deletion: %w", err) } @@ -112,6 +112,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiDeleteLoadBalancerRequest { - req := apiClient.DeleteLoadBalancer(ctx, model.ProjectId, model.LoadBalancerName) + req := apiClient.DeleteLoadBalancer(ctx, model.ProjectId, model.Region, model.LoadBalancerName) return req } diff --git a/internal/cmd/load-balancer/delete/delete_test.go b/internal/cmd/load-balancer/delete/delete_test.go index eac37e0fa..621113c56 100644 --- a/internal/cmd/load-balancer/delete/delete_test.go +++ b/internal/cmd/load-balancer/delete/delete_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -46,6 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, LoadBalancerName: testLoadBalancerName, @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiDeleteLoadBalancerRequest)) loadbalancer.ApiDeleteLoadBalancerRequest { - request := testClient.DeleteLoadBalancer(testCtx, testProjectId, testLoadBalancerName) + request := testClient.DeleteLoadBalancer(testCtx, testProjectId, testRegion, testLoadBalancerName) for _, mod := range mods { mod(&request) } @@ -101,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index 0c759d545..603bfd185 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -94,7 +94,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiGetLoadBalancerRequest { - req := apiClient.GetLoadBalancer(ctx, model.ProjectId, model.LoadBalancerName) + req := apiClient.GetLoadBalancer(ctx, model.ProjectId, model.Region, model.LoadBalancerName) return req } diff --git a/internal/cmd/load-balancer/describe/describe_test.go b/internal/cmd/load-balancer/describe/describe_test.go index 24720dac8..821f942b7 100644 --- a/internal/cmd/load-balancer/describe/describe_test.go +++ b/internal/cmd/load-balancer/describe/describe_test.go @@ -12,14 +12,16 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testloadBalancerName = "loadBalancer" +) type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &loadbalancer.APIClient{} var testProjectId = uuid.NewString() -var testloadBalancerName = "loadBalancer" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -33,7 +35,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -45,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, LoadBalancerName: testloadBalancerName, @@ -56,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiGetLoadBalancerRequest)) loadbalancer.ApiGetLoadBalancerRequest { - request := testClient.GetLoadBalancer(testCtx, testProjectId, testloadBalancerName) + request := testClient.GetLoadBalancer(testCtx, testProjectId, testRegion, testloadBalancerName) for _, mod := range mods { mod(&request) } @@ -100,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -108,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -116,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index b947aa629..ba14de569 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -208,7 +208,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiGetLoadBalancerRequest { - req := apiClient.GetLoadBalancer(ctx, model.ProjectId, *model.LoadBalancerName) + req := apiClient.GetLoadBalancer(ctx, model.ProjectId, model.Region, *model.LoadBalancerName) return req } diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go index e8dd6dd2e..0e2ee4beb 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -28,9 +30,10 @@ const ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - loadBalancerNameFlag: testLoadBalancerName, - filePathFlag: testFilePath, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + loadBalancerNameFlag: testLoadBalancerName, + filePathFlag: testFilePath, } for _, mod := range mods { mod(flagValues) @@ -42,6 +45,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, LoadBalancerName: utils.Ptr(testLoadBalancerName), @@ -54,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiGetLoadBalancerRequest)) loadbalancer.ApiGetLoadBalancerRequest { - request := testClient.GetLoadBalancer(testCtx, testProjectId, testLoadBalancerName) + request := testClient.GetLoadBalancer(testCtx, testProjectId, testRegion, testLoadBalancerName) for _, mod := range mods { mod(&request) } @@ -105,21 +109,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index fa2036c29..a9611e137 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -127,7 +127,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiListLoadBalancersRequest { - req := apiClient.ListLoadBalancers(ctx, model.ProjectId) + req := apiClient.ListLoadBalancers(ctx, model.ProjectId, model.Region) return req } @@ -154,13 +154,21 @@ func outputResult(p *print.Printer, outputFormat string, loadBalancers []loadbal table.SetHeader("NAME", "STATE", "IP ADDRESS", "LISTENERS", "TARGET POOLS") for i := range loadBalancers { l := loadBalancers[i] - externalAdress := utils.PtrStringDefault(l.ExternalAddress, "-") + var numListeners, numTargetPools int + if l.Listeners != nil { + numListeners = len(*l.Listeners) + } + if l.TargetPools != nil { + numTargetPools = len(*l.TargetPools) + } + + externalAddress := utils.PtrStringDefault(l.ExternalAddress, "-") table.AddRow( utils.PtrString(l.Name), utils.PtrString(l.Status), - externalAdress, - len(utils.PtrString(l.Listeners)), - len(utils.PtrString(l.TargetPools)), + externalAddress, + numListeners, + numTargetPools, ) } err := table.Display(p) diff --git a/internal/cmd/load-balancer/list/list_test.go b/internal/cmd/load-balancer/list/list_test.go index 2ad30db36..d0210b9cb 100644 --- a/internal/cmd/load-balancer/list/list_test.go +++ b/internal/cmd/load-balancer/list/list_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -23,8 +25,9 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -36,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -47,7 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiListLoadBalancersRequest)) loadbalancer.ApiListLoadBalancersRequest { - request := testClient.ListLoadBalancers(testCtx, testProjectId) + request := testClient.ListLoadBalancers(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -75,21 +79,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -198,6 +202,13 @@ func TestOutputResult(t *testing.T) { args: args{}, wantErr: false, }, + { + name: "empty loadbalancers slice", + args: args{ + loadBalancers: []loadbalancer.LoadBalancer{}, + }, + wantErr: false, + }, { name: "empty loadbalancer in loadbalancers slice", args: args{ diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index 77dfbf48e..a75b5e064 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -133,7 +133,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiCreateCredentialsRequest { - req := apiClient.CreateCredentials(ctx, model.ProjectId) + req := apiClient.CreateCredentials(ctx, model.ProjectId, model.Region) req = req.XRequestID(uuid.NewString()) req = req.CreateCredentialsPayload(loadbalancer.CreateCredentialsPayload{ diff --git a/internal/cmd/load-balancer/observability-credentials/add/add_test.go b/internal/cmd/load-balancer/observability-credentials/add/add_test.go index a9cfb8719..57557613a 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add_test.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -23,10 +25,11 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - displayNameFlag: "name", - usernameFlag: "username", - passwordFlag: "pwd", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + displayNameFlag: "name", + usernameFlag: "username", + passwordFlag: "pwd", } for _, mod := range mods { mod(flagValues) @@ -38,6 +41,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, DisplayName: utils.Ptr("name"), @@ -51,7 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiCreateCredentialsRequest)) loadbalancer.ApiCreateCredentialsRequest { - request := testClient.CreateCredentials(testCtx, testProjectId) + request := testClient.CreateCredentials(testCtx, testProjectId, testRegion) request = request.CreateCredentialsPayload(loadbalancer.CreateCredentialsPayload{ DisplayName: utils.Ptr("name"), Username: utils.Ptr("username"), @@ -84,21 +88,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go index 221b155e5..28b560b2a 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go @@ -59,7 +59,7 @@ func NewCmd(p *print.Printer) *cobra.Command { var credentials []loadbalancer.CredentialsResponse if resp.Credentials != nil && len(*resp.Credentials) > 0 { - credentials, err = utils.FilterCredentials(ctx, apiClient, *resp.Credentials, model.ProjectId, utils.OP_FILTER_UNUSED) + credentials, err = utils.FilterCredentials(ctx, apiClient, *resp.Credentials, model.ProjectId, model.Region, utils.OP_FILTER_UNUSED) if err != nil { return fmt.Errorf("filter Load Balancer observability credentials: %w", err) } @@ -130,11 +130,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildDeleteCredentialRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient, credentialsRef string) loadbalancer.ApiDeleteCredentialsRequest { - req := apiClient.DeleteCredentials(ctx, model.ProjectId, credentialsRef) + req := apiClient.DeleteCredentials(ctx, model.ProjectId, model.Region, credentialsRef) return req } func buildListCredentialsRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiListCredentialsRequest { - req := apiClient.ListCredentials(ctx, model.ProjectId) + req := apiClient.ListCredentials(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go index ffa7a07e7..ae7b8e3c4 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go @@ -13,9 +13,10 @@ import ( "github.com/google/uuid" ) -const testCredentialsRef = "credentials-1" - -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testCredentialsRef = "credentials-1" +) type testCtxKey struct{} @@ -25,7 +26,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, } @@ -47,7 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureDeleteCredentialRequest(mods ...func(request *loadbalancer.ApiDeleteCredentialsRequest)) loadbalancer.ApiDeleteCredentialsRequest { - request := testClient.DeleteCredentials(testCtx, testProjectId, testCredentialsRef) + request := testClient.DeleteCredentials(testCtx, testProjectId, testRegion, testCredentialsRef) for _, mod := range mods { mod(&request) } @@ -55,7 +58,7 @@ func fixtureDeleteCredentialRequest(mods ...func(request *loadbalancer.ApiDelete } func fixtureListCredentialsRequest(mods ...func(request *loadbalancer.ApiListCredentialsRequest)) loadbalancer.ApiListCredentialsRequest { - request := testClient.ListCredentials(testCtx, testProjectId) + request := testClient.ListCredentials(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -90,21 +93,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete.go b/internal/cmd/load-balancer/observability-credentials/delete/delete.go index a3c6eb87d..73c9db46d 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete.go @@ -56,7 +56,7 @@ func NewCmd(p *print.Printer) *cobra.Command { projectLabel = model.ProjectId } - credentialsLabel, err := loadbalancerUtils.GetCredentialsDisplayName(ctx, apiClient, model.ProjectId, model.CredentialsRef) + credentialsLabel, err := loadbalancerUtils.GetCredentialsDisplayName(ctx, apiClient, model.ProjectId, model.Region, model.CredentialsRef) if err != nil { p.Debug(print.ErrorLevel, "get observability credentials display name: %v", err) credentialsLabel = model.CredentialsRef @@ -110,6 +110,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiDeleteCredentialsRequest { - req := apiClient.DeleteCredentials(ctx, model.ProjectId, model.CredentialsRef) + req := apiClient.DeleteCredentials(ctx, model.ProjectId, model.Region, model.CredentialsRef) return req } diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go b/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go index 629b93f5c..d4f22f799 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go @@ -13,7 +13,10 @@ import ( "github.com/google/uuid" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testCredentialsRef = "credentials-xxx" +) type testCtxKey struct{} @@ -21,8 +24,6 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &loadbalancer.APIClient{} var testProjectId = uuid.NewString() -const testCredentialsRef = "credentials-xxx" - func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testCredentialsRef, @@ -35,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, CredentialsRef: testCredentialsRef, @@ -58,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiDeleteCredentialsRequest)) loadbalancer.ApiDeleteCredentialsRequest { - request := testClient.DeleteCredentials(testCtx, testProjectId, testCredentialsRef) + request := testClient.DeleteCredentials(testCtx, testProjectId, testRegion, testCredentialsRef) for _, mod := range mods { mod(&request) } @@ -102,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -110,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -118,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index e16b9eb4f..9f622f750 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -91,7 +91,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiGetCredentialsRequest { - req := apiClient.GetCredentials(ctx, model.ProjectId, model.CredentialsRef) + req := apiClient.GetCredentials(ctx, model.ProjectId, model.Region, model.CredentialsRef) return req } diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go index 05f8a8d64..a67979219 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go @@ -12,7 +12,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testCredentialsRef = "credentials-test" +) type testCtxKey struct{} @@ -20,8 +23,6 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &loadbalancer.APIClient{} var testProjectId = uuid.NewString() -const testCredentialsRef = "credentials-test" - func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testCredentialsRef, @@ -34,7 +35,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -46,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, CredentialsRef: testCredentialsRef, @@ -57,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiGetCredentialsRequest)) loadbalancer.ApiGetCredentialsRequest { - request := testClient.GetCredentials(testCtx, testProjectId, testCredentialsRef) + request := testClient.GetCredentials(testCtx, testProjectId, testRegion, testCredentialsRef) for _, mod := range mods { mod(&request) } @@ -101,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index bafed9561..87e149053 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -92,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return err } - credentials, err = lbUtils.FilterCredentials(ctx, apiClient, credentials, model.ProjectId, filterOp) + credentials, err = lbUtils.FilterCredentials(ctx, apiClient, credentials, model.ProjectId, model.Region, filterOp) if err != nil { return fmt.Errorf("filter credentials: %w", err) } @@ -162,7 +162,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiListCredentialsRequest { - req := apiClient.ListCredentials(ctx, model.ProjectId) + req := apiClient.ListCredentials(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/load-balancer/observability-credentials/list/list_test.go b/internal/cmd/load-balancer/observability-credentials/list/list_test.go index e37d0b3c2..ddf04272e 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list_test.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -24,8 +26,9 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -37,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -48,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiListCredentialsRequest)) loadbalancer.ApiListCredentialsRequest { - request := testClient.ListCredentials(testCtx, testProjectId) + request := testClient.ListCredentials(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -76,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/observability-credentials/update/update.go b/internal/cmd/load-balancer/observability-credentials/update/update.go index 8c3d7ebbc..4c76da9f9 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update.go @@ -27,6 +27,16 @@ const ( credentialsRefArg = "CREDENTIALS_REF" //nolint:gosec // linter false positive ) +// enforce implementation of interfaces +var ( + _ loadBalancerClient = &loadbalancer.APIClient{} +) + +type loadBalancerClient interface { + UpdateCredentials(ctx context.Context, projectId, region, credentialsRef string) loadbalancer.ApiUpdateCredentialsRequest + GetCredentialsExecute(ctx context.Context, projectId, region, credentialsRef string) (*loadbalancer.GetCredentialsResponse, error) +} + type inputModel struct { *globalflags.GlobalFlagModel CredentialsRef string @@ -68,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { projectLabel = model.ProjectId } - credentialsLabel, err := loadBalancerUtils.GetCredentialsDisplayName(ctx, apiClient, model.ProjectId, model.CredentialsRef) + credentialsLabel, err := loadBalancerUtils.GetCredentialsDisplayName(ctx, apiClient, model.ProjectId, model.Region, model.CredentialsRef) if err != nil { p.Debug(print.ErrorLevel, "get credentials display name: %v", err) credentialsLabel = model.CredentialsRef @@ -137,15 +147,10 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu }, nil } -type loadBalancerClient interface { - UpdateCredentials(ctx context.Context, instanceId, projectId string) loadbalancer.ApiUpdateCredentialsRequest - GetCredentialsExecute(ctx context.Context, instanceId, projectId string) (*loadbalancer.GetCredentialsResponse, error) -} - func buildRequest(ctx context.Context, model *inputModel, apiClient loadBalancerClient) (loadbalancer.ApiUpdateCredentialsRequest, error) { - req := apiClient.UpdateCredentials(ctx, model.ProjectId, model.CredentialsRef) + req := apiClient.UpdateCredentials(ctx, model.ProjectId, model.Region, model.CredentialsRef) - currentCredentials, err := apiClient.GetCredentialsExecute(ctx, model.ProjectId, model.CredentialsRef) + currentCredentials, err := apiClient.GetCredentialsExecute(ctx, model.ProjectId, model.Region, model.CredentialsRef) if err != nil { return req, fmt.Errorf("get Load Balancer observability credentials: %w", err) } diff --git a/internal/cmd/load-balancer/observability-credentials/update/update_test.go b/internal/cmd/load-balancer/observability-credentials/update/update_test.go index 6b30da82b..87677fa86 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update_test.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update_test.go @@ -15,33 +15,35 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testCredentialsRef = "credentials-test" +) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &loadbalancer.APIClient{} +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &loadbalancer.APIClient{} + testProjectId = uuid.NewString() +) type loadBalancerClientMocked struct { getCredentialsError bool getCredentialsResponse *loadbalancer.GetCredentialsResponse } -func (c *loadBalancerClientMocked) UpdateCredentials(ctx context.Context, projectId, credentialsRef string) loadbalancer.ApiUpdateCredentialsRequest { - return testClient.UpdateCredentials(ctx, projectId, credentialsRef) +func (c *loadBalancerClientMocked) UpdateCredentials(ctx context.Context, projectId, region, credentialsRef string) loadbalancer.ApiUpdateCredentialsRequest { + return testClient.UpdateCredentials(ctx, projectId, region, credentialsRef) } -func (c *loadBalancerClientMocked) GetCredentialsExecute(_ context.Context, _, _ string) (*loadbalancer.GetCredentialsResponse, error) { +func (c *loadBalancerClientMocked) GetCredentialsExecute(_ context.Context, _, _, _ string) (*loadbalancer.GetCredentialsResponse, error) { if c.getCredentialsError { return nil, fmt.Errorf("get credentials failed") } return c.getCredentialsResponse, nil } -var testProjectId = uuid.NewString() - -const testCredentialsRef = "credentials-test" - func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testCredentialsRef, @@ -54,10 +56,11 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - displayNameFlag: "name", - usernameFlag: "username", - passwordFlag: "pwd", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + displayNameFlag: "name", + usernameFlag: "username", + passwordFlag: "pwd", } for _, mod := range mods { mod(flagValues) @@ -69,6 +72,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, DisplayName: utils.Ptr("name"), @@ -83,7 +87,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiUpdateCredentialsRequest)) loadbalancer.ApiUpdateCredentialsRequest { - request := testClient.UpdateCredentials(testCtx, testProjectId, testCredentialsRef) + request := testClient.UpdateCredentials(testCtx, testProjectId, testRegion, testCredentialsRef) request = request.UpdateCredentialsPayload(loadbalancer.UpdateCredentialsPayload{ DisplayName: utils.Ptr("name"), Username: utils.Ptr("username"), @@ -145,7 +149,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -153,7 +157,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -161,7 +165,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index fb99fb6f7..9c2fb2840 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -81,7 +81,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiGetQuotaRequest { - req := apiClient.GetQuota(ctx, model.ProjectId) + req := apiClient.GetQuota(ctx, model.ProjectId, model.Region) return req } diff --git a/internal/cmd/load-balancer/quota/quota_test.go b/internal/cmd/load-balancer/quota/quota_test.go index b6938c379..e1ba5a893 100644 --- a/internal/cmd/load-balancer/quota/quota_test.go +++ b/internal/cmd/load-balancer/quota/quota_test.go @@ -12,7 +12,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -22,7 +24,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -34,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, } @@ -44,7 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiGetQuotaRequest)) loadbalancer.ApiGetQuotaRequest { - request := testClient.GetQuota(testCtx, testProjectId) + request := testClient.GetQuota(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -67,21 +71,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target.go b/internal/cmd/load-balancer/target-pool/add-target/add_target.go index 13d816e9f..139dfda26 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target.go @@ -124,9 +124,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient utils.LoadBalancerClient) (loadbalancer.ApiUpdateTargetPoolRequest, error) { - req := apiClient.UpdateTargetPool(ctx, model.ProjectId, model.LBName, model.TargetPoolName) + req := apiClient.UpdateTargetPool(ctx, model.ProjectId, model.Region, model.LBName, model.TargetPoolName) - targetPool, err := utils.GetLoadBalancerTargetPool(ctx, apiClient, model.ProjectId, model.LBName, model.TargetPoolName) + targetPool, err := utils.GetLoadBalancerTargetPool(ctx, apiClient, model.ProjectId, model.Region, model.LBName, model.TargetPoolName) if err != nil { return req, fmt.Errorf("get load balancer target pool: %w", err) } diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go b/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go index 8120dc497..6fd3da6c9 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go @@ -15,8 +15,6 @@ import ( "github.com/google/uuid" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var ( @@ -26,6 +24,7 @@ var ( ) const ( + testRegion = "eu02" testLBName = "my-load-balancer" testTargetPoolName = "target-pool-1" testTargetName = "my-target" @@ -39,25 +38,25 @@ type loadBalancerClientMocked struct { getLoadBalancerResp *loadbalancer.LoadBalancer } -func (m *loadBalancerClientMocked) GetCredentialsExecute(_ context.Context, _, _ string) (*loadbalancer.GetCredentialsResponse, error) { +func (m *loadBalancerClientMocked) GetCredentialsExecute(_ context.Context, _, _, _ string) (*loadbalancer.GetCredentialsResponse, error) { if m.getCredentialsFails { return nil, fmt.Errorf("could not get credentials") } return m.getCredentialsResp, nil } -func (m *loadBalancerClientMocked) GetLoadBalancerExecute(_ context.Context, _, _ string) (*loadbalancer.LoadBalancer, error) { +func (m *loadBalancerClientMocked) GetLoadBalancerExecute(_ context.Context, _, _, _ string) (*loadbalancer.LoadBalancer, error) { if m.getLoadBalancerFails { return nil, fmt.Errorf("could not get load balancer") } return m.getLoadBalancerResp, nil } -func (m *loadBalancerClientMocked) UpdateTargetPool(ctx context.Context, projectId, loadBalancerName, targetPoolName string) loadbalancer.ApiUpdateTargetPoolRequest { - return testClient.UpdateTargetPool(ctx, projectId, loadBalancerName, targetPoolName) +func (m *loadBalancerClientMocked) UpdateTargetPool(ctx context.Context, projectId, region, loadBalancerName, targetPoolName string) loadbalancer.ApiUpdateTargetPoolRequest { + return testClient.UpdateTargetPool(ctx, projectId, region, loadBalancerName, targetPoolName) } -func (m *loadBalancerClientMocked) ListLoadBalancersExecute(_ context.Context, _ string) (*loadbalancer.ListLoadBalancersResponse, error) { +func (m *loadBalancerClientMocked) ListLoadBalancersExecute(_ context.Context, _, _ string) (*loadbalancer.ListLoadBalancersResponse, error) { return nil, nil } @@ -73,10 +72,11 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - lbNameFlag: testLBName, - targetNameFlag: testTargetName, - targetPoolNameFlag: testTargetPoolName, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + lbNameFlag: testLBName, + targetNameFlag: testTargetName, + targetPoolNameFlag: testTargetPoolName, } for _, mod := range mods { mod(flagValues) @@ -88,6 +88,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, TargetPoolName: testTargetPoolName, @@ -171,7 +172,7 @@ func fixturePayload(mods ...func(payload *loadbalancer.UpdateTargetPoolPayload)) } func fixtureRequest(mods ...func(request *loadbalancer.ApiUpdateTargetPoolRequest)) loadbalancer.ApiUpdateTargetPoolRequest { - request := testClient.UpdateTargetPool(testCtx, testProjectId, testLBName, testTargetPoolName) + request := testClient.UpdateTargetPool(testCtx, testProjectId, testRegion, testLBName, testTargetPoolName) request = request.UpdateTargetPoolPayload(*fixturePayload()) for _, mod := range mods { mod(&request) @@ -204,7 +205,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -212,7 +213,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -220,7 +221,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index 70af7ce15..a4ffa6d65 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -115,7 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiGetLoadBalancerRequest { - req := apiClient.GetLoadBalancer(ctx, model.ProjectId, model.LBName) + req := apiClient.GetLoadBalancer(ctx, model.ProjectId, model.Region, model.LBName) return req } diff --git a/internal/cmd/load-balancer/target-pool/describe/describe_test.go b/internal/cmd/load-balancer/target-pool/describe/describe_test.go index 502a965f8..e1acadb53 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe_test.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe_test.go @@ -12,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var ( @@ -23,6 +21,7 @@ var ( ) const ( + testRegion = "eu02" testLoadBalancerName = "my-load-balancer" testTargetPoolName = "target-pool-1" ) @@ -39,8 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - lbNameFlag: testLoadBalancerName, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + lbNameFlag: testLoadBalancerName, } for _, mod := range mods { mod(flagValues) @@ -52,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, LBName: testLoadBalancerName, @@ -64,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiGetLoadBalancerRequest)) loadbalancer.ApiGetLoadBalancerRequest { - request := testClient.GetLoadBalancer(testCtx, testProjectId, testLoadBalancerName) + request := testClient.GetLoadBalancer(testCtx, testProjectId, testRegion, testLoadBalancerName) for _, mod := range mods { mod(&request) } @@ -96,7 +97,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -104,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go index 36a84313f..2fbb0c447 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go @@ -56,7 +56,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - targetLabel, err := utils.GetTargetName(ctx, apiClient, model.ProjectId, model.LBName, model.TargetPoolName, model.IP) + targetLabel, err := utils.GetTargetName(ctx, apiClient, model.ProjectId, model.Region, model.LBName, model.TargetPoolName, model.IP) if err != nil { p.Debug(print.ErrorLevel, "get target name: %v", err) targetLabel = model.IP @@ -124,9 +124,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient utils.LoadBalancerClient) (loadbalancer.ApiUpdateTargetPoolRequest, error) { - req := apiClient.UpdateTargetPool(ctx, model.ProjectId, model.LBName, model.TargetPoolName) + req := apiClient.UpdateTargetPool(ctx, model.ProjectId, model.Region, model.LBName, model.TargetPoolName) - targetPool, err := utils.GetLoadBalancerTargetPool(ctx, apiClient, model.ProjectId, model.LBName, model.TargetPoolName) + targetPool, err := utils.GetLoadBalancerTargetPool(ctx, apiClient, model.ProjectId, model.Region, model.LBName, model.TargetPoolName) if err != nil { return req, fmt.Errorf("get load balancer target pool: %w", err) } diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go index ec31f13e2..e961447d2 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go @@ -15,8 +15,6 @@ import ( "github.com/google/uuid" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var ( @@ -26,9 +24,9 @@ var ( ) const ( + testRegion = "eu02" testLBName = "my-load-balancer" testTargetPoolName = "target-pool-1" - testTargetName = "my-target" testIP = "1.2.3.4" ) @@ -39,25 +37,25 @@ type loadBalancerClientMocked struct { getLoadBalancerResp *loadbalancer.LoadBalancer } -func (m *loadBalancerClientMocked) GetCredentialsExecute(_ context.Context, _, _ string) (*loadbalancer.GetCredentialsResponse, error) { +func (m *loadBalancerClientMocked) GetCredentialsExecute(_ context.Context, _, _, _ string) (*loadbalancer.GetCredentialsResponse, error) { if m.getCredentialsFails { return nil, fmt.Errorf("could not get credentials") } return m.getCredentialsResp, nil } -func (m *loadBalancerClientMocked) GetLoadBalancerExecute(_ context.Context, _, _ string) (*loadbalancer.LoadBalancer, error) { +func (m *loadBalancerClientMocked) GetLoadBalancerExecute(_ context.Context, _, _, _ string) (*loadbalancer.LoadBalancer, error) { if m.getLoadBalancerFails { return nil, fmt.Errorf("could not get load balancer") } return m.getLoadBalancerResp, nil } -func (m *loadBalancerClientMocked) UpdateTargetPool(ctx context.Context, projectId, loadBalancerName, targetPoolName string) loadbalancer.ApiUpdateTargetPoolRequest { - return testClient.UpdateTargetPool(ctx, projectId, loadBalancerName, targetPoolName) +func (m *loadBalancerClientMocked) UpdateTargetPool(ctx context.Context, projectId, region, loadBalancerName, targetPoolName string) loadbalancer.ApiUpdateTargetPoolRequest { + return testClient.UpdateTargetPool(ctx, projectId, region, loadBalancerName, targetPoolName) } -func (m *loadBalancerClientMocked) ListLoadBalancersExecute(_ context.Context, _ string) (*loadbalancer.ListLoadBalancersResponse, error) { +func (m *loadBalancerClientMocked) ListLoadBalancersExecute(_ context.Context, _, _ string) (*loadbalancer.ListLoadBalancersResponse, error) { return nil, nil } @@ -73,9 +71,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - lbNameFlag: testLBName, - targetPoolNameFlag: testTargetPoolName, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + lbNameFlag: testLBName, + targetPoolNameFlag: testTargetPoolName, } for _, mod := range mods { mod(flagValues) @@ -87,6 +86,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, LBName: testLBName, @@ -169,7 +169,7 @@ func fixturePayload(mods ...func(payload *loadbalancer.UpdateTargetPoolPayload)) } func fixtureRequest(mods ...func(request *loadbalancer.ApiUpdateTargetPoolRequest)) loadbalancer.ApiUpdateTargetPoolRequest { - request := testClient.UpdateTargetPool(testCtx, testProjectId, testLBName, testTargetPoolName) + request := testClient.UpdateTargetPool(testCtx, testProjectId, testRegion, testLBName, testTargetPoolName) request = request.UpdateTargetPoolPayload(*fixturePayload()) for _, mod := range mods { mod(&request) @@ -202,7 +202,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -210,7 +210,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -218,7 +218,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/load-balancer/update/update.go b/internal/cmd/load-balancer/update/update.go index ba10a2d7f..154e9d992 100644 --- a/internal/cmd/load-balancer/update/update.go +++ b/internal/cmd/load-balancer/update/update.go @@ -129,7 +129,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiUpdateLoadBalancerRequest { - req := apiClient.UpdateLoadBalancer(ctx, model.ProjectId, model.LoadBalancerName) + req := apiClient.UpdateLoadBalancer(ctx, model.ProjectId, model.Region, model.LoadBalancerName) req = req.UpdateLoadBalancerPayload(model.Payload) return req diff --git a/internal/cmd/load-balancer/update/update_test.go b/internal/cmd/load-balancer/update/update_test.go index ea03f5932..b6c998138 100644 --- a/internal/cmd/load-balancer/update/update_test.go +++ b/internal/cmd/load-balancer/update/update_test.go @@ -14,14 +14,16 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testLoadBalancerName = "loadBalancer" +) type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &loadbalancer.APIClient{} var testProjectId = uuid.NewString() -var testLoadBalancerName = "loadBalancer" var testPayload = loadbalancer.UpdateLoadBalancerPayload{ ExternalAddress: utils.Ptr(""), @@ -108,7 +110,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, payloadFlag: ` { "externalAddress": "", @@ -193,6 +196,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, LoadBalancerName: testLoadBalancerName, @@ -205,7 +209,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *loadbalancer.ApiUpdateLoadBalancerRequest)) loadbalancer.ApiUpdateLoadBalancerRequest { - request := testClient.UpdateLoadBalancer(testCtx, testProjectId, testLoadBalancerName) + request := testClient.UpdateLoadBalancer(testCtx, testProjectId, testRegion, testLoadBalancerName) request = request.UpdateLoadBalancerPayload(testPayload) for _, mod := range mods { mod(&request) @@ -250,7 +254,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -258,7 +262,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -266,7 +270,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/pkg/services/load-balancer/client/client.go b/internal/pkg/services/load-balancer/client/client.go index dc0f51639..94d0b0a17 100644 --- a/internal/pkg/services/load-balancer/client/client.go +++ b/internal/pkg/services/load-balancer/client/client.go @@ -27,8 +27,7 @@ func ConfigureClient(p *print.Printer) (*loadbalancer.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions = append(cfgOptions, authCfgOption) } if p.IsVerbosityDebug() { diff --git a/internal/pkg/services/load-balancer/utils/utils.go b/internal/pkg/services/load-balancer/utils/utils.go index 1ad93ce18..4bc13db61 100644 --- a/internal/pkg/services/load-balancer/utils/utils.go +++ b/internal/pkg/services/load-balancer/utils/utils.go @@ -15,23 +15,28 @@ const ( OP_FILTER_UNUSED ) +// enforce implementation of interfaces +var ( + _ LoadBalancerClient = &loadbalancer.APIClient{} +) + type LoadBalancerClient interface { - GetCredentialsExecute(ctx context.Context, projectId, credentialsRef string) (*loadbalancer.GetCredentialsResponse, error) - GetLoadBalancerExecute(ctx context.Context, projectId, name string) (*loadbalancer.LoadBalancer, error) - UpdateTargetPool(ctx context.Context, projectId, loadBalancerName, targetPoolName string) loadbalancer.ApiUpdateTargetPoolRequest - ListLoadBalancersExecute(ctx context.Context, projectId string) (*loadbalancer.ListLoadBalancersResponse, error) + GetCredentialsExecute(ctx context.Context, projectId, region, credentialsRef string) (*loadbalancer.GetCredentialsResponse, error) + GetLoadBalancerExecute(ctx context.Context, projectId, region, name string) (*loadbalancer.LoadBalancer, error) + UpdateTargetPool(ctx context.Context, projectId, region, loadBalancerName, targetPoolName string) loadbalancer.ApiUpdateTargetPoolRequest + ListLoadBalancersExecute(ctx context.Context, projectId, region string) (*loadbalancer.ListLoadBalancersResponse, error) } -func GetCredentialsDisplayName(ctx context.Context, apiClient LoadBalancerClient, projectId, credentialsRef string) (string, error) { - resp, err := apiClient.GetCredentialsExecute(ctx, projectId, credentialsRef) +func GetCredentialsDisplayName(ctx context.Context, apiClient LoadBalancerClient, projectId, region, credentialsRef string) (string, error) { + resp, err := apiClient.GetCredentialsExecute(ctx, projectId, region, credentialsRef) if err != nil { return "", fmt.Errorf("get Load Balancer credentials: %w", err) } return *resp.Credential.DisplayName, nil } -func GetLoadBalancerTargetPool(ctx context.Context, apiClient LoadBalancerClient, projectId, loadBalancerName, targetPoolName string) (*loadbalancer.TargetPool, error) { - resp, err := apiClient.GetLoadBalancerExecute(ctx, projectId, loadBalancerName) +func GetLoadBalancerTargetPool(ctx context.Context, apiClient LoadBalancerClient, projectId, region, loadBalancerName, targetPoolName string) (*loadbalancer.TargetPool, error) { + resp, err := apiClient.GetLoadBalancerExecute(ctx, projectId, region, loadBalancerName) if err != nil { return nil, fmt.Errorf("get load balancer: %w", err) } @@ -121,8 +126,8 @@ func ToPayloadTargetPool(targetPool *loadbalancer.TargetPool) *loadbalancer.Upda } } -func GetTargetName(ctx context.Context, apiClient LoadBalancerClient, projectId, loadBalancerName, targetPoolName, targetIp string) (string, error) { - targetPool, err := GetLoadBalancerTargetPool(ctx, apiClient, projectId, loadBalancerName, targetPoolName) +func GetTargetName(ctx context.Context, apiClient LoadBalancerClient, projectId, region, loadBalancerName, targetPoolName, targetIp string) (string, error) { + targetPool, err := GetLoadBalancerTargetPool(ctx, apiClient, projectId, region, loadBalancerName, targetPoolName) if err != nil { return "", fmt.Errorf("get target pool: %w", err) } @@ -142,10 +147,10 @@ func GetTargetName(ctx context.Context, apiClient LoadBalancerClient, projectId, // GetUsedObsCredentials returns a list of credentials that are used by load balancers for observability metrics or logs. // It goes through all load balancers and checks what observability credentials are being used, then returns a list of those credentials. -func GetUsedObsCredentials(ctx context.Context, apiClient LoadBalancerClient, allCredentials []loadbalancer.CredentialsResponse, projectId string) ([]loadbalancer.CredentialsResponse, error) { +func GetUsedObsCredentials(ctx context.Context, apiClient LoadBalancerClient, allCredentials []loadbalancer.CredentialsResponse, projectId, region string) ([]loadbalancer.CredentialsResponse, error) { var usedCredentialsSlice []loadbalancer.CredentialsResponse - loadBalancers, err := apiClient.ListLoadBalancersExecute(ctx, projectId) + loadBalancers, err := apiClient.ListLoadBalancersExecute(ctx, projectId, region) if err != nil { return nil, fmt.Errorf("list load balancers: %w", err) } @@ -218,7 +223,7 @@ func GetUnusedObsCredentials(usedCredentials, allCredentials []loadbalancer.Cred // If unused is true, it returns only the credentials that are not used by any load balancer for observability metrics or logs. // If both used and unused are true, it returns an error. // If both used and unused are false, it returns the original list of credentials. -func FilterCredentials(ctx context.Context, client LoadBalancerClient, allCredentials []loadbalancer.CredentialsResponse, projectId string, filterOp int) ([]loadbalancer.CredentialsResponse, error) { +func FilterCredentials(ctx context.Context, client LoadBalancerClient, allCredentials []loadbalancer.CredentialsResponse, projectId, region string, filterOp int) ([]loadbalancer.CredentialsResponse, error) { // check that filter OP is valid if filterOp != OP_FILTER_USED && filterOp != OP_FILTER_UNUSED && filterOp != OP_FILTER_NOP { return nil, fmt.Errorf("invalid filter operation") @@ -228,7 +233,7 @@ func FilterCredentials(ctx context.Context, client LoadBalancerClient, allCreden return allCredentials, nil } - usedCredentials, err := GetUsedObsCredentials(ctx, client, allCredentials, projectId) + usedCredentials, err := GetUsedObsCredentials(ctx, client, allCredentials, projectId, region) if err != nil { return nil, fmt.Errorf("get used observability credentials: %w", err) } diff --git a/internal/pkg/services/load-balancer/utils/utils_test.go b/internal/pkg/services/load-balancer/utils/utils_test.go index 93b8f6ff3..e33fd75b8 100644 --- a/internal/pkg/services/load-balancer/utils/utils_test.go +++ b/internal/pkg/services/load-balancer/utils/utils_test.go @@ -19,6 +19,7 @@ var ( ) const ( + testRegion = "eu02" testCredentialsRef = "credentials-ref" testCredentialsDisplayName = "credentials-name" testLoadBalancerName = "my-load-balancer" @@ -33,28 +34,28 @@ type loadBalancerClientMocked struct { listLoadBalancersResp *loadbalancer.ListLoadBalancersResponse } -func (m *loadBalancerClientMocked) GetCredentialsExecute(_ context.Context, _, _ string) (*loadbalancer.GetCredentialsResponse, error) { +func (m *loadBalancerClientMocked) GetCredentialsExecute(_ context.Context, _, _, _ string) (*loadbalancer.GetCredentialsResponse, error) { if m.getCredentialsFails { return nil, fmt.Errorf("could not get credentials") } return m.getCredentialsResp, nil } -func (m *loadBalancerClientMocked) GetLoadBalancerExecute(_ context.Context, _, _ string) (*loadbalancer.LoadBalancer, error) { +func (m *loadBalancerClientMocked) GetLoadBalancerExecute(_ context.Context, _, _, _ string) (*loadbalancer.LoadBalancer, error) { if m.getLoadBalancerFails { return nil, fmt.Errorf("could not get load balancer") } return m.getLoadBalancerResp, nil } -func (m *loadBalancerClientMocked) ListLoadBalancersExecute(_ context.Context, _ string) (*loadbalancer.ListLoadBalancersResponse, error) { +func (m *loadBalancerClientMocked) ListLoadBalancersExecute(_ context.Context, _, _ string) (*loadbalancer.ListLoadBalancersResponse, error) { if m.listLoadBalancersFails { return nil, fmt.Errorf("could not list load balancers") } return m.listLoadBalancersResp, nil } -func (m *loadBalancerClientMocked) UpdateTargetPool(_ context.Context, _, _, _ string) loadbalancer.ApiUpdateTargetPoolRequest { +func (m *loadBalancerClientMocked) UpdateTargetPool(_ context.Context, _, _, _, _ string) loadbalancer.ApiUpdateTargetPoolRequest { return loadbalancer.ApiUpdateTargetPoolRequest{} } @@ -190,7 +191,7 @@ func TestGetCredentialsDisplayName(t *testing.T) { getCredentialsResp: tt.getCredentialsResp, } - output, err := GetCredentialsDisplayName(context.Background(), client, testProjectId, testCredentialsRef) + output, err := GetCredentialsDisplayName(context.Background(), client, testProjectId, testRegion, testCredentialsRef) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -270,7 +271,7 @@ func TestGetLoadBalancerTargetPool(t *testing.T) { getLoadBalancerResp: tt.getLoadBalancerResp, } - output, err := GetLoadBalancerTargetPool(context.Background(), client, testProjectId, testLoadBalancerName, tt.targetPoolName) + output, err := GetLoadBalancerTargetPool(context.Background(), client, testProjectId, testRegion, testLoadBalancerName, tt.targetPoolName) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -824,7 +825,7 @@ func TestGetTargetName(t *testing.T) { getLoadBalancerResp: tt.getLoadBalancerResp, } - output, err := GetTargetName(context.Background(), client, testProjectId, testLoadBalancerName, tt.targetPoolName, tt.targetIp) + output, err := GetTargetName(context.Background(), client, testProjectId, testRegion, testLoadBalancerName, tt.targetPoolName, tt.targetIp) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -962,7 +963,7 @@ func TestGetUsedObsCredentials(t *testing.T) { listLoadBalancersResp: tt.listLoadBalancersResp, } - output, err := GetUsedObsCredentials(testCtx, client, tt.allCredentials, testProjectId) + output, err := GetUsedObsCredentials(testCtx, client, tt.allCredentials, testProjectId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -1139,7 +1140,7 @@ func TestFilterCredentials(t *testing.T) { listLoadBalancersResp: tt.listLoadBalancersResp, listLoadBalancersFails: tt.listLoadBalancersFails, } - filteredCredentials, err := FilterCredentials(testCtx, client, tt.allCredentials, testProjectId, tt.filterOp) + filteredCredentials, err := FilterCredentials(testCtx, client, tt.allCredentials, testProjectId, testRegion, tt.filterOp) if err != nil { if !tt.isValid { return From 6f83ab25a145ebd1f24bc5797297bf0afc5feb4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 19 Mar 2025 18:06:58 +0100 Subject: [PATCH 229/619] fix(sqlserverflex): require roles flag on user creation (#657) the API requires the roles anyways relates to STACKITCLI-125 --- docs/stackit_beta_sqlserverflex_user_create.md | 2 +- internal/cmd/beta/sqlserverflex/user/create/create.go | 4 ++-- internal/cmd/beta/sqlserverflex/user/create/create_test.go | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/stackit_beta_sqlserverflex_user_create.md b/docs/stackit_beta_sqlserverflex_user_create.md index 26c07f913..f1cf9dbbe 100644 --- a/docs/stackit_beta_sqlserverflex_user_create.md +++ b/docs/stackit_beta_sqlserverflex_user_create.md @@ -22,7 +22,7 @@ stackit beta sqlserverflex user create [flags] ``` Create a SQLServer Flex user for instance with ID "xxx" and specify the username, role and database - $ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_DatabaseManager##" --database my-database + $ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_DatabaseManager##" Create a SQLServer Flex user for instance with ID "xxx", specifying multiple roles $ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_LoginManager##,##STACKIT_DatabaseManager##" diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 2e4f04896..0cd99180c 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -50,7 +50,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a SQLServer Flex user for instance with ID "xxx" and specify the username, role and database`, - `$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_DatabaseManager##" --database my-database`), + `$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_DatabaseManager##"`), examples.NewExample( `Create a SQLServer Flex user for instance with ID "xxx", specifying multiple roles`, `$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_LoginManager##,##STACKIT_DatabaseManager##"`), @@ -104,7 +104,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(usernameFlag, "", "Username of the user") cmd.Flags().StringSlice(rolesFlag, []string{}, "Roles of the user") - err := flags.MarkFlagsRequired(cmd, instanceIdFlag, usernameFlag) + err := flags.MarkFlagsRequired(cmd, instanceIdFlag, usernameFlag, rolesFlag) cobra.CheckErr(err) } diff --git a/internal/cmd/beta/sqlserverflex/user/create/create_test.go b/internal/cmd/beta/sqlserverflex/user/create/create_test.go index 8db8d6db2..a53878b3d 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create_test.go @@ -92,10 +92,7 @@ func TestParseInput(t *testing.T) { flagValues: fixtureFlagValues(func(flagValues map[string]string) { delete(flagValues, rolesFlag) }), - isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.Roles = nil - }), + isValid: false, }, { description: "no values", From 881d2fbd4377ab23a0bf1b854241d77971852aec Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 21 Mar 2025 13:22:18 +0100 Subject: [PATCH 230/619] fix(deps): update module github.com/spf13/viper to v1.20.0 (#650) * fix(deps): update module github.com/spf13/viper to v1.20.0 * fix: viper update contains breaking change - the config type needs to be set --------- Co-authored-by: Renovate Bot Co-authored-by: Marcel Jacek --- go.mod | 23 ++++++-------- go.sum | 57 ++++++++++++----------------------- internal/pkg/config/config.go | 1 + 3 files changed, 30 insertions(+), 51 deletions(-) diff --git a/go.mod b/go.mod index a5b24e46a..cfcc88591 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 - github.com/spf13/viper v1.19.0 + github.com/spf13/viper v1.20.0 github.com/stackitcloud/stackit-sdk-go/core v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0 @@ -41,14 +41,15 @@ require ( ) require ( - golang.org/x/net v0.30.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/time v0.8.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) require ( al.essio.dev/pkg/shellescape v1.5.1 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/x448/float16 v0.8.4 // indirect ) @@ -57,28 +58,24 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/cast v1.7.1 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0 @@ -88,9 +85,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect golang.org/x/sys v0.30.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.31.3 // indirect diff --git a/go.sum b/go.sum index 7059fa771..a91110037 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= @@ -26,6 +26,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-yaml v1.16.0 h1:d7m1G7A0t+logajVtklHfDYJs2Et9g3gHwdBNNFou0w= github.com/goccy/go-yaml v1.16.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -48,8 +50,6 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -70,8 +70,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y= github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= @@ -80,8 +78,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -89,8 +85,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -101,22 +97,20 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= -github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= -github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= -github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= +github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stackitcloud/stackit-sdk-go/core v0.16.0 h1:9caGZwGLZDyBBe6ojk9VR4B2m3/0H5It6znBz76sH1w= github.com/stackitcloud/stackit-sdk-go/core v0.16.0/go.mod h1:LRheSoXTFRHWAyA8Q9skWtWBp3ZZ+bFAKiKuf4lTDkE= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0 h1:nSaSvo9o4c9KGc0vct+JWk5T49Ic6i3hzbLKviJtVhA= @@ -164,15 +158,9 @@ github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0/go.mod h1:63IvXpBJTI github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0 h1:RYJO0rZea9+sxVfaJDWRo2zgfKNgiUcA5c0nbvZURiU= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0/go.mod h1:d2ICXCS2h3IMsZW0OanWkEH2XdLiY/XRKx2TcR940nw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -188,8 +176,6 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= @@ -198,8 +184,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -217,8 +203,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -227,19 +213,16 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 8de467877..da282c335 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -127,6 +127,7 @@ func initConfig(configPath string) { // This hack is required to allow creating the config file with `viper.WriteConfig` // see https://github.com/spf13/viper/issues/851#issuecomment-789393451 viper.SetConfigFile(configFilePath) + viper.SetConfigType(configFileExtension) f, err := os.Open(configFilePath) if !os.IsNotExist(err) { From b3c931a53680452e51490b979b1d109b93f41fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 21 Mar 2025 17:31:47 +0100 Subject: [PATCH 231/619] chore(server): regional adjustment for runcommand (#660) relates to STACKITTPR-135 --- go.mod | 2 +- go.sum | 4 ++-- internal/cmd/server/command/create/create.go | 2 +- .../cmd/server/command/create/create_test.go | 24 +++++++++++-------- .../cmd/server/command/describe/describe.go | 2 +- .../server/command/describe/describe_test.go | 22 ++++++++++------- internal/cmd/server/command/list/list.go | 2 +- internal/cmd/server/command/list/list_test.go | 22 ++++++++++------- .../command/template/describe/describe.go | 2 +- .../template/describe/describe_test.go | 22 ++++++++++------- .../server/command/template/list/list_test.go | 12 ++++------ .../pkg/services/runcommand/client/client.go | 3 +-- 12 files changed, 66 insertions(+), 53 deletions(-) diff --git a/go.mod b/go.mod index cfcc88591..5a55a1a1e 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 diff --git a/go.sum b/go.sum index a91110037..24551dfe7 100644 --- a/go.sum +++ b/go.sum @@ -141,8 +141,8 @@ github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0 h1:UDIRWwiZ2/2ukmn github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0/go.mod h1:ErMQspxm7+XmtOsEM6lTD73oALPq3lUC5s+JQkm6Y/s= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0 h1:fPCdQOsdPB1QqwcgytrROk+h5va49CAnp5YSCIrKZWY= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0/go.mod h1:Hs8RwANfF2ZKqOowPBqMQqLoRHcMobiKAihWWirAdEU= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.3.0 h1:S1DFVy2wwSiAFgNPpB527Q/YDQpSaduIFOMX988sZOE= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v0.3.0/go.mod h1:1bANbviG6h5XaD3bBnC3v+eDWf5LBYLtLEF/ih+U4kA= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 h1:tKUyddNszcif4j2yL6lJd4tDAykcU3shMkAPoM9EzV8= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0/go.mod h1:5n31cpeYcz2DSax4ygpZICEHDoHCTbWHrNGNYWwlRA8= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0 h1:PwfpDFGUUJ8+Go5hJf+/hA5CHfY+DPS1cqIUYH+zWtE= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0/go.mod h1:Hb21FmYP95q0fzOb9jk4/9CIxTsHzrSYDQZh6e82XUg= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 h1:cESGAkm0ftADRBfdbiyx3pp/KVQ8JgmUQdRzpwG61wE= diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index cc258aa81..ed65528ac 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -142,7 +142,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand.APIClient) (runcommand.ApiCreateCommandRequest, error) { - req := apiClient.CreateCommand(ctx, model.ProjectId, model.ServerId) + req := apiClient.CreateCommand(ctx, model.ProjectId, model.ServerId, model.Region) req = req.CreateCommandPayload(runcommand.CreateCommandPayload{ CommandTemplateName: &model.CommandTemplateName, Parameters: model.Params, diff --git a/internal/cmd/server/command/create/create_test.go b/internal/cmd/server/command/create/create_test.go index c1a72f8b6..b7b3657ca 100644 --- a/internal/cmd/server/command/create/create_test.go +++ b/internal/cmd/server/command/create/create_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -24,12 +22,17 @@ var testClient = &runcommand.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() +const ( + testRegion = "eu02" +) + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - commandTemplateNameFlag: "RunShellScript", - paramsFlag: `script='echo hello'`, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, + commandTemplateNameFlag: "RunShellScript", + paramsFlag: `script='echo hello'`, } for _, mod := range mods { mod(flagValues) @@ -41,6 +44,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -54,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *runcommand.ApiCreateCommandRequest)) runcommand.ApiCreateCommandRequest { - request := testClient.CreateCommand(testCtx, testProjectId, testServerId) + request := testClient.CreateCommand(testCtx, testProjectId, testServerId, testRegion) request = request.CreateCommandPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -100,21 +104,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/command/describe/describe.go b/internal/cmd/server/command/describe/describe.go index dfd6beba4..6eb4359c7 100644 --- a/internal/cmd/server/command/describe/describe.go +++ b/internal/cmd/server/command/describe/describe.go @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand.APIClient) runcommand.ApiGetCommandRequest { - req := apiClient.GetCommand(ctx, model.ProjectId, model.ServerId, model.CommandId) + req := apiClient.GetCommand(ctx, model.ProjectId, model.Region, model.ServerId, model.CommandId) return req } diff --git a/internal/cmd/server/command/describe/describe_test.go b/internal/cmd/server/command/describe/describe_test.go index 0d0b76f25..c9d1f3d86 100644 --- a/internal/cmd/server/command/describe/describe_test.go +++ b/internal/cmd/server/command/describe/describe_test.go @@ -13,15 +13,17 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &runcommand.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() -var testCommandId = "5" + +const ( + testRegion = "eu02" + testCommandId = "5" +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +37,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *runcommand.ApiGetCommandRequest)) runcommand.ApiGetCommandRequest { - request := testClient.GetCommand(testCtx, testProjectId, testServerId, testCommandId) + request := testClient.GetCommand(testCtx, testProjectId, testRegion, testServerId, testCommandId) for _, mod := range mods { mod(&request) } @@ -104,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +124,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/command/list/list.go b/internal/cmd/server/command/list/list.go index 3ee9fd364..4a00abf57 100644 --- a/internal/cmd/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -133,7 +133,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand.APIClient) runcommand.ApiListCommandsRequest { - req := apiClient.ListCommands(ctx, model.ProjectId, model.ServerId) + req := apiClient.ListCommands(ctx, model.ProjectId, model.ServerId, model.Region) return req } diff --git a/internal/cmd/server/command/list/list_test.go b/internal/cmd/server/command/list/list_test.go index 3d8ced5f2..6740fac38 100644 --- a/internal/cmd/server/command/list/list_test.go +++ b/internal/cmd/server/command/list/list_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -23,11 +21,16 @@ var testClient = &runcommand.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() +const ( + testRegion = "eu02" +) + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -39,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -51,7 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *runcommand.ApiListCommandsRequest)) runcommand.ApiListCommandsRequest { - request := testClient.ListCommands(testCtx, testProjectId, testServerId) + request := testClient.ListCommands(testCtx, testProjectId, testServerId, testRegion) for _, mod := range mods { mod(&request) } @@ -79,21 +83,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/command/template/describe/describe.go b/internal/cmd/server/command/template/describe/describe.go index d549e8752..816bfa8be 100644 --- a/internal/cmd/server/command/template/describe/describe.go +++ b/internal/cmd/server/command/template/describe/describe.go @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand.APIClient) runcommand.ApiGetCommandTemplateRequest { - req := apiClient.GetCommandTemplate(ctx, model.ProjectId, model.ServerId, model.CommandTemplateName) + req := apiClient.GetCommandTemplate(ctx, model.ProjectId, model.ServerId, model.CommandTemplateName, model.Region) return req } diff --git a/internal/cmd/server/command/template/describe/describe_test.go b/internal/cmd/server/command/template/describe/describe_test.go index b01268ae6..85b97a8ea 100644 --- a/internal/cmd/server/command/template/describe/describe_test.go +++ b/internal/cmd/server/command/template/describe/describe_test.go @@ -13,15 +13,17 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &runcommand.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() -var testCommandTemplateName = "RunShellScript" + +const ( + testCommandTemplateName = "RunShellScript" + testRegion = "eu02" +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +37,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *runcommand.ApiGetCommandTemplateRequest)) runcommand.ApiGetCommandTemplateRequest { - request := testClient.GetCommandTemplate(testCtx, testProjectId, testServerId, testCommandTemplateName) + request := testClient.GetCommandTemplate(testCtx, testProjectId, testServerId, testCommandTemplateName, testRegion) for _, mod := range mods { mod(&request) } @@ -104,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +124,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/command/template/list/list_test.go b/internal/cmd/server/command/template/list/list_test.go index 5c6cb12c8..309716c16 100644 --- a/internal/cmd/server/command/template/list/list_test.go +++ b/internal/cmd/server/command/template/list/list_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -24,8 +22,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -76,21 +74,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/pkg/services/runcommand/client/client.go b/internal/pkg/services/runcommand/client/client.go index 5c43e3223..254978f4d 100644 --- a/internal/pkg/services/runcommand/client/client.go +++ b/internal/pkg/services/runcommand/client/client.go @@ -27,8 +27,7 @@ func ConfigureClient(p *print.Printer) (*runcommand.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions = append(cfgOptions, authCfgOption) } if p.IsVerbosityDebug() { From f219981593ba82cf64492e28eac2bfe66d5cdf88 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Fri, 21 Mar 2025 17:32:17 +0100 Subject: [PATCH 232/619] replace STACKIT logo on login page (#661) * add new STACKIT logo * add logo as base64 to the login-successful.html --- .../pkg/auth/templates/login-successful.html | 2 +- .../auth/templates/stackit_nav_logo_light.svg | 11 ++++++++ internal/pkg/auth/user_login.go | 26 ++++++++++--------- internal/pkg/utils/utils.go | 8 ++++++ 4 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 internal/pkg/auth/templates/stackit_nav_logo_light.svg diff --git a/internal/pkg/auth/templates/login-successful.html b/internal/pkg/auth/templates/login-successful.html index 45cf2721c..d8519cad0 100644 --- a/internal/pkg/auth/templates/login-successful.html +++ b/internal/pkg/auth/templates/login-successful.html @@ -271,7 +271,7 @@ diff --git a/internal/pkg/auth/templates/stackit_nav_logo_light.svg b/internal/pkg/auth/templates/stackit_nav_logo_light.svg new file mode 100644 index 000000000..5da793e0b --- /dev/null +++ b/internal/pkg/auth/templates/stackit_nav_logo_light.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index b8a706a51..8ac94743e 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -1,7 +1,7 @@ package auth import ( - "embed" + _ "embed" "encoding/json" "errors" "fmt" @@ -11,12 +11,12 @@ import ( "net/http" "os" "os/exec" - "path" "runtime" "strconv" "strings" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "golang.org/x/oauth2" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -26,10 +26,7 @@ const ( defaultWellKnownConfig = "https://accounts.stackit.cloud/.well-known/openid-configuration" defaultCLIClientID = "stackit-cli-0000-0000-000000000001" - loginSuccessPath = "/login-successful" - stackitLandingPage = "https://www.stackit.de" - htmlTemplatesPath = "templates" - loginSuccessfulHTMLFile = "login-successful.html" + loginSuccessPath = "/login-successful" // The IDP doesn't support wildcards for the port, // so we configure a range of ports from 8000 to 8020 @@ -37,11 +34,15 @@ const ( configuredPortRange = 20 ) -//go:embed templates/* -var htmlContent embed.FS +//go:embed templates/login-successful.html +var htmlTemplateContent string -type User struct { +//go:embed templates/stackit_nav_logo_light.svg +var logoSvgContent []byte + +type InputValues struct { Email string + Logo string } type apiClient interface { @@ -215,18 +216,19 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { errServer = fmt.Errorf("read user email: %w", err) } - user := User{ + input := InputValues{ Email: email, + Logo: utils.Base64Encode(logoSvgContent), } // ParseFS expects paths using forward slashes, even on Windows // See: https://github.com/golang/go/issues/44305#issuecomment-780111748 - htmlTemplate, err := template.ParseFS(htmlContent, path.Join(htmlTemplatesPath, loginSuccessfulHTMLFile)) + htmlTemplate, err := template.New("loginSuccess").Parse(htmlTemplateContent) if err != nil { errServer = fmt.Errorf("parse html file: %w", err) } - err = htmlTemplate.Execute(w, user) + err = htmlTemplate.Execute(w, input) if err != nil { errServer = fmt.Errorf("render page: %w", err) } diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index a8b2a31b3..5649155cd 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -1,6 +1,7 @@ package utils import ( + "encoding/base64" "fmt" "net/url" "strings" @@ -116,3 +117,10 @@ func PtrByteSizeDefault(size *int64, defaultValue string) string { } return bytesize.New(float64(*size)).String() } + +// Base64Encode encodes a []byte to a base64 representation as string +func Base64Encode(message []byte) string { + b := make([]byte, base64.StdEncoding.EncodedLen(len(message))) + base64.StdEncoding.Encode(b, message) + return string(b) +} From 13c97c95a2ced03b7caf6038c900f6d0628e384b Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 24 Mar 2025 09:41:10 +0100 Subject: [PATCH 233/619] fix(deps): update module github.com/golang-jwt/jwt/v5 to v5.2.2 [security] (#663) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5a55a1a1e..d03e6c7da 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 github.com/goccy/go-yaml v1.16.0 - github.com/golang-jwt/jwt/v5 v5.2.1 + github.com/golang-jwt/jwt/v5 v5.2.2 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf diff --git a/go.sum b/go.sum index 24551dfe7..e2f7ae303 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= From e609e33135d23a0706b963a20068768f7d62ac3b Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 26 Mar 2025 13:28:37 +0100 Subject: [PATCH 234/619] fix(deps): update stackit sdk modules (#658) * fix(deps): update stackit sdk modules * fix: iaas update --------- Co-authored-by: Renovate Bot Co-authored-by: Marcel Jacek --- go.mod | 38 +++++----- go.sum | 76 +++++++++---------- internal/cmd/image/create/create.go | 2 +- internal/cmd/image/list/list.go | 8 +- .../credentials/create/create_test.go | 3 +- internal/cmd/quota/list/list.go | 34 +++++---- internal/cmd/security-group/list/list.go | 4 +- internal/cmd/server/console/console.go | 4 +- internal/cmd/server/create/create.go | 7 +- internal/cmd/server/create/create_test.go | 2 +- internal/cmd/server/log/log.go | 2 +- internal/cmd/server/machine-type/list/list.go | 4 +- 12 files changed, 95 insertions(+), 89 deletions(-) diff --git a/go.mod b/go.mod index d03e6c7da..422df11f7 100644 --- a/go.mod +++ b/go.mod @@ -16,21 +16,21 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.0 github.com/stackitcloud/stackit-sdk-go/core v0.16.0 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.1 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.23.0 golang.org/x/oauth2 v0.26.0 @@ -76,13 +76,13 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.0 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.1 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.1 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.1 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.1 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.30.0 // indirect diff --git a/go.sum b/go.sum index e2f7ae303..5f4cb3f28 100644 --- a/go.sum +++ b/go.sum @@ -113,50 +113,50 @@ github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stackitcloud/stackit-sdk-go/core v0.16.0 h1:9caGZwGLZDyBBe6ojk9VR4B2m3/0H5It6znBz76sH1w= github.com/stackitcloud/stackit-sdk-go/core v0.16.0/go.mod h1:LRheSoXTFRHWAyA8Q9skWtWBp3ZZ+bFAKiKuf4lTDkE= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0 h1:nSaSvo9o4c9KGc0vct+JWk5T49Ic6i3hzbLKviJtVhA= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.0/go.mod h1:LoOkWrUropfVm72oE5aWSC9yRiM3s8Vf3TvC7HtC3b8= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0 h1:gEoA2oj3OcDg3XI0KSJm8mCjQz9WOZENeSgfTFPK8ow= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.0/go.mod h1:JE8POcTfSxTo+g1MkgVQ+OjT4jWEr08MIY8qx3Hi+Tw= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1 h1:ZFFJr54FcYTUBjE+5E3Cx92jTDdHGKT2DTIvvJSRrTc= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.21.1/go.mod h1:9p5IIdOKOM5/DIjbenKrWvz6GlSps4jsPJZkH7QJuRU= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.0 h1:z2p0OobEAgSE5bQr+KR+4Y1QTvDbSC2a7w2eCV/oSp4= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.0/go.mod h1:x0jgrL+/K2cE4BvcIQByFUf0nOPVZRqq5Z074kjjr64= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0 h1:P7bxaVzkZPGMWItLynKIvc88Xh6jCnK4dPTTT+L607o= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.0/go.mod h1:os4Kp2+jkMUJ2dZtgU9A91N3EJSw3MMh2slxgK1609g= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0 h1:ks1i+cfD/YPRss//4aq6uvxbLvUwb5QvcUrOPeboLFY= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.0/go.mod h1:kGAT87SO5Wkv/CSZevMZcPml3V38G6tnT1Wvdkdmkv4= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.0 h1:mXVFa5/5uvOibPAUU0HTM7uf7H95IbnYnIzNvR5gB00= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.0/go.mod h1:uuTdgDo4Ju2W0eMfHc3a5n9SXNKJPdxuq15e3AFss6Q= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.0 h1:kWfmDQeTMijx0ySPiPfL4EU1TL6lcpkRVrzXenSaX6w= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.0/go.mod h1:giKgWW+KXpBDiZFWt/9D7D+sU1WSp27CQy+NolyrL8s= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.0 h1:Hn4BwKCzzmUdIFCU74OD9KgDA9OgmzRJzGMGXjPCWkQ= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.0/go.mod h1:PxfwA6YFtxwOajB4iTp1Eq7G02qUC3HdQPJvHGjQ1hk= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0 h1:y83IhdbQv8EHovWPTqeulGgyZKJ39AQW1klo0g7a7og= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.0/go.mod h1:Gk3hWaQDCJGgaixjGkUmoIr74VNWwdAakiUrvizpOWQ= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.1 h1:vUi9//CyfS6UMv0hftYMamimjJLco5lxT/KW9y4QPqM= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.1/go.mod h1:7TqfCUZRW7sjv8qOrLV5IvS6jqvY9Uxka165zdjYwD4= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.0 h1:zEJXwsuasmYH8dONZrCsZzcann/+6HZDKUPhN3mOmY0= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.0/go.mod h1:SaL9BCTeWcEmU9JiKgNihEXKnFKDTn91L9ehgvauWuM= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0 h1:UDIRWwiZ2/2ukmn60wPo83PUSuWPaXqbuRzkRTjRQNQ= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.0/go.mod h1:ErMQspxm7+XmtOsEM6lTD73oALPq3lUC5s+JQkm6Y/s= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0 h1:fPCdQOsdPB1QqwcgytrROk+h5va49CAnp5YSCIrKZWY= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.0/go.mod h1:Hs8RwANfF2ZKqOowPBqMQqLoRHcMobiKAihWWirAdEU= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1/go.mod h1:+i7jQpfgj/OuZNVZ9A9aUHdVUR/j2SfICLeHbtNn+5c= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 h1:xaNory8kBIsBG7PJnBfPP1cERc+ERqjebxmEmEOvRHU= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0/go.mod h1:LVOYlzNt5BXDC42AHd/GZj6KvlCg4w94of/E6pZOj5k= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 h1:4Kz9MH9VVuXYnnWFjJcPFVBiPtCUnSrHfsyUzBWwhKc= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1/go.mod h1:x0jgrL+/K2cE4BvcIQByFUf0nOPVZRqq5Z074kjjr64= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.1 h1:LwZlY0cANz2HR6U7I6hR+kFShmTKlTPNxBp1XHDoUzE= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.1/go.mod h1:aSdF3zcNoudRx5AzHqGVQVN7Cq05OseCQFyDa7P2cC8= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.1 h1:gAFstHEqncA6nFIrXKHrF1HDNF5jqhB1gzW/lNHAevI= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.1/go.mod h1:kUOByn2sB5KSIiz8Bx3XOLF3z7B8JtqP2nhH+Cr2W7o= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 h1:n6xMTHrLV9L78ureeigHHPwmMC4ZntOgVC+agV81Rpk= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1/go.mod h1:R+fHrtGfy+zx+d5s31cBh09P3TG58dyytb83gB7ldi0= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 h1:yyN3Q4i+5bmUVySPbQC7sSKG6sK21V8AxMjvhfJe2r0= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1/go.mod h1:c5/LHxZZ7qZYOboR01qOw1Mqq5v/VNyONw7WPHctNeY= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.1 h1:V6vvH++exqeqzD7TtzLc86ZRFrbcmxlaQqBJewiUXrE= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.1/go.mod h1:/GFUX/OiR2/SsWh3Vsu7UnY6QLJzsbHwrcxiRBxmYOA= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.1 h1:Bag2KZMwHJhlz2iy5Sy4ANTwPSR/ArGXcF13tbC3O+M= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.1/go.mod h1:F1WyCyjAuzq3YI+YPJxj4AXrmpWXtxjFxGhwo9RIYy4= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 h1:S6uamk6ecVy8K3jE2mgU50h14GoGE0LRVmiK3TvgfTc= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2/go.mod h1:7TqfCUZRW7sjv8qOrLV5IvS6jqvY9Uxka165zdjYwD4= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.1 h1:eShKpZ+YHv1/BfgKPR6gM66oPNFh7LyMBDAztApP388= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.1/go.mod h1:Z6j5yC+5xN/+KL2q8yN9F+DZWoGPYHzTpEaPy5mfYyo= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.1 h1:JKKAeMJAcZ2L/spwMHonmOmFFtcEuaLHRMP3wCF87jg= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.1/go.mod h1:ZPLAvqSApWS7hzinfCVAidPuWrMxizpkVhQ3zoIt8QU= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 h1:6bl/BSVebTnK73ToRn80Mtd1sl0TowfhOninyoSQA/U= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1/go.mod h1:t7Bq7VRIN1D9C2sa2PE5gzwL6d7p1fypnsydYhKaA5k= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 h1:tKUyddNszcif4j2yL6lJd4tDAykcU3shMkAPoM9EzV8= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0/go.mod h1:5n31cpeYcz2DSax4ygpZICEHDoHCTbWHrNGNYWwlRA8= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0 h1:PwfpDFGUUJ8+Go5hJf+/hA5CHfY+DPS1cqIUYH+zWtE= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.0/go.mod h1:Hb21FmYP95q0fzOb9jk4/9CIxTsHzrSYDQZh6e82XUg= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 h1:SZoWUDUA8foNbu+cwRa67VxJXJJx4M8oiHeykVh8Wlg= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2/go.mod h1:PrD0nNG94Dd5D9pu7HJ0bAg8ccDz6/7KaIts7K9p7as= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 h1:cESGAkm0ftADRBfdbiyx3pp/KVQ8JgmUQdRzpwG61wE= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0/go.mod h1:aYPLsiImzWaYXEfYIZ0wJnV56PwcR+buy8Xu9jjbfGA= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 h1:TMUxDh8XGgWUpnWo7GsawVq2ICDsy/r8dMlfC26MR5g= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0/go.mod h1:giHnHz3kHeLY8Av9MZLsyJlaTXYz+BuGqdP/SKB5Vo0= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0 h1:y+XzJcntHJ7M+IWWvAUkiVFA8op+jZxwHs3ktW2aLoA= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.0/go.mod h1:J/Wa67cbDI1wAyxib9PiEbNqGfIoFUH+DSLueVazQx8= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.0 h1:Xxd5KUSWRt7FytnNWClLEa0n9GM6e5xAKo835ODSpAM= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.0/go.mod h1:EMqjiq/72WKXSwnJGLpumUJS4Uwlyhg5vtNg7qWoGtc= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0 h1:3KUVls8zXsbT2tOYRSHyp3/l0Kpjl4f3INmQKYTe65Y= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.0/go.mod h1:63IvXpBJTIVONAnGPSDo0sRJ+6n6tzO918OLqfYBxto= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0 h1:RYJO0rZea9+sxVfaJDWRo2zgfKNgiUcA5c0nbvZURiU= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.0/go.mod h1:d2ICXCS2h3IMsZW0OanWkEH2XdLiY/XRKx2TcR940nw= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 h1:VKgxgjsbaUVMCnntq+MLQ/c1Emn5crVr11B3gJnyHN4= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1/go.mod h1:vn6xmMRxYgEoBhYEy6i2SY2qbeDKjs4IVNdnQHcQpBc= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 h1:7yY68QuntatwRG6ri65FlfeewACChLVbLp67wHCS8Go= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1/go.mod h1:EMqjiq/72WKXSwnJGLpumUJS4Uwlyhg5vtNg7qWoGtc= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 h1:9OnJGvQcL3Xwmc2BRQudjn2GNGvbJr8/xAIlmqtnmfQ= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1/go.mod h1:RlH5d+znKkOVt/HsD7OBAlhgIos7TM7vv0qCeqvCqmo= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 h1:3uPq1jXXw8+6Op/fJuPaKOpTP0nOCHAUobMzZV7aHGg= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1/go.mod h1:d2ICXCS2h3IMsZW0OanWkEH2XdLiY/XRKx2TcR940nw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 5fd2e86f2..d0550b1a4 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -141,7 +141,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !ok { return fmt.Errorf("create image: no upload URL has been provided") } - if err := uploadAsync(ctx, p, model, file, *url); err != nil { + if err := uploadAsync(ctx, p, model, file, url); err != nil { return err } diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index 32316eae0..47779fb83 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -80,13 +80,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("list images: %w", err) } - if items := response.GetItems(); items == nil || len(*items) == 0 { + if items := response.GetItems(); len(items) == 0 { p.Info("No images found for project %q", projectLabel) } else { - if model.Limit != nil && len(*items) > int(*model.Limit) { - *items = (*items)[:*model.Limit] + if model.Limit != nil && len(items) > int(*model.Limit) { + items = (items)[:*model.Limit] } - if err := outputResult(p, model.OutputFormat, *items); err != nil { + if err := outputResult(p, model.OutputFormat, items); err != nil { return fmt.Errorf("output images: %w", err) } } diff --git a/internal/cmd/observability/credentials/create/create_test.go b/internal/cmd/observability/credentials/create/create_test.go index 146fc9090..c261948c7 100644 --- a/internal/cmd/observability/credentials/create/create_test.go +++ b/internal/cmd/observability/credentials/create/create_test.go @@ -6,7 +6,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/observability" "github.com/google/go-cmp/cmp" @@ -218,7 +217,7 @@ func TestOutputResult(t *testing.T) { name: "set response with credentials", args: args{ resp: &observability.CreateCredentialsResponse{ - Credentials: observability.NewCredentials(utils.Ptr("dummy-pw"), utils.Ptr("dummy-user")), + Credentials: observability.NewCredentials("dummy-pw", "dummy-user"), }, }, wantErr: false, diff --git a/internal/cmd/quota/list/list.go b/internal/cmd/quota/list/list.go index e18ed94de..2e7a307c4 100644 --- a/internal/cmd/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -133,40 +133,40 @@ func outputResult(p *print.Printer, outputFormat string, quotas *iaas.QuotaList) table := tables.NewTable() table.SetHeader("NAME", "LIMIT", "CURRENT USAGE", "PERCENT") if val := quotas.BackupGigabytes; val != nil { - table.AddRow("Total size in GiB of backups [GiB]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Total size in GiB of backups [GiB]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.Backups; val != nil { - table.AddRow("Number of backups [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of backups [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.Gigabytes; val != nil { - table.AddRow("Total size in GiB of volumes and snapshots [GiB]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Total size in GiB of volumes and snapshots [GiB]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.Networks; val != nil { - table.AddRow("Number of networks [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of networks [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.Nics; val != nil { - table.AddRow("Number of network interfaces (nics) [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of network interfaces (nics) [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.PublicIps; val != nil { - table.AddRow("Number of public IP addresses [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of public IP addresses [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.Ram; val != nil { - table.AddRow("Amount of server RAM in MiB [MiB]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Amount of server RAM in MiB [MiB]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.SecurityGroupRules; val != nil { - table.AddRow("Number of security group rules [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of security group rules [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.SecurityGroups; val != nil { - table.AddRow("Number of security groups [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of security groups [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.Snapshots; val != nil { - table.AddRow("Number of snapshots [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of snapshots [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.Vcpu; val != nil { - table.AddRow("Number of server cores (vcpu) [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of server cores (vcpu) [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } if val := quotas.Volumes; val != nil { - table.AddRow("Number of volumes [Count]", conv(val.GetLimit()), conv(val.GetUsage()), percentage(val)) + table.AddRow("Number of volumes [Count]", conv(val.Limit), conv(val.Usage), percentage(val)) } err := table.Display(p) if err != nil { @@ -185,11 +185,13 @@ func conv(n *int64) string { } func percentage(val interface { - GetLimit() *int64 - GetUsage() *int64 + GetLimitOk() (int64, bool) + GetUsageOk() (int64, bool) }) string { - if a, b := val.GetLimit(), val.GetUsage(); a != nil && b != nil { - return fmt.Sprintf("%3.1f%%", 100.0/float64(*a)*float64(*b)) + a, aOk := val.GetLimitOk() + b, bOk := val.GetUsageOk() + if aOk && bOk { + return fmt.Sprintf("%3.1f%%", 100.0/float64(a)*float64(b)) } return "n/a" } diff --git a/internal/cmd/security-group/list/list.go b/internal/cmd/security-group/list/list.go index 74a44c943..48caeddb3 100644 --- a/internal/cmd/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -67,10 +67,10 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("list security group: %w", err) } - if items := response.GetItems(); items == nil || len(*items) == 0 { + if items := response.GetItems(); len(items) == 0 { p.Info("No security groups found for project %q", projectLabel) } else { - if err := outputResult(p, model.OutputFormat, *items); err != nil { + if err := outputResult(p, model.OutputFormat, items); err != nil { return fmt.Errorf("output security groups: %w", err) } } diff --git a/internal/cmd/server/console/console.go b/internal/cmd/server/console/console.go index 3c6f08ab8..a9964619c 100644 --- a/internal/cmd/server/console/console.go +++ b/internal/cmd/server/console/console.go @@ -127,11 +127,11 @@ func outputResult(p *print.Printer, outputFormat, serverLabel string, serverUrl return nil default: - if serverUrl.GetUrl() == nil { + if _, ok := serverUrl.GetUrlOk(); !ok { return fmt.Errorf("server url is nil") } // unescape url in order to get rid of e.g. %40 - unescapedURL, err := url.PathUnescape(*serverUrl.GetUrl()) + unescapedURL, err := url.PathUnescape(serverUrl.GetUrl()) if err != nil { return fmt.Errorf("unescape url: %w", err) } diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 461f58ce3..69cfc627b 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -289,6 +289,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } } + var userData *[]byte + if model.UserData != nil { + userData = utils.Ptr([]byte(*model.UserData)) + } + payload := iaas.CreateServerPayload{ Name: model.Name, MachineType: model.MachineType, @@ -299,7 +304,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli KeypairName: model.KeypairName, SecurityGroups: model.SecurityGroups, ServiceAccountMails: model.ServiceAccountMails, - UserData: model.UserData, + UserData: userData, Volumes: model.Volumes, Labels: labelsMap, } diff --git a/internal/cmd/server/create/create_test.go b/internal/cmd/server/create/create_test.go index b5ffb23f9..bf8f815d5 100644 --- a/internal/cmd/server/create/create_test.go +++ b/internal/cmd/server/create/create_test.go @@ -120,7 +120,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateServerPayload)) iaas.Create KeypairName: utils.Ptr("test-keypair-name"), SecurityGroups: utils.Ptr([]string{"test-security-groups"}), ServiceAccountMails: utils.Ptr([]string{"test-service-account"}), - UserData: utils.Ptr("test-user-data"), + UserData: utils.Ptr([]byte("test-user-data")), Volumes: utils.Ptr([]string{testVolumeId}), BootVolume: &iaas.CreateServerPayloadBootVolume{ PerformanceClass: utils.Ptr("test-perf-class"), diff --git a/internal/cmd/server/log/log.go b/internal/cmd/server/log/log.go index 974b149a3..646417b42 100644 --- a/internal/cmd/server/log/log.go +++ b/internal/cmd/server/log/log.go @@ -82,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("server log: %w", err) } - log := *resp.GetOutput() + log := resp.GetOutput() lines := strings.Split(log, "\n") if len(lines) > int(*model.Length) { diff --git a/internal/cmd/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go index e04f3e9f8..19be072d3 100644 --- a/internal/cmd/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -155,8 +155,8 @@ func outputResult(p *print.Printer, outputFormat string, machineTypes iaas.Machi table.SetTitle("Machine-Types") table.SetHeader("NAME", "DESCRIPTION") - if items := machineTypes.GetItems(); items != nil && len(*items) > 0 { - for _, machineType := range *items { + if items := machineTypes.GetItems(); len(items) > 0 { + for _, machineType := range items { table.AddRow(*machineType.Name, utils.PtrString(machineType.Description)) } } From abe00f83733684acd66599b261d85fb216054675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 26 Mar 2025 15:21:42 +0100 Subject: [PATCH 235/619] chore: add make option to create test coverage reports (#659) --- .gitignore | 6 +++++- CONTRIBUTION.md | 1 + Makefile | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 47aabc929..2cf34eb63 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,8 @@ dist/ # Go workspace file go.work -go.work.sum \ No newline at end of file +go.work.sum + +# Test coverage reports +coverage.out +coverage.html diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index be0a54346..07af2da47 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -31,6 +31,7 @@ These commands can be executed from the project root: - `make lint`: lint the code - `make generate-docs`: generate Markdown documentation for every command - `make test`: run unit tests +- `make coverage`: create unit test coverage report (output file: `coverage.html`) ### Repository structure diff --git a/Makefile b/Makefile index 7657fc059..373d2b0fb 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,12 @@ test: @echo ">> Running tests for the CLI application" @go test ./... -count=1 +# Test coverage +coverage: + @echo ">> Creating test coverage report for the CLI application" + @go test ./... -coverprofile=coverage.out || true + @go tool cover -html=coverage.out -o coverage.html + # Generate docs generate-docs: @echo ">> Generating docs..." From 88dc956e2a182032b8a01a1b2b1f2379c56621b8 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 27 Mar 2025 09:23:06 +0100 Subject: [PATCH 236/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/core to v0.16.2 (#666) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 422df11f7..2c64f7523 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.0 - github.com/stackitcloud/stackit-sdk-go/core v0.16.0 + github.com/stackitcloud/stackit-sdk-go/core v0.16.2 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 diff --git a/go.sum b/go.sum index 5f4cb3f28..a3ac57e33 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,8 @@ github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= -github.com/stackitcloud/stackit-sdk-go/core v0.16.0 h1:9caGZwGLZDyBBe6ojk9VR4B2m3/0H5It6znBz76sH1w= -github.com/stackitcloud/stackit-sdk-go/core v0.16.0/go.mod h1:LRheSoXTFRHWAyA8Q9skWtWBp3ZZ+bFAKiKuf4lTDkE= +github.com/stackitcloud/stackit-sdk-go/core v0.16.2 h1:F8A4P/LLlQSbz0S0+G3m8rb3BUOK6EcR/CKx5UQY5jQ= +github.com/stackitcloud/stackit-sdk-go/core v0.16.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA= github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo= From d5834390897eb5b9db6e785dc085c664e05a0c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 27 Mar 2025 09:55:56 +0100 Subject: [PATCH 237/619] chore(server): regional adjustment for server update (#662) relates to STACKITCLI-128 --- docs/stackit_server_os-update_create.md | 4 +-- go.mod | 2 +- go.sum | 4 +-- .../cmd/server/os-update/create/create.go | 6 ++-- .../server/os-update/create/create_test.go | 20 +++++++------ .../cmd/server/os-update/describe/describe.go | 2 +- .../os-update/describe/describe_test.go | 18 +++++++----- .../cmd/server/os-update/disable/disable.go | 4 +-- .../server/os-update/disable/disable_test.go | 20 +++++++------ .../cmd/server/os-update/enable/enable.go | 6 ++-- .../server/os-update/enable/enable_test.go | 20 +++++++------ internal/cmd/server/os-update/list/list.go | 2 +- .../cmd/server/os-update/list/list_test.go | 20 +++++++------ .../os-update/schedule/create/create.go | 2 +- .../os-update/schedule/create/create_test.go | 26 +++++++++-------- .../os-update/schedule/delete/delete.go | 2 +- .../os-update/schedule/delete/delete_test.go | 20 +++++++------ .../os-update/schedule/describe/describe.go | 2 +- .../schedule/describe/describe_test.go | 20 +++++++------ .../server/os-update/schedule/list/list.go | 2 +- .../os-update/schedule/list/list_test.go | 20 +++++++------ .../os-update/schedule/update/update.go | 4 +-- .../os-update/schedule/update/update_test.go | 28 +++++++++++-------- .../services/serverosupdate/client/client.go | 3 +- 24 files changed, 148 insertions(+), 109 deletions(-) diff --git a/docs/stackit_server_os-update_create.md b/docs/stackit_server_os-update_create.md index f84cb6d77..4d110f8bc 100644 --- a/docs/stackit_server_os-update_create.md +++ b/docs/stackit_server_os-update_create.md @@ -14,10 +14,10 @@ stackit server os-update create [flags] ``` Create a Server os-update with name "myupdate" - $ stackit server os-update create --server-id xxx --name=myupdate + $ stackit server os-update create --server-id xxx Create a Server os-update with name "myupdate" and maintenance window for 13 o'clock. - $ stackit server os-update create --server-id xxx --name=mybupdate --maintenance-window=13 + $ stackit server os-update create --server-id xxx --maintenance-window=13 ``` ### Options diff --git a/go.mod b/go.mod index 2c64f7523..01eb483eb 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 diff --git a/go.sum b/go.sum index a3ac57e33..0f6dee7fb 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,8 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 h1:SZoWUD github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2/go.mod h1:PrD0nNG94Dd5D9pu7HJ0bAg8ccDz6/7KaIts7K9p7as= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 h1:cESGAkm0ftADRBfdbiyx3pp/KVQ8JgmUQdRzpwG61wE= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0/go.mod h1:aYPLsiImzWaYXEfYIZ0wJnV56PwcR+buy8Xu9jjbfGA= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0 h1:TMUxDh8XGgWUpnWo7GsawVq2ICDsy/r8dMlfC26MR5g= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v0.5.0/go.mod h1:giHnHz3kHeLY8Av9MZLsyJlaTXYz+BuGqdP/SKB5Vo0= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0 h1:a8logPoRcMCgwa9rCtuzWF6DLiuCIdJgcacZKThFsks= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0/go.mod h1:zDdYYQVHGlju9cnMISX/Ty73Yh/qYcZGcJSOYWRZCbw= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 h1:VKgxgjsbaUVMCnntq+MLQ/c1Emn5crVr11B3gJnyHN4= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1/go.mod h1:vn6xmMRxYgEoBhYEy6i2SY2qbeDKjs4IVNdnQHcQpBc= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 h1:7yY68QuntatwRG6ri65FlfeewACChLVbLp67wHCS8Go= diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index 9c4a1cbf9..71845bc2a 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -43,10 +43,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a Server os-update with name "myupdate"`, - `$ stackit server os-update create --server-id xxx --name=myupdate`), + `$ stackit server os-update create --server-id xxx`), examples.NewExample( `Create a Server os-update with name "myupdate" and maintenance window for 13 o'clock.`, - `$ stackit server os-update create --server-id xxx --name=mybupdate --maintenance-window=13`), + `$ stackit server os-update create --server-id xxx --maintenance-window=13`), ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() @@ -128,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) (serverupdate.ApiCreateUpdateRequest, error) { - req := apiClient.CreateUpdate(ctx, model.ProjectId, model.ServerId) + req := apiClient.CreateUpdate(ctx, model.ProjectId, model.ServerId, model.Region) payload := serverupdate.CreateUpdatePayload{ MaintenanceWindow: &model.MaintenanceWindow, } diff --git a/internal/cmd/server/os-update/create/create_test.go b/internal/cmd/server/os-update/create/create_test.go index e2a38ea36..9dd635e70 100644 --- a/internal/cmd/server/os-update/create/create_test.go +++ b/internal/cmd/server/os-update/create/create_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -26,9 +28,10 @@ var testServerId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - maintenanceWindowFlag: "13", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, + maintenanceWindowFlag: "13", } for _, mod := range mods { mod(flagValues) @@ -40,6 +43,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -52,7 +56,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverupdate.ApiCreateUpdateRequest)) serverupdate.ApiCreateUpdateRequest { - request := testClient.CreateUpdate(testCtx, testProjectId, testServerId) + request := testClient.CreateUpdate(testCtx, testProjectId, testServerId, testRegion) request = request.CreateUpdatePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -102,21 +106,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/os-update/describe/describe.go b/internal/cmd/server/os-update/describe/describe.go index f2f768651..7260131ff 100644 --- a/internal/cmd/server/os-update/describe/describe.go +++ b/internal/cmd/server/os-update/describe/describe.go @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiGetUpdateRequest { - req := apiClient.GetUpdate(ctx, model.ProjectId, model.ServerId, model.UpdateId) + req := apiClient.GetUpdate(ctx, model.ProjectId, model.ServerId, model.UpdateId, model.Region) return req } diff --git a/internal/cmd/server/os-update/describe/describe_test.go b/internal/cmd/server/os-update/describe/describe_test.go index fb345e40a..741bbe6dc 100644 --- a/internal/cmd/server/os-update/describe/describe_test.go +++ b/internal/cmd/server/os-update/describe/describe_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -35,8 +37,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverupdate.ApiGetUpdateRequest)) serverupdate.ApiGetUpdateRequest { - request := testClient.GetUpdate(testCtx, testProjectId, testServerId, testUpdateId) + request := testClient.GetUpdate(testCtx, testProjectId, testServerId, testUpdateId, testRegion) for _, mod := range mods { mod(&request) } @@ -104,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +124,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go index a55ab7e9d..f0270b0cd 100644 --- a/internal/cmd/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -115,7 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiDisableServiceRequest { - req := apiClient.DisableService(ctx, model.ProjectId, model.ServerId) +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiDisableServiceResourceRequest { + req := apiClient.DisableServiceResource(ctx, model.ProjectId, model.ServerId, model.Region) return req } diff --git a/internal/cmd/server/os-update/disable/disable_test.go b/internal/cmd/server/os-update/disable/disable_test.go index 6560a7fae..566300e33 100644 --- a/internal/cmd/server/os-update/disable/disable_test.go +++ b/internal/cmd/server/os-update/disable/disable_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -25,7 +27,8 @@ var testServerId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -47,8 +51,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *serverupdate.ApiDisableServiceRequest)) serverupdate.ApiDisableServiceRequest { - request := testClient.DisableService(testCtx, testProjectId, testServerId) +func fixtureRequest(mods ...func(request *serverupdate.ApiDisableServiceResourceRequest)) serverupdate.ApiDisableServiceResourceRequest { + request := testClient.DisableServiceResource(testCtx, testProjectId, testServerId, testRegion) for _, mod := range mods { mod(&request) } @@ -78,21 +82,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -148,7 +152,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest serverupdate.ApiDisableServiceRequest + expectedRequest serverupdate.ApiDisableServiceResourceRequest }{ { description: "base", diff --git a/internal/cmd/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go index 0dc7cb0f6..c255c778e 100644 --- a/internal/cmd/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -118,8 +118,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiEnableServiceRequest { - payload := serverupdate.EnableServicePayload{} - req := apiClient.EnableService(ctx, model.ProjectId, model.ServerId).EnableServicePayload(payload) +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiEnableServiceResourceRequest { + payload := serverupdate.EnableServiceResourcePayload{} + req := apiClient.EnableServiceResource(ctx, model.ProjectId, model.ServerId, model.Region).EnableServiceResourcePayload(payload) return req } diff --git a/internal/cmd/server/os-update/enable/enable_test.go b/internal/cmd/server/os-update/enable/enable_test.go index 6e55c1c77..d35251a70 100644 --- a/internal/cmd/server/os-update/enable/enable_test.go +++ b/internal/cmd/server/os-update/enable/enable_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -25,7 +27,8 @@ var testServerId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -47,8 +51,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *serverupdate.ApiEnableServiceRequest)) serverupdate.ApiEnableServiceRequest { - request := testClient.EnableService(testCtx, testProjectId, testServerId).EnableServicePayload(serverupdate.EnableServicePayload{}) +func fixtureRequest(mods ...func(request *serverupdate.ApiEnableServiceResourceRequest)) serverupdate.ApiEnableServiceResourceRequest { + request := testClient.EnableServiceResource(testCtx, testProjectId, testServerId, testRegion).EnableServiceResourcePayload(serverupdate.EnableServiceResourcePayload{}) for _, mod := range mods { mod(&request) } @@ -78,21 +82,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -148,7 +152,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest serverupdate.ApiEnableServiceRequest + expectedRequest serverupdate.ApiEnableServiceResourceRequest }{ { description: "base", diff --git a/internal/cmd/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go index af4f15030..e1435badc 100644 --- a/internal/cmd/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -135,7 +135,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiListUpdatesRequest { - req := apiClient.ListUpdates(ctx, model.ProjectId, model.ServerId) + req := apiClient.ListUpdates(ctx, model.ProjectId, model.ServerId, model.Region) return req } diff --git a/internal/cmd/server/os-update/list/list_test.go b/internal/cmd/server/os-update/list/list_test.go index 4b6df9161..36205f88d 100644 --- a/internal/cmd/server/os-update/list/list_test.go +++ b/internal/cmd/server/os-update/list/list_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -25,9 +27,10 @@ var testServerId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -39,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -51,7 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverupdate.ApiListUpdatesRequest)) serverupdate.ApiListUpdatesRequest { - request := testClient.ListUpdates(testCtx, testProjectId, testServerId) + request := testClient.ListUpdates(testCtx, testProjectId, testServerId, testRegion) for _, mod := range mods { mod(&request) } @@ -79,21 +83,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index e61003a95..2f30e876f 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -146,7 +146,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) (serverupdate.ApiCreateUpdateScheduleRequest, error) { - req := apiClient.CreateUpdateSchedule(ctx, model.ProjectId, model.ServerId) + req := apiClient.CreateUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.Region) req = req.CreateUpdateSchedulePayload(serverupdate.CreateUpdateSchedulePayload{ Enabled: &model.Enabled, Name: &model.ScheduleName, diff --git a/internal/cmd/server/os-update/schedule/create/create_test.go b/internal/cmd/server/os-update/schedule/create/create_test.go index 169167532..7d084516e 100644 --- a/internal/cmd/server/os-update/schedule/create/create_test.go +++ b/internal/cmd/server/os-update/schedule/create/create_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -26,12 +28,13 @@ var testServerId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - nameFlag: "example-schedule-name", - enabledFlag: "true", - rruleFlag: defaultRrule, - maintenanceWindowFlag: "23", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, + nameFlag: "example-schedule-name", + enabledFlag: "true", + rruleFlag: defaultRrule, + maintenanceWindowFlag: "23", } for _, mod := range mods { mod(flagValues) @@ -43,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverupdate.ApiCreateUpdateScheduleRequest)) serverupdate.ApiCreateUpdateScheduleRequest { - request := testClient.CreateUpdateSchedule(testCtx, testProjectId, testServerId) + request := testClient.CreateUpdateSchedule(testCtx, testProjectId, testServerId, testRegion) request = request.CreateUpdateSchedulePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -109,21 +113,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/os-update/schedule/delete/delete.go b/internal/cmd/server/os-update/schedule/delete/delete.go index 3c9813a98..855690fa4 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete.go +++ b/internal/cmd/server/os-update/schedule/delete/delete.go @@ -108,6 +108,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiDeleteUpdateScheduleRequest { - req := apiClient.DeleteUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + req := apiClient.DeleteUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId, model.Region) return req } diff --git a/internal/cmd/server/os-update/schedule/delete/delete_test.go b/internal/cmd/server/os-update/schedule/delete/delete_test.go index 60b00b97c..040aa61f7 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete_test.go +++ b/internal/cmd/server/os-update/schedule/delete/delete_test.go @@ -13,7 +13,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testUpdateScheduleId = "5" +) type testCtxKey struct{} @@ -21,7 +24,6 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serverupdate.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() -var testUpdateScheduleId = "5" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +37,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverupdate.ApiDeleteUpdateScheduleRequest)) serverupdate.ApiDeleteUpdateScheduleRequest { - request := testClient.DeleteUpdateSchedule(testCtx, testProjectId, testServerId, testUpdateScheduleId) + request := testClient.DeleteUpdateSchedule(testCtx, testProjectId, testServerId, testUpdateScheduleId, testRegion) for _, mod := range mods { mod(&request) } @@ -104,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +124,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/os-update/schedule/describe/describe.go b/internal/cmd/server/os-update/schedule/describe/describe.go index 98aa50f37..60aa9431c 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/server/os-update/schedule/describe/describe.go @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiGetUpdateScheduleRequest { - req := apiClient.GetUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + req := apiClient.GetUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId, model.Region) return req } diff --git a/internal/cmd/server/os-update/schedule/describe/describe_test.go b/internal/cmd/server/os-update/schedule/describe/describe_test.go index 411148262..5928e712b 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe_test.go +++ b/internal/cmd/server/os-update/schedule/describe/describe_test.go @@ -13,7 +13,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testScheduleId = "5" +) type testCtxKey struct{} @@ -21,7 +24,6 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serverupdate.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() -var testScheduleId = "5" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +37,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverupdate.ApiGetUpdateScheduleRequest)) serverupdate.ApiGetUpdateScheduleRequest { - request := testClient.GetUpdateSchedule(testCtx, testProjectId, testServerId, testScheduleId) + request := testClient.GetUpdateSchedule(testCtx, testProjectId, testServerId, testScheduleId, testRegion) for _, mod := range mods { mod(&request) } @@ -104,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +124,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go index 339f23fea..562b30665 100644 --- a/internal/cmd/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -133,7 +133,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient) serverupdate.ApiListUpdateSchedulesRequest { - req := apiClient.ListUpdateSchedules(ctx, model.ProjectId, model.ServerId) + req := apiClient.ListUpdateSchedules(ctx, model.ProjectId, model.ServerId, model.Region) return req } diff --git a/internal/cmd/server/os-update/schedule/list/list_test.go b/internal/cmd/server/os-update/schedule/list/list_test.go index 61a3ca5ca..d29d3dd5f 100644 --- a/internal/cmd/server/os-update/schedule/list/list_test.go +++ b/internal/cmd/server/os-update/schedule/list/list_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -25,9 +27,10 @@ var testServerId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -39,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -51,7 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverupdate.ApiListUpdateSchedulesRequest)) serverupdate.ApiListUpdateSchedulesRequest { - request := testClient.ListUpdateSchedules(testCtx, testProjectId, testServerId) + request := testClient.ListUpdateSchedules(testCtx, testProjectId, testServerId, testRegion) for _, mod := range mods { mod(&request) } @@ -79,21 +83,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/os-update/schedule/update/update.go b/internal/cmd/server/os-update/schedule/update/update.go index 25f110415..e698f21f7 100644 --- a/internal/cmd/server/os-update/schedule/update/update.go +++ b/internal/cmd/server/os-update/schedule/update/update.go @@ -68,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - currentSchedule, err := apiClient.GetUpdateScheduleExecute(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + currentSchedule, err := apiClient.GetUpdateScheduleExecute(ctx, model.ProjectId, model.ServerId, model.ScheduleId, model.Region) if err != nil { p.Debug(print.ErrorLevel, "get current server os-update schedule: %v", err) return err @@ -142,7 +142,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdate.APIClient, old serverupdate.UpdateSchedule) (serverupdate.ApiUpdateUpdateScheduleRequest, error) { - req := apiClient.UpdateUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + req := apiClient.UpdateUpdateSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId, model.Region) if model.MaintenanceWindow != nil { old.MaintenanceWindow = model.MaintenanceWindow diff --git a/internal/cmd/server/os-update/schedule/update/update_test.go b/internal/cmd/server/os-update/schedule/update/update_test.go index a821be003..63ab21239 100644 --- a/internal/cmd/server/os-update/schedule/update/update_test.go +++ b/internal/cmd/server/os-update/schedule/update/update_test.go @@ -15,7 +15,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testScheduleId = "5" +) type testCtxKey struct{} @@ -23,7 +26,6 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serverupdate.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() -var testScheduleId = "5" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -37,12 +39,13 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - nameFlag: "example-schedule-name", - enabledFlag: "true", - rruleFlag: defaultRrule, - maintenanceWindowFlag: "23", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, + nameFlag: "example-schedule-name", + enabledFlag: "true", + rruleFlag: defaultRrule, + maintenanceWindowFlag: "23", } for _, mod := range mods { mod(flagValues) @@ -54,6 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ScheduleId: testScheduleId, @@ -98,7 +102,7 @@ func fixturePayload(mods ...func(payload *serverupdate.UpdateUpdateSchedulePaylo } func fixtureRequest(mods ...func(request *serverupdate.ApiUpdateUpdateScheduleRequest)) serverupdate.ApiUpdateUpdateScheduleRequest { - request := testClient.UpdateUpdateSchedule(testCtx, testProjectId, testServerId, testScheduleId) + request := testClient.UpdateUpdateSchedule(testCtx, testProjectId, testServerId, testScheduleId, testRegion) request = request.UpdateUpdateSchedulePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -138,7 +142,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -146,7 +150,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -154,7 +158,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/pkg/services/serverosupdate/client/client.go b/internal/pkg/services/serverosupdate/client/client.go index 8b46d6f1d..1f1f2033e 100644 --- a/internal/pkg/services/serverosupdate/client/client.go +++ b/internal/pkg/services/serverosupdate/client/client.go @@ -12,7 +12,6 @@ import ( ) func ConfigureClient(p *print.Printer) (*serverupdate.APIClient, error) { - var err error var apiClient *serverupdate.APIClient var cfgOptions []sdkConfig.ConfigurationOption @@ -27,7 +26,7 @@ func ConfigureClient(p *print.Printer) (*serverupdate.APIClient, error) { if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) + cfgOptions = append(cfgOptions, authCfgOption) } if p.IsVerbosityDebug() { From 7e2f057282c610db6a9b7817e214b5298974bc0e Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Thu, 27 Mar 2025 13:29:59 +0100 Subject: [PATCH 238/619] feat(serverbackup): Region adjustment (#667) Signed-off-by: Alexander Dahmen --- go.mod | 2 +- go.sum | 4 ++-- internal/cmd/server/backup/create/create.go | 2 +- .../cmd/server/backup/create/create_test.go | 15 ++++++------- internal/cmd/server/backup/delete/delete.go | 2 +- .../cmd/server/backup/delete/delete_test.go | 17 ++++++++------- .../cmd/server/backup/describe/describe.go | 2 +- .../server/backup/describe/describe_test.go | 17 ++++++++------- internal/cmd/server/backup/disable/disable.go | 6 +++--- .../cmd/server/backup/disable/disable_test.go | 19 +++++++++-------- internal/cmd/server/backup/enable/enable.go | 6 +++--- .../cmd/server/backup/enable/enable_test.go | 19 +++++++++-------- internal/cmd/server/backup/list/list.go | 2 +- internal/cmd/server/backup/list/list_test.go | 19 +++++++++-------- internal/cmd/server/backup/restore/restore.go | 2 +- .../cmd/server/backup/restore/restore_test.go | 17 ++++++++------- .../server/backup/schedule/create/create.go | 2 +- .../backup/schedule/create/create_test.go | 15 ++++++------- .../server/backup/schedule/delete/delete.go | 2 +- .../backup/schedule/delete/delete_test.go | 17 ++++++++------- .../backup/schedule/describe/describe.go | 2 +- .../backup/schedule/describe/describe_test.go | 17 ++++++++------- .../cmd/server/backup/schedule/list/list.go | 2 +- .../server/backup/schedule/list/list_test.go | 19 +++++++++-------- .../server/backup/schedule/update/update.go | 4 ++-- .../backup/schedule/update/update_test.go | 15 ++++++------- .../backup/volume-backup/delete/delete.go | 2 +- .../volume-backup/delete/delete_test.go | 19 +++++++++-------- .../backup/volume-backup/restore/restore.go | 2 +- .../volume-backup/restore/restore_test.go | 21 ++++++++++--------- .../pkg/services/serverbackup/utils/utils.go | 10 ++++----- .../services/serverbackup/utils/utils_test.go | 7 ++++--- 32 files changed, 161 insertions(+), 146 deletions(-) diff --git a/go.mod b/go.mod index 01eb483eb..c8290fe05 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 diff --git a/go.sum b/go.sum index 0f6dee7fb..9481a8d99 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,8 @@ github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 h1:tKUyddNszci github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0/go.mod h1:5n31cpeYcz2DSax4ygpZICEHDoHCTbWHrNGNYWwlRA8= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 h1:SZoWUDUA8foNbu+cwRa67VxJXJJx4M8oiHeykVh8Wlg= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2/go.mod h1:PrD0nNG94Dd5D9pu7HJ0bAg8ccDz6/7KaIts7K9p7as= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0 h1:cESGAkm0ftADRBfdbiyx3pp/KVQ8JgmUQdRzpwG61wE= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.6.0/go.mod h1:aYPLsiImzWaYXEfYIZ0wJnV56PwcR+buy8Xu9jjbfGA= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 h1:qujhShugc1290NQlPoNqsembqzot8aTToAdSsJg5WrM= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1/go.mod h1:e1fsQL24gTPXcMWptuslNscawmXv/PLUAFuw+sOofbc= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0 h1:a8logPoRcMCgwa9rCtuzWF6DLiuCIdJgcacZKThFsks= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0/go.mod h1:zDdYYQVHGlju9cnMISX/Ty73Yh/qYcZGcJSOYWRZCbw= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 h1:VKgxgjsbaUVMCnntq+MLQ/c1Emn5crVr11B3gJnyHN4= diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index aae197772..28243cdc8 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -140,7 +140,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) (serverbackup.ApiCreateBackupRequest, error) { - req := apiClient.CreateBackup(ctx, model.ProjectId, model.ServerId) + req := apiClient.CreateBackup(ctx, model.ProjectId, model.ServerId, model.Region) payload := serverbackup.CreateBackupPayload{ Name: &model.BackupName, RetentionPeriod: &model.BackupRetentionPeriod, diff --git a/internal/cmd/server/backup/create/create_test.go b/internal/cmd/server/backup/create/create_test.go index a4fd801f3..b0d547f44 100644 --- a/internal/cmd/server/backup/create/create_test.go +++ b/internal/cmd/server/backup/create/create_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -24,10 +22,12 @@ var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testBackupVolumeId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, serverIdFlag: testServerId, backupNameFlag: "example-backup-name", backupRetentionPeriodFlag: "14", @@ -43,6 +43,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -57,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiCreateBackupRequest)) serverbackup.ApiCreateBackupRequest { - request := testClient.CreateBackup(testCtx, testProjectId, testServerId) + request := testClient.CreateBackup(testCtx, testProjectId, testServerId, testRegion) request = request.CreateBackupPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -107,21 +108,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/delete/delete.go b/internal/cmd/server/backup/delete/delete.go index 821e62f74..7805d20c0 100644 --- a/internal/cmd/server/backup/delete/delete.go +++ b/internal/cmd/server/backup/delete/delete.go @@ -109,6 +109,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDeleteBackupRequest { - req := apiClient.DeleteBackup(ctx, model.ProjectId, model.ServerId, model.BackupId) + req := apiClient.DeleteBackup(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupId) return req } diff --git a/internal/cmd/server/backup/delete/delete_test.go b/internal/cmd/server/backup/delete/delete_test.go index feb988f4b..d1f455b3d 100644 --- a/internal/cmd/server/backup/delete/delete_test.go +++ b/internal/cmd/server/backup/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,6 +20,7 @@ var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testBackupId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +34,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiDeleteBackupRequest)) serverbackup.ApiDeleteBackupRequest { - request := testClient.DeleteBackup(testCtx, testProjectId, testServerId, testBackupId) + request := testClient.DeleteBackup(testCtx, testProjectId, testServerId, testRegion, testBackupId) for _, mod := range mods { mod(&request) } @@ -104,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/describe/describe.go b/internal/cmd/server/backup/describe/describe.go index 318b11b01..b1fe36663 100644 --- a/internal/cmd/server/backup/describe/describe.go +++ b/internal/cmd/server/backup/describe/describe.go @@ -106,7 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiGetBackupRequest { - req := apiClient.GetBackup(ctx, model.ProjectId, model.ServerId, model.BackupId) + req := apiClient.GetBackup(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupId) return req } diff --git a/internal/cmd/server/backup/describe/describe_test.go b/internal/cmd/server/backup/describe/describe_test.go index efa3e370a..2760e7e7c 100644 --- a/internal/cmd/server/backup/describe/describe_test.go +++ b/internal/cmd/server/backup/describe/describe_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,6 +20,7 @@ var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testBackupId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +34,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiGetBackupRequest)) serverbackup.ApiGetBackupRequest { - request := testClient.GetBackup(testCtx, testProjectId, testServerId, testBackupId) + request := testClient.GetBackup(testCtx, testProjectId, testServerId, testRegion, testBackupId) for _, mod := range mods { mod(&request) } @@ -104,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go index fc2219dca..0a76151a5 100644 --- a/internal/cmd/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -63,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - canDisable, err := serverbackupUtils.CanDisableBackupService(ctx, apiClient, model.ProjectId, model.ServerId) + canDisable, err := serverbackupUtils.CanDisableBackupService(ctx, apiClient, model.ProjectId, model.ServerId, model.Region) if err != nil { return err } @@ -125,7 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDisableServiceRequest { - req := apiClient.DisableService(ctx, model.ProjectId, model.ServerId) +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDisableServiceResourceRequest { + req := apiClient.DisableServiceResource(ctx, model.ProjectId, model.ServerId, model.Region) return req } diff --git a/internal/cmd/server/backup/disable/disable_test.go b/internal/cmd/server/backup/disable/disable_test.go index 17f9583b2..7b13233e1 100644 --- a/internal/cmd/server/backup/disable/disable_test.go +++ b/internal/cmd/server/backup/disable/disable_test.go @@ -14,18 +14,18 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -47,8 +48,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *serverbackup.ApiDisableServiceRequest)) serverbackup.ApiDisableServiceRequest { - request := testClient.DisableService(testCtx, testProjectId, testServerId) +func fixtureRequest(mods ...func(request *serverbackup.ApiDisableServiceResourceRequest)) serverbackup.ApiDisableServiceResourceRequest { + request := testClient.DisableServiceResource(testCtx, testProjectId, testServerId, testRegion) for _, mod := range mods { mod(&request) } @@ -78,21 +79,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -148,7 +149,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest serverbackup.ApiDisableServiceRequest + expectedRequest serverbackup.ApiDisableServiceResourceRequest }{ { description: "base", diff --git a/internal/cmd/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go index 3eea44927..9f0f48e1b 100644 --- a/internal/cmd/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -118,8 +118,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiEnableServiceRequest { - payload := serverbackup.EnableServicePayload{} - req := apiClient.EnableService(ctx, model.ProjectId, model.ServerId).EnableServicePayload(payload) +func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiEnableServiceResourceRequest { + payload := serverbackup.EnableServiceResourcePayload{} + req := apiClient.EnableServiceResource(ctx, model.ProjectId, model.ServerId, model.Region).EnableServiceResourcePayload(payload) return req } diff --git a/internal/cmd/server/backup/enable/enable_test.go b/internal/cmd/server/backup/enable/enable_test.go index 83b06f9d5..b4cc1cb77 100644 --- a/internal/cmd/server/backup/enable/enable_test.go +++ b/internal/cmd/server/backup/enable/enable_test.go @@ -14,18 +14,18 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -47,8 +48,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *serverbackup.ApiEnableServiceRequest)) serverbackup.ApiEnableServiceRequest { - request := testClient.EnableService(testCtx, testProjectId, testServerId).EnableServicePayload(serverbackup.EnableServicePayload{}) +func fixtureRequest(mods ...func(request *serverbackup.ApiEnableServiceResourceRequest)) serverbackup.ApiEnableServiceResourceRequest { + request := testClient.EnableServiceResource(testCtx, testProjectId, testServerId, testRegion).EnableServiceResourcePayload(serverbackup.EnableServiceResourcePayload{}) for _, mod := range mods { mod(&request) } @@ -78,21 +79,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -148,7 +149,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest serverbackup.ApiEnableServiceRequest + expectedRequest serverbackup.ApiEnableServiceResourceRequest }{ { description: "base", diff --git a/internal/cmd/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go index 8e90413ae..d7cbfeb6f 100644 --- a/internal/cmd/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -133,7 +133,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiListBackupsRequest { - req := apiClient.ListBackups(ctx, model.ProjectId, model.ServerId) + req := apiClient.ListBackups(ctx, model.ProjectId, model.ServerId, model.Region) return req } diff --git a/internal/cmd/server/backup/list/list_test.go b/internal/cmd/server/backup/list/list_test.go index 087803962..c9f5b9c2e 100644 --- a/internal/cmd/server/backup/list/list_test.go +++ b/internal/cmd/server/backup/list/list_test.go @@ -14,20 +14,20 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -39,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -51,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiListBackupsRequest)) serverbackup.ApiListBackupsRequest { - request := testClient.ListBackups(testCtx, testProjectId, testServerId) + request := testClient.ListBackups(testCtx, testProjectId, testServerId, testRegion) for _, mod := range mods { mod(&request) } @@ -79,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/restore/restore.go b/internal/cmd/server/backup/restore/restore.go index 215d12e9f..67bbff395 100644 --- a/internal/cmd/server/backup/restore/restore.go +++ b/internal/cmd/server/backup/restore/restore.go @@ -122,7 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiRestoreBackupRequest { - req := apiClient.RestoreBackup(ctx, model.ProjectId, model.ServerId, model.BackupId) + req := apiClient.RestoreBackup(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupId) payload := serverbackup.RestoreBackupPayload{ StartServerAfterRestore: &model.StartServerAfterRestore, VolumeIds: &model.BackupVolumeIds, diff --git a/internal/cmd/server/backup/restore/restore_test.go b/internal/cmd/server/backup/restore/restore_test.go index cb0c88bba..c352d56cd 100644 --- a/internal/cmd/server/backup/restore/restore_test.go +++ b/internal/cmd/server/backup/restore/restore_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,6 +20,7 @@ var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testBackupId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +34,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiRestoreBackupRequest)) serverbackup.ApiRestoreBackupRequest { - request := testClient.RestoreBackup(testCtx, testProjectId, testServerId, testBackupId) + request := testClient.RestoreBackup(testCtx, testProjectId, testServerId, testRegion, testBackupId) startServerAfterRestore := false request = request.RestoreBackupPayload(serverbackup.RestoreBackupPayload{StartServerAfterRestore: &startServerAfterRestore}) for _, mod := range mods { @@ -106,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -114,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -122,7 +123,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index db22b2366..716e0d5c0 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -154,7 +154,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) (serverbackup.ApiCreateBackupScheduleRequest, error) { - req := apiClient.CreateBackupSchedule(ctx, model.ProjectId, model.ServerId) + req := apiClient.CreateBackupSchedule(ctx, model.ProjectId, model.ServerId, model.Region) backupProperties := serverbackup.BackupProperties{ Name: &model.BackupName, RetentionPeriod: &model.BackupRetentionPeriod, diff --git a/internal/cmd/server/backup/schedule/create/create_test.go b/internal/cmd/server/backup/schedule/create/create_test.go index fbbb4e08e..00ec85560 100644 --- a/internal/cmd/server/backup/schedule/create/create_test.go +++ b/internal/cmd/server/backup/schedule/create/create_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -24,10 +22,12 @@ var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testVolumeId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, serverIdFlag: testServerId, backupScheduleNameFlag: "example-backup-schedule-name", enabledFlag: "true", @@ -46,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -63,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiCreateBackupScheduleRequest)) serverbackup.ApiCreateBackupScheduleRequest { - request := testClient.CreateBackupSchedule(testCtx, testProjectId, testServerId) + request := testClient.CreateBackupSchedule(testCtx, testProjectId, testServerId, testRegion) request = request.CreateBackupSchedulePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -118,21 +119,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/schedule/delete/delete.go b/internal/cmd/server/backup/schedule/delete/delete.go index add739884..e2dcaa7a0 100644 --- a/internal/cmd/server/backup/schedule/delete/delete.go +++ b/internal/cmd/server/backup/schedule/delete/delete.go @@ -121,6 +121,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDeleteBackupScheduleRequest { - req := apiClient.DeleteBackupSchedule(ctx, model.ProjectId, model.ServerId, model.ScheduleId) + req := apiClient.DeleteBackupSchedule(ctx, model.ProjectId, model.ServerId, model.Region, model.ScheduleId) return req } diff --git a/internal/cmd/server/backup/schedule/delete/delete_test.go b/internal/cmd/server/backup/schedule/delete/delete_test.go index 875f1f2db..7915f1c07 100644 --- a/internal/cmd/server/backup/schedule/delete/delete_test.go +++ b/internal/cmd/server/backup/schedule/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -22,6 +20,7 @@ var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testBackupScheduleId = "5" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,8 +34,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -60,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiDeleteBackupScheduleRequest)) serverbackup.ApiDeleteBackupScheduleRequest { - request := testClient.DeleteBackupSchedule(testCtx, testProjectId, testServerId, testBackupScheduleId) + request := testClient.DeleteBackupSchedule(testCtx, testProjectId, testServerId, testRegion, testBackupScheduleId) for _, mod := range mods { mod(&request) } @@ -104,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/schedule/describe/describe.go b/internal/cmd/server/backup/schedule/describe/describe.go index bd3ca9f71..990032499 100644 --- a/internal/cmd/server/backup/schedule/describe/describe.go +++ b/internal/cmd/server/backup/schedule/describe/describe.go @@ -105,7 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiGetBackupScheduleRequest { - req := apiClient.GetBackupSchedule(ctx, model.ProjectId, model.ServerId, model.BackupScheduleId) + req := apiClient.GetBackupSchedule(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupScheduleId) return req } diff --git a/internal/cmd/server/backup/schedule/describe/describe_test.go b/internal/cmd/server/backup/schedule/describe/describe_test.go index d199f2dd3..f94627dc3 100644 --- a/internal/cmd/server/backup/schedule/describe/describe_test.go +++ b/internal/cmd/server/backup/schedule/describe/describe_test.go @@ -12,8 +12,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -21,6 +19,7 @@ var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testBackupScheduleId = "5" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,8 +33,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -47,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -59,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiGetBackupScheduleRequest)) serverbackup.ApiGetBackupScheduleRequest { - request := testClient.GetBackupSchedule(testCtx, testProjectId, testServerId, testBackupScheduleId) + request := testClient.GetBackupSchedule(testCtx, testProjectId, testServerId, testRegion, testBackupScheduleId) for _, mod := range mods { mod(&request) } @@ -103,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go index a1c60d4bc..2920e9853 100644 --- a/internal/cmd/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -134,7 +134,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiListBackupSchedulesRequest { - req := apiClient.ListBackupSchedules(ctx, model.ProjectId, model.ServerId) + req := apiClient.ListBackupSchedules(ctx, model.ProjectId, model.ServerId, model.Region) return req } diff --git a/internal/cmd/server/backup/schedule/list/list_test.go b/internal/cmd/server/backup/schedule/list/list_test.go index 66bcf4748..6c055bcef 100644 --- a/internal/cmd/server/backup/schedule/list/list_test.go +++ b/internal/cmd/server/backup/schedule/list/list_test.go @@ -14,20 +14,20 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &serverbackup.APIClient{} var testProjectId = uuid.NewString() var testServerId = uuid.NewString() +var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -39,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -51,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiListBackupSchedulesRequest)) serverbackup.ApiListBackupSchedulesRequest { - request := testClient.ListBackupSchedules(testCtx, testProjectId, testServerId) + request := testClient.ListBackupSchedules(testCtx, testProjectId, testServerId, testRegion) for _, mod := range mods { mod(&request) } @@ -79,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/schedule/update/update.go b/internal/cmd/server/backup/schedule/update/update.go index aa9793faa..9885cc2a1 100644 --- a/internal/cmd/server/backup/schedule/update/update.go +++ b/internal/cmd/server/backup/schedule/update/update.go @@ -76,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - currentBackupSchedule, err := apiClient.GetBackupScheduleExecute(ctx, model.ProjectId, model.ServerId, model.BackupScheduleId) + currentBackupSchedule, err := apiClient.GetBackupScheduleExecute(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupScheduleId) if err != nil { p.Debug(print.ErrorLevel, "get current server backup schedule: %v", err) return err @@ -154,7 +154,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient, old serverbackup.BackupSchedule) (serverbackup.ApiUpdateBackupScheduleRequest, error) { - req := apiClient.UpdateBackupSchedule(ctx, model.ProjectId, model.ServerId, model.BackupScheduleId) + req := apiClient.UpdateBackupSchedule(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupScheduleId) if model.BackupName != nil { old.BackupProperties.Name = model.BackupName diff --git a/internal/cmd/server/backup/schedule/update/update_test.go b/internal/cmd/server/backup/schedule/update/update_test.go index c30a67cbd..8b127b235 100644 --- a/internal/cmd/server/backup/schedule/update/update_test.go +++ b/internal/cmd/server/backup/schedule/update/update_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -25,6 +23,7 @@ var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testVolumeId = uuid.NewString() var testBackupScheduleId = "5" +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -38,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, serverIdFlag: testServerId, backupScheduleNameFlag: "example-backup-schedule-name", enabledFlag: "true", @@ -57,6 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, BackupScheduleId: testBackupScheduleId, @@ -111,7 +112,7 @@ func fixturePayload(mods ...func(payload *serverbackup.UpdateBackupSchedulePaylo } func fixtureRequest(mods ...func(request *serverbackup.ApiUpdateBackupScheduleRequest)) serverbackup.ApiUpdateBackupScheduleRequest { - request := testClient.UpdateBackupSchedule(testCtx, testProjectId, testServerId, testBackupScheduleId) + request := testClient.UpdateBackupSchedule(testCtx, testProjectId, testServerId, testRegion, testBackupScheduleId) request = request.UpdateBackupSchedulePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -151,7 +152,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -159,7 +160,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -167,7 +168,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/volume-backup/delete/delete.go b/internal/cmd/server/backup/volume-backup/delete/delete.go index 6653c9718..9e3de47a8 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete.go @@ -113,6 +113,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiDeleteVolumeBackupRequest { - req := apiClient.DeleteVolumeBackup(ctx, model.ProjectId, model.ServerId, model.BackupId, model.VolumeId) + req := apiClient.DeleteVolumeBackup(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupId, model.VolumeId) return req } diff --git a/internal/cmd/server/backup/volume-backup/delete/delete_test.go b/internal/cmd/server/backup/volume-backup/delete/delete_test.go index d7f647c86..59af68770 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete_test.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -23,6 +21,7 @@ var testProjectId = uuid.NewString() var testServerId = uuid.NewString() var testBackupId = uuid.NewString() var testVolumeId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -36,9 +35,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - backupIdFlag: testBackupId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, + backupIdFlag: testBackupId, } for _, mod := range mods { mod(flagValues) @@ -50,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -63,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiDeleteVolumeBackupRequest)) serverbackup.ApiDeleteVolumeBackupRequest { - request := testClient.DeleteVolumeBackup(testCtx, testProjectId, testServerId, testBackupId, testVolumeId) + request := testClient.DeleteVolumeBackup(testCtx, testProjectId, testServerId, testRegion, testBackupId, testVolumeId) for _, mod := range mods { mod(&request) } @@ -107,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -115,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -123,7 +124,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/backup/volume-backup/restore/restore.go b/internal/cmd/server/backup/volume-backup/restore/restore.go index bf76ef7c9..8e0881d1f 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore.go @@ -117,7 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbackup.APIClient) serverbackup.ApiRestoreVolumeBackupRequest { - req := apiClient.RestoreVolumeBackup(ctx, model.ProjectId, model.ServerId, model.BackupId, model.VolumeBackupId) + req := apiClient.RestoreVolumeBackup(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupId, model.VolumeBackupId) payload := serverbackup.RestoreVolumeBackupPayload{ RestoreVolumeId: &model.RestoreVolumeId, } diff --git a/internal/cmd/server/backup/volume-backup/restore/restore_test.go b/internal/cmd/server/backup/volume-backup/restore/restore_test.go index f5ca5b1a1..cb3701baa 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore_test.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -24,6 +22,7 @@ var testServerId = uuid.NewString() var testBackupId = uuid.NewString() var testVolumeBackupId = uuid.NewString() var testRestoreVolumeId = uuid.NewString() +var testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -37,10 +36,11 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - backupIdFlag: testBackupId, - restoreVolumeIdFlag: testRestoreVolumeId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, + backupIdFlag: testBackupId, + restoreVolumeIdFlag: testRestoreVolumeId, } for _, mod := range mods { mod(flagValues) @@ -52,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -66,7 +67,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *serverbackup.ApiRestoreVolumeBackupRequest)) serverbackup.ApiRestoreVolumeBackupRequest { - request := testClient.RestoreVolumeBackup(testCtx, testProjectId, testServerId, testBackupId, testVolumeBackupId) + request := testClient.RestoreVolumeBackup(testCtx, testProjectId, testServerId, testRegion, testBackupId, testVolumeBackupId) request = request.RestoreVolumeBackupPayload(serverbackup.RestoreVolumeBackupPayload{ RestoreVolumeId: &testRestoreVolumeId, }) @@ -113,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -121,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/pkg/services/serverbackup/utils/utils.go b/internal/pkg/services/serverbackup/utils/utils.go index ecc02493e..c6974a414 100644 --- a/internal/pkg/services/serverbackup/utils/utils.go +++ b/internal/pkg/services/serverbackup/utils/utils.go @@ -8,12 +8,12 @@ import ( ) type ServerBackupClient interface { - ListBackupSchedulesExecute(ctx context.Context, projectId, serverId string) (*serverbackup.GetBackupSchedulesResponse, error) - ListBackupsExecute(ctx context.Context, projectId, serverId string) (*serverbackup.GetBackupsListResponse, error) + ListBackupSchedulesExecute(ctx context.Context, projectId, serverId, region string) (*serverbackup.GetBackupSchedulesResponse, error) + ListBackupsExecute(ctx context.Context, projectId, serverId, region string) (*serverbackup.GetBackupsListResponse, error) } -func CanDisableBackupService(ctx context.Context, client ServerBackupClient, projectId, serverId string) (bool, error) { - schedules, err := client.ListBackupSchedulesExecute(ctx, projectId, serverId) +func CanDisableBackupService(ctx context.Context, client ServerBackupClient, projectId, serverId, region string) (bool, error) { + schedules, err := client.ListBackupSchedulesExecute(ctx, projectId, serverId, region) if err != nil { return false, fmt.Errorf("list backup schedules: %w", err) } @@ -21,7 +21,7 @@ func CanDisableBackupService(ctx context.Context, client ServerBackupClient, pro return false, nil } - backups, err := client.ListBackupsExecute(ctx, projectId, serverId) + backups, err := client.ListBackupsExecute(ctx, projectId, serverId, region) if err != nil { return false, fmt.Errorf("list backups: %w", err) } diff --git a/internal/pkg/services/serverbackup/utils/utils_test.go b/internal/pkg/services/serverbackup/utils/utils_test.go index ab8425f54..b9ca14087 100644 --- a/internal/pkg/services/serverbackup/utils/utils_test.go +++ b/internal/pkg/services/serverbackup/utils/utils_test.go @@ -14,6 +14,7 @@ import ( var ( testProjectId = uuid.NewString() testServerId = uuid.NewString() + testRegion = "eu01" ) type serverbackupClientMocked struct { @@ -23,14 +24,14 @@ type serverbackupClientMocked struct { listBackupsResp *serverbackup.GetBackupsListResponse } -func (m *serverbackupClientMocked) ListBackupSchedulesExecute(_ context.Context, _, _ string) (*serverbackup.GetBackupSchedulesResponse, error) { +func (m *serverbackupClientMocked) ListBackupSchedulesExecute(_ context.Context, _, _, _ string) (*serverbackup.GetBackupSchedulesResponse, error) { if m.listBackupSchedulesFails { return nil, fmt.Errorf("could not list backup schedules") } return m.listBackupSchedulesResp, nil } -func (m *serverbackupClientMocked) ListBackupsExecute(_ context.Context, _, _ string) (*serverbackup.GetBackupsListResponse, error) { +func (m *serverbackupClientMocked) ListBackupsExecute(_ context.Context, _, _, _ string) (*serverbackup.GetBackupsListResponse, error) { if m.listBackupsFails { return nil, fmt.Errorf("could not list backups") } @@ -126,7 +127,7 @@ func TestCanDisableBackupService(t *testing.T) { listBackupSchedulesResp: tt.listBackupSchedules, } - output, err := CanDisableBackupService(context.Background(), client, testProjectId, testServerId) + output, err := CanDisableBackupService(context.Background(), client, testProjectId, testServerId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") From a6439d2ba3e995c3225a1e8a38b0940e3901524a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 27 Mar 2025 16:15:49 +0100 Subject: [PATCH 239/619] fix(auth): print token to stdout on get-access-token cmd (#669) relates to STACKITCLI-175 / #653 --- internal/cmd/auth/get-access-token/get_access_token.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index cbaa82eb6..85fc9247c 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -42,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return &cliErr.AccessTokenExpiredError{} } - p.Info("%s\n", accessToken) + p.Outputf("%s\n", accessToken) return nil }, } From 67b3b74990d5350371e6932faca8828ad1fdc0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 27 Mar 2025 16:35:48 +0100 Subject: [PATCH 240/619] chore: update stackit logo in README.md (#670) --- .github/images/stackit-logo.png | Bin 10416 -> 0 bytes .github/images/stackit-logo.svg | 43 ++++++++++++++++++++++++++++++++ README.md | 2 +- 3 files changed, 44 insertions(+), 1 deletion(-) delete mode 100644 .github/images/stackit-logo.png create mode 100644 .github/images/stackit-logo.svg diff --git a/.github/images/stackit-logo.png b/.github/images/stackit-logo.png deleted file mode 100644 index de09c4245c51cbf0c5e855bbb84b9613d9d7bb53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10416 zcmY*v>Ng~(o6$5^5w89Uh`m3@mDLt_akODGg!Mz&#u3h6PnDN9)* zW3rn;vhS4L?~dpBeqZ0;A6{N}?&qF+&pGdV?!D){V@-^&9X%p=1OkB^HMp*427xeQ zAP_nxR%Y-^Zk%i<_{ZjV{Z;@3B6pVdM~5oVLP8*CAO?Cm7O1R+5uF#@)*qRvfln^W zAtAm@o28IidOV9@)D?EWjU)DsIulIiIb4nkS~=P1m|sw+ioEvhGF5;4to>a>e64k{ z+5OR__#(gPXm*3^#kJv>fW;uJR(RPbk&3PHo*PGpKRU_^^FbgH-?m4!7WUFR`QRn^ z?Skm3BY{YB%QPw*1d{$Xd=povqQ$cceY6Nem4c6@xS=B=MDFhOG6XvW(iqK(Sxlm` zxtXmnLLf%3sWYcLe#f&|T54i;xtYw0QS=aq#LeYEEej30n|*WSRr5J3AcXBWbR-EU z4mCIvtE>TmIIS|m|6Xb4?#}Pz1d~FEq&<@r#!LT>ULtg1wRWswxdZ5xB0OG8a)Z^d>d!|~XErUMbT@x%&_N*jTu@<3 zO0kyCnGBk0w9cpZ*B*OF=FHr$vpoVl6CuWmNo+?;<`_%^Wq7VE2ii+xA|#@k=^znz zK-Z1s|JD>Iic)_8mXm|Wx2B*UG>S69ArNgvFn8V{n_G=z`AZSIYM{AMDs=|MagyaV z&>k${I8-<(4oF|7N!MQvghoo{d`kol*EX%++1;uLU%_<#j=yGUxu;ev$t2`eXB#$U z3BEPV9iLI98PK}a4nRi2csWprHWV!hf#j%0;wIkZ33uPE=Y~K`goq@6XvTO7J!kGX zP02)Rv1`SaE-=ssM_DG?D*YMZd)&Y#OLo;j7LWFFuhv?2gv44lO@B7bHg25Ft>-=q z=rUODZD=)rsM|<9RPQ+>T=R7&-{5>i;oOGD)_cSSAdL=4I{~EOX~XY;;rHsfyU)?Q z9w&~PeFcE=Ax{{r>+KROe1HCS0}FtjsikFj;(jco&bIs|C0HLA7vN+ziRK7A4O7}W zKNn5g9nCMERuv@U#px@ANdh361%44*g+DgNHCh(PZ6jh40qYpvQ zeFoK*N9J?`K88Rpv0_dDfYNri5IKr@G0Fe1jVuz;G z$7--*R`+TgW#wD9sX$P~C235LdsVwDGuZAB9=+vMC*|8vJbu>e(lHc@hBk-^7tvhM z8@V+*)-LkjpukAnrNMcc)=;#K z+D|}+wn*A1d7X=pIkFketq`8;%e~K(3FswYTAD^*fIQQcRCv{4ry=N!!=Vr3j`kZy zcn}D#NqD^a&;hO=#5vk{01FkMpU=;d$=3HU6!?h>)F8N5w1fBsT1O;MHJL!h;5=yL zIDsxrfo%pM1>QsJC=f}f!M?6K#18No*rGcbOR4`?LrzK5AiUWeMh3u#n5Ys-VE_p< zltIpCQQe>X7rus;3K(bs4w3`BHe#V6>{Mrq|JP`2801A8C}rn8%#XGNEn5HoSd10( z#{_6gi)0X1%*TxX)O)};!hdKkRt&Nm7#sxFFrj}9zI_%oXuO;XVl^1D{Fv&lv6j8+ zUcmrb^;}TzzjxN7Y?#50ptgT4 zwF#_UI4*^y?NA8y0?~YE;-_q&_`kBYM{lfD1HAw1x)Nap!+#@Ck~;LyvHJsb95=i; z*K;PKwksWF9c1n)ouC{%5!?$l`K%_gw{;G+{gNtmXn`CV|L0@wl~#RP$IKlgK+rju z!sGEtrZZc{XPEr#flwWx3T#X6`~Bb-Yp+`TYvWwDaH@&n2`>Mb#JvyB*tzv}d4lox zc0GXAtDmJpq=!UOHBe#dMvZ70EUS7kCw|-G*Nt+X(5KC9!Mo78nLbz|)-^Nb6_`uj zX|z|%+~(8pk!jV$AnC^qmow$%>{J$iKfE(O-oJM#aYReVU8v=EP?$sIweuTc0nW~K zw)O6Nx3l!V|LqB>GEyspToXG~21_kouz!tN2(_=W*qDrj(65Z5 z(rgNLJ?BnR&oRP9Lo`zcWjA9|rj*m@w`#FpPd*||YQD_&T~j#u1Ho!3Z{vvfc~s{( zPY8Gtz$aBW#>jWXOfw!!nMikJF)5eWg)8a3iuJ7WBpWLTMdBKYk!?W}aT8WJ`}M?Z zCiQRQ^q))U!v56D*nqg`@GVFxBC_;BB#xa(`UGMVpTMKf#omcC@)LV1zuSJAK8^c| zy5GljJNefdM$DiiW-EaD$ak-QAMDR1v2zUj+q*y0Znz4R zH(#MtPgt-RS8U~SdWMPkw-RqzeB4*dly_7s6S4F_40!SdJJ~S8!$~L8x*pYa#`@KJ zu5nM}VLz~)d?HtsgWAOvnmih_9-T8r?Ie=!+)6RD7{flfJovC-}LD zBub_JBsa8*O=+zdnVXW%wmNoQLwMv#$UcdM_f)D3GqZ@2p6&7_djID+u-m&`O|Ez! z`l5D}Z$Jd=ikW;*tsfnC%(dlwS^TlcNadwsbfnQDPk_$;SFbLC7wVTD@^!Ho28K}s zVDVO(%pT`TyF*J#{Ir^wPOR1$?P9_k9Azn$K1{~n{Z<-S*;d`-2Yuf1@?Sag^=>(< zdl==f>($>fNW+l3ET@n3Uc1o|-#?3?i}grT`HM0RB#jA;6E$I&CyISb)%`Y~w;n{Y zE|}p(eJ!*<`>|p6$3665qB>C}c25*JUW6ucsn;b*6OvZeoQKBGNV|wMJ&x;yQ{rFo z3CJ=j*d8}pUs1yc@jraGP|@zL$2(YZ*0Nx<$$#g|@6GI*68lObxpn1Qb>d7b{wqGn zrNq@PyWIN5RHtxL1AJC{uyZtry_+^r}L%Xo9G8Sr)AUrC$%jNu7}&%w7HG0ZHO( zN1r-d^z2gdROh3y?{jWJ)AxuX?5{%TR%WeOH^kQPTh!lXO>>vN`rTE&9a!dNs;}l2 z`u%;*-8Np2Z8*mAt~j7-M^dL}RKDG$C`wB6K7 zWU4d#!2Ps)#sN;(x%26|Ur#^>N}f#YYiE5UCq`ARtf?CPu}%u9n$L?2iZi?Yic+cY zd3k_reBF=L+w`da_~l9O$fV9#23f@m=cbN?XtMmmZFmHSVdH;cPX+7K@M`$)xB#mU^x zs)45poRN}iD9$&7#hp7+lxNKIW9Y>x))wDC3hD%%-ob&*FwHMjdqLvyf-5ixLw8R-=bP0 znz*nLOeudTCwHmt^dPi>E;ysVW%K9PWBf_EQIg)KEZjVmYGa*KzaIHEDXJs>n1-%~ z!zvXdPj*c`o5fuqoH8vcyVC3{-(59yv`h4jdFUf*cq{C#M&iP&29Qn>1|Z4886_!e%_HZOzhW6QzrS; z**faYWuFPGwvHX4Zx}qz)iSeVb}&+@FYGnM<~(E3J-HT^D>bX^E6_C*%yqX!H&tLr_N>WD$#nXJ*_qYwJzRDP>|-b@n$ zA*8K(&G0UfF=H#5SxDE9je(E%qC+)h>4Y?*G*_{AOZ)wtjp20@!uS5-ga_xU`vq3$ zCamv*^JZ27&;HR2+yRpf%-eh{jITOx)-Y>ZJ0Rc2ttHR>6!t!r*PMh_3;6JziOK6C zxUZa$-*32_BV72VH%?Mi2S#Q(DzN6Z`H~td(dw4|vP{-jDvis5FE0{jE zW5&1lk>HAb6|DT@9bg-FdClE<$w1)_-03-g5yy*_z5B zOFX7W-znX8;cmKyoqoG#+fK0$q0@bhks1GqYGBt3?$_S57gx@NN#c}(mqW?@2fsfB zI;0=b>nX63t5ab}^}e%^CMdSm@wqA0W+h*J5;BIwA&eGh#WH)!zgK73bieTbEQN}6 zp0!W<#<{>goN;)PFeF?;=nkV9_}YUcpx)Ae3Z)pdRF%3%@?iu*H4QF1I+M?ZK@XMDzA6@kT)%0$0jBseXmT6`;gkWdJ2_FagO z{u-C++s{@blvpumuvP@{;G3RR^8ZP?Dhvx%@Do~e=%X9mnEyH|r>kfAu+Qc3E%;D@ zy~&(yWfv!mnY$4aj(d zTgaM&cQM5DH~+#rhbUZYA`7LhU!nQ0>g{GGOlmeJyy6>2s{S%#aOJ>cMa4NaIZh$N z+gPrHTU}TM3R7aCCt{qeD5tG=eWYr{xT?AOg@MFORhK<*;N z@`Zl;2x)q5mEew%?iyzJv5SN4g))=1EnuNduG3S|))S>8TyKmbC9m@Y zh? zs@5x;mTig1`qpBtzprAKGH*;pn8*>i^FcDA3oRK^;V3)j@fdp|hAn929FkZvv@9oM z_$DRw-5*#at}MJY;}-l@G|S`ocWMP8Gkd_z#fkJ1SC<)Qz?H9Z;719_21&zGLYH3J z__7@=r85*9J@#jA@WY=!u$Uv)2o8P7;qfR*It>BG0!|)~4Ffqx#u*H%^8+~YgAg>-L4fqiy=Bj7XZ>+2wpH+Tt*@Fz>_C zILOtNr`5k9Oz$0KCfcd{yT!$a*Cwb(3;ZbZ-S;cU$5!3B`-keoh$GR1+VsOLVv zlq88YCrslr*DC(F_N^u*_m%9;+KB+D{dnV zG0VF=wkuq8z4{!Y!G|=1%UpAGA6VUb&4Zy(_b^mhm8q8|pt)pfl0v0G9mh0~M{(wkbeE?5q`p+$U5- z$qu||^+RIq-NY9y_e_T?eXXnc-5>i?m)wcmxAiqVJ=(K%CO{^SJ1|dE0_1kC%F`EZ zt1i31c}+e`wn*Q5q?Z5kbt>1}rmjM2tk*`+-Ig4G*&vWM1OpC}K@u(?2STuuL@P_>(qn^6C?WyT=C2MCamGcp4JC|}<9br^ZR zB{ZkMd!a&(KQ>jE5_5^-epa00M(HR&p?Aq6P1-9(-EDWptN#2#1+)GMC~+jqev%OP zCPm?ve_A!nxb{0bF^S#&my*))MA+PB5#^Y_dF2`9GzITuj$G|Cd|Lqy8H>%-&1_lJoeNPd zkGvV-ek$O`N#xd#GlrlFO~|PW^n=9o9p&u?khY??PZk5zE6hl2+Q7caQ&cp;Vsj7#6>Q`gAbO!b5=yH z4e42cdSPY1g>yzj!YYrQ=Hwb9l?yZw-%7@upA1#|<$I6 zGBldU@GCm)IJdU0-RIEAxC%m{$)>+E`&cj4gdnUTaEa54 z6->e22=bwEeC)%$DQ=c<4uiHGe-5(oDX9gdcvWNJ{wY{BFD&T#-Y(SKfQ57x6)8M^ z#I>)awlZUhG2GxNCd=<4>+$n}J{5N5FI|pc%uahMI{R6?t@9pvj~xh{zuT>90u+%a z8*lmK_Atb~dY>FH?|lAy-bO*Z;$!1tZ2OZR4{YLk^$#B7B^RB#Re6k;840&`X=+dm zZ>0t~On-S_5H0KS*2H9^Qs1J?p?Yax#)!yHcf8a-#>oW*BF&YO*OyvHF}UO7w*1X@>1YAlV(MM{3spOZR!iTq~# zwm$FGzSc0Se(FK*K%nanW2T*aD@{$Qx1GEapyFlM|9#iVb|FW0!%#lUtc~8k!;)=q z;p0=2MZ^xKE)2Qf1j~qOxs5N3TG`o8c6FLQ#a)PlQV?11=oNI2pAH-$Z>XP4$+PIX z2#QB4!mcIcp;|5JqR98KuJF+sM8m7Aynau%LpQ{nF=Jm?KbLAaH+_i0P468PAXrR5 zVF5DnM{Mi|?&IB~KQf~uCedPDTgHe+WpHFm#=sGtz0Dz2GUJ!U976p+ge6&6Zan;a zV1G<7yue$yWiHuDqoA@;8Klr#WW`Z}lW1H_sui&Z=}Wji%-rzDS2k##JF2Dp&+ci(|6sYewJHpu@dT(tc>j%PN&-r!O1U2N0~QP`zUF_{dJv z)}2|%!>AVLd`>ou*X3iE2CCRU-l(y0No2xtvDc&q!_3_(hOV<27{0Cf8vK1j0a<|= zuizy|qc2pYt#u^(^W)x94JgX*qLelI<-}2j*$?SL4Q}x_WSeOVYOEnjXVosq>OGxJ z?e$*v)Os~~n)lHn!A+|&rbgUW%{(d}TbHN+`-c|}n{QN(lnhaM{$V>+AK!HxtT^DF zAr1UwHF2x*UzNk;F!{^q8eVnHM2~D0+va*+jWdOgex?R2XH!l=!4B|pA$BPCO3vnG z^PWgMe#|at{=Tu`Uyu-h#x?s}n{!~yFr>8}`sgC#Z%32k*s;0NQ!Wz$8{LXwAPhN= zgOXS1Ke1L!(>FULZK*~35C#qh~{m)ia8v*k|Dflx>}U&Yy@P($EZU1&dT!- z0pH4V{V3Lk_DyVx|LT8Vi->~^uB4gV2I)ua}0-tQI4y7L#^MFUR-pu zZx>F`d$4>dQ@(P5Zs@!)PUXj+3U9hi)z3I0_FZehbxoXU!n z4U7J$!luM)RGrR7Px%XBdp-HEdD~*c6+g3w_Iw;RsylQhy6R#SIMsmdhZ~ipG1L0? zY~dAC9xJ!9-W@|;_k1$-uJf6)hOu6i`P0J()42@KI#67(qHzI`7e081>qg=-zOZz2$t*2e}TGhlj8*P&z9-gxZj(Ko~U5#2K_mUhOXumFb(YqQE4pqz0!(S6aL za>x8RjwKpy*+DER!OFEN?MT5?HUbXB-+!o@!Rf-xv+r>VigZ3?F-+ruHnXT#Mf0S? zypcjOCw&`S_c0-3tF2NDMVk*Z?OcNpQnizM78;kETonsO%BDTyF`sc2to|_0%MpVX zsvt*`wBmsH`no8rbYE>H*!_uun~;P=)i@}OJDu`IuD?lo+_C_fb+mPwJ^8#}a3`tb z0>xUfkABfoX3^X>+AsuL80{rBHgZmXbNve)L#xVby54Vg%d_!f{s{;CNekWa%ZQv+ zivp4l^RqAO`OI)o)bzH1`oBA0ez4M5^7|A#muZOvDkH%OR_S(+NKcynG!FR~Vvc|L zR#5x5?5zEHU5ng6&6C*!f(LU>e{h=7aB?YRwyXd8cyp+gj(-2T5*aCYHOf8d%+M(FZcllqnZ!j|Zz1yziv6i811irX^kcgcF53~0Jm&^7?L>?IL zo^1>fWdD=(vZj!ooy+*E4|1o@fHkd4Hl)D{?Uy z@6G-7>v{TN;M9t7!u|8qW4vrO!xJ$V;!(xpcefZM@g#GKlP+W~TM9QdiBWID$G*4R zl8LUDi2((dJ?vk9N&4)zHl z+5C4Ldx=vE;o;PEbr!gPWX}{Ii^5Uk{Aq_Qg)n!-)3^ec0U6cAx@EVJg*Fw*mu3rr zmUr$sYDP&)ixV&h^$OHYU&Oo9W2BO^r(Lk~+at$~vIl*YlT`clEqIW7Lco`NS`UxL zoV(YO;z7fSuF%csiwE=WizJiYH|8sAPOAT;>fid77A(~@GF9`Y{^>iQ%+IRuoAat+ zuWAH$TemfgrUTPy8yXxM&VZ=!_t6mkJbyb zN-gf9D{s8Sn*GUogZG!)(595XBFfO$MR9yqMUv01$Ft%_irLD&vJPP%;Z_`%wgcrz zR>uSN+)d7#rRaTe=5_|jpHirvv+VOuqMZi4S3JSlmB*SBQ{(qfqBJfb{y6iwd)Ix% zQQKmZmr?ws3BzxWYdNMp#-5B0rkRL1}_k8!yk6bqzjb$-Y-9VZ8PBiG}Em$SlsJQQSRj3 zxu0tqsZelZ=M>lX44T7cksZ&DtcelPbpp|cH9;-y3Fqv z-iZ@hLSr`d{@iK9OUehl7LfIc?;wBl=b*2K;rz(Z`DaglJS~|{y0fxMwYsnsC2S3! z^K-Arv##UXs=SqIlMKnaI$`5@x#l90$-Fvg3hN_GnmY)S3I2OE!e#CRl+50KP`L;( z{OhS{QnAiQV;PLpaPXR!oG&A*(=rfDh_k#qhceV5apa zpo&4>HUFf#|I4Isp5x33q>+Rm(_Wtc4yVng?MjH0^hP!+BP#(BAm<|Bl?{Yc@zBU7 z-2-J*gOdLtc0vBQF@aUkxI?al1HK%SLuy5GJ}(qd2#{Q~0m*mm4h6T+Xi< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 5cda470a5..d3d51cf1b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

-STACKIT logo +STACKIT logo

From 94734594bb84e113b882682bb889d2d924f9f0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 28 Mar 2025 08:18:35 +0100 Subject: [PATCH 241/619] chore(doc): update installation docs (#668) relates to #115 --- INSTALLATION.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/INSTALLATION.md b/INSTALLATION.md index 565eab7dd..72d06b8ec 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -68,6 +68,28 @@ sudo apt-get install stackit > If you can't install the `stackit` package due to an expired key, please go back to step `1` to import the latest public key. +#### Nix / NixOS + +The STACKIT CLI is available as a [Nix package](https://search.nixos.org/packages?channel=unstable&show=stackit-cli), and can be used via: + +```shell +nix-shell -p stackit-cli +``` + +#### Eget + +The STACKIT CLI binaries are available via our [GitHub releases](https://github.com/stackitcloud/stackit-cli/releases), you can install them from there using [Eget](https://github.com/zyedidia/eget). + +```toml +# ~/.eget.toml +["stackitcloud/stackit-cli"] +asset_filters=["stackit-cli_", "_linux_amd64.tar.gz"] +``` + +```shell +eget stackitcloud/stackit-cli +``` + #### Any distribution Alternatively, you can install via [Homebrew](https://brew.sh/) or refer to one of the installation methods below. From c02a31696902410d2d63c26173b07107497df36e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 28 Mar 2025 09:53:54 +0100 Subject: [PATCH 242/619] fix(deps): update module github.com/spf13/viper to v1.20.1 (#665) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c8290fe05..b91df94c3 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 - github.com/spf13/viper v1.20.0 + github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.16.2 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 diff --git a/go.sum b/go.sum index 9481a8d99..f6372fabb 100644 --- a/go.sum +++ b/go.sum @@ -109,8 +109,8 @@ github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= -github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= +github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stackitcloud/stackit-sdk-go/core v0.16.2 h1:F8A4P/LLlQSbz0S0+G3m8rb3BUOK6EcR/CKx5UQY5jQ= github.com/stackitcloud/stackit-sdk-go/core v0.16.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I= From 0e0737a5b5ed44fddb32373b4e15467326bbb9f0 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 28 Mar 2025 09:54:28 +0100 Subject: [PATCH 243/619] fix(deps): update stackit sdk modules (#672) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index b91df94c3..b9b32e277 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 @@ -80,7 +80,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.1 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index f6372fabb..a43e01302 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 h1:n6xMTHrLV github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1/go.mod h1:R+fHrtGfy+zx+d5s31cBh09P3TG58dyytb83gB7ldi0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 h1:yyN3Q4i+5bmUVySPbQC7sSKG6sK21V8AxMjvhfJe2r0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1/go.mod h1:c5/LHxZZ7qZYOboR01qOw1Mqq5v/VNyONw7WPHctNeY= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.1 h1:V6vvH++exqeqzD7TtzLc86ZRFrbcmxlaQqBJewiUXrE= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.3.1/go.mod h1:/GFUX/OiR2/SsWh3Vsu7UnY6QLJzsbHwrcxiRBxmYOA= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0 h1:CPa/SRuX1Gl810K0SearSFyH0k/xKF9JHUV+4j+Tcn4= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0/go.mod h1:/go4bZ76dxGfkvl48EYUmPZ41c+64Yrf/26RodfcFyw= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.1 h1:Bag2KZMwHJhlz2iy5Sy4ANTwPSR/ArGXcF13tbC3O+M= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.1/go.mod h1:F1WyCyjAuzq3YI+YPJxj4AXrmpWXtxjFxGhwo9RIYy4= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 h1:S6uamk6ecVy8K3jE2mgU50h14GoGE0LRVmiK3TvgfTc= @@ -147,8 +147,8 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 h1:SZoWUD github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2/go.mod h1:PrD0nNG94Dd5D9pu7HJ0bAg8ccDz6/7KaIts7K9p7as= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 h1:qujhShugc1290NQlPoNqsembqzot8aTToAdSsJg5WrM= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1/go.mod h1:e1fsQL24gTPXcMWptuslNscawmXv/PLUAFuw+sOofbc= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0 h1:a8logPoRcMCgwa9rCtuzWF6DLiuCIdJgcacZKThFsks= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.0/go.mod h1:zDdYYQVHGlju9cnMISX/Ty73Yh/qYcZGcJSOYWRZCbw= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.1 h1:oYOKoID+PMTb9qX5LyXmr7qk3VNv1qxDhZBxUZcokvM= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.1/go.mod h1:AoQFbTh8pejhIRyvpX8Jm2FHHwen8My85OYA910FIy0= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 h1:VKgxgjsbaUVMCnntq+MLQ/c1Emn5crVr11B3gJnyHN4= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1/go.mod h1:vn6xmMRxYgEoBhYEy6i2SY2qbeDKjs4IVNdnQHcQpBc= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 h1:7yY68QuntatwRG6ri65FlfeewACChLVbLp67wHCS8Go= From 1707cb35f08d800ec12ff6aacaa11d89302f939f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 28 Mar 2025 10:56:32 +0100 Subject: [PATCH 244/619] chore(github): add pull request template (#671) relates to STACKITTPR-138 --- .github/pull_request_template.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..088dfb4c4 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,18 @@ +## Description + + + +relates to #1234 + +## Checklist + +- [ ] Issue was linked above +- [ ] Code format was applied: `make fmt` +- [ ] Examples were added / adjusted (see e.g. [here](https://github.com/stackitcloud/stackit-cli/blob/ef291d1683ca5b0d719ec0a26ecb999a32685117/internal/cmd/ske/cluster/create/create.go#L49-L63)) +- [ ] Docs are up-to-date: `make generate-docs` +- [ ] Unit tests got implemented or updated +- [x] Unit tests are passing: `make test` (will be checked by CI) +- [x] No linter issues: `make lint` (will be checked by CI) From 307787da6f73f8f07d6d8b3cac311fa03fbe1fe1 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 28 Mar 2025 13:31:40 +0100 Subject: [PATCH 245/619] fix(server): List also delete_on_termination (#673) Signed-off-by: Alexander Dahmen --- internal/cmd/server/describe/describe.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/cmd/server/describe/describe.go b/internal/cmd/server/describe/describe.go index 0e3e5dae4..d45086fb2 100644 --- a/internal/cmd/server/describe/describe.go +++ b/internal/cmd/server/describe/describe.go @@ -141,6 +141,8 @@ func outputResult(p *print.Printer, outputFormat string, server *iaas.Server) er if server.BootVolume != nil && server.BootVolume.Id != nil { table.AddRow("BOOT VOLUME", *server.BootVolume.Id) table.AddSeparator() + table.AddRow("DELETE ON TERMINATION", utils.PtrString(server.BootVolume.DeleteOnTermination)) + table.AddSeparator() } table.AddRow("POWER STATUS", utils.PtrString(server.PowerStatus)) table.AddSeparator() From 9203566c703e187e42a761a0fbb2ee8073addc31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 28 Mar 2025 13:51:02 +0100 Subject: [PATCH 246/619] chore(github): add issue templates (#675) relates to STACKITTPR-138 --- .github/ISSUE_TEMPLATE/bug_report.md | 35 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 25 ++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..b9edca504 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,35 @@ +--- +name: Bug report +about: Report a bug in the STACKIT CLI +title: '' +labels: bug +assignees: '' + +--- + +## Description + +*Please add a clear and concise description of what the bug is.* + +## Steps to reproduce + + +1. Run `stackit ...` +2. Run `stackit ...` +3. ... + +## Actual behavior + +*Please describe the current behavior of the STACKIT CLI. Don't forget to add detailed information like error messages.* + +## Expected behavior + +*Please describe the behavior which you would expect from the STACKIT CLI in that case.* + +## Environment + - OS: + - Version of STACKIT CLI (see `stackit --version`): `vX.X.X` + +**Additional information** + +*Feel free to add any additional information here.* diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..0eb26f937 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,25 @@ +--- +name: Feature request +about: Suggest an idea for the STACKIT CLI +title: '' +labels: enhancement +assignees: '' + +--- + +## Problem description + +*Is your feature request related to a problem? If so, please give us a clear and concise description of what the problem is. +Example: I'm always frustrated when [...]* + +## Proposed solution + +*A clear and concise description of what you want to happen.* + +## Alternative solutions (optional) + +*A clear and concise description of any alternative solutions or features you've considered. (optional)* + +## Additional information + +*Feel free to add any additional information here.* From 02c2168de021f4ba2a5650861e6bba8da734a66d Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 1 Apr 2025 10:06:01 +0200 Subject: [PATCH 247/619] fix(deps): update module github.com/goccy/go-yaml to v1.17.1 (#678) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b9b32e277..8cb68111a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.16.0 + github.com/goccy/go-yaml v1.17.1 github.com/golang-jwt/jwt/v5 v5.2.2 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index a43e01302..cf49635c4 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogB github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/goccy/go-yaml v1.16.0 h1:d7m1G7A0t+logajVtklHfDYJs2Et9g3gHwdBNNFou0w= -github.com/goccy/go-yaml v1.16.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY= +github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= From 92c7c213411fed8f7b373b414b1c1d9a77c16351 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 2 Apr 2025 11:22:37 +0200 Subject: [PATCH 248/619] fix(deps): update module golang.org/x/term to v0.30.0 (#643) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update module golang.org/x/term to v0.30.0 * fix: removed toolchain option that confuses snyk --------- Co-authored-by: Renovate Bot Co-authored-by: Rüdiger Schmitz <152157960+bahkauv70@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 8cb68111a..1214a0d5e 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.23.0 golang.org/x/oauth2 v0.26.0 - golang.org/x/term v0.29.0 + golang.org/x/term v0.30.0 golang.org/x/text v0.22.0 k8s.io/apimachinery v0.31.3 k8s.io/client-go v0.31.3 @@ -85,7 +85,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect + golang.org/x/sys v0.31.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.31.3 // indirect diff --git a/go.sum b/go.sum index cf49635c4..e27f02ae6 100644 --- a/go.sum +++ b/go.sum @@ -195,10 +195,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= From 2ad04aff4c76b89c380a9ffd8f246868f31f1b08 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 2 Apr 2025 11:23:00 +0200 Subject: [PATCH 249/619] fix(deps): update module golang.org/x/mod to v0.24.0 (#642) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update module golang.org/x/mod to v0.24.0 * fix: removed toolchain option that confuses snyk --------- Co-authored-by: Renovate Bot Co-authored-by: Rüdiger Schmitz <152157960+bahkauv70@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1214a0d5e..996565e9c 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.23.0 + golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.26.0 golang.org/x/term v0.30.0 golang.org/x/text v0.22.0 diff --git a/go.sum b/go.sum index e27f02ae6..65a794479 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From d44776d41968e831fcbb83f2f504cc2900ee3547 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 2 Apr 2025 11:31:54 +0200 Subject: [PATCH 250/619] fix(deps): update module golang.org/x/text to v0.23.0 (#644) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update module golang.org/x/text to v0.23.0 * fix: removed toolchain option that confuses snyk --------- Co-authored-by: Renovate Bot Co-authored-by: Rüdiger Schmitz <152157960+bahkauv70@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 996565e9c..46c4c20eb 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.26.0 golang.org/x/term v0.30.0 - golang.org/x/text v0.22.0 + golang.org/x/text v0.23.0 k8s.io/apimachinery v0.31.3 k8s.io/client-go v0.31.3 ) diff --git a/go.sum b/go.sum index 65a794479..7ff923e53 100644 --- a/go.sum +++ b/go.sum @@ -201,8 +201,8 @@ golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From c3bb29a5ce01bcbcf78aa84f62d3d28b719fa23e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 2 Apr 2025 11:33:09 +0200 Subject: [PATCH 251/619] fix(deps): update module golang.org/x/oauth2 to v0.28.0 (#632) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update module golang.org/x/oauth2 to v0.28.0 * fix: removed toolchain option that confuses snyk --------- Co-authored-by: Renovate Bot Co-authored-by: Rüdiger Schmitz <152157960+bahkauv70@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 46c4c20eb..4aabb2c5c 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 - golang.org/x/oauth2 v0.26.0 + golang.org/x/oauth2 v0.28.0 golang.org/x/term v0.30.0 golang.org/x/text v0.23.0 k8s.io/apimachinery v0.31.3 diff --git a/go.sum b/go.sum index 7ff923e53..f221d3148 100644 --- a/go.sum +++ b/go.sum @@ -186,8 +186,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= -golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From d6e10437d700e1f4c2aae95dfeb1839ffd4ee719 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 2 Apr 2025 14:59:37 +0200 Subject: [PATCH 252/619] fix(deps): update kubernetes packages to v0.32.3 (#677) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): update kubernetes packages to v0.32.3 * fix: removed toolchain option that confuses snyk --------- Co-authored-by: Renovate Bot Co-authored-by: Rüdiger Schmitz <152157960+bahkauv70@users.noreply.github.com> --- go.mod | 15 +++++++-------- go.sum | 45 ++++++++++++++++++++++----------------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index 4aabb2c5c..99d9326bf 100644 --- a/go.mod +++ b/go.mod @@ -36,8 +36,8 @@ require ( golang.org/x/oauth2 v0.28.0 golang.org/x/term v0.30.0 golang.org/x/text v0.23.0 - k8s.io/apimachinery v0.31.3 - k8s.io/client-go v0.31.3 + k8s.io/apimachinery v0.32.3 + k8s.io/client-go v0.32.3 ) require ( @@ -51,6 +51,7 @@ require ( github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/x448/float16 v0.8.4 // indirect ) @@ -63,7 +64,6 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/imdario/mergo v0.3.6 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect @@ -86,12 +86,11 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.31.3 // indirect + k8s.io/api v0.32.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index f221d3148..ead8384a8 100644 --- a/go.sum +++ b/go.sum @@ -20,12 +20,12 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY= @@ -50,8 +50,6 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= @@ -87,6 +85,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -218,28 +218,27 @@ google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojt gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= -k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= -k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= -k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= -k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= +k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= +k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= +k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= +k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= +k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From 7a56938e380e1636aa3cbf324507a19ff28826d7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 3 Apr 2025 08:21:42 +0200 Subject: [PATCH 253/619] fix(deps): update stackit sdk modules (#680) * fix(deps): update stackit sdk modules * Remove toolchain Signed-off-by: Alexander Dahmen --------- Signed-off-by: Alexander Dahmen Co-authored-by: Renovate Bot Co-authored-by: Alexander Dahmen --- go.mod | 12 ++++++------ go.sum | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 99d9326bf..87cdcd033 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/stackitcloud/stackit-cli -go 1.23 +go 1.23.0 require ( github.com/fatih/color v1.18.0 @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.1 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 @@ -77,12 +77,12 @@ require ( github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.1 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.1 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.2 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.2 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.1 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.1 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.2 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.2 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.31.0 // indirect diff --git a/go.sum b/go.sum index ead8384a8..3975dcb2f 100644 --- a/go.sum +++ b/go.sum @@ -121,24 +121,24 @@ github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 h1:xaNory8kBIsBG7PJ github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0/go.mod h1:LVOYlzNt5BXDC42AHd/GZj6KvlCg4w94of/E6pZOj5k= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 h1:4Kz9MH9VVuXYnnWFjJcPFVBiPtCUnSrHfsyUzBWwhKc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1/go.mod h1:x0jgrL+/K2cE4BvcIQByFUf0nOPVZRqq5Z074kjjr64= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.1 h1:LwZlY0cANz2HR6U7I6hR+kFShmTKlTPNxBp1XHDoUzE= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.1/go.mod h1:aSdF3zcNoudRx5AzHqGVQVN7Cq05OseCQFyDa7P2cC8= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.1 h1:gAFstHEqncA6nFIrXKHrF1HDNF5jqhB1gzW/lNHAevI= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.1/go.mod h1:kUOByn2sB5KSIiz8Bx3XOLF3z7B8JtqP2nhH+Cr2W7o= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.2 h1:VW9/SH1hS0RwgW1UEGSG1NDSE15KRL2eh3ld34svYr4= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.2/go.mod h1:Lb1emAS4KI+pWDXQlbmST058wTsWyD8vLmdsJpRjfEg= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.2 h1:xgTD5QrheayA6q5zfUJklanF1eC+l+OY9RFGYSd4Tlo= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.2/go.mod h1:3SR8YwmMiLmU8WJ8UHF0HwL7n6GZMCJYBCRll+92lYU= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 h1:n6xMTHrLV9L78ureeigHHPwmMC4ZntOgVC+agV81Rpk= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1/go.mod h1:R+fHrtGfy+zx+d5s31cBh09P3TG58dyytb83gB7ldi0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 h1:yyN3Q4i+5bmUVySPbQC7sSKG6sK21V8AxMjvhfJe2r0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1/go.mod h1:c5/LHxZZ7qZYOboR01qOw1Mqq5v/VNyONw7WPHctNeY= github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0 h1:CPa/SRuX1Gl810K0SearSFyH0k/xKF9JHUV+4j+Tcn4= github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0/go.mod h1:/go4bZ76dxGfkvl48EYUmPZ41c+64Yrf/26RodfcFyw= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.1 h1:Bag2KZMwHJhlz2iy5Sy4ANTwPSR/ArGXcF13tbC3O+M= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.1/go.mod h1:F1WyCyjAuzq3YI+YPJxj4AXrmpWXtxjFxGhwo9RIYy4= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.2 h1:Uqwokslv+IrM36TWJqm4Qfvy9z4Pb6S1IJ720TW3qEM= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.2/go.mod h1:zyVy1/etVAq6NkdPG4kNOM2R7+AxXp5zLsiN4nDC7Fs= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 h1:S6uamk6ecVy8K3jE2mgU50h14GoGE0LRVmiK3TvgfTc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2/go.mod h1:7TqfCUZRW7sjv8qOrLV5IvS6jqvY9Uxka165zdjYwD4= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.1 h1:eShKpZ+YHv1/BfgKPR6gM66oPNFh7LyMBDAztApP388= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.1/go.mod h1:Z6j5yC+5xN/+KL2q8yN9F+DZWoGPYHzTpEaPy5mfYyo= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.1 h1:JKKAeMJAcZ2L/spwMHonmOmFFtcEuaLHRMP3wCF87jg= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.1/go.mod h1:ZPLAvqSApWS7hzinfCVAidPuWrMxizpkVhQ3zoIt8QU= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.2 h1:myO1v9n9vXOZoidFCEKnccGLXuJdTJMn29xuYZXWW7A= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.2/go.mod h1:HrT7p4jtiTGfGHUp4kxla+3q5z0ajUWFXZqlw5HjEf4= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.2 h1:BEpk5Pj/pO2ZdzZ5lv7ygSy58btFxcqm/6UizoxNjQ8= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.2/go.mod h1:bjJccrTVRTyLowME8H9oelOrBILQ6xAvh+kVRSq3SBA= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 h1:6bl/BSVebTnK73ToRn80Mtd1sl0TowfhOninyoSQA/U= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1/go.mod h1:t7Bq7VRIN1D9C2sa2PE5gzwL6d7p1fypnsydYhKaA5k= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 h1:tKUyddNszcif4j2yL6lJd4tDAykcU3shMkAPoM9EzV8= From bdf3004208fb8c7a7d0e618b5c21912a2b29b5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 3 Apr 2025 10:48:00 +0200 Subject: [PATCH 254/619] chore(sqlserverflex): show how to get flavors in create instance example (#679) --- docs/stackit_beta_sqlserverflex_instance_create.md | 3 ++- internal/cmd/beta/sqlserverflex/instance/create/create.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/stackit_beta_sqlserverflex_instance_create.md b/docs/stackit_beta_sqlserverflex_instance_create.md index 99ee21d4c..6e8dc16a0 100644 --- a/docs/stackit_beta_sqlserverflex_instance_create.md +++ b/docs/stackit_beta_sqlserverflex_instance_create.md @@ -16,7 +16,8 @@ stackit beta sqlserverflex instance create [flags] Create a SQLServer Flex instance with name "my-instance" and specify flavor by CPU and RAM. Other parameters are set to default values $ stackit beta sqlserverflex instance create --name my-instance --cpu 1 --ram 4 - Create a SQLServer Flex instance with name "my-instance" and specify flavor by ID. Other parameters are set to default values + Create a SQLServer Flex instance with name "my-instance" and specify flavor by ID. Other parameters are set to default values. + The flavor ID can be retrieved by running "$ stackit beta sqlserverflex options --flavors" $ stackit beta sqlserverflex instance create --name my-instance --flavor-id xxx Create a SQLServer Flex instance with name "my-instance", specify flavor by CPU and RAM, set storage size to 20 GB, and restrict access to a specific range of IP addresses. Other parameters are set to default values diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 6436d545f..904b2f6f8 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -76,7 +76,8 @@ func NewCmd(p *print.Printer) *cobra.Command { `Create a SQLServer Flex instance with name "my-instance" and specify flavor by CPU and RAM. Other parameters are set to default values`, `$ stackit beta sqlserverflex instance create --name my-instance --cpu 1 --ram 4`), examples.NewExample( - `Create a SQLServer Flex instance with name "my-instance" and specify flavor by ID. Other parameters are set to default values`, + `Create a SQLServer Flex instance with name "my-instance" and specify flavor by ID. Other parameters are set to default values. + The flavor ID can be retrieved by running "$ stackit beta sqlserverflex options --flavors"`, `$ stackit beta sqlserverflex instance create --name my-instance --flavor-id xxx`), examples.NewExample( `Create a SQLServer Flex instance with name "my-instance", specify flavor by CPU and RAM, set storage size to 20 GB, and restrict access to a specific range of IP addresses. Other parameters are set to default values`, From 60cbbccc3ae3eeb6bdf5835f636d0f47a81437fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 4 Apr 2025 12:22:53 +0200 Subject: [PATCH 255/619] chore(observability): remove argus alias and warning in readme (#683) relates to STACKITCLI-50 --- README.md | 9 --------- internal/cmd/observability/observability.go | 11 +++++------ 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index d3d51cf1b..fd3d5d770 100644 --- a/README.md +++ b/README.md @@ -23,15 +23,6 @@ This CLI is in a BETA state. More services and functionality will be supported s Your feedback is appreciated! Feel free to open [GitHub issues](https://github.com/stackitcloud/stackit-cli) to provide feature requests and bug reports. - - -> [!WARNING] -> On August 26 2024, The STACKIT Argus service was renamed to STACKIT Observability. -> -> This means that there is a new command group `observability`, which offers the same functionality as the deprecated `argus` command. -> -> Please make sure to **update your STACKIT CLI to the latest version after August 26 2024** to ensure that you start using `observability` command. - ## Installation Please refer to our [installation guide](./INSTALLATION.md) for instructions on how to install and get started using the STACKIT CLI. diff --git a/internal/cmd/observability/observability.go b/internal/cmd/observability/observability.go index c6a000568..8737a716e 100644 --- a/internal/cmd/observability/observability.go +++ b/internal/cmd/observability/observability.go @@ -15,12 +15,11 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "observability", - Aliases: []string{"argus"}, - Short: "Provides functionality for Observability", - Long: "Provides functionality for Observability.", - Args: args.NoArgs, - Run: utils.CmdHelp, + Use: "observability", + Short: "Provides functionality for Observability", + Long: "Provides functionality for Observability.", + Args: args.NoArgs, + Run: utils.CmdHelp, } addSubcommands(cmd, p) return cmd From 0d4a46940cd43d1d33cf6a076f1b77f05dd2347a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Fri, 4 Apr 2025 13:01:54 +0200 Subject: [PATCH 256/619] chore: upgraded go version (#685) --- .github/workflows/ci.yaml | 2 +- CONTRIBUTION.md | 2 +- go.mod | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d59bcee93..329ec530c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,7 +3,7 @@ name: CI on: [pull_request, workflow_dispatch] env: - GO_VERSION: "1.23" + GO_VERSION: "1.24" jobs: main: diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index 07af2da47..15034e8a6 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -19,7 +19,7 @@ Your contribution is welcome! Thank you for your interest in contributing to the Prerequisites: -- [`Go`](https://go.dev/doc/install) 1.22+ +- [`Go`](https://go.dev/doc/install) 1.24+ - [`yamllint`](https://yamllint.readthedocs.io/en/stable/quickstart.html) ### Useful Make commands diff --git a/go.mod b/go.mod index 87cdcd033..cc0353bb0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/stackitcloud/stackit-cli -go 1.23.0 +go 1.24 require ( github.com/fatih/color v1.18.0 From c166bac4fdde7c717f9c76934f9e59aad6d538c3 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 4 Apr 2025 13:34:03 +0200 Subject: [PATCH 257/619] feat(auth): Introduce possibility to use an environment variable to authenticate (#682) If STACKIT_ACCESS_TOKEN is set this environment variable is used instead of stored tokens. Additionally the activate-service-account command is extended in order to only print the token but not store them in the keyring or in a file on the disk. Signed-off-by: Alexander Dahmen --- AUTHENTICATION.md | 2 ++ docs/stackit_auth_activate-service-account.md | 4 +++ .../activate_service_account.go | 36 +++++++++++-------- .../activate_service_account_test.go | 22 +++++++++--- internal/cmd/auth/login/login.go | 3 +- internal/pkg/auth/auth.go | 9 +++++ internal/pkg/auth/service_account.go | 31 ++++++++-------- internal/pkg/auth/service_account_test.go | 2 +- internal/pkg/auth/storage.go | 1 + 9 files changed, 76 insertions(+), 34 deletions(-) diff --git a/AUTHENTICATION.md b/AUTHENTICATION.md index f88cb3883..1ec7ea3ba 100644 --- a/AUTHENTICATION.md +++ b/AUTHENTICATION.md @@ -13,6 +13,8 @@ $ stackit auth activate-service-account You can also configure the service account credentials directly in the CLI. To get help and to get a list of the available options run the command with the `-h` flag. +**_Note:_** There is an optional flag `--only-print-access-token` which can be used to only obtain the access token which prevents writing the credentials to the keyring or into `cli-auth-storage.txt` ([File Location](./README.md#configuration)). This access token can be stored as environment variable (STACKIT_ACCESS_TOKEN) in order to be used for all subsequent commands by default. + ### Overview If you don't have a service account, create one in the [STACKIT Portal](https://portal.stackit.cloud/) and assign the necessary permissions to it, e.g. `owner`. There are two ways to authenticate: diff --git a/docs/stackit_auth_activate-service-account.md b/docs/stackit_auth_activate-service-account.md index 8e8b7ac81..3d154ebfb 100644 --- a/docs/stackit_auth_activate-service-account.md +++ b/docs/stackit_auth_activate-service-account.md @@ -23,12 +23,16 @@ stackit auth activate-service-account [flags] Activate service account authentication in the STACKIT CLI using the service account token $ stackit auth activate-service-account --service-account-token my-service-account-token + + Only print the corresponding access token by using the service account token. This access token can be stored as environment variable (STACKIT_ACCESS_TOKEN) in order to be used for all subsequent commands. + $ stackit auth activate-service-account --service-account-token my-service-account-token --only-print-access-token ``` ### Options ``` -h, --help Help for "stackit auth activate-service-account" + --only-print-access-token If this is set to true the credentials are not stored in either the keyring or a file --private-key-path string RSA private key path. It takes precedence over the private key included in the service account key, if present --service-account-key-path string Service account key path --service-account-token string Service account long-lived access token diff --git a/internal/cmd/auth/activate-service-account/activate_service_account.go b/internal/cmd/auth/activate-service-account/activate_service_account.go index 82c549a5d..46922720a 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account.go @@ -22,12 +22,14 @@ const ( serviceAccountTokenFlag = "service-account-token" serviceAccountKeyPathFlag = "service-account-key-path" privateKeyPathFlag = "private-key-path" + onlyPrintAccessTokenFlag = "only-print-access-token" // #nosec G101 ) type inputModel struct { ServiceAccountToken string ServiceAccountKeyPath string PrivateKeyPath string + OnlyPrintAccessToken bool } func NewCmd(p *print.Printer) *cobra.Command { @@ -50,13 +52,19 @@ func NewCmd(p *print.Printer) *cobra.Command { examples.NewExample( `Activate service account authentication in the STACKIT CLI using the service account token`, "$ stackit auth activate-service-account --service-account-token my-service-account-token"), + examples.NewExample( + `Only print the corresponding access token by using the service account token. This access token can be stored as environment variable (STACKIT_ACCESS_TOKEN) in order to be used for all subsequent commands.`, + "$ stackit auth activate-service-account --service-account-token my-service-account-token --only-print-access-token", + ), ), RunE: func(cmd *cobra.Command, _ []string) error { model := parseInput(p, cmd) - tokenCustomEndpoint, err := storeFlags() - if err != nil { - return err + tokenCustomEndpoint := viper.GetString(config.TokenCustomEndpointKey) + if !model.OnlyPrintAccessToken { + if err := storeCustomEndpoint(tokenCustomEndpoint); err != nil { + return err + } } cfg := &sdkConfig.Configuration{ @@ -75,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // Authenticates the service account and stores credentials - email, err := auth.AuthenticateServiceAccount(p, rt) + email, accessToken, err := auth.AuthenticateServiceAccount(p, rt, model.OnlyPrintAccessToken) if err != nil { var activateServiceAccountError *cliErr.ActivateServiceAccountError if !errors.As(err, &activateServiceAccountError) { @@ -84,8 +92,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - p.Info("You have been successfully authenticated to the STACKIT CLI!\nService account email: %s\n", email) - + if model.OnlyPrintAccessToken { + // Only output is the access token + p.Outputf("%s\n", accessToken) + } else { + p.Outputf("You have been successfully authenticated to the STACKIT CLI!\nService account email: %s\n", email) + } return nil }, } @@ -97,6 +109,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(serviceAccountTokenFlag, "", "Service account long-lived access token") cmd.Flags().String(serviceAccountKeyPathFlag, "", "Service account key path") cmd.Flags().String(privateKeyPathFlag, "", "RSA private key path. It takes precedence over the private key included in the service account key, if present") + cmd.Flags().Bool(onlyPrintAccessTokenFlag, false, "If this is set to true the credentials are not stored in either the keyring or a file") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { @@ -104,6 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { ServiceAccountToken: flags.FlagToStringValue(p, cmd, serviceAccountTokenFlag), ServiceAccountKeyPath: flags.FlagToStringValue(p, cmd, serviceAccountKeyPathFlag), PrivateKeyPath: flags.FlagToStringValue(p, cmd, privateKeyPathFlag), + OnlyPrintAccessToken: flags.FlagToBoolValue(p, cmd, onlyPrintAccessTokenFlag), } if p.IsVerbosityDebug() { @@ -118,12 +132,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { return &model } -func storeFlags() (tokenCustomEndpoint string, err error) { - tokenCustomEndpoint = viper.GetString(config.TokenCustomEndpointKey) - - err = auth.SetAuthField(auth.TOKEN_CUSTOM_ENDPOINT, tokenCustomEndpoint) - if err != nil { - return "", fmt.Errorf("set %s: %w", auth.TOKEN_CUSTOM_ENDPOINT, err) - } - return tokenCustomEndpoint, nil +func storeCustomEndpoint(tokenCustomEndpoint string) error { + return auth.SetAuthField(auth.TOKEN_CUSTOM_ENDPOINT, tokenCustomEndpoint) } diff --git a/internal/cmd/auth/activate-service-account/activate_service_account_test.go b/internal/cmd/auth/activate-service-account/activate_service_account_test.go index 854022fd4..9dcbb22b7 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account_test.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account_test.go @@ -20,6 +20,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st serviceAccountTokenFlag: "token", serviceAccountKeyPathFlag: "sa_key", privateKeyPathFlag: "private_key", + onlyPrintAccessTokenFlag: "true", } for _, mod := range mods { mod(flagValues) @@ -32,6 +33,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { ServiceAccountToken: "token", ServiceAccountKeyPath: "sa_key", PrivateKeyPath: "private_key", + OnlyPrintAccessToken: true, } for _, mod := range mods { mod(model) @@ -87,6 +89,18 @@ func TestParseInput(t *testing.T) { }), isValid: false, }, + { + description: "default value OnlyPrintAccessToken", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + delete(flagValues, "only-print-access-token") + }, + ), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.OnlyPrintAccessToken = false + }), + }, } for _, tt := range tests { @@ -121,7 +135,7 @@ func TestParseInput(t *testing.T) { } } -func TestStoreFlags(t *testing.T) { +func TestStoreCustomEndpointFlags(t *testing.T) { tests := []struct { description string model *inputModel @@ -154,7 +168,7 @@ func TestStoreFlags(t *testing.T) { viper.Reset() viper.Set(config.TokenCustomEndpointKey, tt.tokenCustomEndpoint) - tokenCustomEndpoint, err := storeFlags() + err := storeCustomEndpoint(tt.tokenCustomEndpoint) if !tt.isValid { if err == nil { t.Fatalf("did not fail on invalid input") @@ -169,8 +183,8 @@ func TestStoreFlags(t *testing.T) { if err != nil { t.Errorf("Failed to get value of auth field: %v", err) } - if value != tokenCustomEndpoint { - t.Errorf("Value of \"%s\" does not match: expected \"%s\", got \"%s\"", auth.TOKEN_CUSTOM_ENDPOINT, tokenCustomEndpoint, value) + if value != tt.tokenCustomEndpoint { + t.Errorf("Value of \"%s\" does not match: expected \"%s\", got \"%s\"", auth.TOKEN_CUSTOM_ENDPOINT, tt.tokenCustomEndpoint, value) } }) } diff --git a/internal/cmd/auth/login/login.go b/internal/cmd/auth/login/login.go index 9c17acef3..06531f706 100644 --- a/internal/cmd/auth/login/login.go +++ b/internal/cmd/auth/login/login.go @@ -30,7 +30,8 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("authorization failed: %w", err) } - p.Info("Successfully logged into STACKIT CLI.\n") + p.Outputln("Successfully logged into STACKIT CLI.\n") + return nil }, } diff --git a/internal/pkg/auth/auth.go b/internal/pkg/auth/auth.go index fdd64354d..89a39ac29 100644 --- a/internal/pkg/auth/auth.go +++ b/internal/pkg/auth/auth.go @@ -2,6 +2,7 @@ package auth import ( "fmt" + "os" "strconv" "time" @@ -22,7 +23,15 @@ type tokenClaims struct { // It returns the configuration option that can be used to create an authenticated SDK client. // // If the user was logged in and the user session expired, reauthorizeUserRoutine is called to reauthenticate the user again. +// If the environment variable STACKIT_ACCESS_TOKEN is set this token is used instead. func AuthenticationConfig(p *print.Printer, reauthorizeUserRoutine func(p *print.Printer, _ bool) error) (authCfgOption sdkConfig.ConfigurationOption, err error) { + // Get access token from env and use this if present + accessToken := os.Getenv(envAccessTokenName) + if accessToken != "" { + authCfgOption = sdkConfig.WithToken(accessToken) + return authCfgOption, nil + } + flow, err := GetAuthFlow() if err != nil { return nil, fmt.Errorf("get authentication flow: %w", err) diff --git a/internal/pkg/auth/service_account.go b/internal/pkg/auth/service_account.go index 62e154bad..1f1b01729 100644 --- a/internal/pkg/auth/service_account.go +++ b/internal/pkg/auth/service_account.go @@ -35,7 +35,8 @@ var _ http.RoundTripper = &keyFlowWithStorage{} // For the key flow, it fetches an access and refresh token from the Service Account API. // For the token flow, it just stores the provided token and doesn't check if it is valid. // It returns the email associated with the service account -func AuthenticateServiceAccount(p *print.Printer, rt http.RoundTripper) (email string, err error) { +// If disableWriting is set to true the credentials are not stored on disk (keyring, file). +func AuthenticateServiceAccount(p *print.Printer, rt http.RoundTripper, disableWriting bool) (email, accessToken string, err error) { authFields := make(map[authFieldKey]string) var authFlowType AuthFlow switch flow := rt.(type) { @@ -46,12 +47,12 @@ func AuthenticateServiceAccount(p *print.Printer, rt http.RoundTripper) (email s accessToken, err := flow.GetAccessToken() if err != nil { p.Debug(print.ErrorLevel, "get access token: %v", err) - return "", &errors.ActivateServiceAccountError{} + return "", "", &errors.ActivateServiceAccountError{} } serviceAccountKey := flow.GetConfig().ServiceAccountKey saKeyBytes, err := json.Marshal(serviceAccountKey) if err != nil { - return "", fmt.Errorf("marshal service account key: %w", err) + return "", "", fmt.Errorf("marshal service account key: %w", err) } authFields[ACCESS_TOKEN] = accessToken @@ -64,12 +65,12 @@ func AuthenticateServiceAccount(p *print.Printer, rt http.RoundTripper) (email s authFields[ACCESS_TOKEN] = flow.GetConfig().ServiceAccountToken default: - return "", fmt.Errorf("could not authenticate using any of the supported authentication flows (key and token): please report this issue") + return "", "", fmt.Errorf("could not authenticate using any of the supported authentication flows (key and token): please report this issue") } email, err = getEmailFromToken(authFields[ACCESS_TOKEN]) if err != nil { - return "", fmt.Errorf("get email from access token: %w", err) + return "", "", fmt.Errorf("get email from access token: %w", err) } p.Debug(print.DebugLevel, "successfully authenticated service account %s", email) @@ -78,20 +79,22 @@ func AuthenticateServiceAccount(p *print.Printer, rt http.RoundTripper) (email s sessionExpiresAtUnix, err := getStartingSessionExpiresAtUnix() if err != nil { - return "", fmt.Errorf("compute session expiration timestamp: %w", err) + return "", "", fmt.Errorf("compute session expiration timestamp: %w", err) } authFields[SESSION_EXPIRES_AT_UNIX] = sessionExpiresAtUnix - err = SetAuthFlow(authFlowType) - if err != nil { - return "", fmt.Errorf("set auth flow type: %w", err) - } - err = SetAuthFieldMap(authFields) - if err != nil { - return "", fmt.Errorf("set in auth storage: %w", err) + if !disableWriting { + err = SetAuthFlow(authFlowType) + if err != nil { + return "", "", fmt.Errorf("set auth flow type: %w", err) + } + err = SetAuthFieldMap(authFields) + if err != nil { + return "", "", fmt.Errorf("set in auth storage: %w", err) + } } - return authFields[SERVICE_ACCOUNT_EMAIL], nil + return authFields[SERVICE_ACCOUNT_EMAIL], authFields[ACCESS_TOKEN], nil } // initKeyFlowWithStorage initializes the keyFlow from the SDK and creates a keyFlowWithStorage struct that uses that keyFlow diff --git a/internal/pkg/auth/service_account_test.go b/internal/pkg/auth/service_account_test.go index a4b3a72ce..adc0f8bc5 100644 --- a/internal/pkg/auth/service_account_test.go +++ b/internal/pkg/auth/service_account_test.go @@ -153,7 +153,7 @@ func TestAuthenticateServiceAccount(t *testing.T) { } p := print.NewPrinter() - email, err := AuthenticateServiceAccount(p, flow) + email, _, err := AuthenticateServiceAccount(p, flow, false) if !tt.isValid { if err == nil { diff --git a/internal/pkg/auth/storage.go b/internal/pkg/auth/storage.go index 02f397386..7b6901424 100644 --- a/internal/pkg/auth/storage.go +++ b/internal/pkg/auth/storage.go @@ -25,6 +25,7 @@ const ( keyringService = "stackit-cli" textFileFolderName = "stackit" textFileName = "cli-auth-storage.txt" + envAccessTokenName = "STACKIT_ACCESS_TOKEN" ) const ( From d1915e92c3d9533e869c8d8d21168c3fb30ec972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 4 Apr 2025 16:34:06 +0200 Subject: [PATCH 258/619] feat(ci): enusure docs are up-to-date for PRs (#686) relates to STACKITCLI-131 --- .github/pull_request_template.md | 2 +- .github/workflows/ci.yaml | 7 +++++++ scripts/check-docs.sh | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100755 scripts/check-docs.sh diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 088dfb4c4..b01df3feb 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,7 +12,7 @@ relates to #1234 - [ ] Issue was linked above - [ ] Code format was applied: `make fmt` - [ ] Examples were added / adjusted (see e.g. [here](https://github.com/stackitcloud/stackit-cli/blob/ef291d1683ca5b0d719ec0a26ecb999a32685117/internal/cmd/ske/cluster/create/create.go#L49-L63)) -- [ ] Docs are up-to-date: `make generate-docs` +- [x] Docs are up-to-date: `make generate-docs` (will be checked by CI) - [ ] Unit tests got implemented or updated - [x] Unit tests are passing: `make test` (will be checked by CI) - [x] No linter issues: `make lint` (will be checked by CI) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 329ec530c..d069884e7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,11 +12,18 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Build uses: ./.github/actions/build with: go-version: ${{ env.GO_VERSION }} + + - name: "Ensure docs are up-to-date" + if: ${{ github.event_name == 'pull_request' }} + run: ./scripts/check-docs.sh + - name: Lint run: make lint + - name: Test run: make test diff --git a/scripts/check-docs.sh b/scripts/check-docs.sh new file mode 100755 index 000000000..d81181db9 --- /dev/null +++ b/scripts/check-docs.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# This script is used to ensure for PRs the docs are up-to-date via the CI pipeline +# Usage: ./check-docs.sh +set -eo pipefail + +ROOT_DIR=$(git rev-parse --show-toplevel) + +before_hash=$(find docs -type f -exec sha256sum {} \; | sort | sha256sum | awk '{print $1}') + +# re-generate the docs +go run $ROOT_DIR/scripts/generate.go + +after_hash=$(find docs -type f -exec sha256sum {} \; | sort | sha256sum | awk '{print $1}') + +if [[ "$before_hash" == "$after_hash" ]]; then + echo "Docs are up-to-date" +else + echo "Changes detected. Docs are *not* up-to-date." + exit 1 +fi From 1bd68428dfb6cc95e3102258711999c9cf7c5c7a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:30:24 +0200 Subject: [PATCH 259/619] fix(deps): update module golang.org/x/text to v0.24.0 (#690) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cc0353bb0..557d96cb9 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.28.0 golang.org/x/term v0.30.0 - golang.org/x/text v0.23.0 + golang.org/x/text v0.24.0 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 ) diff --git a/go.sum b/go.sum index 3975dcb2f..d6f51007f 100644 --- a/go.sum +++ b/go.sum @@ -201,8 +201,8 @@ golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 1ffc368987835c8d64b1ec13169ca56c40ea0bf8 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:30:49 +0200 Subject: [PATCH 260/619] fix(deps): update module golang.org/x/oauth2 to v0.29.0 (#688) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 557d96cb9..32c320936 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 - golang.org/x/oauth2 v0.28.0 + golang.org/x/oauth2 v0.29.0 golang.org/x/term v0.30.0 golang.org/x/text v0.24.0 k8s.io/apimachinery v0.32.3 diff --git a/go.sum b/go.sum index d6f51007f..a48416f7c 100644 --- a/go.sum +++ b/go.sum @@ -186,8 +186,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= +golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 69e408c98dd9c0dded958ac3b643d2dacfbe66ac Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:34:54 +0200 Subject: [PATCH 261/619] fix(deps): update stackit sdk modules (#684) Co-authored-by: Renovate Bot --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 32c320936..6d2afedf5 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.2 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 @@ -77,12 +77,12 @@ require ( github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.2 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.2 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.2 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.2 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.31.0 // indirect diff --git a/go.sum b/go.sum index a48416f7c..74bce8368 100644 --- a/go.sum +++ b/go.sum @@ -121,24 +121,24 @@ github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 h1:xaNory8kBIsBG7PJ github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0/go.mod h1:LVOYlzNt5BXDC42AHd/GZj6KvlCg4w94of/E6pZOj5k= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 h1:4Kz9MH9VVuXYnnWFjJcPFVBiPtCUnSrHfsyUzBWwhKc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1/go.mod h1:x0jgrL+/K2cE4BvcIQByFUf0nOPVZRqq5Z074kjjr64= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.2 h1:VW9/SH1hS0RwgW1UEGSG1NDSE15KRL2eh3ld34svYr4= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.21.2/go.mod h1:Lb1emAS4KI+pWDXQlbmST058wTsWyD8vLmdsJpRjfEg= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.2 h1:xgTD5QrheayA6q5zfUJklanF1eC+l+OY9RFGYSd4Tlo= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.21.2/go.mod h1:3SR8YwmMiLmU8WJ8UHF0HwL7n6GZMCJYBCRll+92lYU= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0 h1:5pcvoWS2sO3MIBP026OZEdImBNVvI27lksehqDMbAh0= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0/go.mod h1:Lb1emAS4KI+pWDXQlbmST058wTsWyD8vLmdsJpRjfEg= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.0 h1:BvEQmJwCmyAoCH5zG4apu8co/neLMtBdv9znwmbGj78= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.0/go.mod h1:3SR8YwmMiLmU8WJ8UHF0HwL7n6GZMCJYBCRll+92lYU= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 h1:n6xMTHrLV9L78ureeigHHPwmMC4ZntOgVC+agV81Rpk= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1/go.mod h1:R+fHrtGfy+zx+d5s31cBh09P3TG58dyytb83gB7ldi0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 h1:yyN3Q4i+5bmUVySPbQC7sSKG6sK21V8AxMjvhfJe2r0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1/go.mod h1:c5/LHxZZ7qZYOboR01qOw1Mqq5v/VNyONw7WPHctNeY= github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0 h1:CPa/SRuX1Gl810K0SearSFyH0k/xKF9JHUV+4j+Tcn4= github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0/go.mod h1:/go4bZ76dxGfkvl48EYUmPZ41c+64Yrf/26RodfcFyw= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.2 h1:Uqwokslv+IrM36TWJqm4Qfvy9z4Pb6S1IJ720TW3qEM= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.20.2/go.mod h1:zyVy1/etVAq6NkdPG4kNOM2R7+AxXp5zLsiN4nDC7Fs= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0 h1:Au07XkATgBqrGpjO5t6ASAjuif7VXcKKF3t4edRh+Yw= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0/go.mod h1:zyVy1/etVAq6NkdPG4kNOM2R7+AxXp5zLsiN4nDC7Fs= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 h1:S6uamk6ecVy8K3jE2mgU50h14GoGE0LRVmiK3TvgfTc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2/go.mod h1:7TqfCUZRW7sjv8qOrLV5IvS6jqvY9Uxka165zdjYwD4= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.2 h1:myO1v9n9vXOZoidFCEKnccGLXuJdTJMn29xuYZXWW7A= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.21.2/go.mod h1:HrT7p4jtiTGfGHUp4kxla+3q5z0ajUWFXZqlw5HjEf4= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.2 h1:BEpk5Pj/pO2ZdzZ5lv7ygSy58btFxcqm/6UizoxNjQ8= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.21.2/go.mod h1:bjJccrTVRTyLowME8H9oelOrBILQ6xAvh+kVRSq3SBA= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.0 h1:/hHxcTvSQc1tG5gqRdFV3g7cMy7nU0/Av0p9UX9PyPQ= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.0/go.mod h1:HrT7p4jtiTGfGHUp4kxla+3q5z0ajUWFXZqlw5HjEf4= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 h1:F+oTIOWeU5Jl0xsrJ+IV+Hz756UIOxBd7TFOD4YAv4k= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0/go.mod h1:bjJccrTVRTyLowME8H9oelOrBILQ6xAvh+kVRSq3SBA= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 h1:6bl/BSVebTnK73ToRn80Mtd1sl0TowfhOninyoSQA/U= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1/go.mod h1:t7Bq7VRIN1D9C2sa2PE5gzwL6d7p1fypnsydYhKaA5k= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 h1:tKUyddNszcif4j2yL6lJd4tDAykcU3shMkAPoM9EzV8= From 5dcca3b726d58da53964764ecf692ba3f0c2f422 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:04:56 +0200 Subject: [PATCH 262/619] fix: project list command does not work with service account (#691) - fix: project list command does not work with service account - add GetAuthEmail() function to get the email of the authenticated user --- internal/cmd/project/list/list.go | 2 +- internal/cmd/project/list/list_test.go | 7 ++++++- internal/pkg/auth/storage.go | 25 +++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 9051dc145..4459558ad 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -167,7 +167,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient resourceMana } if model.ParentId == nil && model.ProjectIdLike == nil && model.Member == nil { - email, err := auth.GetAuthField(auth.USER_EMAIL) + email, err := auth.GetAuthEmail() if err != nil { return req, fmt.Errorf("get email of authenticated user: %w", err) } diff --git a/internal/cmd/project/list/list_test.go b/internal/cmd/project/list/list_test.go index 7c6e73cee..47db45bac 100644 --- a/internal/cmd/project/list/list_test.go +++ b/internal/cmd/project/list/list_test.go @@ -259,7 +259,12 @@ func TestParseInput(t *testing.T) { func TestBuildRequest(t *testing.T) { keyring.MockInit() - err := auth.SetAuthField(auth.USER_EMAIL, "test@test.com") + err := auth.SetAuthFlow(auth.AUTH_FLOW_USER_TOKEN) + if err != nil { + t.Fatalf("Failed to set auth flow: %v", err) + } + + err = auth.SetAuthField(auth.USER_EMAIL, "test@test.com") if err != nil { t.Fatalf("Failed to set auth user email: %v", err) } diff --git a/internal/pkg/auth/storage.go b/internal/pkg/auth/storage.go index 7b6901424..5e857f6a7 100644 --- a/internal/pkg/auth/storage.go +++ b/internal/pkg/auth/storage.go @@ -5,7 +5,6 @@ import ( "encoding/json" "errors" "fmt" - "os" "path/filepath" @@ -23,7 +22,6 @@ type AuthFlow string const ( keyringService = "stackit-cli" - textFileFolderName = "stackit" textFileName = "cli-auth-storage.txt" envAccessTokenName = "STACKIT_ACCESS_TOKEN" ) @@ -342,6 +340,29 @@ func GetProfileEmail(profile string) string { return email } +// GetAuthEmail returns the email of the authenticated account. +// If the environment variable STACKIT_ACCESS_TOKEN is set, the email of this token will be returned. +func GetAuthEmail() (string, error) { + // If STACKIT_ACCESS_TOKEN is set, get the mail from the token + if accessToken := os.Getenv(envAccessTokenName); accessToken != "" { + email, err := getEmailFromToken(accessToken) + if err != nil { + return "", fmt.Errorf("error getting email from token: %w", err) + } + return email, nil + } + + profile, err := config.GetProfile() + if err != nil { + return "", fmt.Errorf("error getting profile: %w", err) + } + email := GetProfileEmail(profile) + if email == "" { + return "", fmt.Errorf("error getting profile email. email is empty") + } + return email, nil +} + func LoginUser(email, accessToken, refreshToken, sessionExpiresAtUnix string) error { authFields := map[authFieldKey]string{ SESSION_EXPIRES_AT_UNIX: sessionExpiresAtUnix, From b7461f5c9cb920eb18ebefe40e49e9ad833336e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 8 Apr 2025 10:19:45 +0200 Subject: [PATCH 263/619] chore(doc): add documentation of release process (#687) relates to STACKITTPR-200 --- README.md | 4 ++++ RELEASE.md | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 RELEASE.md diff --git a/README.md b/README.md index fd3d5d770..2b48581ad 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,10 @@ If you encounter any issues or have suggestions for improvements, please open an Your contribution is welcome! For more details on how to contribute, refer to our [contribution guide](./CONTRIBUTION.md). +## Release creation + +See the [release documentation](./RELEASE.md) for further information. + ## License Apache 2.0 diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 000000000..7b701cf6b --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,17 @@ +# Release + +## Release cycle + +A release should be created at least every 2 weeks. + +## Release creation + +> [!IMPORTANT] +> Consider informing / syncing with the team before creating a new release. + +1. Check out latest main branch on your machine +2. Create git tag: `git tag vX.X.X` +3. Push the git tag: `git push origin --tags` +4. The [release pipeline](https://github.com/stackitcloud/stackit-cli/actions/workflows/release.yaml) will build the release and publish it on GitHub +5. Ensure the release was created properly using the [releases page](https://github.com/stackitcloud/stackit-cli/releases) + From 9d002bad76066783b19c1e5c8f2b3b4ff3198a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 8 Apr 2025 16:18:57 +0200 Subject: [PATCH 264/619] feat(ci): close stale PRs automatically (#693) relates to STACKITTPR-207 --- .github/workflows/stale.yaml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/stale.yaml diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 000000000..3ee54f0da --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,35 @@ +name: "Stale" +on: + schedule: + # every night at 01:30 + - cron: "30 1 * * *" + # run this workflow if the workflow definition gets changed within a PR + pull_request: + branches: ["main"] + paths: [".github/workflows/stale.yaml"] + +env: + DAYS_BEFORE_PR_STALE: 7 + DAYS_BEFORE_PR_CLOSE: 7 + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + name: "Stale" + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: "Mark old PRs as stale" + uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-pr-message: "This PR was marked as stale after ${{ env.DAYS_BEFORE_PR_STALE }} days of inactivity and will be closed after another ${{ env.DAYS_BEFORE_PR_CLOSE }} days of further inactivity. If this PR should be kept open, just add a comment, remove the stale label or push new commits to it." + close-pr-message: "This PR was closed automatically because it has been stalled for ${{ env.DAYS_BEFORE_PR_CLOSE }} days with no activity. Feel free to re-open it at any time." + days-before-pr-stale: ${{ env.DAYS_BEFORE_PR_STALE }} + days-before-pr-close: ${{ env.DAYS_BEFORE_PR_CLOSE }} + # never mark issues as stale or close them + days-before-issue-stale: -1 + days-before-issue-close: -1 From 585e0d30470065c8aa8edfd52dd53d70966e6015 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Tue, 8 Apr 2025 16:52:44 +0200 Subject: [PATCH 265/619] feat(network-interface): Extend list output to contain device and ipv4 (#695) Signed-off-by: Alexander Dahmen --- internal/cmd/network-interface/list/list.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/cmd/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go index 9ee88cd2f..3164f956b 100644 --- a/internal/cmd/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -173,13 +173,15 @@ func outputResult(p *print.Printer, outputFormat string, nics []iaas.NIC) error return nil default: table := tables.NewTable() - table.SetHeader("ID", "NAME", "NIC SECURITY", "STATUS", "TYPE") + table.SetHeader("ID", "NAME", "NIC SECURITY", "DEVICE ID", "IPv4 ADDRESS", "STATUS", "TYPE") for _, nic := range nics { table.AddRow( utils.PtrString(nic.Id), utils.PtrString(nic.Name), utils.PtrString(nic.NicSecurity), + utils.PtrString(nic.Device), + utils.PtrString(nic.Ipv4), utils.PtrString(nic.Status), utils.PtrString(nic.Type), ) From f589bb4e1fd61fb4007d6bb9d430c818867d984c Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 9 Apr 2025 08:55:03 +0200 Subject: [PATCH 266/619] fix(deps): update module golang.org/x/term to v0.31.0 (#689) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 6d2afedf5..53bcd893b 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.29.0 - golang.org/x/term v0.30.0 + golang.org/x/term v0.31.0 golang.org/x/text v0.24.0 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 @@ -85,7 +85,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.31.0 // indirect + golang.org/x/sys v0.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 74bce8368..6511aef37 100644 --- a/go.sum +++ b/go.sum @@ -195,10 +195,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= +golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= From 39c1fe0c22731e93ba36cafae11f2e2dc332c037 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Wed, 9 Apr 2025 10:27:10 +0200 Subject: [PATCH 267/619] feat: add completion to homebrew installation (#692) --- .goreleaser.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 6e861a4f8..6e766acc7 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -108,6 +108,9 @@ brews: # If set to auto, the release will not be uploaded to the homebrew tap repo # if the tag has a prerelease indicator (e.g. v0.0.1-alpha1) skip_upload: auto + install: | + bin.install "stackit" + generate_completions_from_executable(bin/"stackit", "completion") snapcrafts: # IDs of the builds for which to create packages for From 91bd0bb8075fc219326e925feb0692c586f33361 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Wed, 9 Apr 2025 16:25:04 +0200 Subject: [PATCH 268/619] fix(image): Uefi flag cannot be set to false (#698) Signed-off-by: Alexander Dahmen --- docs/stackit_image_create.md | 2 +- internal/cmd/image/create/create.go | 8 ++++---- internal/cmd/image/create/create_test.go | 14 ++++++++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/stackit_image_create.md b/docs/stackit_image_create.md index 83c798f6d..3c608126c 100644 --- a/docs/stackit_image_create.md +++ b/docs/stackit_image_create.md @@ -42,7 +42,7 @@ stackit image create [flags] --rescue-bus string Sets the device bus when the image is used as a rescue image. --rescue-device string Sets the device when the image is used as a rescue image. --secure-boot Enables Secure Boot. - --uefi Enables UEFI boot. + --uefi Enables UEFI boot. (default true) --video-model string Sets Graphic device model. --virtio-scsi Enables the use of VirtIO SCSI to provide block device access. By default instances use VirtIO Block. ``` diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index d0550b1a4..b29048efb 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -62,7 +62,7 @@ type imageConfig struct { RescueBus *string RescueDevice *string SecureBoot *bool - Uefi *bool + Uefi bool VideoModel *string VirtioScsi *bool } @@ -270,7 +270,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(rescueBusFlag, "", "Sets the device bus when the image is used as a rescue image.") cmd.Flags().String(rescueDeviceFlag, "", "Sets the device when the image is used as a rescue image.") cmd.Flags().Bool(secureBootFlag, false, "Enables Secure Boot.") - cmd.Flags().Bool(uefiFlag, false, "Enables UEFI boot.") + cmd.Flags().Bool(uefiFlag, true, "Enables UEFI boot.") cmd.Flags().String(videoModelFlag, "", "Sets Graphic device model.") cmd.Flags().Bool(virtioScsiFlag, false, "Enables the use of VirtIO SCSI to provide block device access. By default instances use VirtIO Block.") @@ -311,7 +311,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { RescueBus: flags.FlagToStringPointer(p, cmd, rescueBusFlag), RescueDevice: flags.FlagToStringPointer(p, cmd, rescueDeviceFlag), SecureBoot: flags.FlagToBoolPointer(p, cmd, secureBootFlag), - Uefi: flags.FlagToBoolPointer(p, cmd, uefiFlag), + Uefi: flags.FlagToBoolValue(p, cmd, uefiFlag), VideoModel: flags.FlagToStringPointer(p, cmd, videoModelFlag), VirtioScsi: flags.FlagToBoolPointer(p, cmd, virtioScsiFlag), }, @@ -367,7 +367,7 @@ func createPayload(_ context.Context, model *inputModel) iaas.CreateImagePayload RescueBus: iaas.NewNullableString(model.Config.RescueBus), RescueDevice: iaas.NewNullableString(model.Config.RescueDevice), SecureBoot: model.Config.SecureBoot, - Uefi: model.Config.Uefi, + Uefi: utils.Ptr(model.Config.Uefi), VideoModel: iaas.NewNullableString(model.Config.VideoModel), VirtioScsi: model.Config.VirtioScsi, } diff --git a/internal/cmd/image/create/create_test.go b/internal/cmd/image/create/create_test.go index 5e0bee59d..262dc029e 100644 --- a/internal/cmd/image/create/create_test.go +++ b/internal/cmd/image/create/create_test.go @@ -105,7 +105,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { RescueBus: &testRescueBus, RescueDevice: &testRescueDevice, SecureBoot: &testSecureBoot, - Uefi: &testUefi, + Uefi: testUefi, VideoModel: &testVideoModel, VirtioScsi: &testVirtioScsi, }, @@ -246,6 +246,16 @@ func TestParseInput(t *testing.T) { }), isValid: false, }, + { + description: "uefi flag is set to false", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[uefiFlag] = strconv.FormatBool(false) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Config.Uefi = false + }), + }, { description: "no rescue device and no bus is valid", flagValues: fixtureFlagValues(func(flagValues map[string]string) { @@ -347,7 +357,7 @@ func TestBuildRequest(t *testing.T) { { description: "uefi flag", model: fixtureInputModel(func(model *inputModel) { - model.Config.Uefi = utils.Ptr(false) + model.Config.Uefi = false }), expectedRequest: fixtureRequest(func(request *iaas.ApiCreateImageRequest) { *request = request.CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { From 417564851c6569b4a47ac7030a876fd0752ab50f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 10 Apr 2025 07:35:00 +0200 Subject: [PATCH 269/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/core to v0.17.1 (#699) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 53bcd893b..540ee75f3 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 - github.com/stackitcloud/stackit-sdk-go/core v0.16.2 + github.com/stackitcloud/stackit-sdk-go/core v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 diff --git a/go.sum b/go.sum index 6511aef37..8f4665360 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,8 @@ github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= -github.com/stackitcloud/stackit-sdk-go/core v0.16.2 h1:F8A4P/LLlQSbz0S0+G3m8rb3BUOK6EcR/CKx5UQY5jQ= -github.com/stackitcloud/stackit-sdk-go/core v0.16.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= +github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJSjtaGnUI7UE7ITb5IT0= +github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA= github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo= From 1f4c97e2a03765870987484dcc37b7da473ec22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Schmitz?= Date: Mon, 14 Apr 2025 16:56:38 +0200 Subject: [PATCH 270/619] Feat/stackitcli 134 onboading alb service (#697) * feat(alb): list command * feat(alb): bugfix * feat(alb): add template support * feat(alb): create command * feat(alb): fix testcases * feat(alb): add update * feat(alb): add describe command * feat(alb): delete command * feat(alb): fix linter issues * feat(alb): code cleanup * feat(alb): template support for pool * feat(alb): added target pool update * feat(alb): add list of errors to describe output * feat(alb): Include number of errors * feat(alb): retrieve the existing loadbalancer config to evaluate the current version * feat(alb): switch source of templates to yaml to allow comments * feat(alb): corrected template for target pool * feat(alb): retrieve target pool name from configuration file * feat(alb): updated documentation * feat(alb): add missing delete confirmation * feat(alb): review findings * Feat/stackitcli 184 onboarding alb credentials (#696) * feat(credentials): list command * feat(credentials): commands working * feat(credentials): corrected chaining of commands * feat(credentials): fixed linter issues * feat(credentials): command implementation * feat(credentials): code cleanup * feat(credentials): updated documentation * feat(credentials): bug fixes * feat(credentials): updated docs * feat(credentials): fixed testcases * feat(credentials): code cleanup * Feat/stackitcli 183 onboarding alb project api (#700) * feat(credentials) * feat(credentials): code cleanup * feat(credentials): updated documentation * feat(credentials): bug fixes * feat(credentials): updated docs * feat(credentials): fixed testcases * feat(credentials): code cleanup * feat(alb project): support for quota and plans * feat(alb project): updated documentation * feat(alb project): review findings * feat(credentials): Integrated review findings * feat(credentials): more review findings --- docs/stackit_beta.md | 1 + docs/stackit_beta_alb.md | 43 +++ docs/stackit_beta_alb_create.md | 41 +++ docs/stackit_beta_alb_delete.md | 40 +++ docs/stackit_beta_alb_describe.md | 40 +++ docs/stackit_beta_alb_list.md | 44 +++ ...ckit_beta_alb_observability-credentials.md | 38 +++ ..._beta_alb_observability-credentials_add.md | 43 +++ ...ta_alb_observability-credentials_delete.md | 40 +++ ..._alb_observability-credentials_describe.md | 40 +++ ...beta_alb_observability-credentials_list.md | 47 +++ ...ta_alb_observability-credentials_update.md | 43 +++ docs/stackit_beta_alb_plans.md | 40 +++ docs/stackit_beta_alb_pool.md | 34 +++ docs/stackit_beta_alb_pool_update.md | 42 +++ docs/stackit_beta_alb_quotas.md | 40 +++ docs/stackit_beta_alb_template.md | 45 +++ docs/stackit_beta_alb_update.md | 41 +++ go.mod | 1 + go.sum | 2 + internal/cmd/beta/alb/alb.go | 47 +++ internal/cmd/beta/alb/create/create.go | 197 +++++++++++++ internal/cmd/beta/alb/create/create_test.go | 259 +++++++++++++++++ .../beta/alb/create/testdata/testconfig.json | 125 ++++++++ internal/cmd/beta/alb/delete/delete.go | 103 +++++++ internal/cmd/beta/alb/delete/delete_test.go | 192 +++++++++++++ internal/cmd/beta/alb/describe/describe.go | 220 ++++++++++++++ .../cmd/beta/alb/describe/describe_test.go | 224 +++++++++++++++ internal/cmd/beta/alb/list/list.go | 178 ++++++++++++ internal/cmd/beta/alb/list/list_test.go | 207 ++++++++++++++ .../alb/observability-credentials/add/add.go | 146 ++++++++++ .../observability-credentials/add/add_test.go | 213 ++++++++++++++ .../delete/delete.go | 98 +++++++ .../delete/delete_test.go | 192 +++++++++++++ .../describe/describe.go | 133 +++++++++ .../describe/describe_test.go | 224 +++++++++++++++ .../observability-credentials/list/list.go | 163 +++++++++++ .../list/list_test.go | 226 +++++++++++++++ .../observability-credentials.go | 33 +++ .../update/update.go | 161 +++++++++++ .../update/update_test.go | 227 +++++++++++++++ internal/cmd/beta/alb/plans/plans.go | 146 ++++++++++ internal/cmd/beta/alb/plans/plans_test.go | 203 +++++++++++++ internal/cmd/beta/alb/pool/pool.go | 27 ++ .../alb/pool/update/testdata/testconfig.json | 28 ++ internal/cmd/beta/alb/pool/update/update.go | 191 +++++++++++++ .../cmd/beta/alb/pool/update/update_test.go | 268 ++++++++++++++++++ internal/cmd/beta/alb/quotas/quotas.go | 132 +++++++++ internal/cmd/beta/alb/quotas/quotas_test.go | 203 +++++++++++++ .../cmd/beta/alb/template/template-alb.yaml | 91 ++++++ .../cmd/beta/alb/template/template-pool.yaml | 23 ++ internal/cmd/beta/alb/template/template.go | 124 ++++++++ .../cmd/beta/alb/template/template_test.go | 180 ++++++++++++ .../beta/alb/update/testdata/testconfig.json | 125 ++++++++ internal/cmd/beta/alb/update/update.go | 227 +++++++++++++++ internal/cmd/beta/alb/update/update_test.go | 262 +++++++++++++++++ internal/cmd/beta/beta.go | 2 + internal/pkg/services/alb/client/client.go | 46 +++ internal/pkg/services/alb/utils/utils.go | 4 + internal/pkg/services/alb/utils/utils_test.go | 4 + internal/pkg/utils/strings.go | 23 ++ internal/pkg/utils/strings_test.go | 32 +++ 62 files changed, 6614 insertions(+) create mode 100644 docs/stackit_beta_alb.md create mode 100644 docs/stackit_beta_alb_create.md create mode 100644 docs/stackit_beta_alb_delete.md create mode 100644 docs/stackit_beta_alb_describe.md create mode 100644 docs/stackit_beta_alb_list.md create mode 100644 docs/stackit_beta_alb_observability-credentials.md create mode 100644 docs/stackit_beta_alb_observability-credentials_add.md create mode 100644 docs/stackit_beta_alb_observability-credentials_delete.md create mode 100644 docs/stackit_beta_alb_observability-credentials_describe.md create mode 100644 docs/stackit_beta_alb_observability-credentials_list.md create mode 100644 docs/stackit_beta_alb_observability-credentials_update.md create mode 100644 docs/stackit_beta_alb_plans.md create mode 100644 docs/stackit_beta_alb_pool.md create mode 100644 docs/stackit_beta_alb_pool_update.md create mode 100644 docs/stackit_beta_alb_quotas.md create mode 100644 docs/stackit_beta_alb_template.md create mode 100644 docs/stackit_beta_alb_update.md create mode 100644 internal/cmd/beta/alb/alb.go create mode 100644 internal/cmd/beta/alb/create/create.go create mode 100644 internal/cmd/beta/alb/create/create_test.go create mode 100644 internal/cmd/beta/alb/create/testdata/testconfig.json create mode 100644 internal/cmd/beta/alb/delete/delete.go create mode 100644 internal/cmd/beta/alb/delete/delete_test.go create mode 100644 internal/cmd/beta/alb/describe/describe.go create mode 100644 internal/cmd/beta/alb/describe/describe_test.go create mode 100644 internal/cmd/beta/alb/list/list.go create mode 100644 internal/cmd/beta/alb/list/list_test.go create mode 100644 internal/cmd/beta/alb/observability-credentials/add/add.go create mode 100644 internal/cmd/beta/alb/observability-credentials/add/add_test.go create mode 100644 internal/cmd/beta/alb/observability-credentials/delete/delete.go create mode 100644 internal/cmd/beta/alb/observability-credentials/delete/delete_test.go create mode 100644 internal/cmd/beta/alb/observability-credentials/describe/describe.go create mode 100644 internal/cmd/beta/alb/observability-credentials/describe/describe_test.go create mode 100644 internal/cmd/beta/alb/observability-credentials/list/list.go create mode 100644 internal/cmd/beta/alb/observability-credentials/list/list_test.go create mode 100644 internal/cmd/beta/alb/observability-credentials/observability-credentials.go create mode 100644 internal/cmd/beta/alb/observability-credentials/update/update.go create mode 100644 internal/cmd/beta/alb/observability-credentials/update/update_test.go create mode 100644 internal/cmd/beta/alb/plans/plans.go create mode 100644 internal/cmd/beta/alb/plans/plans_test.go create mode 100644 internal/cmd/beta/alb/pool/pool.go create mode 100644 internal/cmd/beta/alb/pool/update/testdata/testconfig.json create mode 100644 internal/cmd/beta/alb/pool/update/update.go create mode 100644 internal/cmd/beta/alb/pool/update/update_test.go create mode 100644 internal/cmd/beta/alb/quotas/quotas.go create mode 100644 internal/cmd/beta/alb/quotas/quotas_test.go create mode 100644 internal/cmd/beta/alb/template/template-alb.yaml create mode 100644 internal/cmd/beta/alb/template/template-pool.yaml create mode 100644 internal/cmd/beta/alb/template/template.go create mode 100644 internal/cmd/beta/alb/template/template_test.go create mode 100644 internal/cmd/beta/alb/update/testdata/testconfig.json create mode 100644 internal/cmd/beta/alb/update/update.go create mode 100644 internal/cmd/beta/alb/update/update_test.go create mode 100644 internal/pkg/services/alb/client/client.go create mode 100644 internal/pkg/services/alb/utils/utils.go create mode 100644 internal/pkg/services/alb/utils/utils_test.go create mode 100644 internal/pkg/utils/strings_test.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 59bbbc485..b58eb067a 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -41,5 +41,6 @@ stackit beta [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit beta alb](./stackit_beta_alb.md) - Manages application loadbalancers * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_alb.md b/docs/stackit_beta_alb.md new file mode 100644 index 000000000..a4e8d9866 --- /dev/null +++ b/docs/stackit_beta_alb.md @@ -0,0 +1,43 @@ +## stackit beta alb + +Manages application loadbalancers + +### Synopsis + +Manage the lifecycle of application loadbalancers. + +``` +stackit beta alb [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta alb" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta alb create](./stackit_beta_alb_create.md) - Creates an application loadbalancer +* [stackit beta alb delete](./stackit_beta_alb_delete.md) - Deletes an application loadbalancer +* [stackit beta alb describe](./stackit_beta_alb_describe.md) - Describes an application loadbalancer +* [stackit beta alb list](./stackit_beta_alb_list.md) - Lists albs +* [stackit beta alb observability-credentials](./stackit_beta_alb_observability-credentials.md) - Provides functionality for application loadbalancer credentials +* [stackit beta alb plans](./stackit_beta_alb_plans.md) - Lists the application load balancer plans +* [stackit beta alb pool](./stackit_beta_alb_pool.md) - Manages target pools for application loadbalancers +* [stackit beta alb quotas](./stackit_beta_alb_quotas.md) - Shows the application load balancer quotas +* [stackit beta alb template](./stackit_beta_alb_template.md) - creates configuration templates to use for resource creation +* [stackit beta alb update](./stackit_beta_alb_update.md) - Updates an application loadbalancer + diff --git a/docs/stackit_beta_alb_create.md b/docs/stackit_beta_alb_create.md new file mode 100644 index 000000000..d33b66ab2 --- /dev/null +++ b/docs/stackit_beta_alb_create.md @@ -0,0 +1,41 @@ +## stackit beta alb create + +Creates an application loadbalancer + +### Synopsis + +Creates an application loadbalancer. + +``` +stackit beta alb create [flags] +``` + +### Examples + +``` + Create an application loadbalancer from a configuration file + $ stackit beta alb create --configuration my-loadbalancer.json +``` + +### Options + +``` + -c, --configuration string Filename of the input configuration file + -h, --help Help for "stackit beta alb create" +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers + diff --git a/docs/stackit_beta_alb_delete.md b/docs/stackit_beta_alb_delete.md new file mode 100644 index 000000000..a83567e86 --- /dev/null +++ b/docs/stackit_beta_alb_delete.md @@ -0,0 +1,40 @@ +## stackit beta alb delete + +Deletes an application loadbalancer + +### Synopsis + +Deletes an application loadbalancer. + +``` +stackit beta alb delete LOADBALANCER_NAME_ARG [flags] +``` + +### Examples + +``` + Delete an application loadbalancer with name "my-load-balancer" + $ stackit beta alb delete my-load-balancer +``` + +### Options + +``` + -h, --help Help for "stackit beta alb delete" +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers + diff --git a/docs/stackit_beta_alb_describe.md b/docs/stackit_beta_alb_describe.md new file mode 100644 index 000000000..008ba874c --- /dev/null +++ b/docs/stackit_beta_alb_describe.md @@ -0,0 +1,40 @@ +## stackit beta alb describe + +Describes an application loadbalancer + +### Synopsis + +Describes an application alb. + +``` +stackit beta alb describe LOADBALANCER_NAME_ARG [flags] +``` + +### Examples + +``` + Get details about an application loadbalancer with name "my-load-balancer" + $ stackit beta alb describe my-load-balancer +``` + +### Options + +``` + -h, --help Help for "stackit beta alb 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers + diff --git a/docs/stackit_beta_alb_list.md b/docs/stackit_beta_alb_list.md new file mode 100644 index 000000000..639b541dd --- /dev/null +++ b/docs/stackit_beta_alb_list.md @@ -0,0 +1,44 @@ +## stackit beta alb list + +Lists albs + +### Synopsis + +Lists application load balancers. + +``` +stackit beta alb list [flags] +``` + +### Examples + +``` + List all load balancers + $ stackit beta alb list + + List the first 10 application load balancers + $ stackit beta alb list --limit=10 +``` + +### Options + +``` + -h, --help Help for "stackit beta alb list" + --limit int Limit the output to the first n elements +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers + diff --git a/docs/stackit_beta_alb_observability-credentials.md b/docs/stackit_beta_alb_observability-credentials.md new file mode 100644 index 000000000..f704d001a --- /dev/null +++ b/docs/stackit_beta_alb_observability-credentials.md @@ -0,0 +1,38 @@ +## stackit beta alb observability-credentials + +Provides functionality for application loadbalancer credentials + +### Synopsis + +Provides functionality for application loadbalancer credentials + +``` +stackit beta alb observability-credentials [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta alb observability-credentials" +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers +* [stackit beta alb observability-credentials add](./stackit_beta_alb_observability-credentials_add.md) - Adds observability credentials to an application load balancer +* [stackit beta alb observability-credentials delete](./stackit_beta_alb_observability-credentials_delete.md) - Deletes credentials +* [stackit beta alb observability-credentials describe](./stackit_beta_alb_observability-credentials_describe.md) - Describes observability credentials for the Application Load Balancer +* [stackit beta alb observability-credentials list](./stackit_beta_alb_observability-credentials_list.md) - Lists all credentials +* [stackit beta alb observability-credentials update](./stackit_beta_alb_observability-credentials_update.md) - Update credentials + diff --git a/docs/stackit_beta_alb_observability-credentials_add.md b/docs/stackit_beta_alb_observability-credentials_add.md new file mode 100644 index 000000000..9e4e544cc --- /dev/null +++ b/docs/stackit_beta_alb_observability-credentials_add.md @@ -0,0 +1,43 @@ +## stackit beta alb observability-credentials add + +Adds observability credentials to an application load balancer + +### Synopsis + +Adds observability credentials (username and password) to an application load balancer. The credentials can be for Observability or another monitoring tool. + +``` +stackit beta alb observability-credentials add [flags] +``` + +### Examples + +``` + Add observability credentials to a load balancer with username "xxx" and display name "yyy", providing the path to a file with the password as flag + $ stackit beta alb observability-credentials add --username xxx --password @./password.txt --display-name yyy +``` + +### Options + +``` + -d, --displayname string Displayname for the credentials + -h, --help Help for "stackit beta alb observability-credentials add" + --password string Password. Can be a string or a file path, if prefixed with "@" (example: @./password.txt). + -u, --username string Username for the credentials +``` + +### 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 beta alb observability-credentials](./stackit_beta_alb_observability-credentials.md) - Provides functionality for application loadbalancer credentials + diff --git a/docs/stackit_beta_alb_observability-credentials_delete.md b/docs/stackit_beta_alb_observability-credentials_delete.md new file mode 100644 index 000000000..8cdbdde27 --- /dev/null +++ b/docs/stackit_beta_alb_observability-credentials_delete.md @@ -0,0 +1,40 @@ +## stackit beta alb observability-credentials delete + +Deletes credentials + +### Synopsis + +Deletes credentials. + +``` +stackit beta alb observability-credentials delete CREDENTIAL_REF [flags] +``` + +### Examples + +``` + Delete credential with name "credential-12345" + $ stackit beta alb observability-credentials delete credential-12345 +``` + +### Options + +``` + -h, --help Help for "stackit beta alb observability-credentials delete" +``` + +### 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 beta alb observability-credentials](./stackit_beta_alb_observability-credentials.md) - Provides functionality for application loadbalancer credentials + diff --git a/docs/stackit_beta_alb_observability-credentials_describe.md b/docs/stackit_beta_alb_observability-credentials_describe.md new file mode 100644 index 000000000..9eafb8d93 --- /dev/null +++ b/docs/stackit_beta_alb_observability-credentials_describe.md @@ -0,0 +1,40 @@ +## stackit beta alb observability-credentials describe + +Describes observability credentials for the Application Load Balancer + +### Synopsis + +Describes observability credentials for the Application Load Balancer. + +``` +stackit beta alb observability-credentials describe CREDENTIAL_REF [flags] +``` + +### Examples + +``` + Get details about credentials with name "credential-12345" + $ stackit beta alb observability-credentials describe credential-12345 +``` + +### Options + +``` + -h, --help Help for "stackit beta alb observability-credentials 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 beta alb observability-credentials](./stackit_beta_alb_observability-credentials.md) - Provides functionality for application loadbalancer credentials + diff --git a/docs/stackit_beta_alb_observability-credentials_list.md b/docs/stackit_beta_alb_observability-credentials_list.md new file mode 100644 index 000000000..9a71757b2 --- /dev/null +++ b/docs/stackit_beta_alb_observability-credentials_list.md @@ -0,0 +1,47 @@ +## stackit beta alb observability-credentials list + +Lists all credentials + +### Synopsis + +Lists all credentials. + +``` +stackit beta alb observability-credentials list [flags] +``` + +### Examples + +``` + Lists all credentials + $ stackit beta alb observability-credentials list + + Lists all credentials in JSON format + $ stackit beta alb observability-credentials list --output-format json + + Lists up to 10 credentials + $ stackit beta alb observability-credentials list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta alb observability-credentials list" + --limit int Number of credentials to list +``` + +### 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 beta alb observability-credentials](./stackit_beta_alb_observability-credentials.md) - Provides functionality for application loadbalancer credentials + diff --git a/docs/stackit_beta_alb_observability-credentials_update.md b/docs/stackit_beta_alb_observability-credentials_update.md new file mode 100644 index 000000000..61994726d --- /dev/null +++ b/docs/stackit_beta_alb_observability-credentials_update.md @@ -0,0 +1,43 @@ +## stackit beta alb observability-credentials update + +Update credentials + +### Synopsis + +Update credentials. + +``` +stackit beta alb observability-credentials update CREDENTIAL_REF_ARG [flags] +``` + +### Examples + +``` + Update the password of observability credentials of Application Load Balancer with credentials reference "credentials-xxx", by providing the path to a file with the new password as flag + $ stackit beta alb observability-credentials update credentials-xxx --username user1 --displayname user1 --password @./new-password.txt +``` + +### Options + +``` + -d, --displayname string Displayname for the credentials + -h, --help Help for "stackit beta alb observability-credentials update" + --password string Password. Can be a string or a file path, if prefixed with "@" (example: @./password.txt). + -u, --username string Username for the credentials +``` + +### 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 beta alb observability-credentials](./stackit_beta_alb_observability-credentials.md) - Provides functionality for application loadbalancer credentials + diff --git a/docs/stackit_beta_alb_plans.md b/docs/stackit_beta_alb_plans.md new file mode 100644 index 000000000..3e46e1185 --- /dev/null +++ b/docs/stackit_beta_alb_plans.md @@ -0,0 +1,40 @@ +## stackit beta alb plans + +Lists the application load balancer plans + +### Synopsis + +Lists the available application load balancer plans. + +``` +stackit beta alb plans [flags] +``` + +### Examples + +``` + List all application load balancer plans + $ stackit beta alb plans +``` + +### Options + +``` + -h, --help Help for "stackit beta alb plans" +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers + diff --git a/docs/stackit_beta_alb_pool.md b/docs/stackit_beta_alb_pool.md new file mode 100644 index 000000000..1553d06bc --- /dev/null +++ b/docs/stackit_beta_alb_pool.md @@ -0,0 +1,34 @@ +## stackit beta alb pool + +Manages target pools for application loadbalancers + +### Synopsis + +Manage the lifecycle of target pools for application loadbalancers. + +``` +stackit beta alb pool [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta alb pool" +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers +* [stackit beta alb pool update](./stackit_beta_alb_pool_update.md) - Updates an application target pool + diff --git a/docs/stackit_beta_alb_pool_update.md b/docs/stackit_beta_alb_pool_update.md new file mode 100644 index 000000000..156452e11 --- /dev/null +++ b/docs/stackit_beta_alb_pool_update.md @@ -0,0 +1,42 @@ +## stackit beta alb pool update + +Updates an application target pool + +### Synopsis + +Updates an application target pool. + +``` +stackit beta alb pool update [flags] +``` + +### Examples + +``` + Update an application target pool from a configuration file (the name of the pool is read from the file) + $ stackit beta alb update --configuration my-target-pool.json --name my-load-balancer +``` + +### Options + +``` + -c, --configuration string Filename of the input configuration file + -h, --help Help for "stackit beta alb pool update" + -n, --name string Name of the target pool name to update +``` + +### 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 beta alb pool](./stackit_beta_alb_pool.md) - Manages target pools for application loadbalancers + diff --git a/docs/stackit_beta_alb_quotas.md b/docs/stackit_beta_alb_quotas.md new file mode 100644 index 000000000..26f9168ce --- /dev/null +++ b/docs/stackit_beta_alb_quotas.md @@ -0,0 +1,40 @@ +## stackit beta alb quotas + +Shows the application load balancer quotas + +### Synopsis + +Shows the application load balancer quotas for the application load balancers. + +``` +stackit beta alb quotas [flags] +``` + +### Examples + +``` + List all application load balancer quotas + $ stackit beta alb quotas +``` + +### Options + +``` + -h, --help Help for "stackit beta alb quotas" +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers + diff --git a/docs/stackit_beta_alb_template.md b/docs/stackit_beta_alb_template.md new file mode 100644 index 000000000..e914e3024 --- /dev/null +++ b/docs/stackit_beta_alb_template.md @@ -0,0 +1,45 @@ +## stackit beta alb template + +creates configuration templates to use for resource creation + +### Synopsis + +creates a json or yaml template file for creating/updating an application loadbalancer or target pool. + +``` +stackit beta alb template [flags] +``` + +### Examples + +``` + Create a yaml template + $ stackit beta alb template --format=yaml --type alb + + Create a json template + $ stackit beta alb template --format=json --type pool +``` + +### Options + +``` + -f, --format string Defines the output format ('yaml' or 'json'), default is 'json' (default "json") + -h, --help Help for "stackit beta alb template" + -t, --type string Defines the output type ('alb' or 'pool'), default is 'alb' (default "alb") +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers + diff --git a/docs/stackit_beta_alb_update.md b/docs/stackit_beta_alb_update.md new file mode 100644 index 000000000..36c4a8dd7 --- /dev/null +++ b/docs/stackit_beta_alb_update.md @@ -0,0 +1,41 @@ +## stackit beta alb update + +Updates an application loadbalancer + +### Synopsis + +Updates an application loadbalancer. + +``` +stackit beta alb update [flags] +``` + +### Examples + +``` + Update an application loadbalancer from a configuration file + $ stackit beta alb update --configuration my-loadbalancer.json +``` + +### Options + +``` + -c, --configuration string Filename of the input configuration file + -h, --help Help for "stackit beta alb update" +``` + +### 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 beta alb](./stackit_beta_alb.md) - Manages application loadbalancers + diff --git a/go.mod b/go.mod index 540ee75f3..e8c9959d9 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.1 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 diff --git a/go.sum b/go.sum index 8f4665360..3e7029eac 100644 --- a/go.sum +++ b/go.sum @@ -113,6 +113,8 @@ github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJSjtaGnUI7UE7ITb5IT0= github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1 h1:7VOUNsnNBL2iQsZ3lJogNzKx4lrYEawDYllcXV1gEik= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1/go.mod h1:J2/Jk+leR6AjBotd7USJJzX+AEIHH11yxnmx+6ciJEk= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA= github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo= diff --git a/internal/cmd/beta/alb/alb.go b/internal/cmd/beta/alb/alb.go new file mode 100644 index 000000000..94f082da8 --- /dev/null +++ b/internal/cmd/beta/alb/alb.go @@ -0,0 +1,47 @@ +package alb + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/list" + observabilitycredentials "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/plans" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/pool" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/quotas" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/template" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "alb", + Short: "Manages application loadbalancers", + Long: "Manage the lifecycle of application loadbalancers.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand( + list.NewCmd(p), + template.NewCmd(p), + create.NewCmd(p), + update.NewCmd(p), + observabilitycredentials.NewCmd(p), + describe.NewCmd(p), + delete.NewCmd(p), + pool.NewCmd(p), + plans.NewCmd(p), + quotas.NewCmd(p), + ) +} diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go new file mode 100644 index 000000000..462d4e381 --- /dev/null +++ b/internal/cmd/beta/alb/create/create.go @@ -0,0 +1,197 @@ +package create + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "os" + "strings" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" + "github.com/stackitcloud/stackit-sdk-go/services/alb/wait" +) + +const ( + configurationFlag = "configuration" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Configuration *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates an application loadbalancer", + Long: "Creates an application loadbalancer.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create an application loadbalancer from a configuration file`, + "$ stackit beta alb create --configuration my-loadbalancer.json"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create an application loadbalancer for project %q?", projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create application loadbalancer: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("Creating loadbalancer") + _, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for loadbalancer creation: %w", err) + } + s.Stop() + } + + return outputResult(p, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(configurationFlag, "c", "", "Filename of the input configuration file") + err := flags.MarkFlagsRequired(cmd, configurationFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Configuration: flags.FlagToStringPointer(p, cmd, configurationFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) (req alb.ApiCreateLoadBalancerRequest, err error) { + req = apiClient.CreateLoadBalancer(ctx, model.ProjectId, model.Region) + payload, err := readPayload(ctx, model) + if err != nil { + return req, err + } + return req.CreateLoadBalancerPayload(payload), nil +} + +func readPayload(_ context.Context, model *inputModel) (payload alb.CreateLoadBalancerPayload, err error) { + if model.Configuration == nil { + return payload, fmt.Errorf("no configuration file defined") + } + file, err := os.Open(*model.Configuration) + if err != nil { + return payload, fmt.Errorf("cannot open configuration file %q: %w", *model.Configuration, err) + } + defer file.Close() // nolint:errcheck // at this point close errors are not relevant anymore + + if strings.HasSuffix(*model.Configuration, ".yaml") { + decoder := yaml.NewDecoder(bufio.NewReader(file), yaml.UseJSONUnmarshaler()) + if err := decoder.Decode(&payload); err != nil { + return payload, fmt.Errorf("cannot deserialize yaml configuration from %q: %w", *model.Configuration, err) + } + } else if strings.HasSuffix(*model.Configuration, ".json") { + decoder := json.NewDecoder(bufio.NewReader(file)) + if err := decoder.Decode(&payload); err != nil { + return payload, fmt.Errorf("cannot deserialize json configuration from %q: %w", *model.Configuration, err) + } + } else { + return payload, fmt.Errorf("cannot determine configuration fileformat of %q by extension. Must be '.json' or '.yaml'", *model.Configuration) + } + + return payload, nil +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *alb.LoadBalancer) error { + if resp == nil { + return fmt.Errorf("create loadbalancer response is empty") + } + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal loadbalancer: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal loadbalancer: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s application loadbalancer for %q. Name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name)) + return nil + } +} diff --git a/internal/cmd/beta/alb/create/create_test.go b/internal/cmd/beta/alb/create/create_test.go new file mode 100644 index 000000000..d77fb2022 --- /dev/null +++ b/internal/cmd/beta/alb/create/create_test.go @@ -0,0 +1,259 @@ +package create + +import ( + "context" + _ "embed" + "encoding/json" + "log" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +//go:embed testdata/testconfig.json +var testConfiguration []byte + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &alb.APIClient{} +var testProjectId = uuid.NewString() +var testRegion = "eu01" +var testConfig = "testdata/testconfig.json" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + configurationFlag: testConfig, + 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, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Configuration: utils.Ptr(testConfig), + } + for _, mod := range mods { + mod(model) + } + return model +} +func fixturePayload(mods ...func(payload *alb.CreateLoadBalancerPayload)) (payload alb.CreateLoadBalancerPayload) { + if err := json.Unmarshal(testConfiguration, &payload); err != nil { + log.Panicf("cannot deserialize test configuration: %v", err) + } + for _, f := range mods { + f(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *alb.ApiCreateLoadBalancerRequest)) alb.ApiCreateLoadBalancerRequest { + request := testClient.CreateLoadBalancer(testCtx, testProjectId, testRegion) + + request = request.CreateLoadBalancerPayload(fixturePayload()) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "required fields only", + flagValues: map[string]string{ + projectIdFlag: testProjectId, + configurationFlag: testConfig, + }, + isValid: true, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Configuration: &testConfig, + }, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiCreateLoadBalancerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "required fields only", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + Configuration: &testConfig, + }, + expectedRequest: testClient. + CreateLoadBalancer(testCtx, testProjectId, testRegion). + CreateLoadBalancerPayload(fixturePayload()), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + t.Fatalf("canno create request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + resp *alb.LoadBalancer + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty response as argument", + args: args{ + model: fixtureInputModel(), + resp: &alb.LoadBalancer{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/create/testdata/testconfig.json b/internal/cmd/beta/alb/create/testdata/testconfig.json new file mode 100644 index 000000000..b81294c66 --- /dev/null +++ b/internal/cmd/beta/alb/create/testdata/testconfig.json @@ -0,0 +1,125 @@ +{ + "externalAddress": "10.100.42.1", + "listeners": [ + { + "displayName": "listener1", + "http": {}, + "https": { + "certificateConfig": { + "certificateIds": [ + "cert-1", + "cert-2", + "cert-3" + ] + } + }, + "port": 443, + "protocol": "PROTOCOL_HTTPS", + "rules": [ + { + "host": "front.facing.host", + "http": { + "subRules": [ + { + "cookiePersistence": { + "name": "cookie1", + "ttl": "120s" + }, + "headers": [ + { + "name": "testheader1", + "exactMatch": "X-test-header1" + }, + { + "name": "testheader2", + "exactMatch": "X-test-header2" + }, + { + "name": "testheader3", + "exactMatch": "X-test-header3" + } + ], + "pathPrefix": "/foo", + "queryParameters": [ + { + "name": "query-param", + "exactMatch": "q" + }, + { + "name": "region", + "exactMatch": "region" + } + ], + "targetPool": "my-target-pool", + "webSocket": false + } + ] + } + } + ] + } + ], + "name": "my-load-balancer", + "networks": [ + { + "networkId": "00000000-0000-0000-0000-000000000000", + "role": "ROLE_LISTENERS_AND_TARGETS" + }, + { + "networkId": "00000000-0000-0000-0000-000000000001", + "role": "ROLE_LISTENERS_AND_TARGETS" + } + ], + "options": { + "accessControl": { + "allowedSourceRanges": [ + "192.168.42.0-192.168.42.10", + "192.168.54.0-192.168.54.10" + ] + }, + "ephemeralAddress": true, + "observability": { + "logs": { + "credentialsRef": "my-credentials", + "pushUrl": "https://my.observability.host//loki/api/v1/push" + }, + "metrics": { + "credentialsRef": "my-credentials", + "pushUrl": "https://my.observability.host///api/v1/receive" + } + }, + "privateNetworkOnly": true + }, + "planId": "p10", + "targetPools": [ + { + "activeHealthCheck": { + "healthyThreshold": 3, + "httpHealthChecks": { + "okStatuses": [ + "200", + "204" + ], + "path": "/health" + }, + "interval": "10s", + "intervalJitter": "3s", + "timeout": "5s", + "unhealthyThreshold": 1 + }, + "name": "my-target-pool", + "targetPort": 5732, + "targets": [ + { + "displayName": "my-target1", + "ip": "192.11.2.5" + } + ], + "tlsConfig": { + "customCa": "my.private.ca", + "enabled": true, + "skipCertificateValidation": false + } + } + ] +} diff --git a/internal/cmd/beta/alb/delete/delete.go b/internal/cmd/beta/alb/delete/delete.go new file mode 100644 index 000000000..c3709e8a9 --- /dev/null +++ b/internal/cmd/beta/alb/delete/delete.go @@ -0,0 +1,103 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "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/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + loadbalancerNameArg = "LOADBALANCER_NAME_ARG" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", loadbalancerNameArg), + Short: "Deletes an application loadbalancer", + Long: "Deletes an application loadbalancer.", + Args: args.SingleArg(loadbalancerNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Delete an application loadbalancer with name "my-load-balancer"`, + "$ stackit beta alb delete my-load-balancer", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete the application loadbalancer %q for project %q?", model.Name, projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("delete loadbalancer: %w", err) + } + + p.Outputf("Load balancer %q deleted.", model.Name) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + loadbalancerName := inputArgs[0] + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: loadbalancerName, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiDeleteLoadBalancerRequest { + return apiClient.DeleteLoadBalancer(ctx, model.ProjectId, model.Region, model.Name) +} diff --git a/internal/cmd/beta/alb/delete/delete_test.go b/internal/cmd/beta/alb/delete/delete_test.go new file mode 100644 index 000000000..3bc65bfd1 --- /dev/null +++ b/internal/cmd/beta/alb/delete/delete_test.go @@ -0,0 +1,192 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") + testProjectId = uuid.NewString() + testRegion = "eu01" + testClient = &alb.APIClient{} + testLoadBalancerName = "my-test-loadbalancer" +) + +func fixtureArgValues(mods ...func(argVales []string)) []string { + argVales := []string{ + testLoadBalancerName, + } + for _, m := range mods { + m(argVales) + } + return argVales +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + } + for _, m := range mods { + m(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + Region: testRegion, + }, + Name: testLoadBalancerName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *alb.ApiDeleteLoadBalancerRequest)) alb.ApiDeleteLoadBalancerRequest { + request := testClient.DeleteLoadBalancer(testCtx, testProjectId, testRegion, testLoadBalancerName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argsValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argsValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argsValues: []string{}, + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: false, + }, + { + description: "no arg values", + argsValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argsValues: fixtureArgValues(), + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: true, + expectedModel: fixtureInputModel(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argsValues) + 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.argsValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedResult alb.ApiDeleteLoadBalancerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedResult: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, tt.model, testClient) + + diff := cmp.Diff(request, tt.expectedResult, + cmp.AllowUnexported(tt.expectedResult), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/alb/describe/describe.go b/internal/cmd/beta/alb/describe/describe.go new file mode 100644 index 000000000..8a1403585 --- /dev/null +++ b/internal/cmd/beta/alb/describe/describe.go @@ -0,0 +1,220 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "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/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + loadbalancerNameArg = "LOADBALANCER_NAME_ARG" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", loadbalancerNameArg), + Short: "Describes an application loadbalancer", + Long: "Describes an application alb.", + Args: args.SingleArg(loadbalancerNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details about an application loadbalancer with name "my-load-balancer"`, + "$ stackit beta alb describe my-load-balancer", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read loadbalancer: %w", err) + } + + if loadbalancer := resp; loadbalancer != nil { + return outputResult(p, model.OutputFormat, loadbalancer) + } + p.Outputln("No load balancer found.") + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + loadbalancerName := inputArgs[0] + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: loadbalancerName, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiGetLoadBalancerRequest { + return apiClient.GetLoadBalancer(ctx, model.ProjectId, model.Region, model.Name) +} + +func outputResult(p *print.Printer, outputFormat string, response *alb.LoadBalancer) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(response, "", " ") + + if err != nil { + return fmt.Errorf("marshal loadbalancer: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(response, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + + if err != nil { + return fmt.Errorf("marshal loadbalancer: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + if err := outputResultAsTable(p, response); err != nil { + return err + } + } + + return nil +} + +func outputResultAsTable(p *print.Printer, loadbalancer *alb.LoadBalancer) error { + content := []tables.Table{} + + content = append(content, buildLoadBalancerTable(loadbalancer)) + + if loadbalancer.Listeners != nil { + content = append(content, buildListenersTable(*loadbalancer.Listeners)) + } + + if loadbalancer.TargetPools != nil { + content = append(content, buildTargetPoolsTable(*loadbalancer.TargetPools)) + } + + err := tables.DisplayTables(p, content) + if err != nil { + return fmt.Errorf("display output: %w", err) + } + + return nil +} + +func buildLoadBalancerTable(loadbalancer *alb.LoadBalancer) tables.Table { + acl := []string{} + privateAccessOnly := false + if loadbalancer.Options != nil { + if loadbalancer.Options.AccessControl != nil && loadbalancer.Options.AccessControl.AllowedSourceRanges != nil { + acl = *loadbalancer.Options.AccessControl.AllowedSourceRanges + } + + if loadbalancer.Options.PrivateNetworkOnly != nil { + privateAccessOnly = *loadbalancer.Options.PrivateNetworkOnly + } + } + + networkId := "-" + if loadbalancer.Networks != nil && len(*loadbalancer.Networks) > 0 { + networks := *loadbalancer.Networks + networkId = *networks[0].NetworkId + } + + externalAddress := utils.PtrStringDefault(loadbalancer.ExternalAddress, "-") + + errorDescriptions := []string{} + if loadbalancer.Errors != nil && len((*loadbalancer.Errors)) > 0 { + for _, err := range *loadbalancer.Errors { + errorDescriptions = append(errorDescriptions, *err.Description) + } + } + + table := tables.NewTable() + table.SetTitle("Load Balancer") + table.AddRow("NAME", utils.PtrString(loadbalancer.Name)) + table.AddSeparator() + table.AddRow("STATE", utils.PtrString(loadbalancer.Status)) + table.AddSeparator() + if len(errorDescriptions) > 0 { + table.AddRow("ERROR DESCRIPTIONS", strings.Join(errorDescriptions, "\n")) + table.AddSeparator() + } + table.AddRow("PRIVATE ACCESS ONLY", privateAccessOnly) + table.AddSeparator() + table.AddRow("ATTACHED PUBLIC IP", externalAddress) + table.AddSeparator() + table.AddRow("ATTACHED NETWORK ID", networkId) + table.AddSeparator() + table.AddRow("ACL", acl) + return table +} + +func buildListenersTable(listeners []alb.Listener) tables.Table { + table := tables.NewTable() + table.SetTitle("Listeners") + table.SetHeader("NAME", "PORT", "PROTOCOL", "TARGET POOL") + for i := range listeners { + listener := listeners[i] + table.AddRow( + utils.PtrString(listener.Name), + utils.PtrString(listener.Port), + utils.PtrString(listener.Protocol), + ) + } + return table +} + +func buildTargetPoolsTable(targetPools []alb.TargetPool) tables.Table { + table := tables.NewTable() + table.SetTitle("Target Pools") + table.SetHeader("NAME", "PORT", "TARGETS") + for _, targetPool := range targetPools { + table.AddRow(utils.PtrString(targetPool.Name), utils.PtrString(targetPool.TargetPort), len(*targetPool.Targets)) + } + return table +} diff --git a/internal/cmd/beta/alb/describe/describe_test.go b/internal/cmd/beta/alb/describe/describe_test.go new file mode 100644 index 000000000..0f621c72e --- /dev/null +++ b/internal/cmd/beta/alb/describe/describe_test.go @@ -0,0 +1,224 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") + testProjectId = uuid.NewString() + testRegion = "eu01" + testClient = &alb.APIClient{} + testLoadBalancerName = "my-test-loadbalancer" +) + +func fixtureArgValues(mods ...func(argVales []string)) []string { + argVales := []string{ + testLoadBalancerName, + } + for _, m := range mods { + m(argVales) + } + return argVales +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + } + for _, m := range mods { + m(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + Region: testRegion, + }, + Name: testLoadBalancerName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *alb.ApiGetLoadBalancerRequest)) alb.ApiGetLoadBalancerRequest { + request := testClient.GetLoadBalancer(testCtx, testProjectId, testRegion, testLoadBalancerName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argsValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argsValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argsValues: []string{}, + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: false, + }, + { + description: "no arg values", + argsValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argsValues: fixtureArgValues(), + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: true, + expectedModel: fixtureInputModel(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argsValues) + 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.argsValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedResult alb.ApiGetLoadBalancerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedResult: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, tt.model, testClient) + + diff := cmp.Diff(request, tt.expectedResult, + cmp.AllowUnexported(tt.expectedResult), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + showOnlyPublicKey bool + response *alb.LoadBalancer + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "base", + args: args{ + outputFormat: "", + showOnlyPublicKey: false, + response: &alb.LoadBalancer{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go new file mode 100644 index 000000000..4050e8791 --- /dev/null +++ b/internal/cmd/beta/alb/list/list.go @@ -0,0 +1,178 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +const ( + labelSelectorFlag = "label-selector" + limitFlag = "limit" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists albs", + Long: "Lists application load balancers.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all load balancers`, + `$ stackit beta alb list`, + ), + examples.NewExample( + `List the first 10 application load balancers`, + `$ stackit beta alb list --limit=10`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + response, err := request.Execute() + if err != nil { + return fmt.Errorf("list load balancerse: %w", err) + } + + if items := response.LoadBalancers; items == nil || len(*items) == 0 { + p.Info("No load balancers found for project %q", projectLabel) + } else { + if model.Limit != nil && len(*items) > int(*model.Limit) { + *items = (*items)[:*model.Limit] + } + if err := outputResult(p, model.OutputFormat, *items); err != nil { + return fmt.Errorf("output loadbalancers: %w", err) + } + } + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiListLoadBalancersRequest { + request := apiClient.ListLoadBalancers(ctx, model.ProjectId, model.Region) + + return request +} +func outputResult(p *print.Printer, outputFormat string, items []alb.LoadBalancer) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(items, "", " ") + if err != nil { + return fmt.Errorf("marshal loadbalancer list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal loadbalancer list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("NAME", "EXTERNAL ADDRESS", "REGION", "STATUS", "VERSION", "ERRORS") + for _, item := range items { + var errNo int + if item.Errors != nil { + errNo = len(*item.Errors) + } + table.AddRow(utils.PtrString(item.Name), + utils.PtrString(item.ExternalAddress), + utils.PtrString(item.Region), + utils.PtrString(item.Status), + utils.PtrString(item.Version), + errNo, + ) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/alb/list/list_test.go b/internal/cmd/beta/alb/list/list_test.go new file mode 100644 index 000000000..77c915266 --- /dev/null +++ b/internal/cmd/beta/alb/list/list_test.go @@ -0,0 +1,207 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &alb.APIClient{} + testProjectId = uuid.NewString() + testRegion = "eu01" + testLimit int64 = 10 +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: strconv.Itoa(int(testLimit)), + } + 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}, + Limit: &testLimit, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *alb.ApiListLoadBalancersRequest)) alb.ApiListLoadBalancersRequest { + request := testClient.ListLoadBalancers(context.Background(), 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiListLoadBalancersRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmpopts.IgnoreFields(alb.ApiListLoadBalancersRequest{}, "ctx"), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + items []alb.LoadBalancer + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + outputFormat: "", + items: []alb.LoadBalancer{}, + }, + wantErr: false, + }, + { + name: "output format json", + args: args{ + outputFormat: print.JSONOutputFormat, + items: []alb.LoadBalancer{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/observability-credentials/add/add.go b/internal/cmd/beta/alb/observability-credentials/add/add.go new file mode 100644 index 000000000..806af5e13 --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/add/add.go @@ -0,0 +1,146 @@ +package add + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + usernameFlag = "username" + displaynameFlag = "displayname" + passwordFlag = "password" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Username *string + Displayname *string + Password *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "add", + Short: "Adds observability credentials to an application load balancer", + Long: "Adds observability credentials (username and password) to an application load balancer. The credentials can be for Observability or another monitoring tool.", + Args: cobra.NoArgs, + Example: examples.Build( + examples.NewExample( + `Add observability credentials to a load balancer with username "xxx" and display name "yyy", providing the path to a file with the password as flag`, + "$ stackit beta alb observability-credentials add --username xxx --password @./password.txt --display-name yyy"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := "Are your sure you want to add credentials?" + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("add credential: %w", err) + } + + return outputResult(p, model.GlobalFlagModel.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(usernameFlag, "u", "", "Username for the credentials") + cmd.Flags().StringP(displaynameFlag, "d", "", "Displayname for the credentials") + cmd.Flags().Var(flags.ReadFromFileFlag(), passwordFlag, `Password. Can be a string or a file path, if prefixed with "@" (example: @./password.txt).`) + + cobra.CheckErr(flags.MarkFlagsRequired(cmd, usernameFlag, displaynameFlag)) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Username: flags.FlagToStringPointer(p, cmd, usernameFlag), + Displayname: flags.FlagToStringPointer(p, cmd, displaynameFlag), + Password: flags.FlagToStringPointer(p, cmd, passwordFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string fo debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiCreateCredentialsRequest { + req := apiClient.CreateCredentials(ctx, model.ProjectId, model.Region) + payload := alb.CreateCredentialsPayload{ + DisplayName: model.Displayname, + Password: model.Password, + Username: model.Username, + } + return req.CreateCredentialsPayload(payload) +} + +func outputResult(p *print.Printer, outputFormat string, item *alb.CreateCredentialsResponse) error { + if item == nil { + return fmt.Errorf("no credential found") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(item, "", " ") + if err != nil { + return fmt.Errorf("marshal credential: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(item, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal credential: %w", err) + } + p.Outputln(string(details)) + default: + if item.Credential != nil { + p.Outputf("Created credential %s\n", + utils.PtrString(item.Credential.CredentialsRef), + ) + } + } + return nil +} diff --git a/internal/cmd/beta/alb/observability-credentials/add/add_test.go b/internal/cmd/beta/alb/observability-credentials/add/add_test.go new file mode 100644 index 000000000..a84b1405b --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/add/add_test.go @@ -0,0 +1,213 @@ +package add + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &alb.APIClient{} + +var ( + testProjectId = uuid.NewString() + testRegion = "eu01" + testDisplayname = "displayname" + testUsername = "testuser" + testPassword = "testpassword" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + usernameFlag: testUsername, + displaynameFlag: testDisplayname, + passwordFlag: testPassword, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + Region: testRegion, + }, + Username: &testUsername, + Displayname: &testDisplayname, + Password: &testPassword, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *alb.ApiCreateCredentialsRequest)) alb.ApiCreateCredentialsRequest { + request := testClient.CreateCredentials(testCtx, testProjectId, testRegion) + request = request.CreateCredentialsPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *alb.CreateCredentialsPayload)) alb.CreateCredentialsPayload { + payload := alb.CreateCredentialsPayload{ + DisplayName: &testDisplayname, + Password: &testPassword, + Username: &testUsername, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiCreateCredentialsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(alb.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + item *alb.CreateCredentialsResponse + outputFormat string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + item: nil, + outputFormat: "", + }, + wantErr: true, + }, + { + name: "base", + args: args{ + item: &alb.CreateCredentialsResponse{}, + outputFormat: "", + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.item); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete.go b/internal/cmd/beta/alb/observability-credentials/delete/delete.go new file mode 100644 index 000000000..e71a6fee4 --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete.go @@ -0,0 +1,98 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "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/alb/client" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + credentialRefArg = "CREDENTIAL_REF" // nolint:gosec // false alert, these are not valid credentials +) + +type inputModel struct { + *globalflags.GlobalFlagModel + CredentialsRef string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", credentialRefArg), + Short: "Deletes credentials", + Long: "Deletes credentials.", + Args: args.SingleArg(credentialRefArg, nil), + Example: examples.Build( + examples.NewExample( + `Delete credential with name "credential-12345"`, + "$ stackit beta alb observability-credentials delete credential-12345", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete credentials %q?", model.CredentialsRef) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("delete credential: %w", err) + } + + p.Info("Deleted credential %q\n", model.CredentialsRef) + + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + credentialRef := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + CredentialsRef: credentialRef, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiDeleteCredentialsRequest { + return apiClient.DeleteCredentials(ctx, model.ProjectId, model.Region, model.CredentialsRef) +} diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go b/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go new file mode 100644 index 000000000..6f5ff0dd8 --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go @@ -0,0 +1,192 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/alb" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") + testProjectId = uuid.NewString() + testRegion = "eu01" + testClient = &alb.APIClient{} + testCredentialRef = "credential-12345" +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testCredentialRef, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +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{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + Region: testRegion, + }, + CredentialsRef: testCredentialRef, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *alb.ApiDeleteCredentialsRequest)) alb.ApiDeleteCredentialsRequest { + request := testClient.DeleteCredentials(testCtx, testProjectId, testRegion, testCredentialRef) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: false, + }, + { + description: "no args", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flags", + argValues: fixtureArgValues(), + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: true, + expectedModel: fixtureInputModel(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + 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 input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiDeleteCredentialsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe.go b/internal/cmd/beta/alb/observability-credentials/describe/describe.go new file mode 100644 index 000000000..091d08ef2 --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe.go @@ -0,0 +1,133 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "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/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + credentialRefArg = "CREDENTIAL_REF" // nolint:gosec // false alert, these are not valid credentials +) + +type inputModel struct { + *globalflags.GlobalFlagModel + CredentialRef string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", credentialRefArg), + Short: "Describes observability credentials for the Application Load Balancer", + Long: "Describes observability credentials for the Application Load Balancer.", + Args: args.SingleArg(credentialRefArg, nil), + Example: examples.Build( + examples.NewExample( + `Get details about credentials with name "credential-12345"`, + "$ stackit beta alb observability-credentials describe credential-12345", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read credentials: %w", err) + } + + if credential := resp; credential != nil && credential.Credential != nil { + return outputResult(p, model.OutputFormat, *credential.Credential) + } + p.Outputln("No credentials found.") + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + credentialRef := inputArgs[0] + model := inputModel{ + GlobalFlagModel: globalFlags, + CredentialRef: credentialRef, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiGetCredentialsRequest { + return apiClient.GetCredentials(ctx, model.ProjectId, model.Region, model.CredentialRef) +} + +func outputResult(p *print.Printer, outputFormat string, response alb.CredentialsResponse) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(response, "", " ") + + if err != nil { + return fmt.Errorf("marshal credentials: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(response, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + + if err != nil { + return fmt.Errorf("marshal credentials: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("CREDENTIAL REF", utils.PtrString(response.CredentialsRef)) + table.AddSeparator() + table.AddRow("DISPLAYNAME", utils.PtrString(response.DisplayName)) + table.AddSeparator() + table.AddRow("UESRNAME", utils.PtrString(response.Username)) + table.AddSeparator() + table.AddRow("REGION", utils.PtrString(response.Region)) + table.AddSeparator() + + p.Outputln(table.Render()) + } + + return nil +} diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go b/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go new file mode 100644 index 000000000..1d4f201a5 --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go @@ -0,0 +1,224 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") + testProjectId = uuid.NewString() + testRegion = "eu01" + testClient = &alb.APIClient{} + testCredentialRef = "credential-12345" +) + +func fixtureArgValues(mods ...func(argVales []string)) []string { + argVales := []string{ + testCredentialRef, + } + for _, m := range mods { + m(argVales) + } + return argVales +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + } + for _, m := range mods { + m(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + Region: testRegion, + }, + CredentialRef: testCredentialRef, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *alb.ApiGetCredentialsRequest)) alb.ApiGetCredentialsRequest { + request := testClient.GetCredentials(testCtx, testProjectId, testRegion, testCredentialRef) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argsValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argsValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argsValues: []string{}, + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: false, + }, + { + description: "no arg values", + argsValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argsValues: fixtureArgValues(), + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: true, + expectedModel: fixtureInputModel(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateArgs(tt.argsValues) + 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.argsValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedResult alb.ApiGetCredentialsRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedResult: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, tt.model, testClient) + + diff := cmp.Diff(request, tt.expectedResult, + cmp.AllowUnexported(tt.expectedResult), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + showOnlyPublicKey bool + response alb.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "base", + args: args{ + outputFormat: "", + showOnlyPublicKey: false, + response: alb.CredentialsResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/observability-credentials/list/list.go b/internal/cmd/beta/alb/observability-credentials/list/list.go new file mode 100644 index 000000000..d08a9026e --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/list/list.go @@ -0,0 +1,163 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all credentials", + Long: "Lists all credentials.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all credentials`, + "$ stackit beta alb observability-credentials list", + ), + examples.NewExample( + `Lists all credentials in JSON format`, + "$ stackit beta alb observability-credentials list --output-format json", + ), + examples.NewExample( + `Lists up to 10 credentials`, + "$ stackit beta alb observability-credentials list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list credentials: %w", err) + } + + if resp.Credentials == nil || len(*resp.Credentials) == 0 { + p.Info("No credentials found\n") + return nil + } + + items := *resp.Credentials + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(p, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Number of credentials to list") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.InfoLevel, modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiListCredentialsRequest { + req := apiClient.ListCredentials(ctx, model.ProjectId, model.Region) + return req +} + +func outputResult(p *print.Printer, outputFormat string, items []alb.CredentialsResponse) error { + if items == nil { + p.Outputln("no credentials found") + return nil + } + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(items, "", " ") + if err != nil { + return fmt.Errorf("marshal credentials: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal credentials: %w", err) + } + p.Outputln(string(details)) + + default: + table := tables.NewTable() + table.SetHeader("CREDENTIAL REF", "DISPLAYNAME", "USERNAME", "REGION") + + for _, item := range items { + table.AddRow( + utils.PtrString(item.CredentialsRef), + utils.PtrString(item.DisplayName), + utils.PtrString(item.Username), + utils.PtrString(item.Region), + ) + } + + p.Outputln(table.Render()) + } + return nil +} diff --git a/internal/cmd/beta/alb/observability-credentials/list/list_test.go b/internal/cmd/beta/alb/observability-credentials/list/list_test.go new file mode 100644 index 000000000..f3c305298 --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/list/list_test.go @@ -0,0 +1,226 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") + testClient = &alb.APIClient{} + + testProjectId = uuid.NewString() + testRegion = "eu01" + testLimit = int64(64) +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: strconv.FormatInt(testLimit, 10), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(inputModel *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + Region: testRegion, + }, + Limit: utils.Ptr(testLimit), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *alb.ApiListCredentialsRequest)) alb.ApiListCredentialsRequest { + request := testClient.ListCredentials(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: "no values", + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.Limit = nil + }), + }, + { + description: "withoutLimit", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, "limit") + }), + isValid: true, + expectedModel: fixtureInputModel(func(inputModel *inputModel) { + inputModel.Limit = nil + }), + }, + { + description: "invalid limit 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "invalid limit 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "label selector empty", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %v", err) + } + + if !tt.isValid { + t.Fatal("did not fail on invalid input") + } + diff := cmp.Diff(model, tt.expectedModel) + if diff != "" { + t.Fatalf("data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiListCredentialsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("request does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + response []alb.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + outputFormat: "", + response: []alb.CredentialsResponse{ + {}, + }, + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(p) + + if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/observability-credentials/observability-credentials.go b/internal/cmd/beta/alb/observability-credentials/observability-credentials.go new file mode 100644 index 000000000..04dee2407 --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/observability-credentials.go @@ -0,0 +1,33 @@ +package credentials + +import ( + "github.com/spf13/cobra" + + add "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/add" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "observability-credentials", + Short: "Provides functionality for application loadbalancer credentials", + Long: "Provides functionality for application loadbalancer credentials", + Args: cobra.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(add.NewCmd(p)) + cmd.AddCommand(delete.NewCmd(p)) + cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(list.NewCmd(p)) + cmd.AddCommand(update.NewCmd(p)) +} diff --git a/internal/cmd/beta/alb/observability-credentials/update/update.go b/internal/cmd/beta/alb/observability-credentials/update/update.go new file mode 100644 index 000000000..03a9fe8ad --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/update/update.go @@ -0,0 +1,161 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + usernameFlag = "username" + displaynameFlag = "displayname" + passwordFlag = "password" + credentialRefArg = "CREDENTIAL_REF_ARG" //nolint:gosec // false alert, these are not valid credentials +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Username *string + Displayname *string + Password *string + CredentialsRef *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", credentialRefArg), + Short: "Update credentials", + Long: "Update credentials.", + Args: args.SingleArg(credentialRefArg, nil), + Example: examples.Build( + examples.NewExample( + `Update the password of observability credentials of Application Load Balancer with credentials reference "credentials-xxx", by providing the path to a file with the new password as flag`, + "$ stackit beta alb observability-credentials update credentials-xxx --username user1 --displayname user1 --password @./new-password.txt"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model := parseInput(p, cmd, args) + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + req, err := buildRequest(ctx, &model, apiClient) + if err != nil { + return err + } + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update credential %q for %q?", *model.CredentialsRef, projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return fmt.Errorf("update credential: %w", err) + } + } + + // Call API + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update credential: %w", err) + } + if resp == nil { + return fmt.Errorf("response is nil") + } + + return outputResult(p, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(usernameFlag, "u", "", "Username for the credentials") + cmd.Flags().StringP(displaynameFlag, "d", "", "Displayname for the credentials") + cmd.Flags().Var(flags.ReadFromFileFlag(), passwordFlag, `Password. Can be a string or a file path, if prefixed with "@" (example: @./password.txt).`) + + cobra.CheckErr(flags.MarkFlagsRequired(cmd, displaynameFlag, usernameFlag)) +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) (req alb.ApiUpdateCredentialsRequest, err error) { + req = apiClient.UpdateCredentials(ctx, model.ProjectId, model.Region, *model.CredentialsRef) + + payload := alb.UpdateCredentialsPayload{ + DisplayName: model.Displayname, + Password: model.Password, + Username: model.Username, + } + + if model.Displayname == nil && model.Username == nil { + return req, fmt.Errorf("no attribute to change passed") + } + + return req.UpdateCredentialsPayload(payload), nil +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) inputModel { + model := inputModel{ + GlobalFlagModel: globalflags.Parse(p, cmd), + Username: flags.FlagToStringPointer(p, cmd, usernameFlag), + Displayname: flags.FlagToStringPointer(p, cmd, displaynameFlag), + CredentialsRef: &inputArgs[0], + Password: flags.FlagToStringPointer(p, cmd, passwordFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return model +} + +func outputResult(p *print.Printer, model inputModel, response *alb.UpdateCredentialsResponse) error { + var outputFormat string + if model.GlobalFlagModel != nil { + outputFormat = model.GlobalFlagModel.OutputFormat + } + if response == nil { + return fmt.Errorf("no response passewd") + } + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(response.Credential, "", " ") + if err != nil { + return fmt.Errorf("marshal credential: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(response.Credential, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal credential: %w", err) + } + p.Outputln(string(details)) + default: + p.Outputf("Updated credential %q\n", utils.PtrString(model.CredentialsRef)) + } + return nil +} diff --git a/internal/cmd/beta/alb/observability-credentials/update/update_test.go b/internal/cmd/beta/alb/observability-credentials/update/update_test.go new file mode 100644 index 000000000..bdfab0080 --- /dev/null +++ b/internal/cmd/beta/alb/observability-credentials/update/update_test.go @@ -0,0 +1,227 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &alb.APIClient{} + +var ( + testProjectId = uuid.NewString() + testRegion = "eu01" + testCredentialRef = "credential-12345" + testDisplayname = "displayname" + testUsername = "testuser" + testPassword = "testpassword" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + usernameFlag: testUsername, + displaynameFlag: testDisplayname, + passwordFlag: testPassword, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) inputModel { + model := inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + Region: testRegion, + }, + Username: &testUsername, + Displayname: &testDisplayname, + CredentialsRef: &testCredentialRef, + Password: &testPassword, + } + for _, mod := range mods { + mod(&model) + } + return model +} + +func fixtureRequest(mods ...func(request *alb.ApiUpdateCredentialsRequest)) alb.ApiUpdateCredentialsRequest { + request := testClient.UpdateCredentials(testCtx, testProjectId, testRegion, testCredentialRef) + request = request.UpdateCredentialsPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *alb.UpdateCredentialsPayload)) alb.UpdateCredentialsPayload { + payload := alb.UpdateCredentialsPayload{ + DisplayName: &testDisplayname, + Password: &testPassword, + Username: &testUsername, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + args []string + isValid bool + expectedModel inputModel + }{ + { + description: "base", + args: []string{testCredentialRef}, + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + args: []string{testCredentialRef}, + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: false, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Username = nil + model.Displayname = nil + }), + }, + { + description: "required values", + args: []string{testCredentialRef}, + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + usernameFlag: testUsername, + displaynameFlag: testDisplayname, + passwordFlag: testPassword, + }, + isValid: true, + expectedModel: fixtureInputModel(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model := parseInput(p, cmd, tt.args) + + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model inputModel + expectedRequest alb.ApiUpdateCredentialsRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, &tt.model, testClient) + if err != nil { + t.Fatalf("cannot build request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(alb.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + item *alb.UpdateCredentialsResponse + model inputModel + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + item: nil, + model: fixtureInputModel(), + }, + wantErr: true, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.item); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/plans/plans.go b/internal/cmd/beta/alb/plans/plans.go new file mode 100644 index 000000000..13719baac --- /dev/null +++ b/internal/cmd/beta/alb/plans/plans.go @@ -0,0 +1,146 @@ +package plans + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type inputModel struct { + *globalflags.GlobalFlagModel +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "plans", + Short: "Lists the application load balancer plans", + Long: "Lists the available application load balancer plans.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all application load balancer plans`, + `$ stackit beta alb plans`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } else if projectLabel == "" { + projectLabel = model.ProjectId + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + response, err := request.Execute() + if err != nil { + return fmt.Errorf("list plans: %w", err) + } + + if items := response.ValidPlans; items == nil || len(*items) == 0 { + p.Info("No plans found for project %q", projectLabel) + } else { + if err := outputResult(p, model.OutputFormat, *items); err != nil { + return fmt.Errorf("output plans: %w", err) + } + } + + return nil + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiListPlansRequest { + request := apiClient.ListPlans(ctx, model.Region) + + return request +} + +func outputResult(p *print.Printer, outputFormat string, items []alb.PlanDetails) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(items, "", " ") + if err != nil { + return fmt.Errorf("marshal plans: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal plans: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("PLAN ID", "NAME", "FLAVOR", "MAX CONNS", "DESCRIPTION") + for _, item := range items { + table.AddRow(utils.PtrString(item.PlanId), + utils.PtrString(item.Name), + utils.PtrString(item.FlavorName), + utils.PtrString(item.MaxConnections), + utils.Truncate(item.Description, 70), + ) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/alb/plans/plans_test.go b/internal/cmd/beta/alb/plans/plans_test.go new file mode 100644 index 000000000..3184f5696 --- /dev/null +++ b/internal/cmd/beta/alb/plans/plans_test.go @@ -0,0 +1,203 @@ +package plans + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &alb.APIClient{} + testProjectId = uuid.NewString() + 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 *alb.ApiListPlansRequest)) alb.ApiListPlansRequest { + request := testClient.ListPlans(testCtx, 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiListPlansRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmpopts.IgnoreFields(alb.ApiListLoadBalancersRequest{}, "ctx"), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + items []alb.PlanDetails + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + outputFormat: "", + items: []alb.PlanDetails{}, + }, + wantErr: false, + }, + { + name: "output format json", + args: args{ + outputFormat: print.JSONOutputFormat, + items: []alb.PlanDetails{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/pool/pool.go b/internal/cmd/beta/alb/pool/pool.go new file mode 100644 index 000000000..5d8d5fd41 --- /dev/null +++ b/internal/cmd/beta/alb/pool/pool.go @@ -0,0 +1,27 @@ +package pool + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/pool/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "pool", + Short: "Manages target pools for application loadbalancers", + Long: "Manage the lifecycle of target pools for application loadbalancers.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, p) + return cmd +} + +func addSubcommands(cmd *cobra.Command, p *print.Printer) { + cmd.AddCommand(update.NewCmd(p)) +} diff --git a/internal/cmd/beta/alb/pool/update/testdata/testconfig.json b/internal/cmd/beta/alb/pool/update/testdata/testconfig.json new file mode 100644 index 000000000..0486c66f4 --- /dev/null +++ b/internal/cmd/beta/alb/pool/update/testdata/testconfig.json @@ -0,0 +1,28 @@ +{ + "activeHealthCheck": { + "healthyThreshold": 1, + "httpHealthChecks": { + "okStatuses": [ + "string" + ], + "path": "string" + }, + "interval": "3s", + "intervalJitter": "3s", + "timeout": "3s", + "unhealthyThreshold": 1 + }, + "name": "my-target-pool", + "targetPort": 5732, + "targets": [ + { + "displayName": "my-target", + "ip": "192.0.2.5" + } + ], + "tlsConfig": { + "customCa": "string", + "enabled": true, + "skipCertificateValidation": true + } +} \ No newline at end of file diff --git a/internal/cmd/beta/alb/pool/update/update.go b/internal/cmd/beta/alb/pool/update/update.go new file mode 100644 index 000000000..e8b2aa2fa --- /dev/null +++ b/internal/cmd/beta/alb/pool/update/update.go @@ -0,0 +1,191 @@ +package update + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "os" + "strings" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + configurationFlag = "configuration" + albNameFlag = "name" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Configuration *string + AlbName *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates an application target pool", + Long: "Updates an application target pool.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Update an application target pool from a configuration file (the name of the pool is read from the file)`, + "$ stackit beta alb update --configuration my-target-pool.json --name my-load-balancer"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update an application target pool for project %q?", projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update application target pool: %w", err) + } + + return outputResult(p, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(configurationFlag, "c", "", "Filename of the input configuration file") + cmd.Flags().StringP(albNameFlag, "n", "", "Name of the target pool name to update") + err := flags.MarkFlagsRequired(cmd, configurationFlag, albNameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Configuration: flags.FlagToStringPointer(p, cmd, configurationFlag), + AlbName: flags.FlagToStringPointer(p, cmd, albNameFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) (req alb.ApiUpdateTargetPoolRequest, err error) { + payload, err := readPayload(ctx, model) + if err != nil { + return req, err + } + if payload.Name == nil { + return req, fmt.Errorf("update target pool: no poolname provided") + } + req = apiClient.UpdateTargetPool(ctx, model.ProjectId, model.Region, *model.AlbName, *payload.Name) + return req.UpdateTargetPoolPayload(payload), nil +} + +func readPayload(_ context.Context, model *inputModel) (payload alb.UpdateTargetPoolPayload, err error) { + if model.Configuration == nil { + return payload, fmt.Errorf("no configuration file defined") + } + file, err := os.Open(*model.Configuration) + if err != nil { + return payload, fmt.Errorf("cannot open configuration file %q: %w", *model.Configuration, err) + } + defer file.Close() // nolint:errcheck // at this point close errors are not relevant anymore + + if strings.HasSuffix(*model.Configuration, ".yaml") { + decoder := yaml.NewDecoder(bufio.NewReader(file), yaml.UseJSONUnmarshaler()) + if err := decoder.Decode(&payload); err != nil { + return payload, fmt.Errorf("cannot deserialize yaml configuration from %q: %w", *model.Configuration, err) + } + } else if strings.HasSuffix(*model.Configuration, ".json") { + decoder := json.NewDecoder(bufio.NewReader(file)) + if err := decoder.Decode(&payload); err != nil { + return payload, fmt.Errorf("cannot deserialize json configuration from %q: %w", *model.Configuration, err) + } + } else { + return payload, fmt.Errorf("cannot determine configuration fileformat of %q by extension. Must be '.json' or '.yaml'", *model.Configuration) + } + + return payload, nil +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *alb.TargetPool) error { + if resp == nil { + return fmt.Errorf("update target pool response is empty") + } + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal target pool: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal target pool: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Updated" + if model.Async { + operationState = "Triggered update of" + } + p.Outputf("%s application target pool for %q. Name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name)) + return nil + } +} diff --git a/internal/cmd/beta/alb/pool/update/update_test.go b/internal/cmd/beta/alb/pool/update/update_test.go new file mode 100644 index 000000000..b9b9ec080 --- /dev/null +++ b/internal/cmd/beta/alb/pool/update/update_test.go @@ -0,0 +1,268 @@ +package update + +import ( + "context" + _ "embed" + "encoding/json" + "log" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +//go:embed testdata/testconfig.json +var testConfiguration []byte + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &alb.APIClient{} + testProjectId = uuid.NewString() + testRegion = "eu01" + testLoadBalancer = "my-load-balancer" + testPool = "my-target-pool" + testConfig = "testdata/testconfig.json" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + configurationFlag: testConfig, + globalflags.RegionFlag: testRegion, + albNameFlag: testLoadBalancer, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Configuration: utils.Ptr(testConfig), + AlbName: &testLoadBalancer, + } + for _, mod := range mods { + mod(model) + } + return model +} +func fixturePayload(mods ...func(payload *alb.UpdateTargetPoolPayload)) (payload alb.UpdateTargetPoolPayload) { + if err := json.Unmarshal(testConfiguration, &payload); err != nil { + log.Panicf("cannot deserialize test configuration: %v", err) + } + for _, f := range mods { + f(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *alb.ApiUpdateTargetPoolRequest)) alb.ApiUpdateTargetPoolRequest { + request := testClient.UpdateTargetPool(testCtx, testProjectId, testRegion, testLoadBalancer, testPool) + + request = request.UpdateTargetPoolPayload(fixturePayload()) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "required fields only", + flagValues: map[string]string{ + projectIdFlag: testProjectId, + configurationFlag: testConfig, + albNameFlag: testLoadBalancer, + }, + isValid: true, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Configuration: &testConfig, + AlbName: &testLoadBalancer, + }, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiUpdateTargetPoolRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "required fields only", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + Configuration: &testConfig, + AlbName: &testLoadBalancer, + }, + expectedRequest: testClient. + UpdateTargetPool(testCtx, testProjectId, testRegion, testLoadBalancer, testPool). + UpdateTargetPoolPayload(fixturePayload()), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + t.Fatalf("cannot create request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + resp *alb.TargetPool + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty response as argument", + args: args{ + model: fixtureInputModel(), + resp: &alb.TargetPool{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/quotas/quotas.go b/internal/cmd/beta/alb/quotas/quotas.go new file mode 100644 index 000000000..07bc2eb21 --- /dev/null +++ b/internal/cmd/beta/alb/quotas/quotas.go @@ -0,0 +1,132 @@ +package quotas + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type inputModel struct { + *globalflags.GlobalFlagModel +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "quotas", + Short: "Shows the application load balancer quotas", + Long: "Shows the application load balancer quotas for the application load balancers.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all application load balancer quotas`, + `$ stackit beta alb quotas`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + response, err := request.Execute() + if err != nil { + return fmt.Errorf("get quotas: %w", err) + } + + if response == nil { + p.Outputln("no quotas found") + return nil + } + + if err := outputResult(p, model.OutputFormat, *response); err != nil { + return fmt.Errorf("output loadbalancers: %w", err) + } + + return nil + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiGetQuotaRequest { + request := apiClient.GetQuota(ctx, model.ProjectId, model.Region) + + return request +} + +func outputResult(p *print.Printer, outputFormat string, response alb.GetQuotaResponse) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(response, "", " ") + if err != nil { + return fmt.Errorf("marshal quotas: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(response, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal quotas: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.AddRow("REGION", utils.PtrString(response.Region)) + table.AddSeparator() + table.AddRow("MAX LOADBALANCERS", utils.PtrString(response.MaxLoadBalancers)) + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/beta/alb/quotas/quotas_test.go b/internal/cmd/beta/alb/quotas/quotas_test.go new file mode 100644 index 000000000..b840d9ef0 --- /dev/null +++ b/internal/cmd/beta/alb/quotas/quotas_test.go @@ -0,0 +1,203 @@ +package quotas + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &alb.APIClient{} + testProjectId = uuid.NewString() + 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 *alb.ApiGetQuotaRequest)) alb.ApiGetQuotaRequest { + request := testClient.GetQuota(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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiGetQuotaRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmpopts.IgnoreFields(alb.ApiListLoadBalancersRequest{}, "ctx"), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + response alb.GetQuotaResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + outputFormat: "", + response: alb.GetQuotaResponse{}, + }, + wantErr: false, + }, + { + name: "output format json", + args: args{ + outputFormat: print.JSONOutputFormat, + response: alb.GetQuotaResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/alb/template/template-alb.yaml b/internal/cmd/beta/alb/template/template-alb.yaml new file mode 100644 index 000000000..541aaf3de --- /dev/null +++ b/internal/cmd/beta/alb/template/template-alb.yaml @@ -0,0 +1,91 @@ +name: my-load-balancer +# public ip, must be removed when ephemeral address option is true +externalAddress: 123.123.123.123 + +# public listening interfaces of the loadbalancer +listeners: + - displayName: listener1 + # for plain http the https block must be removed + # http: {} + https: + certificateConfig: + certificateIds: + - cert-1 + - cert-2 + - cert-3 + port: 443 + # protocal may be PROTOCOL_HTTPS or PROTOCOL_HTTP + protocol: PROTOCOL_HTTPS + rules: + # fqdn of the virtual host of the load balancer + - host: front.facing.host + http: + subRules: + - cookiePersistence: + name: cookie1 + ttl: 120s + headers: + - name: testheader1 + exactMatch: X-test-header1 + - name: testheader2 + exactMatch: X-test-header2 + - name: testheader3 + exactMatch: X-test-header3 + pathPrefix: /foo + queryParameters: + - name: query-param + exactMatch: q + - name: region + exactMatch: region + targetPool: my-target-pool + webSocket: false +networks: + - networkId: 00000000-0000-0000-0000-000000000000 + role: ROLE_LISTENERS_AND_TARGETS + - networkId: 00000000-0000-0000-0000-000000000001 + role: ROLE_LISTENERS_AND_TARGETS +options: + accessControl: + # which host may access the loadbalancer in prefix notation + allowedSourceRanges: + - 10.100.42.0/24 + ephemeralAddress: true + privateNetworkOnly: true + + # Enable observability features. Appropriate credentials must be made + # available using the credentials endpoint + # observability: + # logs: + # credentialsRef: my-credentials + # pushUrl: https://my.observability.host//loki/api/v1/push + # metrics: + # credentialsRef: my-credentials + # pushUrl: https://my.observability.host///api/v1/receive + +planId: p10 + +# definition of the backend servers +targetPools: + - name: my-target-pool + activeHealthCheck: + healthyThreshold: 3 + httpHealthChecks: + okStatuses: + - "200" + path: /health + interval: 10s + intervalJitter: 3s + timeout: 5s + unhealthyThreshold: 1 + targetPort: 5732 + targets: + # configuration of the backend servers + - displayName: my-target1 + ip: 192.11.2.5 + # if the backend servers must be accessed via TLS the following block + # allows defining the TLS configuration + # tlsConfig: + # # A PEM and base64 encoded certificate + # customCa: LS0t... + # enabled: true + # skipCertificateValidation: false diff --git a/internal/cmd/beta/alb/template/template-pool.yaml b/internal/cmd/beta/alb/template/template-pool.yaml new file mode 100644 index 000000000..d3a56af9b --- /dev/null +++ b/internal/cmd/beta/alb/template/template-pool.yaml @@ -0,0 +1,23 @@ +activeHealthCheck: + healthyThreshold: 1 + httpHealthChecks: + okStatuses: + - "200" + path: /health + interval: 3s + intervalJitter: 3s + timeout: 3s + unhealthyThreshold: 1 +name: my-target-pool +targetPort: 4000 +targets: + - displayName: my-target + ip: 10.0.1.155 + # if the backend servers must be accessed via TLS the following block + # allows defining the TLS configuration + # tlsConfig: + # # A PEM and base64 encoded certificate + # customCa: LS0... + # enabled: true + # skipCertificateValidation: false + diff --git a/internal/cmd/beta/alb/template/template.go b/internal/cmd/beta/alb/template/template.go new file mode 100644 index 000000000..18d0cd427 --- /dev/null +++ b/internal/cmd/beta/alb/template/template.go @@ -0,0 +1,124 @@ +package template + +import ( + _ "embed" + "encoding/json" + "fmt" + "os" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +const ( + formatFlag = "format" + typeFlag = "type" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Format *string + Type *string +} + +var ( + //go:embed template-alb.yaml + templateAlb string + //go:embed template-pool.yaml + templatePool string +) + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "template", + Short: "creates configuration templates to use for resource creation", + Long: "creates a json or yaml template file for creating/updating an application loadbalancer or target pool.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a yaml template`, + `$ stackit beta alb template --format=yaml --type alb`, + ), + examples.NewExample( + `Create a json template`, + `$ stackit beta alb template --format=json --type pool`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + var ( + template string + target any + ) + if model.Type != nil && *model.Type == "pool" { + template = templatePool + target = alb.CreateLoadBalancerPayload{} + } else if model.Type == nil || *model.Type == "alb" { + template = templateAlb + target = alb.UpdateTargetPoolPayload{} + } else { + return fmt.Errorf("invalid type %q", utils.PtrString(model.Type)) + } + + if model.Format == nil || *model.Format == "yaml" { + p.Outputln(template) + } else if *model.Format == "json" { + if err := yaml.Unmarshal([]byte(template), &target); err != nil { + return fmt.Errorf("cannot unmarshal template: %w", err) + } + encoder := json.NewEncoder(os.Stdout) + if err := encoder.Encode(target); err != nil { + return fmt.Errorf("cannot marshal template to yaml: %w", err) + } + } else { + return fmt.Errorf("invalid format %q defined. Must be 'json' or 'yaml'", *model.Format) + } + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().VarP(flags.EnumFlag(true, "json", "json", "yaml"), formatFlag, "f", "Defines the output format ('yaml' or 'json'), default is 'json'") + cmd.Flags().VarP(flags.EnumFlag(true, "alb", "alb", "pool"), typeFlag, "t", "Defines the output type ('alb' or 'pool'), default is 'alb'") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Format: flags.FlagToStringPointer(p, cmd, formatFlag), + Type: flags.FlagToStringPointer(p, cmd, typeFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} diff --git a/internal/cmd/beta/alb/template/template_test.go b/internal/cmd/beta/alb/template/template_test.go new file mode 100644 index 000000000..3ca5404e8 --- /dev/null +++ b/internal/cmd/beta/alb/template/template_test.go @@ -0,0 +1,180 @@ +package template + +import ( + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" +) + +var ( + testProjectId = uuid.NewString() + 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 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "alb with yaml", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[formatFlag] = "yaml" + flagValues[typeFlag] = "alb" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Format = utils.Ptr("yaml") + model.Type = utils.Ptr("alb") + }), + }, { + description: "alb with yaml", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[formatFlag] = "yaml" + flagValues[typeFlag] = "alb" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Format = utils.Ptr("yaml") + model.Type = utils.Ptr("alb") + }), + }, { + description: "alb with json", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[formatFlag] = "json" + flagValues[typeFlag] = "alb" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Format = utils.Ptr("json") + model.Type = utils.Ptr("alb") + }), + }, { + description: "pool with yaml", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[formatFlag] = "yaml" + flagValues[typeFlag] = "pool" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Format = utils.Ptr("yaml") + model.Type = utils.Ptr("pool") + }), + }, + { + description: "pool with json", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[formatFlag] = "json" + flagValues[typeFlag] = "pool" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Format = utils.Ptr("json") + model.Type = utils.Ptr("pool") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(p) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} diff --git a/internal/cmd/beta/alb/update/testdata/testconfig.json b/internal/cmd/beta/alb/update/testdata/testconfig.json new file mode 100644 index 000000000..b81294c66 --- /dev/null +++ b/internal/cmd/beta/alb/update/testdata/testconfig.json @@ -0,0 +1,125 @@ +{ + "externalAddress": "10.100.42.1", + "listeners": [ + { + "displayName": "listener1", + "http": {}, + "https": { + "certificateConfig": { + "certificateIds": [ + "cert-1", + "cert-2", + "cert-3" + ] + } + }, + "port": 443, + "protocol": "PROTOCOL_HTTPS", + "rules": [ + { + "host": "front.facing.host", + "http": { + "subRules": [ + { + "cookiePersistence": { + "name": "cookie1", + "ttl": "120s" + }, + "headers": [ + { + "name": "testheader1", + "exactMatch": "X-test-header1" + }, + { + "name": "testheader2", + "exactMatch": "X-test-header2" + }, + { + "name": "testheader3", + "exactMatch": "X-test-header3" + } + ], + "pathPrefix": "/foo", + "queryParameters": [ + { + "name": "query-param", + "exactMatch": "q" + }, + { + "name": "region", + "exactMatch": "region" + } + ], + "targetPool": "my-target-pool", + "webSocket": false + } + ] + } + } + ] + } + ], + "name": "my-load-balancer", + "networks": [ + { + "networkId": "00000000-0000-0000-0000-000000000000", + "role": "ROLE_LISTENERS_AND_TARGETS" + }, + { + "networkId": "00000000-0000-0000-0000-000000000001", + "role": "ROLE_LISTENERS_AND_TARGETS" + } + ], + "options": { + "accessControl": { + "allowedSourceRanges": [ + "192.168.42.0-192.168.42.10", + "192.168.54.0-192.168.54.10" + ] + }, + "ephemeralAddress": true, + "observability": { + "logs": { + "credentialsRef": "my-credentials", + "pushUrl": "https://my.observability.host//loki/api/v1/push" + }, + "metrics": { + "credentialsRef": "my-credentials", + "pushUrl": "https://my.observability.host///api/v1/receive" + } + }, + "privateNetworkOnly": true + }, + "planId": "p10", + "targetPools": [ + { + "activeHealthCheck": { + "healthyThreshold": 3, + "httpHealthChecks": { + "okStatuses": [ + "200", + "204" + ], + "path": "/health" + }, + "interval": "10s", + "intervalJitter": "3s", + "timeout": "5s", + "unhealthyThreshold": 1 + }, + "name": "my-target-pool", + "targetPort": 5732, + "targets": [ + { + "displayName": "my-target1", + "ip": "192.11.2.5" + } + ], + "tlsConfig": { + "customCa": "my.private.ca", + "enabled": true, + "skipCertificateValidation": false + } + } + ] +} diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go new file mode 100644 index 000000000..546f89990 --- /dev/null +++ b/internal/cmd/beta/alb/update/update.go @@ -0,0 +1,227 @@ +package update + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "os" + "strings" + + "github.com/goccy/go-yaml" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/alb" + "github.com/stackitcloud/stackit-sdk-go/services/alb/wait" +) + +const ( + configurationFlag = "configuration" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Configuration *string + Version *string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates an application loadbalancer", + Long: "Updates an application loadbalancer.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Update an application loadbalancer from a configuration file`, + "$ stackit beta alb update --configuration my-loadbalancer.json"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + if err != nil { + p.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update an application loadbalancer for project %q?", projectLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // for updates of an existing ALB the current version must be passed to the request + model.Version, err = getCurrentAlbVersion(ctx, apiClient, model) + if err != nil { + return err + } + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update application loadbalancer: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(p) + s.Start("updating loadbalancer") + _, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name). + WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for loadbalancer update: %w", err) + } + s.Stop() + } + + return outputResult(p, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(configurationFlag, "c", "", "Filename of the input configuration file") + err := flags.MarkFlagsRequired(cmd, configurationFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Configuration: flags.FlagToStringPointer(p, cmd, configurationFlag), + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func getCurrentAlbVersion(ctx context.Context, apiClient *alb.APIClient, model *inputModel) (*string, error) { + // use the configuration file to find the name of the loadbalancer + updatePayload, err := readPayload(ctx, model) + if err != nil { + return nil, err + } + if updatePayload.Name == nil { + return nil, fmt.Errorf("no name found in configuration") + } + if err != nil { + return nil, err + } + resp, err := apiClient.GetLoadBalancer(ctx, model.ProjectId, model.Region, *updatePayload.Name).Execute() + if err != nil { + return nil, err + } + return resp.Version, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) (req alb.ApiUpdateLoadBalancerRequest, err error) { + payload, err := readPayload(ctx, model) + if err != nil { + return req, err + } + if payload.Name == nil { + return req, fmt.Errorf("no name found in loadbalancer configuration") + } + payload.Version = model.Version + req = apiClient.UpdateLoadBalancer(ctx, model.ProjectId, model.Region, *payload.Name) + return req.UpdateLoadBalancerPayload(payload), nil +} + +func readPayload(_ context.Context, model *inputModel) (payload alb.UpdateLoadBalancerPayload, err error) { + if model.Configuration == nil { + return payload, fmt.Errorf("no configuration file defined") + } + file, err := os.Open(*model.Configuration) + if err != nil { + return payload, fmt.Errorf("cannot open configuration file %q: %w", *model.Configuration, err) + } + defer file.Close() // nolint:errcheck // at this point close errors are not relevant anymore + + if strings.HasSuffix(*model.Configuration, ".yaml") { + decoder := yaml.NewDecoder(bufio.NewReader(file), yaml.UseJSONUnmarshaler()) + if err := decoder.Decode(&payload); err != nil { + return payload, fmt.Errorf("cannot deserialize yaml configuration from %q: %w", *model.Configuration, err) + } + } else if strings.HasSuffix(*model.Configuration, ".json") { + decoder := json.NewDecoder(bufio.NewReader(file)) + if err := decoder.Decode(&payload); err != nil { + return payload, fmt.Errorf("cannot deserialize json configuration from %q: %w", *model.Configuration, err) + } + } else { + return payload, fmt.Errorf("cannot determine configuration fileformat of %q by extension. Must be '.json' or '.yaml'", *model.Configuration) + } + + return payload, nil +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *alb.LoadBalancer) error { + if resp == nil { + return fmt.Errorf("update loadbalancer response is empty") + } + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal loadbalancer: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal loadbalancer: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + operationState := "Updated" + if model.Async { + operationState = "Triggered update of" + } + p.Outputf("%s application loadbalancer for %q. Name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name)) + return nil + } +} diff --git a/internal/cmd/beta/alb/update/update_test.go b/internal/cmd/beta/alb/update/update_test.go new file mode 100644 index 000000000..176a130a3 --- /dev/null +++ b/internal/cmd/beta/alb/update/update_test.go @@ -0,0 +1,262 @@ +package update + +import ( + "context" + _ "embed" + "encoding/json" + "log" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +//go:embed testdata/testconfig.json +var testConfiguration []byte + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &alb.APIClient{} + testProjectId = uuid.NewString() + testRegion = "eu01" + testLoadBalancer = "my-load-balancer" + testConfig = "testdata/testconfig.json" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + configurationFlag: testConfig, + 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, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Configuration: utils.Ptr(testConfig), + } + for _, mod := range mods { + mod(model) + } + return model +} +func fixturePayload(mods ...func(payload *alb.UpdateLoadBalancerPayload)) (payload alb.UpdateLoadBalancerPayload) { + if err := json.Unmarshal(testConfiguration, &payload); err != nil { + log.Panicf("cannot deserialize test configuration: %v", err) + } + for _, f := range mods { + f(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *alb.ApiUpdateLoadBalancerRequest)) alb.ApiUpdateLoadBalancerRequest { + request := testClient.UpdateLoadBalancer(testCtx, testProjectId, testRegion, testLoadBalancer) + + request = request.UpdateLoadBalancerPayload(fixturePayload()) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "required fields only", + flagValues: map[string]string{ + projectIdFlag: testProjectId, + configurationFlag: testConfig, + }, + isValid: true, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Configuration: &testConfig, + }, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest alb.ApiUpdateLoadBalancerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "required fields only", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + Configuration: &testConfig, + }, + expectedRequest: testClient. + UpdateLoadBalancer(testCtx, testProjectId, testRegion, testLoadBalancer). + UpdateLoadBalancerPayload(fixturePayload()), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + t.Fatalf("cannot create request: %v", err) + } + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + resp *alb.LoadBalancer + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty response as argument", + args: args{ + model: fixtureInputModel(), + resp: &alb.LoadBalancer{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index ed6873b0e..37b5e4bd9 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,6 +3,7 @@ package beta import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,4 +37,5 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(sqlserverflex.NewCmd(p)) + cmd.AddCommand(alb.NewCmd(p)) } diff --git a/internal/pkg/services/alb/client/client.go b/internal/pkg/services/alb/client/client.go new file mode 100644 index 000000000..c29f9eddb --- /dev/null +++ b/internal/pkg/services/alb/client/client.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/spf13/viper" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/alb" +) + +func ConfigureClient(p *print.Printer) (*alb.APIClient, error) { + var err error + var apiClient *alb.APIClient + var cfgOptions []sdkConfig.ConfigurationOption + + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return nil, &errors.AuthError{} + } + cfgOptions = append(cfgOptions, authCfgOption) + + customEndpoint := viper.GetString(config.IaaSCustomEndpointKey) + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } else { + cfgOptions = append(cfgOptions, authCfgOption) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err = alb.NewAPIClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return nil, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/internal/pkg/services/alb/utils/utils.go b/internal/pkg/services/alb/utils/utils.go new file mode 100644 index 000000000..7a32e1986 --- /dev/null +++ b/internal/pkg/services/alb/utils/utils.go @@ -0,0 +1,4 @@ +package utils + +type AlbClient interface { +} diff --git a/internal/pkg/services/alb/utils/utils_test.go b/internal/pkg/services/alb/utils/utils_test.go new file mode 100644 index 000000000..489b7a2c5 --- /dev/null +++ b/internal/pkg/services/alb/utils/utils_test.go @@ -0,0 +1,4 @@ +package utils + +type AlbClientMocked struct { +} diff --git a/internal/pkg/utils/strings.go b/internal/pkg/utils/strings.go index 36cfda139..401287fa1 100644 --- a/internal/pkg/utils/strings.go +++ b/internal/pkg/utils/strings.go @@ -2,6 +2,7 @@ package utils import ( "strings" + "unicode/utf8" ) // JoinStringKeys concatenates the string keys of a map, each separatore by the @@ -33,3 +34,25 @@ func JoinStringPtr(vals *[]string, sep string) string { } return strings.Join(*vals, sep) } + +// Truncate trims the passed string (if it is not nil). If the input string is +// longer than the given length, it is truncated to _maxLen_ and a ellipsis (…) +// is attached. Therefore the resulting string has at most length _maxLen-1_ +func Truncate(s *string, maxLen int) string { + if s == nil { + return "" + } + + if utf8.RuneCountInString(*s) > maxLen { + var builder strings.Builder + for i, r := range *s { + if i >= maxLen { + break + } + builder.WriteRune(r) + } + builder.WriteRune('…') + return builder.String() + } + return *s +} diff --git a/internal/pkg/utils/strings_test.go b/internal/pkg/utils/strings_test.go new file mode 100644 index 000000000..a7fb023bc --- /dev/null +++ b/internal/pkg/utils/strings_test.go @@ -0,0 +1,32 @@ +package utils + +import ( + "testing" + + "github.com/stackitcloud/stackit-sdk-go/core/utils" +) + +func TestTruncate(t *testing.T) { + type args struct { + s *string + maxLen int + } + tests := []struct { + name string + args args + want string + }{ + {"nil string", args{nil, 3}, ""}, + {"empty string", args{utils.Ptr(""), 10}, ""}, + {"length below maxlength", args{utils.Ptr("foo"), 10}, "foo"}, + {"exactly maxlength", args{utils.Ptr("foo"), 3}, "foo"}, + {"above maxlength", args{utils.Ptr("foobarbaz"), 3}, "foo…"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := Truncate(tt.args.s, tt.args.maxLen); got != tt.want { + t.Errorf("Truncate() = %v, want %v", got, tt.want) + } + }) + } +} From 6986c7cd0cde5f4ddb64d95e86f9068740f16474 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 17 Apr 2025 08:53:41 +0200 Subject: [PATCH 271/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/observability to v0.5.0 (#701) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e8c9959d9..5673e9f9f 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 3e7029eac..7ab9f6e7c 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 h1:n6xMTHrLV github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1/go.mod h1:R+fHrtGfy+zx+d5s31cBh09P3TG58dyytb83gB7ldi0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 h1:yyN3Q4i+5bmUVySPbQC7sSKG6sK21V8AxMjvhfJe2r0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1/go.mod h1:c5/LHxZZ7qZYOboR01qOw1Mqq5v/VNyONw7WPHctNeY= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0 h1:CPa/SRuX1Gl810K0SearSFyH0k/xKF9JHUV+4j+Tcn4= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.4.0/go.mod h1:/go4bZ76dxGfkvl48EYUmPZ41c+64Yrf/26RodfcFyw= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.0 h1:BpHIZdoAZwtzYgXznFE7lhqpUvnDJjc+HaEAQmA7NOk= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.0/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0 h1:Au07XkATgBqrGpjO5t6ASAjuif7VXcKKF3t4edRh+Yw= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0/go.mod h1:zyVy1/etVAq6NkdPG4kNOM2R7+AxXp5zLsiN4nDC7Fs= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 h1:S6uamk6ecVy8K3jE2mgU50h14GoGE0LRVmiK3TvgfTc= From ba016e40dc3d288f45bd50fa1dec1f1729d1aaea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 24 Apr 2025 11:09:40 +0200 Subject: [PATCH 272/619] feat(github): enable dependabot for golang and gh actions (#703) --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..5400a08cb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" From 22dfa06268ad98b6c79db80f3f4574801601dec3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Apr 2025 11:20:22 +0200 Subject: [PATCH 273/619] chore(deps): bump renovatebot/github-action from 41.0.5 to 41.0.21 (#705) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 41.0.5 to 41.0.21. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v41.0.5...v41.0.21) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 41.0.21 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 7a7d69056..6f756b7c0 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v41.0.5 + uses: renovatebot/github-action@v41.0.21 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From dfc560aa7ba67da9444dda4a18199c804c3fee8e Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Thu, 24 Apr 2025 12:50:21 +0200 Subject: [PATCH 274/619] Fix: Exit less if an interrupt character is typed (#704) Signed-off-by: Alexander Dahmen --- internal/pkg/print/print.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/pkg/print/print.go b/internal/pkg/print/print.go index 470fb49ac..63f48fe89 100644 --- a/internal/pkg/print/print.go +++ b/internal/pkg/print/print.go @@ -189,7 +189,8 @@ func (p *Printer) PagerDisplay(content string) error { // -S: disables line wrapping // -w: highlight the first line after moving one full page down // -R: interprets ANSI color and style sequences - pagerCmd := exec.Command("less", "-F", "-S", "-w", "-R") + // -K: exits if an interrupt character is typed + pagerCmd := exec.Command("less", "-F", "-S", "-w", "-R", "-K") pager, pagerExists := os.LookupEnv("PAGER") if pagerExists && pager != "nil" && pager != "" { From d1e050408e3fe4a8e151c7c9c9856cac310390e8 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 25 Apr 2025 09:34:06 +0200 Subject: [PATCH 275/619] chore(deps): update samuelmeuli/action-snapcraft action to v3 (#710) Co-authored-by: Renovate Bot --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b672b5150..0e3d6e9da 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -63,7 +63,7 @@ jobs: - name: Install Aptly version 1.5.0 run: brew install aptly.rb - name: Install Snapcraft - uses: samuelmeuli/action-snapcraft@v2 + uses: samuelmeuli/action-snapcraft@v3 - name: Run GoReleaser uses: goreleaser/goreleaser-action@v6 with: From c9b85815a84984df44a7680ff2e5247cce2fc8db Mon Sep 17 00:00:00 2001 From: Mauritz Uphoff <39736813+h3adex@users.noreply.github.com> Date: Fri, 25 Apr 2025 16:21:49 +0200 Subject: [PATCH 276/619] docs: sort available services (#711) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2b48581ad..fad966e7b 100644 --- a/README.md +++ b/README.md @@ -71,15 +71,15 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Service | CLI Commands | Status | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -| Observability | `observability` | :white_check_mark: | -| Infrastructure as a Service (IaaS) | `network-area`
`network`
`volume`
`network-interface`
`public-ip`
`security-group`
`key-pair`
`image`
`quota` | :white_check_mark:| | Authorization | `project`, `organization` | :white_check_mark: | | DNS | `dns` | :white_check_mark: | +| Infrastructure as a Service (IaaS) | `image`
`key-pair`
`network`
`network-area`
`network-interface`
`public-ip`
`quota`
`security-group`
`server`
`volume` | :white_check_mark:| | Kubernetes Engine (SKE) | `ske` | :white_check_mark: | | Load Balancer | `load-balancer` | :white_check_mark: | | LogMe | `logme` | :white_check_mark: | | MariaDB | `mariadb` | :white_check_mark: | | MongoDB Flex | `mongodbflex` | :white_check_mark: | +| Observability | `observability` | :white_check_mark: | | Object Storage | `object-storage` | :white_check_mark: | | OpenSearch | `opensearch` | :white_check_mark: | | PostgreSQL Flex | `postgresflex` | :white_check_mark: | @@ -87,8 +87,8 @@ Below you can find a list of the STACKIT services already available in the CLI ( | Redis | `redis` | :white_check_mark: | | Resource Manager | `project` | :white_check_mark: | | Secrets Manager | `secrets-manager` | :white_check_mark: | -| Server Backup Management | `server backup` | :white_check_mark: | -| Server Command (Run Command) | `server command` | :white_check_mark: | +| Server Backup Management | `server backup` | :white_check_mark: | +| Server Command (Run Command) | `server command` | :white_check_mark: | | Service Account | `service-account` | :white_check_mark: | | SQLServer Flex | `beta sqlserverflex` | :white_check_mark: (beta) | From c6f37c360cca14cac73c33a502c991b00c5bed16 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 30 Apr 2025 10:49:42 +0200 Subject: [PATCH 277/619] fix(deps): update stackit sdk modules (#717) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 5673e9f9f..3fe4db79c 100644 --- a/go.mod +++ b/go.mod @@ -27,8 +27,8 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 diff --git a/go.sum b/go.sum index 7ab9f6e7c..429e757fe 100644 --- a/go.sum +++ b/go.sum @@ -149,10 +149,10 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 h1:SZoWUD github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2/go.mod h1:PrD0nNG94Dd5D9pu7HJ0bAg8ccDz6/7KaIts7K9p7as= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 h1:qujhShugc1290NQlPoNqsembqzot8aTToAdSsJg5WrM= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1/go.mod h1:e1fsQL24gTPXcMWptuslNscawmXv/PLUAFuw+sOofbc= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.1 h1:oYOKoID+PMTb9qX5LyXmr7qk3VNv1qxDhZBxUZcokvM= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.1/go.mod h1:AoQFbTh8pejhIRyvpX8Jm2FHHwen8My85OYA910FIy0= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1 h1:VKgxgjsbaUVMCnntq+MLQ/c1Emn5crVr11B3gJnyHN4= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.1/go.mod h1:vn6xmMRxYgEoBhYEy6i2SY2qbeDKjs4IVNdnQHcQpBc= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 h1:MCHMaS3hRTEYu+rWIDOas9tVn5+ddaulXzcE2porMek= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 h1:SdQ9VqDmamOhnTp6fd0QYKhCcoxB2GP938o7hGAubqg= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 h1:7yY68QuntatwRG6ri65FlfeewACChLVbLp67wHCS8Go= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1/go.mod h1:EMqjiq/72WKXSwnJGLpumUJS4Uwlyhg5vtNg7qWoGtc= github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 h1:9OnJGvQcL3Xwmc2BRQudjn2GNGvbJr8/xAIlmqtnmfQ= From 7fb25efb307b1c49788b237b171571665da68f45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 11:18:37 +0200 Subject: [PATCH 278/619] chore(deps): bump renovatebot/github-action from 41.0.21 to 41.0.22 (#712) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 41.0.21 to 41.0.22. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v41.0.21...v41.0.22) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 41.0.22 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 6f756b7c0..28d5b38a9 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v41.0.21 + uses: renovatebot/github-action@v41.0.22 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 6e0d89808b00ff2f65b3d46ac71b10a44eec93e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 13:36:53 +0200 Subject: [PATCH 279/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/rabbitmq (#720) Bumps [github.com/stackitcloud/stackit-sdk-go/services/rabbitmq](https://github.com/stackitcloud/stackit-sdk-go) from 0.22.0 to 0.22.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.22.0...services/ske/v0.22.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/rabbitmq dependency-version: 0.22.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3fe4db79c..7f88b7a2f 100644 --- a/go.mod +++ b/go.mod @@ -82,7 +82,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.0 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum index 429e757fe..dcd9a0cfe 100644 --- a/go.sum +++ b/go.sum @@ -137,8 +137,8 @@ github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0 h1:Au07XkATgB github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0/go.mod h1:zyVy1/etVAq6NkdPG4kNOM2R7+AxXp5zLsiN4nDC7Fs= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 h1:S6uamk6ecVy8K3jE2mgU50h14GoGE0LRVmiK3TvgfTc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2/go.mod h1:7TqfCUZRW7sjv8qOrLV5IvS6jqvY9Uxka165zdjYwD4= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.0 h1:/hHxcTvSQc1tG5gqRdFV3g7cMy7nU0/Av0p9UX9PyPQ= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.0/go.mod h1:HrT7p4jtiTGfGHUp4kxla+3q5z0ajUWFXZqlw5HjEf4= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1 h1:CHRxxDBW+4VrpZDyXabOJCF7LY0i+PNYY5QWE0kwGIo= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 h1:F+oTIOWeU5Jl0xsrJ+IV+Hz756UIOxBd7TFOD4YAv4k= github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0/go.mod h1:bjJccrTVRTyLowME8H9oelOrBILQ6xAvh+kVRSq3SBA= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 h1:6bl/BSVebTnK73ToRn80Mtd1sl0TowfhOninyoSQA/U= From 0acb9e3ba151f2434151d2e85cdb03ef0f44dd2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 13:37:15 +0200 Subject: [PATCH 280/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mariadb (#719) Bumps [github.com/stackitcloud/stackit-sdk-go/services/mariadb](https://github.com/stackitcloud/stackit-sdk-go) from 0.22.0 to 0.22.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.22.0...services/ske/v0.22.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/mariadb dependency-version: 0.22.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7f88b7a2f..7bebe1291 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/spf13/cast v1.7.1 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.0 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1 diff --git a/go.sum b/go.sum index dcd9a0cfe..8c9d8844b 100644 --- a/go.sum +++ b/go.sum @@ -125,8 +125,8 @@ github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 h1:4Kz9MH9VV github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1/go.mod h1:x0jgrL+/K2cE4BvcIQByFUf0nOPVZRqq5Z074kjjr64= github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0 h1:5pcvoWS2sO3MIBP026OZEdImBNVvI27lksehqDMbAh0= github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0/go.mod h1:Lb1emAS4KI+pWDXQlbmST058wTsWyD8vLmdsJpRjfEg= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.0 h1:BvEQmJwCmyAoCH5zG4apu8co/neLMtBdv9znwmbGj78= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.0/go.mod h1:3SR8YwmMiLmU8WJ8UHF0HwL7n6GZMCJYBCRll+92lYU= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1 h1:bdfgwsFNJRqCDUu/r4ZYyACzHCo1bD3y8fGFLYvX9C4= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 h1:n6xMTHrLV9L78ureeigHHPwmMC4ZntOgVC+agV81Rpk= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1/go.mod h1:R+fHrtGfy+zx+d5s31cBh09P3TG58dyytb83gB7ldi0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 h1:yyN3Q4i+5bmUVySPbQC7sSKG6sK21V8AxMjvhfJe2r0= From 19d9bca753bb3d447a2c61155d0554160c1eb6af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 09:52:19 +0200 Subject: [PATCH 281/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/secretsmanager (#723) Bumps [github.com/stackitcloud/stackit-sdk-go/services/secretsmanager](https://github.com/stackitcloud/stackit-sdk-go) from 0.11.2 to 0.11.3. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/secretsmanager/v0.11.2...services/secretsmanager/v0.11.3) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/secretsmanager dependency-version: 0.11.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7bebe1291..2f0e250a3 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 diff --git a/go.sum b/go.sum index 8c9d8844b..eb02bedbe 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,8 @@ github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 h1:6bl/B github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1/go.mod h1:t7Bq7VRIN1D9C2sa2PE5gzwL6d7p1fypnsydYhKaA5k= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 h1:tKUyddNszcif4j2yL6lJd4tDAykcU3shMkAPoM9EzV8= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0/go.mod h1:5n31cpeYcz2DSax4ygpZICEHDoHCTbWHrNGNYWwlRA8= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2 h1:SZoWUDUA8foNbu+cwRa67VxJXJJx4M8oiHeykVh8Wlg= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.2/go.mod h1:PrD0nNG94Dd5D9pu7HJ0bAg8ccDz6/7KaIts7K9p7as= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3 h1:L8uFydvDVJBdXLSQdgRwztbQewwNtTtuPhM1L1ehIvA= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 h1:qujhShugc1290NQlPoNqsembqzot8aTToAdSsJg5WrM= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1/go.mod h1:e1fsQL24gTPXcMWptuslNscawmXv/PLUAFuw+sOofbc= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 h1:MCHMaS3hRTEYu+rWIDOas9tVn5+ddaulXzcE2porMek= From 77a15a326a76f5a4d40f36140d743bca28c9b597 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 09:52:57 +0200 Subject: [PATCH 282/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/ske (#722) Bumps [github.com/stackitcloud/stackit-sdk-go/services/ske](https://github.com/stackitcloud/stackit-sdk-go) from 0.22.1 to 0.22.2. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.22.1...services/ske/v0.22.2) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/ske dependency-version: 0.22.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2f0e250a3..1416a795f 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 diff --git a/go.sum b/go.sum index eb02bedbe..47c63ed77 100644 --- a/go.sum +++ b/go.sum @@ -155,8 +155,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 h1:SdQ9VqD github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 h1:7yY68QuntatwRG6ri65FlfeewACChLVbLp67wHCS8Go= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1/go.mod h1:EMqjiq/72WKXSwnJGLpumUJS4Uwlyhg5vtNg7qWoGtc= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1 h1:9OnJGvQcL3Xwmc2BRQudjn2GNGvbJr8/xAIlmqtnmfQ= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.1/go.mod h1:RlH5d+znKkOVt/HsD7OBAlhgIos7TM7vv0qCeqvCqmo= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2 h1:SYX9IXg+2YAIdiUzLyqs9ga+S+bjhZs8WYeqU3GK3hk= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 h1:3uPq1jXXw8+6Op/fJuPaKOpTP0nOCHAUobMzZV7aHGg= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1/go.mod h1:d2ICXCS2h3IMsZW0OanWkEH2XdLiY/XRKx2TcR940nw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From e2622db88f6173be4743f8aaf2e95c9baa9a8b69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 09:53:25 +0200 Subject: [PATCH 283/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/observability (#718) Bumps [github.com/stackitcloud/stackit-sdk-go/services/observability](https://github.com/stackitcloud/stackit-sdk-go) from 0.5.0 to 0.5.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.5.0...services/authorization/v0.5.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/observability dependency-version: 0.5.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1416a795f..1a4a6c346 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 47c63ed77..8ff2e67c3 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 h1:n6xMTHrLV github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1/go.mod h1:R+fHrtGfy+zx+d5s31cBh09P3TG58dyytb83gB7ldi0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 h1:yyN3Q4i+5bmUVySPbQC7sSKG6sK21V8AxMjvhfJe2r0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1/go.mod h1:c5/LHxZZ7qZYOboR01qOw1Mqq5v/VNyONw7WPHctNeY= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.0 h1:BpHIZdoAZwtzYgXznFE7lhqpUvnDJjc+HaEAQmA7NOk= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.0/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1 h1:BIMl8ISsDGsFB6dBqfxQMPFVyS5gB5EcwM4Jzpg65XE= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0 h1:Au07XkATgBqrGpjO5t6ASAjuif7VXcKKF3t4edRh+Yw= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0/go.mod h1:zyVy1/etVAq6NkdPG4kNOM2R7+AxXp5zLsiN4nDC7Fs= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 h1:S6uamk6ecVy8K3jE2mgU50h14GoGE0LRVmiK3TvgfTc= From 2f67743d95ce53d8b30d08f6a1210e5693630a04 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 5 May 2025 11:27:18 +0200 Subject: [PATCH 284/619] fix(deps): update stackit sdk modules (#721) Co-authored-by: Renovate Bot --- go.mod | 32 ++++++++++++++--------------- go.sum | 64 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/go.mod b/go.mod index 1a4a6c346..acead4be8 100644 --- a/go.mod +++ b/go.mod @@ -16,22 +16,22 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.1 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.2 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.2 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.2 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.1 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.3 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.2 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.29.0 @@ -77,13 +77,13 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.2 github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.32.0 // indirect diff --git a/go.sum b/go.sum index 8ff2e67c3..197fdbb2e 100644 --- a/go.sum +++ b/go.sum @@ -113,52 +113,52 @@ github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJSjtaGnUI7UE7ITb5IT0= github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1 h1:7VOUNsnNBL2iQsZ3lJogNzKx4lrYEawDYllcXV1gEik= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1/go.mod h1:J2/Jk+leR6AjBotd7USJJzX+AEIHH11yxnmx+6ciJEk= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1/go.mod h1:+i7jQpfgj/OuZNVZ9A9aUHdVUR/j2SfICLeHbtNn+5c= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 h1:xaNory8kBIsBG7PJnBfPP1cERc+ERqjebxmEmEOvRHU= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0/go.mod h1:LVOYlzNt5BXDC42AHd/GZj6KvlCg4w94of/E6pZOj5k= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1 h1:4Kz9MH9VVuXYnnWFjJcPFVBiPtCUnSrHfsyUzBWwhKc= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1/go.mod h1:x0jgrL+/K2cE4BvcIQByFUf0nOPVZRqq5Z074kjjr64= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0 h1:5pcvoWS2sO3MIBP026OZEdImBNVvI27lksehqDMbAh0= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.0/go.mod h1:Lb1emAS4KI+pWDXQlbmST058wTsWyD8vLmdsJpRjfEg= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.2 h1:7PIcO05sveIb0CNfJiwsWhcR7tc+9/e4p580Hm398ww= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.2/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.2 h1:erpN0BM7lTkV/zhxka5fTYHssQaOqdGjj76c2FWMec0= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.2/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2 h1:6rb3EM0yXuMIBd1U6WsJoMzEiVaHC3WQFWFvT23OE4Y= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1 h1:JXcLcbVesTtwVVb+jJjU3o0FmSpXBRnOw6PVETaeK+E= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2 h1:5rVt3n7kDJvJQxFCtxfx8uZI9PGkvJY9fVJ4yar10Uc= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1 h1:ZeEuUf0DrTTU/acHOg+pQcpLZV1NF9SZbqI6ogjdLao= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1 h1:bdfgwsFNJRqCDUu/r4ZYyACzHCo1bD3y8fGFLYvX9C4= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1 h1:n6xMTHrLV9L78ureeigHHPwmMC4ZntOgVC+agV81Rpk= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.1/go.mod h1:R+fHrtGfy+zx+d5s31cBh09P3TG58dyytb83gB7ldi0= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1 h1:yyN3Q4i+5bmUVySPbQC7sSKG6sK21V8AxMjvhfJe2r0= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.1/go.mod h1:c5/LHxZZ7qZYOboR01qOw1Mqq5v/VNyONw7WPHctNeY= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.2 h1:xpgP7/fYBn26vvTEKmITH94bNJdrFJ7C89V7c3b2XYs= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.2/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.2 h1:h+EwnBOflLAKTZTlnl9YoB/z3ilvW34uezJO8YNG6Bo= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.2/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1 h1:BIMl8ISsDGsFB6dBqfxQMPFVyS5gB5EcwM4Jzpg65XE= github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0 h1:Au07XkATgBqrGpjO5t6ASAjuif7VXcKKF3t4edRh+Yw= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.0/go.mod h1:zyVy1/etVAq6NkdPG4kNOM2R7+AxXp5zLsiN4nDC7Fs= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2 h1:S6uamk6ecVy8K3jE2mgU50h14GoGE0LRVmiK3TvgfTc= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.2/go.mod h1:7TqfCUZRW7sjv8qOrLV5IvS6jqvY9Uxka165zdjYwD4= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.1 h1:yukHymULIXiSu7RQSnYOaPlBXegFR3ICMXdQzG8v14g= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.1/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.3 h1:IFXdEoN92c7qpvzeXqMnhz9OsiLR7Hiub7UkxK8luWo= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.3/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1 h1:CHRxxDBW+4VrpZDyXabOJCF7LY0i+PNYY5QWE0kwGIo= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0 h1:F+oTIOWeU5Jl0xsrJ+IV+Hz756UIOxBd7TFOD4YAv4k= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.0/go.mod h1:bjJccrTVRTyLowME8H9oelOrBILQ6xAvh+kVRSq3SBA= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1 h1:6bl/BSVebTnK73ToRn80Mtd1sl0TowfhOninyoSQA/U= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.1/go.mod h1:t7Bq7VRIN1D9C2sa2PE5gzwL6d7p1fypnsydYhKaA5k= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0 h1:tKUyddNszcif4j2yL6lJd4tDAykcU3shMkAPoM9EzV8= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.0/go.mod h1:5n31cpeYcz2DSax4ygpZICEHDoHCTbWHrNGNYWwlRA8= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.1 h1:bYIczS7iJNSQGkoSghicCC3F657TqLl4CelCgyt3tbw= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.1/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.2 h1:k+Nr9JBzBBy6di7T0pmQGEKqjPkbv8goRFdWo6BaIhQ= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.2/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.1 h1:VUoD+yQKwWFfgYAZd9JkjgKQCWjs0dDuf6ZgNYcXi6Y= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.1/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3 h1:L8uFydvDVJBdXLSQdgRwztbQewwNtTtuPhM1L1ehIvA= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1 h1:qujhShugc1290NQlPoNqsembqzot8aTToAdSsJg5WrM= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.1/go.mod h1:e1fsQL24gTPXcMWptuslNscawmXv/PLUAFuw+sOofbc= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.2 h1:mf4ej9oTc45huZxRe231DAPY9MOgm9qV1gflXdYQN4Q= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.2/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 h1:MCHMaS3hRTEYu+rWIDOas9tVn5+ddaulXzcE2porMek= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 h1:SdQ9VqDmamOhnTp6fd0QYKhCcoxB2GP938o7hGAubqg= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1 h1:7yY68QuntatwRG6ri65FlfeewACChLVbLp67wHCS8Go= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.1/go.mod h1:EMqjiq/72WKXSwnJGLpumUJS4Uwlyhg5vtNg7qWoGtc= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.2 h1:KsfdYvi24Mli50gEDuruXk5lg5mQIFqr/hfLfHHFJXU= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.2/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2 h1:SYX9IXg+2YAIdiUzLyqs9ga+S+bjhZs8WYeqU3GK3hk= github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1 h1:3uPq1jXXw8+6Op/fJuPaKOpTP0nOCHAUobMzZV7aHGg= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.1/go.mod h1:d2ICXCS2h3IMsZW0OanWkEH2XdLiY/XRKx2TcR940nw= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2 h1:uNwgJMHRuihWJJbnCw2FiJ9zZB9ZaE9YJ8e7ytZG1Pc= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= From fdb5bc6ecc7c8bf2da2baa25cacd0b2daaf0d875 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 5 May 2025 11:37:47 +0200 Subject: [PATCH 285/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/mongodbflex to v1 (#724) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index acead4be8..4751511be 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.2 github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.2 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.3 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.2 diff --git a/go.sum b/go.sum index 197fdbb2e..8ae569ae6 100644 --- a/go.sum +++ b/go.sum @@ -127,8 +127,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1 h1:ZeEuUf0DrTTU/ac github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1 h1:bdfgwsFNJRqCDUu/r4ZYyACzHCo1bD3y8fGFLYvX9C4= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.2 h1:xpgP7/fYBn26vvTEKmITH94bNJdrFJ7C89V7c3b2XYs= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v0.18.2/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.0 h1:kUdCkqVFEOP1GCUoLwdkMi9o+qtghvBT+grIE0nvvlc= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.2 h1:h+EwnBOflLAKTZTlnl9YoB/z3ilvW34uezJO8YNG6Bo= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.2/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1 h1:BIMl8ISsDGsFB6dBqfxQMPFVyS5gB5EcwM4Jzpg65XE= From 7624fb6ab320b7f77cfbdf4fc7a3f18d9450b7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 5 May 2025 13:49:28 +0200 Subject: [PATCH 286/619] feat(deps): use go 1.24 tool feature to install golangci-lint (#709) relates to STACKITCLI-178 --- .github/actions/build/action.yaml | 16 - .github/workflows/ci.yaml | 12 +- .github/workflows/release.yaml | 6 +- CONTRIBUTION.md | 1 - Makefile | 9 +- go.mod | 163 +++++- go.sum | 869 +++++++++++++++++++++++++++++- scripts/project.sh | 20 - 8 files changed, 1032 insertions(+), 64 deletions(-) delete mode 100644 .github/actions/build/action.yaml delete mode 100755 scripts/project.sh diff --git a/.github/actions/build/action.yaml b/.github/actions/build/action.yaml deleted file mode 100644 index 3601b23f3..000000000 --- a/.github/actions/build/action.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: Build -description: "Build pipeline" -inputs: - go-version: - description: "Go version to install" - required: true -runs: - using: "composite" - steps: - - name: Install Go ${{ inputs.go-version }} - uses: actions/setup-go@v5 - with: - go-version: ${{ inputs.go-version }} - - name: Install project tools and dependencies - shell: bash - run: make project-tools \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d069884e7..66c094cd5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,9 +2,6 @@ name: CI on: [pull_request, workflow_dispatch] -env: - GO_VERSION: "1.24" - jobs: main: name: CI @@ -13,11 +10,12 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Build - uses: ./.github/actions/build + - name: Install go + uses: actions/setup-go@v5 with: - go-version: ${{ env.GO_VERSION }} - + go-version-file: "go.mod" + cache: true + - name: "Ensure docs are up-to-date" if: ${{ github.event_name == 'pull_request' }} run: ./scripts/check-docs.sh diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0e3d6e9da..0bddeed42 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -25,11 +25,13 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.OBJECT_STORAGE_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.OBJECT_STORAGE_SECRET_ACCESS_KEY }} steps: - - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@v4 with: # Allow goreleaser to access older tag information. fetch-depth: 0 - - uses: actions/setup-go@v5 + - name: Install go + uses: actions/setup-go@v5 with: go-version-file: "go.mod" cache: true diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index 15034e8a6..a73808087 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -26,7 +26,6 @@ Prerequisites: These commands can be executed from the project root: -- `make project-tools`: install the required dependencies - `make build`: compile the CLI and save the binary under _./bin/stackit_ - `make lint`: lint the code - `make generate-docs`: generate Markdown documentation for every command diff --git a/Makefile b/Makefile index 373d2b0fb..e7b1abba0 100644 --- a/Makefile +++ b/Makefile @@ -10,17 +10,10 @@ build: fmt: @gofmt -s -w . -# Setup and tool initialization tasks -project-help: - @$(SCRIPTS_BASE)/project.sh help - -project-tools: - @$(SCRIPTS_BASE)/project.sh tools - # Lint lint-golangci-lint: @echo ">> Linting with golangci-lint" - @golangci-lint run ${GOLANG_CI_ARGS} + @go tool golangci-lint run ${GOLANG_CI_ARGS} lint-yamllint: @echo ">> Linting with yamllint" diff --git a/go.mod b/go.mod index 4751511be..f17316f31 100644 --- a/go.mod +++ b/go.mod @@ -42,18 +42,175 @@ require ( ) require ( - golang.org/x/net v0.33.0 // indirect - golang.org/x/time v0.8.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/time v0.10.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) require ( + 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect + 4d63.com/gochecknoglobals v0.2.2 // indirect al.essio.dev/pkg/shellescape v1.5.1 // indirect + github.com/4meepo/tagalign v1.4.2 // indirect + github.com/Abirdcfly/dupword v0.1.3 // indirect + github.com/Antonboom/errname v1.0.0 // indirect + github.com/Antonboom/nilnil v1.0.1 // indirect + github.com/Antonboom/testifylint v1.5.2 // indirect + github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect + github.com/Crocmagnon/fatcontext v0.7.1 // indirect + github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect + github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect + github.com/alecthomas/go-check-sumtype v0.3.1 // indirect + github.com/alexkohler/nakedret/v2 v2.0.5 // indirect + github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alingse/asasalint v0.0.11 // indirect + github.com/alingse/nilnesserr v0.1.2 // indirect + github.com/ashanbrown/forbidigo v1.6.0 // indirect + github.com/ashanbrown/makezero v1.2.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bkielbasa/cyclop v1.2.3 // indirect + github.com/blizzy78/varnamelen v0.8.0 // indirect + github.com/bombsimon/wsl/v4 v4.5.0 // indirect + github.com/breml/bidichk v0.3.2 // indirect + github.com/breml/errchkjson v0.4.0 // indirect + github.com/butuzov/ireturn v0.3.1 // indirect + github.com/butuzov/mirror v1.3.0 // indirect + github.com/catenacyber/perfsprint v0.8.2 // indirect + github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/charithe/durationcheck v0.0.10 // indirect + github.com/chavacava/garif v0.1.0 // indirect + github.com/ckaznocha/intrange v0.3.0 // indirect + github.com/curioswitch/go-reassign v0.3.0 // indirect + github.com/daixiang0/gci v0.13.5 // indirect + github.com/denis-tingaikin/go-header v0.5.0 // indirect + github.com/ettle/strcase v0.2.0 // indirect + github.com/fatih/structtag v1.2.0 // indirect + github.com/firefart/nonamedreturns v1.0.5 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/fzipp/gocyclo v0.6.0 // indirect + github.com/ghostiam/protogetter v0.3.9 // indirect + github.com/go-critic/go-critic v0.12.0 // indirect + github.com/go-toolsmith/astcast v1.1.0 // indirect + github.com/go-toolsmith/astcopy v1.1.0 // indirect + github.com/go-toolsmith/astequal v1.2.0 // indirect + github.com/go-toolsmith/astfmt v1.1.0 // indirect + github.com/go-toolsmith/astp v1.1.0 // indirect + github.com/go-toolsmith/strparse v1.1.0 // indirect + github.com/go-toolsmith/typep v1.1.0 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/gofrs/flock v0.12.1 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect + github.com/golangci/go-printf-func-name v0.1.0 // indirect + github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect + github.com/golangci/golangci-lint v1.64.8 // indirect + github.com/golangci/misspell v0.6.0 // indirect + github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/revgrep v0.8.0 // indirect + github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect + github.com/gordonklaus/ineffassign v0.1.0 // indirect + github.com/gostaticanalysis/analysisutil v0.7.1 // indirect + github.com/gostaticanalysis/comment v1.5.0 // indirect + github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect + github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hexops/gotextdiff v1.0.3 // indirect + github.com/jgautheron/goconst v1.7.1 // indirect + github.com/jingyugao/rowserrcheck v1.1.1 // indirect + github.com/jjti/go-spancheck v0.6.4 // indirect + github.com/julz/importas v0.2.0 // indirect + github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect + github.com/kisielk/errcheck v1.9.0 // indirect + github.com/kkHAIKE/contextcheck v1.1.6 // indirect + github.com/kulti/thelper v0.6.3 // indirect + github.com/kunwardeep/paralleltest v1.0.10 // indirect + github.com/lasiar/canonicalheader v1.1.2 // indirect + github.com/ldez/exptostd v0.4.2 // indirect + github.com/ldez/gomoddirectives v0.6.1 // indirect + github.com/ldez/grignotin v0.9.0 // indirect + github.com/ldez/tagliatelle v0.7.1 // indirect + github.com/ldez/usetesting v0.4.2 // indirect + github.com/leonklingele/grouper v1.1.2 // indirect + github.com/macabu/inamedparam v0.1.3 // indirect + github.com/maratori/testableexamples v1.0.0 // indirect + github.com/maratori/testpackage v1.1.1 // indirect + github.com/matoous/godox v1.1.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mgechev/revive v1.7.0 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/moricho/tparallel v0.3.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/nakabonne/nestif v0.3.1 // indirect + github.com/nishanths/exhaustive v0.12.0 // indirect + github.com/nishanths/predeclared v0.2.2 // indirect + github.com/nunnatsa/ginkgolinter v0.19.1 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/polyfloyd/go-errorlint v1.7.1 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect + github.com/quasilyte/gogrep v0.5.0 // indirect + github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect + github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect + github.com/raeperd/recvcheck v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/ryancurrah/gomodguard v1.3.5 // indirect + github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect + github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/sashamelentyev/interfacebloat v1.1.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect + github.com/securego/gosec/v2 v2.22.2 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sivchari/containedctx v1.0.3 // indirect + github.com/sivchari/tenv v1.12.1 // indirect + github.com/sonatard/noctx v0.1.0 // indirect + github.com/sourcegraph/go-diff v0.7.0 // indirect + github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect + github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.10.0 // indirect + github.com/tdakkota/asciicheck v0.4.1 // indirect + github.com/tetafro/godot v1.5.0 // indirect + github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 // indirect + github.com/timonwong/loggercheck v0.10.1 // indirect + github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect + github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect + github.com/ultraware/funlen v0.2.0 // indirect + github.com/ultraware/whitespace v0.2.0 // indirect + github.com/uudashr/gocognit v1.2.0 // indirect + github.com/uudashr/iface v1.3.1 // indirect github.com/x448/float16 v0.8.4 // indirect + github.com/xen0n/gosmopolitan v1.2.2 // indirect + github.com/yagipy/maintidx v1.0.0 // indirect + github.com/yeya24/promlinter v0.3.0 // indirect + github.com/ykadowak/zerologlint v0.1.5 // indirect + gitlab.com/bosi/decorder v0.4.2 // indirect + go-simpler.org/musttag v0.13.0 // indirect + go-simpler.org/sloglint v0.9.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect + golang.org/x/sync v0.13.0 // indirect + golang.org/x/tools v0.31.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + honnef.co/go/tools v0.6.1 // indirect + mvdan.cc/gofumpt v0.7.0 // indirect + mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect ) require ( @@ -95,3 +252,5 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) + +tool github.com/golangci/golangci-lint/cmd/golangci-lint diff --git a/go.sum b/go.sum index 8ae569ae6..3d0d69e46 100644 --- a/go.sum +++ b/go.sum @@ -1,23 +1,180 @@ +4d63.com/gocheckcompilerdirectives v1.3.0 h1:Ew5y5CtcAAQeTVKUVFrE7EwHMrTO6BggtEj8BZSjZ3A= +4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY= +4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= +4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho= al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= +github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= +github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= +github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= +github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= +github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= +github.com/Antonboom/nilnil v1.0.1 h1:C3Tkm0KUxgfO4Duk3PM+ztPncTFlOf0b2qadmS0s4xs= +github.com/Antonboom/nilnil v1.0.1/go.mod h1:CH7pW2JsRNFgEh8B2UaPZTEPhCMuFowP/e8Udp9Nnb0= +github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= +github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= +github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= +github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= +github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= +github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= +github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= +github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= +github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= +github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= +github.com/alingse/nilnesserr v0.1.2 h1:Yf8Iwm3z2hUUrP4muWfW83DF4nE3r1xZ26fGWUKCZlo= +github.com/alingse/nilnesserr v0.1.2/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= +github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= +github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= +github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= +github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= +github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= +github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= +github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= +github.com/bombsimon/wsl/v4 v4.5.0 h1:iZRsEvDdyhd2La0FVi5k6tYehpOR/R7qIUjmKk7N74A= +github.com/bombsimon/wsl/v4 v4.5.0/go.mod h1:NOQ3aLF4nD7N5YPXMruR6ZXDOAqLoM0GEpLwTdvmOSc= +github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs= +github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos= +github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk= +github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= +github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= +github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= +github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= +github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= +github.com/catenacyber/perfsprint v0.8.2 h1:+o9zVmCSVa7M4MvabsWvESEhpsMkhfE7k0sHNGL95yw= +github.com/catenacyber/perfsprint v0.8.2/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= +github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= +github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= +github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= +github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY= +github.com/ckaznocha/intrange v0.3.0/go.mod h1:+I/o2d2A1FBHgGELbGxzIcyd3/9l9DuwjM8FsbSS3Lo= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= +github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= +github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= +github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= +github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= +github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= +github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= +github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= +github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ= +github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= +github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= @@ -26,91 +183,385 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= +github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= +github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= +github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= +github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= +github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= +github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= +github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= +github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= +github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= +github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= +github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= +github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= +github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY= github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw= +github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E= +github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= +github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= +github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= +github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= +github.com/golangci/golangci-lint v1.64.8 h1:y5TdeVidMtBGG32zgSC7ZXTFNHrsJkDnpO4ItB3Am+I= +github.com/golangci/golangci-lint v1.64.8/go.mod h1:5cEsUQBSr6zi8XI8OjmcY2Xmliqc4iYL7YoPrL+zLJ4= +github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= +github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= +github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= +github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= +github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= +github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= +github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= +github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= +github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/comment v1.5.0 h1:X82FLl+TswsUMpMh17srGRuKaaXprTaytmEpgnKIDu8= +github.com/gostaticanalysis/comment v1.5.0/go.mod h1:V6eb3gpCv9GNVqb6amXzEUX3jXLVK/AdA+IrAMSqvEc= +github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk= +github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY= +github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= +github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= +github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= +github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= +github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo= github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= +github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= +github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= +github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= +github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= +github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= +github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI= +github.com/karamaru-alpha/copyloopvar v1.2.1/go.mod h1:nFmMlFNlClC2BPvNaHMdkirmTJxVCY0lhxBtlfOypMM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M= +github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE= +github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= +github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= +github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= +github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= +github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= +github.com/ldez/exptostd v0.4.2 h1:l5pOzHBz8mFOlbcifTxzfyYbgEmoUqjxLFHZkjlbHXs= +github.com/ldez/exptostd v0.4.2/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= +github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= +github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= +github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= +github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= +github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= +github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= +github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA= +github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= +github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y= github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= +github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= +github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= +github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= +github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4= +github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= +github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= +github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= +github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= +github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= +github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= +github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= +github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= +github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= +github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= +github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polyfloyd/go-errorlint v1.7.1 h1:RyLVXIbosq1gBdk/pChWA8zWYLsq9UEw7a1L5TVMCnA= +github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnXPhwEMtEXukiLR8= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= +github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= +github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= +github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= +github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/raeperd/recvcheck v0.2.0 h1:GnU+NsbiCqdC2XX5+vMZzP+jAJC5fht7rcVTAhX74UI= +github.com/raeperd/recvcheck v0.2.0/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= +github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= +github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= +github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= +github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= +github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= +github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= +github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/securego/gosec/v2 v2.22.2 h1:IXbuI7cJninj0nRpZSLCUlotsj8jGusohfONMrHoF6g= +github.com/securego/gosec/v2 v2.22.2/go.mod h1:UEBGA+dSKb+VqM6TdehR7lnQtIIMorYJ4/9CW1KVQBE= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= +github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= +github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= +github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= +github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= +github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= +github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= +github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJSjtaGnUI7UE7ITb5IT0= github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.2 h1:7PIcO05sveIb0CNfJiwsWhcR7tc+9/e4p580Hm398ww= @@ -159,73 +610,468 @@ github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2 h1:SYX9IXg+2YAIdiUzL github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2 h1:uNwgJMHRuihWJJbnCw2FiJ9zZB9ZaE9YJ8e7ytZG1Pc= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= +github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= +github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8= +github.com/tdakkota/asciicheck v0.4.1/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= +github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= +github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= +github.com/tetafro/godot v1.5.0 h1:aNwfVI4I3+gdxjMgYPus9eHmoBeJIbnajOyqZYStzuw= +github.com/tetafro/godot v1.5.0/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 h1:y4mJRFlM6fUyPhoXuFg/Yu02fg/nIPFMOY8tOqppoFg= +github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= +github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= +github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/tomarrell/wrapcheck/v2 v2.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg= +github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= +github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= +github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= +github.com/ultraware/funlen v0.2.0/go.mod h1:ZE0q4TsJ8T1SQcjmkhN/w+MceuatI6pBFSxxyteHIJA= +github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSWoFa+g= +github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= +github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= +github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= +github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= +github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= +github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= +github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= +github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= +github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= +github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4= +github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= +github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s= github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= +gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= +gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= +go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= +go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= +go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= +go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= +go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE= +go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= +golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= -google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= +honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= @@ -238,6 +1084,13 @@ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= +mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= +mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= +mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= diff --git a/scripts/project.sh b/scripts/project.sh deleted file mode 100755 index f8acf4e38..000000000 --- a/scripts/project.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# This script is used to manage the project, only used for installing the required tools for now -# Usage: ./project.sh [action] -# * tools: Install required tools to run the project -set -eo pipefail - -ROOT_DIR=$(git rev-parse --show-toplevel) - -action=$1 - -if [ "$action" = "help" ]; then - [ -f "$0".man ] && man "$0".man || echo "No help, please read the script in ${script}, we will add help later" -elif [ "$action" = "tools" ]; then - cd ${ROOT_DIR} - go mod download - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 -else - echo "! Invalid action: '$action', please use $0 help for help" -fi From 9cd9952f13964c9b874f136de6d20de5f643bc17 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 6 May 2025 08:25:26 +0200 Subject: [PATCH 287/619] chore(deps): update renovatebot/github-action action to v42 (#732) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 28d5b38a9..952f88e2f 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v41.0.22 + uses: renovatebot/github-action@v42.0.1 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 9176bd50910b22bbb0fe42c118a0f5b6853dff00 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 6 May 2025 08:26:27 +0200 Subject: [PATCH 288/619] fix(deps): update module golang.org/x/text to v0.25.0 (#730) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f17316f31..4156e0767 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.29.0 golang.org/x/term v0.31.0 - golang.org/x/text v0.24.0 + golang.org/x/text v0.25.0 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 ) @@ -204,7 +204,7 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/sync v0.13.0 // indirect + golang.org/x/sync v0.14.0 // indirect golang.org/x/tools v0.31.0 // indirect google.golang.org/protobuf v1.36.5 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 3d0d69e46..86a479231 100644 --- a/go.sum +++ b/go.sum @@ -817,8 +817,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -894,8 +894,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 81c1fb3d648f2b9fcd821805c42e1a60675642b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 May 2025 08:27:12 +0200 Subject: [PATCH 289/619] chore(deps): bump golang.org/x/oauth2 from 0.29.0 to 0.30.0 (#727) Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.29.0 to 0.30.0. - [Commits](https://github.com/golang/oauth2/compare/v0.29.0...v0.30.0) --- updated-dependencies: - dependency-name: golang.org/x/oauth2 dependency-version: 0.30.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4156e0767..ee4bc850f 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 - golang.org/x/oauth2 v0.29.0 + golang.org/x/oauth2 v0.30.0 golang.org/x/term v0.31.0 golang.org/x/text v0.25.0 k8s.io/apimachinery v0.32.3 diff --git a/go.sum b/go.sum index 86a479231..00ec03e43 100644 --- a/go.sum +++ b/go.sum @@ -800,8 +800,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= -golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 7e419c51a766d6ab3ad89a5f133f4ebd2f858f2e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 6 May 2025 08:27:51 +0200 Subject: [PATCH 290/619] fix(deps): update module golang.org/x/oauth2 to v0.30.0 (#728) Co-authored-by: Renovate Bot From 6a6a5bf099147556e8e59c35892e2400b7d809a7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 6 May 2025 08:37:03 +0200 Subject: [PATCH 291/619] fix(deps): update module golang.org/x/term to v0.32.0 (#729) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ee4bc850f..17b9519ec 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.30.0 - golang.org/x/term v0.31.0 + golang.org/x/term v0.32.0 golang.org/x/text v0.25.0 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 @@ -243,7 +243,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.32.0 // indirect + golang.org/x/sys v0.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 00ec03e43..96974ea87 100644 --- a/go.sum +++ b/go.sum @@ -870,8 +870,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -880,8 +880,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From f572e14940df6a98781dc3871bca880bd03da3b5 Mon Sep 17 00:00:00 2001 From: Mauritz Uphoff <39736813+h3adex@users.noreply.github.com> Date: Wed, 7 May 2025 08:49:31 +0200 Subject: [PATCH 292/619] feat: prettify json output using stackit curl (#713) --- internal/cmd/curl/curl.go | 41 +++++++++++++++++++++++++++++++--- internal/cmd/curl/curl_test.go | 18 +++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index f52217b73..9959e50f1 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -2,6 +2,7 @@ package curl import ( "bytes" + "encoding/json" "fmt" "io" "net/http" @@ -170,11 +171,29 @@ func getBearerToken(p *print.Printer) (string, error) { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return "", &errors.AuthError{} } - token, err := auth.GetAuthField(auth.ACCESS_TOKEN) + + userSessionExpired, err := auth.UserSessionExpired() + if err != nil { + return "", err + } + if userSessionExpired { + return "", &errors.SessionExpiredError{} + } + + accessToken, err := auth.GetAccessToken() if err != nil { - return "", fmt.Errorf("get access token: %w", err) + return "", err + } + + accessTokenExpired, err := auth.TokenExpired(accessToken) + if err != nil { + return "", err + } + if accessTokenExpired { + return "", &errors.AccessTokenExpiredError{} } - return token, nil + + return accessToken, nil } func buildRequest(model *inputModel, bearerToken string) (*http.Request, error) { @@ -213,6 +232,22 @@ func outputResponse(p *print.Printer, model *inputModel, resp *http.Response) er if err != nil { return fmt.Errorf("read response body: %w", err) } + + if strings.Contains(strings.ToLower(string(respBody)), "jwt is expired") { + return &errors.SessionExpiredError{} + } + + if strings.Contains(strings.ToLower(string(respBody)), "jwt is missing") { + return &errors.AuthError{} + } + + var prettyJSON bytes.Buffer + if json.Valid(respBody) { + if err := json.Indent(&prettyJSON, respBody, "", " "); err == nil { + respBody = prettyJSON.Bytes() + } // if indenting fails, fall back to original body + } + output = append(output, respBody...) if model.OutputFile == nil { diff --git a/internal/cmd/curl/curl_test.go b/internal/cmd/curl/curl_test.go index 372d5663d..c7b4dcf4b 100644 --- a/internal/cmd/curl/curl_test.go +++ b/internal/cmd/curl/curl_test.go @@ -4,8 +4,10 @@ import ( "bytes" "context" "fmt" + "io" "net/http" "os" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -427,6 +429,22 @@ func TestOutputResponse(t *testing.T) { }, wantErr: false, }, + { + name: "expired jwt curl", + args: args{ + model: fixtureInputModel(), + resp: &http.Response{Body: io.NopCloser(strings.NewReader("Jwt is expired"))}, + }, + wantErr: true, + }, + { + name: "mssing jwt curl", + args: args{ + model: fixtureInputModel(), + resp: &http.Response{Body: io.NopCloser(strings.NewReader("Jwt is missing"))}, + }, + wantErr: true, + }, } p := print.NewPrinter() p.Cmd = NewCmd(p) From 420650c06b9e5000d47d1062e8af046c3d130adc Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 7 May 2025 08:50:33 +0200 Subject: [PATCH 293/619] chore(deps): update module github.com/golangci/golangci-lint to v2 (#731) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update module github.com/golangci/golangci-lint to v2 * chore: fixed dependencies for golangci compatibility --------- Co-authored-by: Renovate Bot Co-authored-by: Rüdiger Schmitz <152157960+bahkauv70@users.noreply.github.com> --- go.mod | 81 +++++++++++++-------------- go.sum | 172 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 127 insertions(+), 126 deletions(-) diff --git a/go.mod b/go.mod index 17b9519ec..115e36520 100644 --- a/go.mod +++ b/go.mod @@ -42,8 +42,8 @@ require ( ) require ( - golang.org/x/net v0.37.0 // indirect - golang.org/x/time v0.10.0 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -53,46 +53,47 @@ require ( al.essio.dev/pkg/shellescape v1.5.1 // indirect github.com/4meepo/tagalign v1.4.2 // indirect github.com/Abirdcfly/dupword v0.1.3 // indirect - github.com/Antonboom/errname v1.0.0 // indirect - github.com/Antonboom/nilnil v1.0.1 // indirect - github.com/Antonboom/testifylint v1.5.2 // indirect - github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect + github.com/Antonboom/errname v1.1.0 // indirect + github.com/Antonboom/nilnil v1.1.0 // indirect + github.com/Antonboom/testifylint v1.6.1 // indirect + github.com/BurntSushi/toml v1.5.0 // indirect github.com/Crocmagnon/fatcontext v0.7.1 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect - github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.5 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect - github.com/alingse/nilnesserr v0.1.2 // indirect + github.com/alingse/nilnesserr v0.2.0 // indirect github.com/ashanbrown/forbidigo v1.6.0 // indirect github.com/ashanbrown/makezero v1.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v4 v4.5.0 // indirect - github.com/breml/bidichk v0.3.2 // indirect - github.com/breml/errchkjson v0.4.0 // indirect - github.com/butuzov/ireturn v0.3.1 // indirect + github.com/bombsimon/wsl/v4 v4.7.0 // indirect + github.com/breml/bidichk v0.3.3 // indirect + github.com/breml/errchkjson v0.4.1 // indirect + github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect - github.com/catenacyber/perfsprint v0.8.2 // indirect + github.com/catenacyber/perfsprint v0.9.1 // indirect github.com/ccojocar/zxcvbn-go v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charithe/durationcheck v0.0.10 // indirect github.com/chavacava/garif v0.1.0 // indirect - github.com/ckaznocha/intrange v0.3.0 // indirect + github.com/ckaznocha/intrange v0.3.1 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect - github.com/daixiang0/gci v0.13.5 // indirect + github.com/daixiang0/gci v0.13.6 // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.5 // indirect + github.com/firefart/nonamedreturns v1.0.6 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.9 // indirect - github.com/go-critic/go-critic v0.12.0 // indirect + github.com/ghostiam/protogetter v0.3.15 // indirect + github.com/go-critic/go-critic v0.13.0 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.2.0 // indirect @@ -130,21 +131,21 @@ require ( github.com/kisielk/errcheck v1.9.0 // indirect github.com/kkHAIKE/contextcheck v1.1.6 // indirect github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.10 // indirect + github.com/kunwardeep/paralleltest v1.0.14 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.2 // indirect + github.com/ldez/exptostd v0.4.3 // indirect github.com/ldez/gomoddirectives v0.6.1 // indirect github.com/ldez/grignotin v0.9.0 // indirect github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.2 // indirect + github.com/ldez/usetesting v0.4.3 // indirect github.com/leonklingele/grouper v1.1.2 // indirect - github.com/macabu/inamedparam v0.1.3 // indirect + github.com/macabu/inamedparam v0.2.0 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v1.1.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mgechev/revive v1.7.0 // indirect + github.com/mgechev/revive v1.9.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -154,25 +155,25 @@ require ( github.com/nunnatsa/ginkgolinter v0.19.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/polyfloyd/go-errorlint v1.7.1 // indirect + github.com/polyfloyd/go-errorlint v1.8.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect + github.com/quasilyte/go-ruleguard v0.4.4 // indirect github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/raeperd/recvcheck v0.2.0 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect - github.com/ryancurrah/gomodguard v1.3.5 // indirect + github.com/ryancurrah/gomodguard v1.4.1 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect - github.com/securego/gosec/v2 v2.22.2 // indirect + github.com/securego/gosec/v2 v2.22.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/sivchari/tenv v1.12.1 // indirect @@ -183,34 +184,34 @@ require ( github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/testify v1.10.0 // indirect github.com/tdakkota/asciicheck v0.4.1 // indirect - github.com/tetafro/godot v1.5.0 // indirect - github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 // indirect - github.com/timonwong/loggercheck v0.10.1 // indirect - github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect + github.com/tetafro/godot v1.5.1 // indirect + github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect + github.com/timonwong/loggercheck v0.11.0 // indirect + github.com/tomarrell/wrapcheck/v2 v2.11.0 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect github.com/uudashr/gocognit v1.2.0 // indirect github.com/uudashr/iface v1.3.1 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xen0n/gosmopolitan v1.2.2 // indirect + github.com/xen0n/gosmopolitan v1.3.0 // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect - go-simpler.org/musttag v0.13.0 // indirect - go-simpler.org/sloglint v0.9.0 // indirect + go-simpler.org/musttag v0.13.1 // indirect + go-simpler.org/sloglint v0.11.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.14.0 // indirect - golang.org/x/tools v0.31.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect + golang.org/x/tools v0.32.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect honnef.co/go/tools v0.6.1 // indirect - mvdan.cc/gofumpt v0.7.0 // indirect - mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect + mvdan.cc/gofumpt v0.8.0 // indirect + mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect ) require ( @@ -227,12 +228,12 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2 github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1 diff --git a/go.sum b/go.sum index 96974ea87..babf8358f 100644 --- a/go.sum +++ b/go.sum @@ -41,15 +41,15 @@ github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= -github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= -github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= -github.com/Antonboom/nilnil v1.0.1 h1:C3Tkm0KUxgfO4Duk3PM+ztPncTFlOf0b2qadmS0s4xs= -github.com/Antonboom/nilnil v1.0.1/go.mod h1:CH7pW2JsRNFgEh8B2UaPZTEPhCMuFowP/e8Udp9Nnb0= -github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= -github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= +github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= +github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= +github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= +github.com/Antonboom/nilnil v1.1.0/go.mod h1:b7sAlogQjFa1wV8jUW3o4PMzDVFLbTux+xnQdvzdcIE= +github.com/Antonboom/testifylint v1.6.1 h1:6ZSytkFWatT8mwZlmRCHkWz1gPi+q6UBSbieji2Gj/o= +github.com/Antonboom/testifylint v1.6.1/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= @@ -57,8 +57,8 @@ github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rW github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= +github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= @@ -78,8 +78,8 @@ github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pO github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/alingse/nilnesserr v0.1.2 h1:Yf8Iwm3z2hUUrP4muWfW83DF4nE3r1xZ26fGWUKCZlo= -github.com/alingse/nilnesserr v0.1.2/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= +github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= +github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= @@ -94,18 +94,18 @@ github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5 github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v4 v4.5.0 h1:iZRsEvDdyhd2La0FVi5k6tYehpOR/R7qIUjmKk7N74A= -github.com/bombsimon/wsl/v4 v4.5.0/go.mod h1:NOQ3aLF4nD7N5YPXMruR6ZXDOAqLoM0GEpLwTdvmOSc= -github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs= -github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos= -github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk= -github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= -github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= -github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= +github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= +github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= +github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= +github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= +github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= +github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s= +github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E= +github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= -github.com/catenacyber/perfsprint v0.8.2 h1:+o9zVmCSVa7M4MvabsWvESEhpsMkhfE7k0sHNGL95yw= -github.com/catenacyber/perfsprint v0.8.2/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= +github.com/catenacyber/perfsprint v0.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= +github.com/catenacyber/perfsprint v0.9.1/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -120,16 +120,16 @@ github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+U github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY= -github.com/ckaznocha/intrange v0.3.0/go.mod h1:+I/o2d2A1FBHgGELbGxzIcyd3/9l9DuwjM8FsbSS3Lo= +github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs= +github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= -github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/daixiang0/gci v0.13.6 h1:RKuEOSkGpSadkGbvZ6hJ4ddItT3cVZ9Vn9Rybk6xjl8= +github.com/daixiang0/gci v0.13.6/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -138,8 +138,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= -github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= -github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -152,8 +152,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= -github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= +github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E= +github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= @@ -162,10 +162,10 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ= -github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= -github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= -github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= +github.com/ghostiam/protogetter v0.3.15 h1:1KF5sXel0HE48zh1/vn0Loiw25A9ApyseLzQuif1mLY= +github.com/ghostiam/protogetter v0.3.15/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= +github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -384,26 +384,26 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= -github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= +github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.2 h1:l5pOzHBz8mFOlbcifTxzfyYbgEmoUqjxLFHZkjlbHXs= -github.com/ldez/exptostd v0.4.2/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= +github.com/ldez/exptostd v0.4.3 h1:Ag1aGiq2epGePuRJhez2mzOpZ8sI9Gimcb4Sb3+pk9Y= +github.com/ldez/exptostd v0.4.3/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA= -github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k= +github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y= github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= -github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= +github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= +github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= @@ -423,8 +423,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= -github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= +github.com/mgechev/revive v1.9.0 h1:8LaA62XIKrb8lM6VsBSQ92slt/o92z5+hTw3CmrvSrM= +github.com/mgechev/revive v1.9.0/go.mod h1:LAPq3+MgOf7GcL5PlWIkHb0PT7XH4NuC2LdWymhb9Mo= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -450,10 +450,10 @@ github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= +github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -461,8 +461,8 @@ github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -470,8 +470,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.7.1 h1:RyLVXIbosq1gBdk/pChWA8zWYLsq9UEw7a1L5TVMCnA= -github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnXPhwEMtEXukiLR8= +github.com/polyfloyd/go-errorlint v1.8.0 h1:DL4RestQqRLr8U4LygLw8g2DX6RN1eBJOpa2mzsrl1Q= +github.com/polyfloyd/go-errorlint v1.8.0/go.mod h1:G2W0Q5roxbLCt0ZQbdoxQxXktTjwNyDbEaj3n7jvl4s= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -496,8 +496,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= -github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= +github.com/quasilyte/go-ruleguard v0.4.4 h1:53DncefIeLX3qEpjzlS1lyUmQoUEeOWPFWqaTJq9eAQ= +github.com/quasilyte/go-ruleguard v0.4.4/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= @@ -516,8 +516,8 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= -github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= +github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb7Elr+g= +github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= @@ -530,8 +530,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= -github.com/securego/gosec/v2 v2.22.2 h1:IXbuI7cJninj0nRpZSLCUlotsj8jGusohfONMrHoF6g= -github.com/securego/gosec/v2 v2.22.2/go.mod h1:UEBGA+dSKb+VqM6TdehR7lnQtIIMorYJ4/9CW1KVQBE= +github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4trLRc= +github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -549,8 +549,8 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= +github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= @@ -636,14 +636,14 @@ github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.5.0 h1:aNwfVI4I3+gdxjMgYPus9eHmoBeJIbnajOyqZYStzuw= -github.com/tetafro/godot v1.5.0/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= -github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 h1:y4mJRFlM6fUyPhoXuFg/Yu02fg/nIPFMOY8tOqppoFg= -github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= -github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= -github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= -github.com/tomarrell/wrapcheck/v2 v2.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg= -github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= +github.com/tetafro/godot v1.5.1 h1:PZnjCol4+FqaEzvZg5+O8IY2P3hfY9JzRBNPv1pEDS4= +github.com/tetafro/godot v1.5.1/go.mod h1:cCdPtEndkmqqrhiCfkmxDodMQJ/f3L1BCNskCUZdTwk= +github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk= +github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= +github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= +github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/tomarrell/wrapcheck/v2 v2.11.0 h1:BJSt36snX9+4WTIXeJ7nvHBQBcm1h2SjQMSlmQ6aFSU= +github.com/tomarrell/wrapcheck/v2 v2.11.0/go.mod h1:wFL9pDWDAbXhhPZZt+nG8Fu+h29TtnZ2MW6Lx4BRXIU= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= @@ -656,8 +656,8 @@ github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= -github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= +github.com/xen0n/gosmopolitan v1.3.0 h1:zAZI1zefvo7gcpbCOrPSHJZJYA9ZgLfJqtKzZ5pHqQM= +github.com/xen0n/gosmopolitan v1.3.0/go.mod h1:rckfr5T6o4lBtM1ga7mLGKZmLxswUoH1zxHgNXOsEt4= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= @@ -677,10 +677,10 @@ gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= -go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= -go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE= -go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww= +go-simpler.org/musttag v0.13.1 h1:lw2sJyu7S1X8lc8zWUAdH42y+afdcCnHhWpnkWvd6vU= +go-simpler.org/musttag v0.13.1/go.mod h1:8r450ehpMLQgvpb6sg+hV5Ur47eH6olp/3yEanfG97k= +go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= +go-simpler.org/sloglint v0.11.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -792,8 +792,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -899,8 +899,8 @@ golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= -golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -959,8 +959,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= +golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1040,8 +1040,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1084,10 +1084,10 @@ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= -mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= -mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= -mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= +mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= +mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= +mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= +mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From de4712f3213dfe7bab2c060917e8ff2dbda38a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 8 May 2025 13:30:06 +0200 Subject: [PATCH 294/619] feat(fmt): run goimports on format make command (#733) --- Makefile | 1 + go.mod | 9 ++++++--- go.sum | 4 ++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index e7b1abba0..171d9864d 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ build: fmt: @gofmt -s -w . + @go tool goimports -w . # Lint lint-golangci-lint: diff --git a/go.mod b/go.mod index 115e36520..3e5f0a4b2 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( ) require ( - golang.org/x/net v0.39.0 // indirect + golang.org/x/net v0.40.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -206,7 +206,7 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.14.0 // indirect - golang.org/x/tools v0.32.0 // indirect + golang.org/x/tools v0.33.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect honnef.co/go/tools v0.6.1 // indirect @@ -254,4 +254,7 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -tool github.com/golangci/golangci-lint/cmd/golangci-lint +tool ( + github.com/golangci/golangci-lint/cmd/golangci-lint + golang.org/x/tools/cmd/goimports +) diff --git a/go.sum b/go.sum index babf8358f..43889808a 100644 --- a/go.sum +++ b/go.sum @@ -794,6 +794,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -961,6 +963,8 @@ golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58 golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 8622b5f04964a8ba4ff18e39724884420c89ed04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 9 May 2025 15:25:58 +0200 Subject: [PATCH 295/619] refactor(cli): pass parameter struct to cmd factories (#735) relates to STACKITCLI-180 --- .github/docs/contribution-guide/client.go | 35 ++++ .github/docs/contribution-guide/cmd.go | 156 +++++++++++++++ CONTRIBUTION.md | 177 +----------------- .../cmd/affinity-groups/affinity-groups.go | 16 +- internal/cmd/affinity-groups/create/create.go | 11 +- .../cmd/affinity-groups/create/create_test.go | 5 +- internal/cmd/affinity-groups/delete/delete.go | 17 +- .../cmd/affinity-groups/delete/delete_test.go | 3 +- .../cmd/affinity-groups/describe/describe.go | 9 +- .../affinity-groups/describe/describe_test.go | 5 +- internal/cmd/affinity-groups/list/list.go | 11 +- .../cmd/affinity-groups/list/list_test.go | 5 +- .../activate_service_account.go | 13 +- .../activate_service_account_test.go | 3 +- internal/cmd/auth/auth.go | 16 +- .../auth/get-access-token/get_access_token.go | 6 +- internal/cmd/auth/login/login.go | 8 +- internal/cmd/auth/logout/logout.go | 6 +- internal/cmd/beta/alb/alb.go | 28 +-- internal/cmd/beta/alb/create/create.go | 17 +- internal/cmd/beta/alb/create/create_test.go | 5 +- internal/cmd/beta/alb/delete/delete.go | 15 +- internal/cmd/beta/alb/delete/delete_test.go | 3 +- internal/cmd/beta/alb/describe/describe.go | 11 +- .../cmd/beta/alb/describe/describe_test.go | 5 +- internal/cmd/beta/alb/list/list.go | 15 +- internal/cmd/beta/alb/list/list_test.go | 5 +- .../alb/observability-credentials/add/add.go | 11 +- .../observability-credentials/add/add_test.go | 5 +- .../delete/delete.go | 11 +- .../delete/delete_test.go | 3 +- .../describe/describe.go | 11 +- .../describe/describe_test.go | 5 +- .../observability-credentials/list/list.go | 11 +- .../list/list_test.go | 5 +- .../observability-credentials.go | 18 +- .../update/update.go | 15 +- .../update/update_test.go | 5 +- internal/cmd/beta/alb/plans/plans.go | 15 +- internal/cmd/beta/alb/plans/plans_test.go | 5 +- internal/cmd/beta/alb/pool/pool.go | 10 +- internal/cmd/beta/alb/pool/update/update.go | 15 +- .../cmd/beta/alb/pool/update/update_test.go | 5 +- internal/cmd/beta/alb/quotas/quotas.go | 11 +- internal/cmd/beta/alb/quotas/quotas_test.go | 5 +- internal/cmd/beta/alb/template/template.go | 7 +- .../cmd/beta/alb/template/template_test.go | 3 +- internal/cmd/beta/alb/update/update.go | 17 +- internal/cmd/beta/alb/update/update_test.go | 5 +- internal/cmd/beta/beta.go | 12 +- .../sqlserverflex/database/create/create.go | 13 +- .../database/create/create_test.go | 5 +- .../beta/sqlserverflex/database/database.go | 16 +- .../sqlserverflex/database/delete/delete.go | 13 +- .../database/delete/delete_test.go | 3 +- .../database/describe/describe.go | 9 +- .../database/describe/describe_test.go | 5 +- .../beta/sqlserverflex/database/list/list.go | 15 +- .../sqlserverflex/database/list/list_test.go | 3 +- .../sqlserverflex/instance/create/create.go | 17 +- .../instance/create/create_test.go | 5 +- .../sqlserverflex/instance/delete/delete.go | 15 +- .../instance/delete/delete_test.go | 3 +- .../instance/describe/describe.go | 9 +- .../instance/describe/describe_test.go | 5 +- .../beta/sqlserverflex/instance/instance.go | 18 +- .../beta/sqlserverflex/instance/list/list.go | 15 +- .../sqlserverflex/instance/list/list_test.go | 3 +- .../sqlserverflex/instance/update/update.go | 15 +- .../instance/update/update_test.go | 5 +- .../cmd/beta/sqlserverflex/options/options.go | 9 +- .../sqlserverflex/options/options_test.go | 7 +- .../cmd/beta/sqlserverflex/sqlserverflex.go | 16 +- .../beta/sqlserverflex/user/create/create.go | 13 +- .../sqlserverflex/user/create/create_test.go | 3 +- .../beta/sqlserverflex/user/delete/delete.go | 15 +- .../sqlserverflex/user/delete/delete_test.go | 3 +- .../sqlserverflex/user/describe/describe.go | 9 +- .../user/describe/describe_test.go | 5 +- .../cmd/beta/sqlserverflex/user/list/list.go | 13 +- .../beta/sqlserverflex/user/list/list_test.go | 3 +- .../user/reset-password/reset_password.go | 15 +- .../reset-password/reset_password_test.go | 5 +- internal/cmd/beta/sqlserverflex/user/user.go | 18 +- internal/cmd/config/config.go | 16 +- internal/cmd/config/list/list.go | 7 +- internal/cmd/config/list/list_test.go | 3 +- internal/cmd/config/profile/create/create.go | 17 +- .../cmd/config/profile/create/create_test.go | 3 +- internal/cmd/config/profile/delete/delete.go | 13 +- .../cmd/config/profile/delete/delete_test.go | 3 +- internal/cmd/config/profile/export/export.go | 9 +- .../cmd/config/profile/export/export_test.go | 3 +- internal/cmd/config/profile/import/import.go | 9 +- .../cmd/config/profile/import/import_test.go | 3 +- internal/cmd/config/profile/list/list.go | 7 +- internal/cmd/config/profile/list/list_test.go | 3 +- internal/cmd/config/profile/profile.go | 22 +-- internal/cmd/config/profile/set/set.go | 15 +- internal/cmd/config/profile/set/set_test.go | 3 +- internal/cmd/config/profile/unset/unset.go | 13 +- internal/cmd/config/set/set.go | 7 +- internal/cmd/config/set/set_test.go | 3 +- internal/cmd/config/unset/unset.go | 5 +- internal/cmd/config/unset/unset_test.go | 3 +- internal/cmd/curl/curl.go | 9 +- internal/cmd/curl/curl_test.go | 5 +- internal/cmd/dns/dns.go | 12 +- internal/cmd/dns/record-set/create/create.go | 15 +- .../cmd/dns/record-set/create/create_test.go | 5 +- internal/cmd/dns/record-set/delete/delete.go | 17 +- .../cmd/dns/record-set/delete/delete_test.go | 3 +- .../cmd/dns/record-set/describe/describe.go | 9 +- .../dns/record-set/describe/describe_test.go | 5 +- internal/cmd/dns/record-set/list/list.go | 13 +- internal/cmd/dns/record-set/list/list_test.go | 5 +- internal/cmd/dns/record-set/record_set.go | 18 +- internal/cmd/dns/record-set/update/update.go | 19 +- .../cmd/dns/record-set/update/update_test.go | 3 +- internal/cmd/dns/zone/clone/clone.go | 15 +- internal/cmd/dns/zone/clone/clone_test.go | 5 +- internal/cmd/dns/zone/create/create.go | 17 +- internal/cmd/dns/zone/create/create_test.go | 5 +- internal/cmd/dns/zone/delete/delete.go | 15 +- internal/cmd/dns/zone/delete/delete_test.go | 3 +- internal/cmd/dns/zone/describe/describe.go | 9 +- .../cmd/dns/zone/describe/describe_test.go | 5 +- internal/cmd/dns/zone/list/list.go | 15 +- internal/cmd/dns/zone/list/list_test.go | 5 +- internal/cmd/dns/zone/update/update.go | 15 +- internal/cmd/dns/zone/update/update_test.go | 3 +- internal/cmd/dns/zone/zone.go | 20 +- internal/cmd/image/create/create.go | 13 +- internal/cmd/image/create/create_test.go | 5 +- internal/cmd/image/delete/delete.go | 17 +- internal/cmd/image/delete/delete_test.go | 3 +- internal/cmd/image/describe/describe.go | 9 +- internal/cmd/image/describe/describe_test.go | 5 +- internal/cmd/image/image.go | 18 +- internal/cmd/image/list/list.go | 15 +- internal/cmd/image/list/list_test.go | 5 +- internal/cmd/image/update/update.go | 17 +- internal/cmd/image/update/update_test.go | 3 +- internal/cmd/key-pair/create/create.go | 11 +- internal/cmd/key-pair/create/create_test.go | 5 +- internal/cmd/key-pair/delete/delete.go | 11 +- internal/cmd/key-pair/delete/delete_test.go | 3 +- internal/cmd/key-pair/describe/describe.go | 11 +- .../cmd/key-pair/describe/describe_test.go | 5 +- internal/cmd/key-pair/key-pair.go | 18 +- internal/cmd/key-pair/list/list.go | 11 +- internal/cmd/key-pair/list/list_test.go | 5 +- internal/cmd/key-pair/update/update.go | 11 +- internal/cmd/key-pair/update/update_test.go | 5 +- internal/cmd/load-balancer/create/create.go | 17 +- .../cmd/load-balancer/create/create_test.go | 3 +- internal/cmd/load-balancer/delete/delete.go | 13 +- .../cmd/load-balancer/delete/delete_test.go | 3 +- .../cmd/load-balancer/describe/describe.go | 9 +- .../load-balancer/describe/describe_test.go | 5 +- .../generate-payload/generate_payload.go | 11 +- .../generate-payload/generate_payload_test.go | 7 +- internal/cmd/load-balancer/list/list.go | 15 +- internal/cmd/load-balancer/list/list_test.go | 5 +- internal/cmd/load-balancer/load_balancer.go | 26 +-- .../observability-credentials/add/add.go | 17 +- .../observability-credentials/add/add_test.go | 5 +- .../cleanup/cleanup.go | 17 +- .../cleanup/cleanup_test.go | 3 +- .../delete/delete.go | 17 +- .../delete/delete_test.go | 3 +- .../describe/describe.go | 9 +- .../describe/describe_test.go | 5 +- .../observability-credentials/list/list.go | 15 +- .../list/list_test.go | 5 +- .../observability-credentials.go | 20 +- .../update/update.go | 19 +- .../update/update_test.go | 3 +- internal/cmd/load-balancer/quota/quota.go | 9 +- .../cmd/load-balancer/quota/quota_test.go | 5 +- .../target-pool/add-target/add_target.go | 11 +- .../target-pool/add-target/add_target_test.go | 3 +- .../target-pool/describe/describe.go | 9 +- .../target-pool/describe/describe_test.go | 5 +- .../remove-target/remove_target.go | 13 +- .../remove-target/remove_target_test.go | 3 +- .../load-balancer/target-pool/target_pool.go | 14 +- internal/cmd/load-balancer/update/update.go | 11 +- .../cmd/load-balancer/update/update_test.go | 3 +- .../cmd/logme/credentials/create/create.go | 13 +- .../logme/credentials/create/create_test.go | 5 +- internal/cmd/logme/credentials/credentials.go | 16 +- .../cmd/logme/credentials/delete/delete.go | 15 +- .../logme/credentials/delete/delete_test.go | 3 +- .../logme/credentials/describe/describe.go | 9 +- .../credentials/describe/describe_test.go | 5 +- internal/cmd/logme/credentials/list/list.go | 13 +- .../cmd/logme/credentials/list/list_test.go | 5 +- internal/cmd/logme/instance/create/create.go | 17 +- .../cmd/logme/instance/create/create_test.go | 5 +- internal/cmd/logme/instance/delete/delete.go | 15 +- .../cmd/logme/instance/delete/delete_test.go | 3 +- .../cmd/logme/instance/describe/describe.go | 9 +- .../logme/instance/describe/describe_test.go | 5 +- internal/cmd/logme/instance/instance.go | 18 +- internal/cmd/logme/instance/list/list.go | 15 +- internal/cmd/logme/instance/list/list_test.go | 3 +- internal/cmd/logme/instance/update/update.go | 15 +- .../cmd/logme/instance/update/update_test.go | 3 +- internal/cmd/logme/logme.go | 14 +- internal/cmd/logme/plans/plans.go | 15 +- internal/cmd/logme/plans/plans_test.go | 3 +- .../cmd/mariadb/credentials/create/create.go | 13 +- .../mariadb/credentials/create/create_test.go | 5 +- .../cmd/mariadb/credentials/credentials.go | 16 +- .../cmd/mariadb/credentials/delete/delete.go | 15 +- .../mariadb/credentials/delete/delete_test.go | 3 +- .../mariadb/credentials/describe/describe.go | 9 +- .../credentials/describe/describe_test.go | 5 +- internal/cmd/mariadb/credentials/list/list.go | 13 +- .../cmd/mariadb/credentials/list/list_test.go | 5 +- .../cmd/mariadb/instance/create/create.go | 17 +- .../mariadb/instance/create/create_test.go | 5 +- .../cmd/mariadb/instance/delete/delete.go | 15 +- .../mariadb/instance/delete/delete_test.go | 3 +- .../cmd/mariadb/instance/describe/describe.go | 9 +- .../instance/describe/describe_test.go | 5 +- internal/cmd/mariadb/instance/instance.go | 18 +- internal/cmd/mariadb/instance/list/list.go | 15 +- .../cmd/mariadb/instance/list/list_test.go | 3 +- .../cmd/mariadb/instance/update/update.go | 15 +- .../mariadb/instance/update/update_test.go | 3 +- internal/cmd/mariadb/mariadb.go | 14 +- internal/cmd/mariadb/plans/plans.go | 15 +- internal/cmd/mariadb/plans/plans_test.go | 3 +- internal/cmd/mongodbflex/backup/backup.go | 20 +- .../mongodbflex/backup/describe/describe.go | 11 +- .../backup/describe/describe_test.go | 5 +- internal/cmd/mongodbflex/backup/list/list.go | 11 +- .../cmd/mongodbflex/backup/list/list_test.go | 5 +- .../backup/restore-jobs/restore_jobs.go | 11 +- .../backup/restore-jobs/restore_jobs_test.go | 5 +- .../cmd/mongodbflex/backup/restore/restore.go | 19 +- .../backup/restore/restore_test.go | 3 +- .../mongodbflex/backup/schedule/schedule.go | 9 +- .../backup/schedule/schedule_test.go | 3 +- .../backup/update-schedule/update_schedule.go | 11 +- .../cmd/mongodbflex/instance/create/create.go | 17 +- .../instance/create/create_test.go | 5 +- .../cmd/mongodbflex/instance/delete/delete.go | 15 +- .../instance/delete/delete_test.go | 3 +- .../mongodbflex/instance/describe/describe.go | 9 +- .../instance/describe/describe_test.go | 5 +- internal/cmd/mongodbflex/instance/instance.go | 18 +- .../cmd/mongodbflex/instance/list/list.go | 15 +- .../mongodbflex/instance/list/list_test.go | 3 +- .../cmd/mongodbflex/instance/update/update.go | 15 +- .../instance/update/update_test.go | 5 +- internal/cmd/mongodbflex/mongodbflex.go | 16 +- internal/cmd/mongodbflex/options/options.go | 10 +- .../cmd/mongodbflex/options/options_test.go | 9 +- .../cmd/mongodbflex/user/create/create.go | 13 +- .../mongodbflex/user/create/create_test.go | 3 +- .../cmd/mongodbflex/user/delete/delete.go | 15 +- .../mongodbflex/user/delete/delete_test.go | 3 +- .../cmd/mongodbflex/user/describe/describe.go | 9 +- .../user/describe/describe_test.go | 5 +- internal/cmd/mongodbflex/user/list/list.go | 13 +- .../cmd/mongodbflex/user/list/list_test.go | 3 +- .../user/reset-password/reset_password.go | 15 +- .../reset-password/reset_password_test.go | 5 +- .../cmd/mongodbflex/user/update/update.go | 15 +- .../mongodbflex/user/update/update_test.go | 3 +- internal/cmd/mongodbflex/user/user.go | 20 +- internal/cmd/network-area/create/create.go | 17 +- .../cmd/network-area/create/create_test.go | 5 +- internal/cmd/network-area/delete/delete.go | 15 +- .../cmd/network-area/delete/delete_test.go | 3 +- .../cmd/network-area/describe/describe.go | 9 +- .../network-area/describe/describe_test.go | 5 +- internal/cmd/network-area/list/list.go | 17 +- internal/cmd/network-area/list/list_test.go | 5 +- .../network-range/create/create.go | 13 +- .../network-range/create/create_test.go | 5 +- .../network-range/delete/delete.go | 15 +- .../network-range/delete/delete_test.go | 3 +- .../network-range/describe/describe.go | 9 +- .../network-range/describe/describe_test.go | 5 +- .../network-area/network-range/list/list.go | 13 +- .../network-range/list/list_test.go | 5 +- .../network-range/network_range.go | 16 +- internal/cmd/network-area/network_area.go | 22 +-- .../cmd/network-area/route/create/create.go | 13 +- .../network-area/route/create/create_test.go | 5 +- .../cmd/network-area/route/delete/delete.go | 13 +- .../network-area/route/delete/delete_test.go | 3 +- .../network-area/route/describe/describe.go | 9 +- .../route/describe/describe_test.go | 5 +- internal/cmd/network-area/route/list/list.go | 13 +- .../cmd/network-area/route/list/list_test.go | 5 +- internal/cmd/network-area/route/routes.go | 18 +- .../cmd/network-area/route/update/update.go | 11 +- .../network-area/route/update/update_test.go | 5 +- internal/cmd/network-area/update/update.go | 17 +- .../cmd/network-area/update/update_test.go | 5 +- .../cmd/network-interface/create/create.go | 15 +- .../network-interface/create/create_test.go | 5 +- .../cmd/network-interface/delete/delete.go | 11 +- .../network-interface/delete/delete_test.go | 3 +- .../network-interface/describe/describe.go | 9 +- .../describe/describe_test.go | 5 +- internal/cmd/network-interface/list/list.go | 13 +- .../cmd/network-interface/list/list_test.go | 5 +- .../network-interface/network-interface.go | 18 +- .../cmd/network-interface/update/update.go | 11 +- .../network-interface/update/update_test.go | 5 +- internal/cmd/network/create/create.go | 17 +- internal/cmd/network/create/create_test.go | 5 +- internal/cmd/network/delete/delete.go | 15 +- internal/cmd/network/delete/delete_test.go | 3 +- internal/cmd/network/describe/describe.go | 9 +- .../cmd/network/describe/describe_test.go | 5 +- internal/cmd/network/list/list.go | 15 +- internal/cmd/network/list/list_test.go | 5 +- internal/cmd/network/network.go | 18 +- internal/cmd/network/update/update.go | 15 +- internal/cmd/network/update/update_test.go | 3 +- internal/cmd/object-storage/bucket/bucket.go | 16 +- .../object-storage/bucket/create/create.go | 13 +- .../bucket/create/create_test.go | 5 +- .../object-storage/bucket/delete/delete.go | 13 +- .../bucket/delete/delete_test.go | 3 +- .../bucket/describe/describe.go | 9 +- .../bucket/describe/describe_test.go | 5 +- .../cmd/object-storage/bucket/list/list.go | 15 +- .../object-storage/bucket/list/list_test.go | 3 +- .../credentials-group/create/create.go | 11 +- .../credentials-group/create/create_test.go | 5 +- .../credentials-group/credentials_group.go | 14 +- .../credentials-group/delete/delete.go | 13 +- .../credentials-group/delete/delete_test.go | 3 +- .../credentials-group/list/list.go | 11 +- .../credentials-group/list/list_test.go | 5 +- .../credentials/create/create.go | 13 +- .../credentials/create/create_test.go | 5 +- .../object-storage/credentials/credentials.go | 14 +- .../credentials/delete/delete.go | 15 +- .../credentials/delete/delete_test.go | 3 +- .../object-storage/credentials/list/list.go | 13 +- .../credentials/list/list_test.go | 5 +- .../cmd/object-storage/disable/disable.go | 15 +- internal/cmd/object-storage/enable/enable.go | 15 +- internal/cmd/object-storage/object_storage.go | 18 +- .../credentials/create/create.go | 13 +- .../credentials/create/create_test.go | 3 +- .../observability/credentials/credentials.go | 14 +- .../credentials/delete/delete.go | 13 +- .../observability/credentials/list/list.go | 13 +- .../credentials/list/list_test.go | 3 +- .../grafana/describe/describe.go | 9 +- .../grafana/describe/describe_test.go | 5 +- internal/cmd/observability/grafana/grafana.go | 14 +- .../public-read-access/disable/disable.go | 11 +- .../disable/disable_test.go | 3 +- .../public-read-access/enable/enable.go | 11 +- .../public-read-access/enable/enable_test.go | 3 +- .../public-read-access/public_read_access.go | 12 +- .../grafana/single-sign-on/disable/disable.go | 11 +- .../single-sign-on/disable/disable_test.go | 3 +- .../grafana/single-sign-on/enable/enable.go | 11 +- .../single-sign-on/enable/enable_test.go | 3 +- .../grafana/single-sign-on/single_sign_on.go | 12 +- .../observability/instance/create/create.go | 17 +- .../instance/create/create_test.go | 5 +- .../observability/instance/delete/delete.go | 15 +- .../instance/delete/delete_test.go | 3 +- .../instance/describe/describe.go | 9 +- .../instance/describe/describe_test.go | 5 +- .../cmd/observability/instance/instance.go | 18 +- .../cmd/observability/instance/list/list.go | 15 +- .../observability/instance/list/list_test.go | 3 +- .../observability/instance/update/update.go | 15 +- .../instance/update/update_test.go | 3 +- internal/cmd/observability/observability.go | 18 +- internal/cmd/observability/plans/plans.go | 15 +- .../cmd/observability/plans/plans_test.go | 3 +- .../scrape-config/create/create.go | 15 +- .../scrape-config/delete/delete.go | 15 +- .../scrape-config/describe/describe.go | 9 +- .../scrape-config/describe/describe_test.go | 3 +- .../generate-payload/generate_payload.go | 11 +- .../generate-payload/generate_payload_test.go | 5 +- .../observability/scrape-config/list/list.go | 13 +- .../scrape-config/list/list_test.go | 3 +- .../scrape-config/scrape_config.go | 20 +- .../scrape-config/update/update.go | 11 +- .../opensearch/credentials/create/create.go | 13 +- .../credentials/create/create_test.go | 5 +- .../cmd/opensearch/credentials/credentials.go | 16 +- .../opensearch/credentials/delete/delete.go | 15 +- .../credentials/delete/delete_test.go | 3 +- .../credentials/describe/describe.go | 9 +- .../credentials/describe/describe_test.go | 5 +- .../cmd/opensearch/credentials/list/list.go | 13 +- .../opensearch/credentials/list/list_test.go | 5 +- .../cmd/opensearch/instance/create/create.go | 17 +- .../opensearch/instance/create/create_test.go | 5 +- .../cmd/opensearch/instance/delete/delete.go | 15 +- .../opensearch/instance/delete/delete_test.go | 3 +- .../opensearch/instance/describe/describe.go | 9 +- .../instance/describe/describe_test.go | 5 +- internal/cmd/opensearch/instance/instance.go | 18 +- internal/cmd/opensearch/instance/list/list.go | 15 +- .../cmd/opensearch/instance/list/list_test.go | 3 +- .../cmd/opensearch/instance/update/update.go | 15 +- .../opensearch/instance/update/update_test.go | 3 +- internal/cmd/opensearch/opensearch.go | 14 +- internal/cmd/opensearch/plans/plans.go | 15 +- internal/cmd/opensearch/plans/plans_test.go | 3 +- internal/cmd/organization/member/add/add.go | 11 +- .../cmd/organization/member/add/add_test.go | 3 +- internal/cmd/organization/member/list/list.go | 11 +- .../cmd/organization/member/list/list_test.go | 3 +- internal/cmd/organization/member/member.go | 14 +- .../cmd/organization/member/remove/remove.go | 11 +- .../organization/member/remove/remove_test.go | 3 +- internal/cmd/organization/organization.go | 12 +- internal/cmd/organization/role/list/list.go | 11 +- .../cmd/organization/role/list/list_test.go | 3 +- internal/cmd/organization/role/role.go | 10 +- internal/cmd/params/cmd_params.go | 10 + internal/cmd/postgresflex/backup/backup.go | 14 +- .../postgresflex/backup/describe/describe.go | 9 +- .../backup/describe/describe_test.go | 3 +- internal/cmd/postgresflex/backup/list/list.go | 11 +- .../cmd/postgresflex/backup/list/list_test.go | 3 +- .../backup/update-schedule/update_schedule.go | 11 +- .../cmd/postgresflex/instance/clone/clone.go | 15 +- .../postgresflex/instance/clone/clone_test.go | 5 +- .../postgresflex/instance/create/create.go | 17 +- .../instance/create/create_test.go | 5 +- .../postgresflex/instance/delete/delete.go | 17 +- .../instance/delete/delete_test.go | 3 +- .../instance/describe/describe.go | 9 +- .../instance/describe/describe_test.go | 5 +- .../cmd/postgresflex/instance/instance.go | 20 +- .../cmd/postgresflex/instance/list/list.go | 15 +- .../postgresflex/instance/list/list_test.go | 3 +- .../postgresflex/instance/update/update.go | 15 +- .../instance/update/update_test.go | 5 +- internal/cmd/postgresflex/options/options.go | 10 +- .../cmd/postgresflex/options/options_test.go | 7 +- internal/cmd/postgresflex/postgresflex.go | 16 +- .../cmd/postgresflex/user/create/create.go | 13 +- .../postgresflex/user/create/create_test.go | 3 +- .../cmd/postgresflex/user/delete/delete.go | 15 +- .../postgresflex/user/delete/delete_test.go | 3 +- .../postgresflex/user/describe/describe.go | 9 +- .../user/describe/describe_test.go | 5 +- internal/cmd/postgresflex/user/list/list.go | 13 +- .../cmd/postgresflex/user/list/list_test.go | 3 +- .../user/reset-password/reset_password.go | 15 +- .../reset-password/reset_password_test.go | 5 +- .../cmd/postgresflex/user/update/update.go | 15 +- .../postgresflex/user/update/update_test.go | 3 +- internal/cmd/postgresflex/user/user.go | 20 +- internal/cmd/project/create/create.go | 11 +- internal/cmd/project/create/create_test.go | 5 +- internal/cmd/project/delete/delete.go | 17 +- internal/cmd/project/describe/describe.go | 9 +- .../cmd/project/describe/describe_test.go | 5 +- internal/cmd/project/list/list.go | 11 +- internal/cmd/project/list/list_test.go | 5 +- internal/cmd/project/member/add/add.go | 15 +- internal/cmd/project/member/add/add_test.go | 3 +- internal/cmd/project/member/list/list.go | 15 +- internal/cmd/project/member/list/list_test.go | 3 +- internal/cmd/project/member/member.go | 14 +- internal/cmd/project/member/remove/remove.go | 15 +- .../cmd/project/member/remove/remove_test.go | 3 +- internal/cmd/project/project.go | 22 +-- internal/cmd/project/role/list/list.go | 15 +- internal/cmd/project/role/list/list_test.go | 3 +- internal/cmd/project/role/role.go | 10 +- internal/cmd/project/update/update.go | 15 +- internal/cmd/project/update/update_test.go | 3 +- internal/cmd/public-ip/associate/associate.go | 13 +- .../cmd/public-ip/associate/associate_test.go | 3 +- internal/cmd/public-ip/create/create.go | 15 +- internal/cmd/public-ip/create/create_test.go | 5 +- internal/cmd/public-ip/delete/delete.go | 13 +- internal/cmd/public-ip/delete/delete_test.go | 3 +- internal/cmd/public-ip/describe/describe.go | 9 +- .../cmd/public-ip/describe/describe_test.go | 5 +- .../public-ip/disassociate/disassociate.go | 13 +- .../disassociate/disassociate_test.go | 3 +- internal/cmd/public-ip/list/list.go | 15 +- internal/cmd/public-ip/list/list_test.go | 5 +- internal/cmd/public-ip/public-ip.go | 22 +-- internal/cmd/public-ip/update/update.go | 13 +- internal/cmd/public-ip/update/update_test.go | 3 +- internal/cmd/quota/list/list.go | 15 +- internal/cmd/quota/list/list_test.go | 5 +- internal/cmd/quota/quota.go | 10 +- .../cmd/rabbitmq/credentials/create/create.go | 13 +- .../credentials/create/create_test.go | 5 +- .../cmd/rabbitmq/credentials/credentials.go | 16 +- .../cmd/rabbitmq/credentials/delete/delete.go | 15 +- .../credentials/delete/delete_test.go | 3 +- .../rabbitmq/credentials/describe/describe.go | 9 +- .../credentials/describe/describe_test.go | 5 +- .../cmd/rabbitmq/credentials/list/list.go | 13 +- .../rabbitmq/credentials/list/list_test.go | 5 +- .../cmd/rabbitmq/instance/create/create.go | 17 +- .../rabbitmq/instance/create/create_test.go | 5 +- .../cmd/rabbitmq/instance/delete/delete.go | 15 +- .../rabbitmq/instance/delete/delete_test.go | 3 +- .../rabbitmq/instance/describe/describe.go | 9 +- .../instance/describe/describe_test.go | 5 +- internal/cmd/rabbitmq/instance/instance.go | 18 +- internal/cmd/rabbitmq/instance/list/list.go | 15 +- .../cmd/rabbitmq/instance/list/list_test.go | 3 +- .../cmd/rabbitmq/instance/update/update.go | 15 +- .../rabbitmq/instance/update/update_test.go | 3 +- internal/cmd/rabbitmq/plans/plans.go | 15 +- internal/cmd/rabbitmq/plans/plans_test.go | 3 +- internal/cmd/rabbitmq/rabbitmq.go | 14 +- .../cmd/redis/credentials/create/create.go | 13 +- .../redis/credentials/create/create_test.go | 5 +- internal/cmd/redis/credentials/credentials.go | 16 +- .../cmd/redis/credentials/delete/delete.go | 15 +- .../redis/credentials/delete/delete_test.go | 3 +- .../redis/credentials/describe/describe.go | 9 +- .../credentials/describe/describe_test.go | 5 +- internal/cmd/redis/credentials/list/list.go | 13 +- .../cmd/redis/credentials/list/list_test.go | 5 +- internal/cmd/redis/instance/create/create.go | 17 +- .../cmd/redis/instance/create/create_test.go | 5 +- internal/cmd/redis/instance/delete/delete.go | 15 +- .../cmd/redis/instance/delete/delete_test.go | 3 +- .../cmd/redis/instance/describe/describe.go | 9 +- .../redis/instance/describe/describe_test.go | 5 +- internal/cmd/redis/instance/instance.go | 18 +- internal/cmd/redis/instance/list/list.go | 15 +- internal/cmd/redis/instance/list/list_test.go | 3 +- internal/cmd/redis/instance/update/update.go | 15 +- .../cmd/redis/instance/update/update_test.go | 3 +- internal/cmd/redis/plans/plans.go | 15 +- internal/cmd/redis/plans/plans_test.go | 3 +- internal/cmd/redis/redis.go | 14 +- internal/cmd/root.go | 71 +++---- .../secrets-manager/instance/create/create.go | 15 +- .../instance/create/create_test.go | 5 +- .../secrets-manager/instance/delete/delete.go | 13 +- .../instance/delete/delete_test.go | 3 +- .../instance/describe/describe.go | 9 +- .../instance/describe/describe_test.go | 5 +- .../cmd/secrets-manager/instance/instance.go | 18 +- .../cmd/secrets-manager/instance/list/list.go | 15 +- .../instance/list/list_test.go | 3 +- .../secrets-manager/instance/update/update.go | 13 +- .../instance/update/update_test.go | 3 +- .../cmd/secrets-manager/secrets_manager.go | 12 +- .../cmd/secrets-manager/user/create/create.go | 13 +- .../user/create/create_test.go | 3 +- .../cmd/secrets-manager/user/delete/delete.go | 15 +- .../user/delete/delete_test.go | 3 +- .../secrets-manager/user/describe/describe.go | 9 +- .../user/describe/describe_test.go | 5 +- .../cmd/secrets-manager/user/list/list.go | 13 +- .../secrets-manager/user/list/list_test.go | 3 +- .../cmd/secrets-manager/user/update/update.go | 15 +- .../user/update/update_test.go | 3 +- internal/cmd/secrets-manager/user/user.go | 18 +- internal/cmd/security-group/create/create.go | 11 +- .../cmd/security-group/create/create_test.go | 5 +- internal/cmd/security-group/delete/delete.go | 17 +- .../cmd/security-group/delete/delete_test.go | 3 +- .../cmd/security-group/describe/describe.go | 9 +- .../security-group/describe/describe_test.go | 5 +- internal/cmd/security-group/list/list.go | 15 +- internal/cmd/security-group/list/list_test.go | 5 +- .../cmd/security-group/rule/create/create.go | 17 +- .../security-group/rule/create/create_test.go | 5 +- .../cmd/security-group/rule/delete/delete.go | 15 +- .../security-group/rule/delete/delete_test.go | 3 +- .../security-group/rule/describe/describe.go | 9 +- .../rule/describe/describe_test.go | 5 +- internal/cmd/security-group/rule/list/list.go | 17 +- .../cmd/security-group/rule/list/list_test.go | 5 +- .../rule/security_group_rule.go | 16 +- internal/cmd/security-group/security_group.go | 20 +- internal/cmd/security-group/update/update.go | 17 +- .../cmd/security-group/update/update_test.go | 3 +- internal/cmd/server/backup/backup.go | 26 +-- internal/cmd/server/backup/create/create.go | 15 +- .../cmd/server/backup/create/create_test.go | 5 +- internal/cmd/server/backup/delete/delete.go | 11 +- .../cmd/server/backup/delete/delete_test.go | 3 +- .../cmd/server/backup/describe/describe.go | 9 +- .../server/backup/describe/describe_test.go | 5 +- internal/cmd/server/backup/disable/disable.go | 17 +- internal/cmd/server/backup/enable/enable.go | 15 +- internal/cmd/server/backup/list/list.go | 15 +- internal/cmd/server/backup/list/list_test.go | 5 +- internal/cmd/server/backup/restore/restore.go | 11 +- .../cmd/server/backup/restore/restore_test.go | 3 +- .../server/backup/schedule/create/create.go | 15 +- .../backup/schedule/create/create_test.go | 5 +- .../server/backup/schedule/delete/delete.go | 15 +- .../backup/schedule/delete/delete_test.go | 3 +- .../backup/schedule/describe/describe.go | 9 +- .../backup/schedule/describe/describe_test.go | 5 +- .../cmd/server/backup/schedule/list/list.go | 15 +- .../server/backup/schedule/list/list_test.go | 5 +- .../cmd/server/backup/schedule/schedule.go | 18 +- .../server/backup/schedule/update/update.go | 13 +- .../backup/schedule/update/update_test.go | 5 +- .../backup/volume-backup/delete/delete.go | 11 +- .../volume-backup/delete/delete_test.go | 3 +- .../backup/volume-backup/restore/restore.go | 11 +- .../volume-backup/restore/restore_test.go | 3 +- .../backup/volume-backup/volumebackup.go | 12 +- internal/cmd/server/command/command.go | 16 +- internal/cmd/server/command/create/create.go | 15 +- .../cmd/server/command/create/create_test.go | 5 +- .../cmd/server/command/describe/describe.go | 9 +- .../server/command/describe/describe_test.go | 5 +- internal/cmd/server/command/list/list.go | 15 +- internal/cmd/server/command/list/list_test.go | 5 +- .../command/template/describe/describe.go | 9 +- .../template/describe/describe_test.go | 5 +- .../cmd/server/command/template/list/list.go | 11 +- .../server/command/template/list/list_test.go | 5 +- .../cmd/server/command/template/template.go | 12 +- internal/cmd/server/console/console.go | 11 +- internal/cmd/server/console/console_test.go | 5 +- internal/cmd/server/create/create.go | 17 +- internal/cmd/server/create/create_test.go | 5 +- internal/cmd/server/deallocate/deallocate.go | 15 +- .../cmd/server/deallocate/deallocate_test.go | 3 +- internal/cmd/server/delete/delete.go | 15 +- internal/cmd/server/delete/delete_test.go | 3 +- internal/cmd/server/describe/describe.go | 9 +- internal/cmd/server/describe/describe_test.go | 5 +- internal/cmd/server/list/list.go | 15 +- internal/cmd/server/list/list_test.go | 5 +- internal/cmd/server/log/log.go | 13 +- internal/cmd/server/log/log_test.go | 5 +- .../server/machine-type/describe/describe.go | 9 +- .../machine-type/describe/describe_test.go | 5 +- internal/cmd/server/machine-type/list/list.go | 15 +- .../cmd/server/machine-type/list/list_test.go | 5 +- .../cmd/server/machine-type/machine-type.go | 12 +- .../server/network-interface/attach/attach.go | 19 +- .../network-interface/attach/attach_test.go | 3 +- .../server/network-interface/detach/detach.go | 19 +- .../network-interface/detach/detach_test.go | 3 +- .../cmd/server/network-interface/list/list.go | 13 +- .../network-interface/list/list_test.go | 5 +- .../network-interface/network-interface.go | 14 +- .../cmd/server/os-update/create/create.go | 15 +- .../server/os-update/create/create_test.go | 5 +- .../cmd/server/os-update/describe/describe.go | 9 +- .../os-update/describe/describe_test.go | 5 +- .../cmd/server/os-update/disable/disable.go | 15 +- .../cmd/server/os-update/enable/enable.go | 15 +- internal/cmd/server/os-update/list/list.go | 15 +- .../cmd/server/os-update/list/list_test.go | 5 +- internal/cmd/server/os-update/os-update.go | 20 +- .../os-update/schedule/create/create.go | 15 +- .../os-update/schedule/create/create_test.go | 5 +- .../os-update/schedule/delete/delete.go | 11 +- .../os-update/schedule/delete/delete_test.go | 3 +- .../os-update/schedule/describe/describe.go | 9 +- .../schedule/describe/describe_test.go | 5 +- .../server/os-update/schedule/list/list.go | 15 +- .../os-update/schedule/list/list_test.go | 5 +- .../cmd/server/os-update/schedule/schedule.go | 18 +- .../os-update/schedule/update/update.go | 13 +- .../os-update/schedule/update/update_test.go | 5 +- .../cmd/server/public-ip/attach/attach.go | 15 +- .../server/public-ip/attach/attach_test.go | 3 +- .../cmd/server/public-ip/detach/detach.go | 15 +- .../server/public-ip/detach/detach_test.go | 3 +- internal/cmd/server/public-ip/public_ip.go | 12 +- internal/cmd/server/reboot/reboot.go | 13 +- internal/cmd/server/reboot/reboot_test.go | 3 +- internal/cmd/server/rescue/rescue.go | 15 +- internal/cmd/server/rescue/rescue_test.go | 3 +- internal/cmd/server/resize/resize.go | 15 +- internal/cmd/server/resize/resize_test.go | 3 +- internal/cmd/server/server.go | 52 ++--- .../server/service-account/attach/attach.go | 13 +- .../service-account/attach/attach_test.go | 5 +- .../server/service-account/detach/detach.go | 13 +- .../service-account/detach/detach_test.go | 5 +- .../cmd/server/service-account/list/list.go | 13 +- .../server/service-account/list/list_test.go | 5 +- .../server/service-account/service-account.go | 14 +- internal/cmd/server/start/start.go | 13 +- internal/cmd/server/start/start_test.go | 3 +- internal/cmd/server/stop/stop.go | 15 +- internal/cmd/server/stop/stop_test.go | 3 +- internal/cmd/server/unrescue/unrescue.go | 15 +- internal/cmd/server/unrescue/unrescue_test.go | 3 +- internal/cmd/server/update/update.go | 13 +- internal/cmd/server/update/update_test.go | 5 +- internal/cmd/server/volume/attach/attach.go | 15 +- .../cmd/server/volume/attach/attach_test.go | 5 +- .../cmd/server/volume/describe/describe.go | 13 +- .../server/volume/describe/describe_test.go | 5 +- internal/cmd/server/volume/detach/detach.go | 15 +- .../cmd/server/volume/detach/detach_test.go | 3 +- internal/cmd/server/volume/list/list.go | 15 +- internal/cmd/server/volume/list/list_test.go | 5 +- internal/cmd/server/volume/update/update.go | 15 +- .../cmd/server/volume/update/update_test.go | 5 +- internal/cmd/server/volume/volume.go | 18 +- internal/cmd/service-account/create/create.go | 15 +- .../cmd/service-account/create/create_test.go | 5 +- internal/cmd/service-account/delete/delete.go | 11 +- .../cmd/service-account/delete/delete_test.go | 3 +- .../cmd/service-account/get-jwks/get_jwks.go | 11 +- .../service-account/get-jwks/get_jwks_test.go | 5 +- .../cmd/service-account/key/create/create.go | 13 +- .../service-account/key/create/create_test.go | 3 +- .../cmd/service-account/key/delete/delete.go | 11 +- .../service-account/key/delete/delete_test.go | 3 +- .../service-account/key/describe/describe.go | 9 +- .../key/describe/describe_test.go | 5 +- internal/cmd/service-account/key/key.go | 18 +- internal/cmd/service-account/key/list/list.go | 11 +- .../cmd/service-account/key/list/list_test.go | 3 +- .../cmd/service-account/key/update/update.go | 11 +- .../service-account/key/update/update_test.go | 3 +- internal/cmd/service-account/list/list.go | 15 +- .../cmd/service-account/list/list_test.go | 3 +- .../cmd/service-account/service_account.go | 20 +- .../service-account/token/create/create.go | 11 +- .../token/create/create_test.go | 5 +- .../cmd/service-account/token/list/list.go | 11 +- .../service-account/token/list/list_test.go | 3 +- .../service-account/token/revoke/revoke.go | 11 +- .../token/revoke/revoke_test.go | 3 +- internal/cmd/service-account/token/token.go | 14 +- internal/cmd/ske/cluster/cluster.go | 20 +- internal/cmd/ske/cluster/create/create.go | 19 +- .../cmd/ske/cluster/create/create_test.go | 5 +- internal/cmd/ske/cluster/delete/delete.go | 13 +- .../cmd/ske/cluster/delete/delete_test.go | 3 +- internal/cmd/ske/cluster/describe/describe.go | 9 +- .../cmd/ske/cluster/describe/describe_test.go | 5 +- .../generate-payload/generate_payload.go | 9 +- .../generate-payload/generate_payload_test.go | 5 +- internal/cmd/ske/cluster/list/list.go | 17 +- internal/cmd/ske/cluster/list/list_test.go | 3 +- internal/cmd/ske/cluster/update/update.go | 13 +- .../cmd/ske/cluster/update/update_test.go | 5 +- .../complete-rotation/complete_rotation.go | 15 +- .../complete_rotation_test.go | 3 +- internal/cmd/ske/credentials/credentials.go | 12 +- .../start-rotation/start_rotation.go | 15 +- .../start-rotation/start_rotation_test.go | 3 +- internal/cmd/ske/describe/describe.go | 9 +- internal/cmd/ske/describe/describe_test.go | 3 +- internal/cmd/ske/disable/disable.go | 17 +- internal/cmd/ske/enable/enable.go | 17 +- internal/cmd/ske/kubeconfig/create/create.go | 13 +- .../cmd/ske/kubeconfig/create/create_test.go | 5 +- internal/cmd/ske/kubeconfig/kubeconfig.go | 12 +- internal/cmd/ske/kubeconfig/login/login.go | 17 +- internal/cmd/ske/options/options.go | 9 +- internal/cmd/ske/options/options_test.go | 7 +- internal/cmd/ske/ske.go | 22 +-- internal/cmd/volume/create/create.go | 17 +- internal/cmd/volume/create/create_test.go | 5 +- internal/cmd/volume/delete/delete.go | 15 +- internal/cmd/volume/delete/delete_test.go | 3 +- internal/cmd/volume/describe/describe.go | 9 +- internal/cmd/volume/describe/describe_test.go | 5 +- internal/cmd/volume/list/list.go | 15 +- internal/cmd/volume/list/list_test.go | 5 +- .../performance-class/describe/describe.go | 9 +- .../describe/describe_test.go | 5 +- .../cmd/volume/performance-class/list/list.go | 15 +- .../performance-class/list/list_test.go | 5 +- .../performance-class/performance_class.go | 12 +- internal/cmd/volume/resize/resize.go | 13 +- internal/cmd/volume/resize/resize_test.go | 3 +- internal/cmd/volume/update/update.go | 13 +- internal/cmd/volume/update/update_test.go | 5 +- internal/cmd/volume/volume.go | 22 +-- 793 files changed, 4407 insertions(+), 3681 deletions(-) create mode 100644 .github/docs/contribution-guide/client.go create mode 100644 .github/docs/contribution-guide/cmd.go create mode 100644 internal/cmd/params/cmd_params.go diff --git a/.github/docs/contribution-guide/client.go b/.github/docs/contribution-guide/client.go new file mode 100644 index 000000000..4b84a6538 --- /dev/null +++ b/.github/docs/contribution-guide/client.go @@ -0,0 +1,35 @@ +package client + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-sdk-go/services/foo" + // (...) +) + +func ConfigureClient(cmd *cobra.Command) (*foo.APIClient, error) { + var err error + var apiClient foo.APIClient + var cfgOptions []sdkConfig.ConfigurationOption + + authCfgOption, err := auth.AuthenticationConfig(cmd, auth.AuthorizeUser) + if err != nil { + return nil, &errors.AuthError{} + } + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) // Configuring region is needed if "foo" is a regional API + + customEndpoint := viper.GetString(config.fooCustomEndpointKey) + + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } + + apiClient, err = foo.NewAPIClient(cfgOptions...) + if err != nil { + return nil, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/.github/docs/contribution-guide/cmd.go b/.github/docs/contribution-guide/cmd.go new file mode 100644 index 000000000..5fb05d2f4 --- /dev/null +++ b/.github/docs/contribution-guide/cmd.go @@ -0,0 +1,156 @@ +package bar + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "gopkg.in/yaml.v2" + // (...) +) + +// Define consts for command flags +const ( + someArg = "MY_ARG" + someFlag = "my-flag" +) + +// Struct to model user input (arguments and/or flags) +type inputModel struct { + *globalflags.GlobalFlagModel + MyArg string + MyFlag *string +} + +// "bar" command constructor +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "bar", + Short: "Short description of the command (is shown in the help of parent command)", + Long: "Long description of the command. Can contain some more information about the command usage. It is shown in the help of the current command.", + Args: args.SingleArg(someArg, utils.ValidateUUID), // Validate argument, with an optional validation function + Example: examples.Build( + examples.NewExample( + `Do something with command "bar"`, + "$ stackit foo bar arg-value --my-flag flag-value"), + //... + ), + 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, cmd) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("(...): %w", err) + } + + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + if err != nil { + projectLabel = model.ProjectId + } + + // Check API response "resp" and output accordingly + if resp.Item == nil { + params.Printer.Info("(...)", projectLabel) + return nil + } + return outputResult(params.Printer, cmd, model.OutputFormat, instances) + }, + } + + configureFlags(cmd) + return cmd +} + +// Configure command flags (type, default value, and description) +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(myFlag, "defaultValue", "My flag description") +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + myArg := inputArgs[0] + + globalFlags := globalflags.Parse(cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + MyArg: myArg, + MyFlag: flags.FlagToStringPointer(cmd, myFlag), + } + + // Write the input model to the debug logs + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +// Build request to the API +func buildRequest(ctx context.Context, model *inputModel, apiClient *foo.APIClient) foo.ApiListInstancesRequest { + req := apiClient.GetBar(ctx, model.ProjectId, model.MyArg, someParam) + return req +} + +// Output result based on the configured output format +func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, resources []foo.Resource) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resources, "", " ") + if err != nil { + return fmt.Errorf("marshal resource list: %w", err) + } + p.Outputln(string(details)) + return nil + case print.YAMLOutputFormat: + details, err := yaml.Marshal(resources) + if err != nil { + return fmt.Errorf("marshal resource list: %w", err) + } + p.Outputln(string(details)) + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "STATE") + for i := range resources { + resource := resources[i] + table.AddRow(*resource.ResourceId, *resource.Name, *resource.State) + } + err := table.Display(cmd) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + } +} diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index a73808087..d182c6534 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -53,148 +53,7 @@ Please remember to run `make generate-docs` after your changes to keep the comma Below is a typical structure of a CLI command: -```go -package bar - -import ( - (...) -) - -// Define consts for command flags -const ( - someArg = "MY_ARG" - someFlag = "my-flag" -) - -// Struct to model user input (arguments and/or flags) -type inputModel struct { - *globalflags.GlobalFlagModel - MyArg string - MyFlag *string -} - -// "bar" command constructor -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)", - Long: "Long description of the command. Can contain some more information about the command usage. It is shown in the help of the current command.", - Args: args.SingleArg(someArg, utils.ValidateUUID), // Validate argument, with an optional validation function - Example: examples.Build( - examples.NewExample( - `Do something with command "bar"`, - "$ stackit foo bar arg-value --my-flag flag-value"), - ... - ), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() - model, err := parseInput(p, cmd, args) - if err != nil { - return err - } - - // Configure API client - apiClient, err := client.ConfigureClient(p, cmd) - if err != nil { - return err - } - - // Call API - req := buildRequest(ctx, model, apiClient) - resp, err := req.Execute() - if err != nil { - return fmt.Errorf("(...): %w", err) - } - - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) - if err != nil { - projectLabel = model.ProjectId - } - - // Check API response "resp" and output accordingly - if resp.Item == nil { - p.Info("(...)", projectLabel) - return nil - } - return outputResult(p, cmd, model.OutputFormat, instances) - }, - } - - configureFlags(cmd) - return cmd -} - -// Configure command flags (type, default value, and description) -func configureFlags(cmd *cobra.Command) { - cmd.Flags().StringP(myFlag, "defaultValue", "My flag description") -} - -// Parse user input (arguments and/or flags) -func parseInput(cmd *cobra.Command, inputArgs []string) (*inputModel, error) { - myArg := inputArgs[0] - - globalFlags := globalflags.Parse(cmd) - if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} - } - - model := inputModel{ - GlobalFlagModel: globalFlags, - MyArg myArg, - MyFlag: flags.FlagToStringPointer(cmd, myFlag), - }, nil - - // Write the input model to the debug logs - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - - return &model, nil -} - -// Build request to the API -func buildRequest(ctx context.Context, model *inputModel, apiClient *foo.APIClient) foo.ApiListInstancesRequest { - req := apiClient.GetBar(ctx, model.ProjectId, model.MyArg, someParam) - return req -} - -// Output result based on the configured output format -func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, resources []foo.Resource) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resources, "", " ") - if err != nil { - return fmt.Errorf("marshal resource list: %w", err) - } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.Marshal(resources) - if err != nil { - return fmt.Errorf("marshal resource list: %w", err) - } - p.Outputln(string(details)) - return nil - default: - table := tables.NewTable() - table.SetHeader("ID", "NAME", "STATE") - for i := range resources { - resource := resources[i] - table.AddRow(*resource.ResourceId, *resource.Name, *resource.State) - } - err := table.Display(cmd) - if err != nil { - return fmt.Errorf("render table: %w", err) - } - return nil - } -} -``` +https://github.com/stackitcloud/stackit-cli/blob/6f762bd56407ed232080efabc4d2bf87f260b71d/.github/docs/contribution-guide/cmd.go#L23-L156 Please remember to always add unit tests for `parseInput`, `buildRequest` (in `bar_test.go`), and any other util functions used. @@ -224,39 +83,7 @@ If you want to add a command that uses a STACKIT service `foo` that was not yet 1. This is done in `internal/pkg/services/foo/client/client.go` 2. Below is an example of a typical `client.go` file structure: - ```go - package client - - import ( - (...) - "github.com/stackitcloud/stackit-sdk-go/services/foo" - ) - - func ConfigureClient(cmd *cobra.Command) (*foo.APIClient, error) { - var err error - var apiClient foo.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - - authCfgOption, err := auth.AuthenticationConfig(cmd, auth.AuthorizeUser) - if err != nil { - return nil, &errors.AuthError{} - } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) // Configuring region is needed if "foo" is a regional API - - customEndpoint := viper.GetString(config.fooCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - apiClient, err = foo.NewAPIClient(cfgOptions...) - if err != nil { - return nil, &errors.AuthError{} - } - - return apiClient, nil - } - ``` +https://github.com/stackitcloud/stackit-cli/blob/6f762bd56407ed232080efabc4d2bf87f260b71d/.github/docs/contribution-guide/client.go#L12-L35 ### Local development diff --git a/internal/cmd/affinity-groups/affinity-groups.go b/internal/cmd/affinity-groups/affinity-groups.go index 57f44f65e..a750b2047 100644 --- a/internal/cmd/affinity-groups/affinity-groups.go +++ b/internal/cmd/affinity-groups/affinity-groups.go @@ -6,12 +6,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "affinity-group", Short: "Manage server affinity groups", @@ -19,15 +19,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand( - create.NewCmd(p), - delete.NewCmd(p), - describe.NewCmd(p), - list.NewCmd(p), + create.NewCmd(params), + delete.NewCmd(params), + describe.NewCmd(params), + list.NewCmd(params), ) } diff --git a/internal/cmd/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go index ab1f48d3a..fc8482ea8 100644 --- a/internal/cmd/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Policy string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an affinity groups", @@ -43,20 +44,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create the affinity group %q?", model.Name) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create affinity group: %w", err) } if resp := result; resp != nil { - return outputResult(p, *model, *resp) + return outputResult(params.Printer, *model, *resp) } return fmt.Errorf("create affinity group: nil result") }, diff --git a/internal/cmd/affinity-groups/create/create_test.go b/internal/cmd/affinity-groups/create/create_test.go index 3ab7db59f..0f71d31db 100644 --- a/internal/cmd/affinity-groups/create/create_test.go +++ b/internal/cmd/affinity-groups/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Fatalf("configure global flags: %v", err) } @@ -212,7 +213,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.model, tt.response) diff --git a/internal/cmd/affinity-groups/delete/delete.go b/internal/cmd/affinity-groups/delete/delete.go index 195b4539d..f36371648 100644 --- a/internal/cmd/affinity-groups/delete/delete.go +++ b/internal/cmd/affinity-groups/delete/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ const ( affinityGroupIdArg = "AFFINITY_GROUP" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", affinityGroupIdArg), Short: "Deletes an affinity group", @@ -40,32 +41,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } affinityGroupLabel, err := iaasUtils.GetAffinityGroupName(ctx, apiClient, model.ProjectId, model.AffinityGroupId) if err != nil { - p.Debug(print.ErrorLevel, "get affinity group name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get affinity group name: %v", err) affinityGroupLabel = model.AffinityGroupId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete affinity group %q?", affinityGroupLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("delete affinity group: %w", err) } - p.Info("Deleted affinity group %q for %q\n", affinityGroupLabel, projectLabel) + params.Printer.Info("Deleted affinity group %q for %q\n", affinityGroupLabel, projectLabel) return nil }, diff --git a/internal/cmd/affinity-groups/delete/delete_test.go b/internal/cmd/affinity-groups/delete/delete_test.go index 71f2b84a7..e3df49cbb 100644 --- a/internal/cmd/affinity-groups/delete/delete_test.go +++ b/internal/cmd/affinity-groups/delete/delete_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -97,7 +98,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/affinity-groups/describe/describe.go b/internal/cmd/affinity-groups/describe/describe.go index 410937fb1..566e42d5e 100644 --- a/internal/cmd/affinity-groups/describe/describe.go +++ b/internal/cmd/affinity-groups/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ const ( affinityGroupId = "AFFINITY_GROUP_ID" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", affinityGroupId), Short: "Show details of an affinity group", @@ -41,13 +42,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -59,7 +60,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get affinity group: %w", err) } - if err := outputResult(p, *model, *result); err != nil { + if err := outputResult(params.Printer, *model, *result); err != nil { return err } return nil diff --git a/internal/cmd/affinity-groups/describe/describe_test.go b/internal/cmd/affinity-groups/describe/describe_test.go index 1d8a1f23b..530319c96 100644 --- a/internal/cmd/affinity-groups/describe/describe_test.go +++ b/internal/cmd/affinity-groups/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -98,7 +99,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -191,7 +192,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { diff --git a/internal/cmd/affinity-groups/list/list.go b/internal/cmd/affinity-groups/list/list.go index 3c270bcdb..cb06a6612 100644 --- a/internal/cmd/affinity-groups/list/list.go +++ b/internal/cmd/affinity-groups/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -27,7 +28,7 @@ type inputModel struct { const limitFlag = "limit" -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists affinity groups", @@ -45,13 +46,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,10 +68,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(*items) > int(*model.Limit) { *items = (*items)[:*model.Limit] } - return outputResult(p, *model, *items) + return outputResult(params.Printer, *model, *items) } - p.Outputln("No affinity groups found") + params.Printer.Outputln("No affinity groups found") return nil }, } diff --git a/internal/cmd/affinity-groups/list/list_test.go b/internal/cmd/affinity-groups/list/list_test.go index da35b5778..b44af626c 100644 --- a/internal/cmd/affinity-groups/list/list_test.go +++ b/internal/cmd/affinity-groups/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -105,7 +106,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Fatalf("configure global flags: %v", err) } @@ -186,7 +187,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.model, tt.response) diff --git a/internal/cmd/auth/activate-service-account/activate_service_account.go b/internal/cmd/auth/activate-service-account/activate_service_account.go index 46922720a..5ddc73f29 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -32,7 +33,7 @@ type inputModel struct { OnlyPrintAccessToken bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "activate-service-account", Short: "Authenticates using a service account", @@ -58,7 +59,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), ), RunE: func(cmd *cobra.Command, _ []string) error { - model := parseInput(p, cmd) + model := parseInput(params.Printer, cmd) tokenCustomEndpoint := viper.GetString(config.TokenCustomEndpointKey) if !model.OnlyPrintAccessToken { @@ -78,12 +79,12 @@ func NewCmd(p *print.Printer) *cobra.Command { // Initializes the authentication flow rt, err := sdkAuth.SetupAuth(cfg) if err != nil { - p.Debug(print.ErrorLevel, "setup auth: %v", err) + params.Printer.Debug(print.ErrorLevel, "setup auth: %v", err) return &cliErr.ActivateServiceAccountError{} } // Authenticates the service account and stores credentials - email, accessToken, err := auth.AuthenticateServiceAccount(p, rt, model.OnlyPrintAccessToken) + email, accessToken, err := auth.AuthenticateServiceAccount(params.Printer, rt, model.OnlyPrintAccessToken) if err != nil { var activateServiceAccountError *cliErr.ActivateServiceAccountError if !errors.As(err, &activateServiceAccountError) { @@ -94,9 +95,9 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.OnlyPrintAccessToken { // Only output is the access token - p.Outputf("%s\n", accessToken) + params.Printer.Outputf("%s\n", accessToken) } else { - p.Outputf("You have been successfully authenticated to the STACKIT CLI!\nService account email: %s\n", email) + params.Printer.Outputf("You have been successfully authenticated to the STACKIT CLI!\nService account email: %s\n", email) } return nil }, diff --git a/internal/cmd/auth/activate-service-account/activate_service_account_test.go b/internal/cmd/auth/activate-service-account/activate_service_account_test.go index 9dcbb22b7..84532195c 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account_test.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -106,7 +107,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/auth/auth.go b/internal/cmd/auth/auth.go index 2a8b3a7f2..7e1c020cf 100644 --- a/internal/cmd/auth/auth.go +++ b/internal/cmd/auth/auth.go @@ -5,14 +5,14 @@ import ( getaccesstoken "github.com/stackitcloud/stackit-cli/internal/cmd/auth/get-access-token" "github.com/stackitcloud/stackit-cli/internal/cmd/auth/login" "github.com/stackitcloud/stackit-cli/internal/cmd/auth/logout" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "auth", Short: "Authenticates the STACKIT CLI", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(login.NewCmd(p)) - cmd.AddCommand(logout.NewCmd(p)) - cmd.AddCommand(activateserviceaccount.NewCmd(p)) - cmd.AddCommand(getaccesstoken.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(login.NewCmd(params)) + cmd.AddCommand(logout.NewCmd(params)) + cmd.AddCommand(activateserviceaccount.NewCmd(params)) + cmd.AddCommand(getaccesstoken.NewCmd(params)) } diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index 85fc9247c..0b13fd2fa 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -2,14 +2,14 @@ package getaccesstoken import ( "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "get-access-token", Short: "Prints a short-lived access token.", @@ -42,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return &cliErr.AccessTokenExpiredError{} } - p.Outputf("%s\n", accessToken) + params.Printer.Outputf("%s\n", accessToken) return nil }, } diff --git a/internal/cmd/auth/login/login.go b/internal/cmd/auth/login/login.go index 06531f706..8740fead7 100644 --- a/internal/cmd/auth/login/login.go +++ b/internal/cmd/auth/login/login.go @@ -3,15 +3,15 @@ package login import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "login", Short: "Logs in to the STACKIT CLI", @@ -25,12 +25,12 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit auth login"), ), RunE: func(_ *cobra.Command, _ []string) error { - err := auth.AuthorizeUser(p, false) + err := auth.AuthorizeUser(params.Printer, false) if err != nil { return fmt.Errorf("authorization failed: %w", err) } - p.Outputln("Successfully logged into STACKIT CLI.\n") + params.Printer.Outputln("Successfully logged into STACKIT CLI.\n") return nil }, diff --git a/internal/cmd/auth/logout/logout.go b/internal/cmd/auth/logout/logout.go index adc6f7069..4b318b2e7 100644 --- a/internal/cmd/auth/logout/logout.go +++ b/internal/cmd/auth/logout/logout.go @@ -3,15 +3,15 @@ package logout import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "logout", Short: "Logs the user account out of the STACKIT CLI", @@ -28,7 +28,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("log out failed: %w", err) } - p.Info("Successfully logged out of the STACKIT CLI.\n") + params.Printer.Info("Successfully logged out of the STACKIT CLI.\n") return nil }, } diff --git a/internal/cmd/beta/alb/alb.go b/internal/cmd/beta/alb/alb.go index 94f082da8..fde1da311 100644 --- a/internal/cmd/beta/alb/alb.go +++ b/internal/cmd/beta/alb/alb.go @@ -11,15 +11,15 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/quotas" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/template" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "alb", Short: "Manages application loadbalancers", @@ -27,21 +27,21 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand( - list.NewCmd(p), - template.NewCmd(p), - create.NewCmd(p), - update.NewCmd(p), - observabilitycredentials.NewCmd(p), - describe.NewCmd(p), - delete.NewCmd(p), - pool.NewCmd(p), - plans.NewCmd(p), - quotas.NewCmd(p), + list.NewCmd(params), + template.NewCmd(params), + create.NewCmd(params), + update.NewCmd(params), + observabilitycredentials.NewCmd(params), + describe.NewCmd(params), + delete.NewCmd(params), + pool.NewCmd(params), + plans.NewCmd(params), + quotas.NewCmd(params), ) } diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go index 462d4e381..4d5abe3c1 100644 --- a/internal/cmd/beta/alb/create/create.go +++ b/internal/cmd/beta/alb/create/create.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Configuration *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an application loadbalancer", @@ -47,26 +48,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create an application loadbalancer for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating loadbalancer") _, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name).WaitWithContext(ctx) if err != nil { @@ -93,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(params.Printer, model, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/alb/create/create_test.go b/internal/cmd/beta/alb/create/create_test.go index d77fb2022..82517b0f5 100644 --- a/internal/cmd/beta/alb/create/create_test.go +++ b/internal/cmd/beta/alb/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -134,7 +135,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -248,7 +249,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/delete/delete.go b/internal/cmd/beta/alb/delete/delete.go index c3709e8a9..0c443d593 100644 --- a/internal/cmd/beta/alb/delete/delete.go +++ b/internal/cmd/beta/alb/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -24,7 +25,7 @@ type inputModel struct { Name string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", loadbalancerNameArg), Short: "Deletes an application loadbalancer", @@ -38,26 +39,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete the application loadbalancer %q for project %q?", model.Name, projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete loadbalancer: %w", err) } - p.Outputf("Load balancer %q deleted.", model.Name) + params.Printer.Outputf("Load balancer %q deleted.", model.Name) return nil }, } diff --git a/internal/cmd/beta/alb/delete/delete_test.go b/internal/cmd/beta/alb/delete/delete_test.go index 3bc65bfd1..ce6808fbd 100644 --- a/internal/cmd/beta/alb/delete/delete_test.go +++ b/internal/cmd/beta/alb/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/beta/alb/describe/describe.go b/internal/cmd/beta/alb/describe/describe.go index 8a1403585..db4418ddf 100644 --- a/internal/cmd/beta/alb/describe/describe.go +++ b/internal/cmd/beta/alb/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -29,7 +30,7 @@ type inputModel struct { Name string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", loadbalancerNameArg), Short: "Describes an application loadbalancer", @@ -43,13 +44,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -62,9 +63,9 @@ func NewCmd(p *print.Printer) *cobra.Command { } if loadbalancer := resp; loadbalancer != nil { - return outputResult(p, model.OutputFormat, loadbalancer) + return outputResult(params.Printer, model.OutputFormat, loadbalancer) } - p.Outputln("No load balancer found.") + params.Printer.Outputln("No load balancer found.") return nil }, } diff --git a/internal/cmd/beta/alb/describe/describe_test.go b/internal/cmd/beta/alb/describe/describe_test.go index 0f621c72e..4d1195313 100644 --- a/internal/cmd/beta/alb/describe/describe_test.go +++ b/internal/cmd/beta/alb/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -213,7 +214,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go index 4050e8791..cf1d478c5 100644 --- a/internal/cmd/beta/alb/list/list.go +++ b/internal/cmd/beta/alb/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ const ( limitFlag = "limit" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists albs", @@ -48,20 +49,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId @@ -76,12 +77,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if items := response.LoadBalancers; items == nil || len(*items) == 0 { - p.Info("No load balancers found for project %q", projectLabel) + params.Printer.Info("No load balancers found for project %q", projectLabel) } else { if model.Limit != nil && len(*items) > int(*model.Limit) { *items = (*items)[:*model.Limit] } - if err := outputResult(p, model.OutputFormat, *items); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, *items); err != nil { return fmt.Errorf("output loadbalancers: %w", err) } } diff --git a/internal/cmd/beta/alb/list/list_test.go b/internal/cmd/beta/alb/list/list_test.go index 77c915266..547787166 100644 --- a/internal/cmd/beta/alb/list/list_test.go +++ b/internal/cmd/beta/alb/list/list_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -99,7 +100,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -196,7 +197,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/observability-credentials/add/add.go b/internal/cmd/beta/alb/observability-credentials/add/add.go index 806af5e13..e0eff7449 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -30,7 +31,7 @@ type inputModel struct { Password *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "add", Short: "Adds observability credentials to an application load balancer", @@ -44,20 +45,20 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := "Are your sure you want to add credentials?" - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("add credential: %w", err) } - return outputResult(p, model.GlobalFlagModel.OutputFormat, resp) + return outputResult(params.Printer, model.GlobalFlagModel.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/alb/observability-credentials/add/add_test.go b/internal/cmd/beta/alb/observability-credentials/add/add_test.go index a84b1405b..b5fa2bac6 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add_test.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -101,7 +102,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -202,7 +203,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.item); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete.go b/internal/cmd/beta/alb/observability-credentials/delete/delete.go index e71a6fee4..df9f462f0 100644 --- a/internal/cmd/beta/alb/observability-credentials/delete/delete.go +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -23,7 +24,7 @@ type inputModel struct { CredentialsRef string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialRefArg), Short: "Deletes credentials", @@ -37,20 +38,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials %q?", model.CredentialsRef) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete credential: %w", err) } - p.Info("Deleted credential %q\n", model.CredentialsRef) + params.Printer.Info("Deleted credential %q\n", model.CredentialsRef) return nil }, diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go b/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go index 6f5ff0dd8..09ecaa532 100644 --- a/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/alb" @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe.go b/internal/cmd/beta/alb/observability-credentials/describe/describe.go index 091d08ef2..4081421ca 100644 --- a/internal/cmd/beta/alb/observability-credentials/describe/describe.go +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -28,7 +29,7 @@ type inputModel struct { CredentialRef string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialRefArg), Short: "Describes observability credentials for the Application Load Balancer", @@ -42,13 +43,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -61,9 +62,9 @@ func NewCmd(p *print.Printer) *cobra.Command { } if credential := resp; credential != nil && credential.Credential != nil { - return outputResult(p, model.OutputFormat, *credential.Credential) + return outputResult(params.Printer, model.OutputFormat, *credential.Credential) } - p.Outputln("No credentials found.") + params.Printer.Outputln("No credentials found.") return nil }, } diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go b/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go index 1d4f201a5..79412281b 100644 --- a/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -112,7 +113,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -213,7 +214,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/observability-credentials/list/list.go b/internal/cmd/beta/alb/observability-credentials/list/list.go index d08a9026e..bbbdd6db4 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials", @@ -52,13 +53,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Credentials == nil || len(*resp.Credentials) == 0 { - p.Info("No credentials found\n") + params.Printer.Info("No credentials found\n") return nil } @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/alb/observability-credentials/list/list_test.go b/internal/cmd/beta/alb/observability-credentials/list/list_test.go index f3c305298..77863ded8 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list_test.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -216,7 +217,7 @@ func Test_outputResult(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) diff --git a/internal/cmd/beta/alb/observability-credentials/observability-credentials.go b/internal/cmd/beta/alb/observability-credentials/observability-credentials.go index 04dee2407..3d18486ee 100644 --- a/internal/cmd/beta/alb/observability-credentials/observability-credentials.go +++ b/internal/cmd/beta/alb/observability-credentials/observability-credentials.go @@ -8,11 +8,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/update" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "observability-credentials", Short: "Provides functionality for application loadbalancer credentials", @@ -20,14 +20,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: cobra.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(add.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(add.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/beta/alb/observability-credentials/update/update.go b/internal/cmd/beta/alb/observability-credentials/update/update.go index 03a9fe8ad..3231f0d95 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -34,7 +35,7 @@ type inputModel struct { CredentialsRef *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", credentialRefArg), Short: "Update credentials", @@ -47,10 +48,10 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model := parseInput(p, cmd, args) + model := parseInput(params.Printer, cmd, args) // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -59,14 +60,14 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update credential %q for %q?", *model.CredentialsRef, projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return fmt.Errorf("update credential: %w", err) } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("response is nil") } - return outputResult(p, model, resp) + return outputResult(params.Printer, model, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/alb/observability-credentials/update/update_test.go b/internal/cmd/beta/alb/observability-credentials/update/update_test.go index bdfab0080..4d3780ba1 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update_test.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -126,7 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -216,7 +217,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.item); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/plans/plans.go b/internal/cmd/beta/alb/plans/plans.go index 13719baac..f7d09bec6 100644 --- a/internal/cmd/beta/alb/plans/plans.go +++ b/internal/cmd/beta/alb/plans/plans.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -23,7 +24,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists the application load balancer plans", @@ -37,20 +38,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId @@ -65,9 +66,9 @@ func NewCmd(p *print.Printer) *cobra.Command { } if items := response.ValidPlans; items == nil || len(*items) == 0 { - p.Info("No plans found for project %q", projectLabel) + params.Printer.Info("No plans found for project %q", projectLabel) } else { - if err := outputResult(p, model.OutputFormat, *items); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, *items); err != nil { return fmt.Errorf("output plans: %w", err) } } diff --git a/internal/cmd/beta/alb/plans/plans_test.go b/internal/cmd/beta/alb/plans/plans_test.go index 3184f5696..bfbda8586 100644 --- a/internal/cmd/beta/alb/plans/plans_test.go +++ b/internal/cmd/beta/alb/plans/plans_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -95,7 +96,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -192,7 +193,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/pool/pool.go b/internal/cmd/beta/alb/pool/pool.go index 5d8d5fd41..d40f8733a 100644 --- a/internal/cmd/beta/alb/pool/pool.go +++ b/internal/cmd/beta/alb/pool/pool.go @@ -2,15 +2,15 @@ package pool import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/pool/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "pool", Short: "Manages target pools for application loadbalancers", @@ -18,10 +18,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/beta/alb/pool/update/update.go b/internal/cmd/beta/alb/pool/update/update.go index e8b2aa2fa..94bdd2872 100644 --- a/internal/cmd/beta/alb/pool/update/update.go +++ b/internal/cmd/beta/alb/pool/update/update.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { AlbName *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "Updates an application target pool", @@ -47,26 +48,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update an application target pool for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update application target pool: %w", err) } - return outputResult(p, model, projectLabel, resp) + return outputResult(params.Printer, model, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/alb/pool/update/update_test.go b/internal/cmd/beta/alb/pool/update/update_test.go index b9b9ec080..f279c1f01 100644 --- a/internal/cmd/beta/alb/pool/update/update_test.go +++ b/internal/cmd/beta/alb/pool/update/update_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -142,7 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -257,7 +258,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/quotas/quotas.go b/internal/cmd/beta/alb/quotas/quotas.go index 07bc2eb21..09735a914 100644 --- a/internal/cmd/beta/alb/quotas/quotas.go +++ b/internal/cmd/beta/alb/quotas/quotas.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -22,7 +23,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "quotas", Short: "Shows the application load balancer quotas", @@ -36,13 +37,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -56,11 +57,11 @@ func NewCmd(p *print.Printer) *cobra.Command { } if response == nil { - p.Outputln("no quotas found") + params.Printer.Outputln("no quotas found") return nil } - if err := outputResult(p, model.OutputFormat, *response); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, *response); err != nil { return fmt.Errorf("output loadbalancers: %w", err) } diff --git a/internal/cmd/beta/alb/quotas/quotas_test.go b/internal/cmd/beta/alb/quotas/quotas_test.go index b840d9ef0..1ff2aaacd 100644 --- a/internal/cmd/beta/alb/quotas/quotas_test.go +++ b/internal/cmd/beta/alb/quotas/quotas_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -95,7 +96,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -192,7 +193,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/template/template.go b/internal/cmd/beta/alb/template/template.go index 18d0cd427..c33ca2846 100644 --- a/internal/cmd/beta/alb/template/template.go +++ b/internal/cmd/beta/alb/template/template.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ var ( templatePool string ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "template", Short: "creates configuration templates to use for resource creation", @@ -53,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), ), RunE: func(cmd *cobra.Command, _ []string) error { - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } @@ -73,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if model.Format == nil || *model.Format == "yaml" { - p.Outputln(template) + params.Printer.Outputln(template) } else if *model.Format == "json" { if err := yaml.Unmarshal([]byte(template), &target); err != nil { return fmt.Errorf("cannot unmarshal template: %w", err) diff --git a/internal/cmd/beta/alb/template/template_test.go b/internal/cmd/beta/alb/template/template_test.go index 3ca5404e8..be7bed72d 100644 --- a/internal/cmd/beta/alb/template/template_test.go +++ b/internal/cmd/beta/alb/template/template_test.go @@ -3,6 +3,7 @@ package template import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go index 546f89990..10e0b9bc5 100644 --- a/internal/cmd/beta/alb/update/update.go +++ b/internal/cmd/beta/alb/update/update.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Version *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "Updates an application loadbalancer", @@ -48,26 +49,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update an application loadbalancer for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -90,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("updating loadbalancer") _, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name). WaitWithContext(ctx) @@ -100,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(params.Printer, model, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/alb/update/update_test.go b/internal/cmd/beta/alb/update/update_test.go index 176a130a3..5749b8b86 100644 --- a/internal/cmd/beta/alb/update/update_test.go +++ b/internal/cmd/beta/alb/update/update_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -251,7 +252,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 37b5e4bd9..5a007b87e 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -5,15 +5,15 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "beta", Short: "Contains beta STACKIT CLI commands", @@ -31,11 +31,11 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit beta MY_COMMAND"), ), } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(sqlserverflex.NewCmd(p)) - cmd.AddCommand(alb.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(sqlserverflex.NewCmd(params)) + cmd.AddCommand(alb.NewCmd(params)) } diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index fe137c435..ac7e345a8 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Owner string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", databaseNameArg), Short: "Creates a SQLServer Flex database", @@ -49,20 +50,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create database %q? (This cannot be undone)", model.DatabaseName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Call API req := buildRequest(ctx, model, apiClient) - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating database") resp, err := req.Execute() if err != nil { @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } s.Stop() - return outputResult(p, model.OutputFormat, model.DatabaseName, resp) + return outputResult(params.Printer, model.OutputFormat, model.DatabaseName, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/sqlserverflex/database/create/create_test.go b/internal/cmd/beta/sqlserverflex/database/create/create_test.go index ada824cb6..c6359313e 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" @@ -177,7 +178,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -281,7 +282,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.databaseName, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/database/database.go b/internal/cmd/beta/sqlserverflex/database/database.go index 3fbd641ce..f11cf2bd0 100644 --- a/internal/cmd/beta/sqlserverflex/database/database.go +++ b/internal/cmd/beta/sqlserverflex/database/database.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "database", Short: "Provides functionality for SQLServer Flex databases", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete.go b/internal/cmd/beta/sqlserverflex/database/delete/delete.go index d47633cf3..b1950aa86 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", databaseNameArg), Short: "Deletes a SQLServer Flex database", @@ -45,20 +46,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete database %q? (This cannot be undone)", model.DatabaseName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Call API req := buildRequest(ctx, model, apiClient) - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting database") err = req.Execute() if err != nil { @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } s.Stop() - p.Info("Deleted database %q\n", model.DatabaseName) + params.Printer.Info("Deleted database %q\n", model.DatabaseName) return nil }, } diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go index 315341040..53a099f48 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" @@ -160,7 +161,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index ed2caecf7..3ddbfa086 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", databaseNameArg), Short: "Shows details of an SQLServer Flex database", @@ -47,12 +48,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -64,7 +65,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read SQLServer Flex database: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go index b55faf4a2..919b1e3c5 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" @@ -159,7 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -269,7 +270,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index 6d660f8a1..ba22c593e 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all SQLServer Flex databases", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -68,12 +69,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get SQLServer Flex databases: %w", err) } if resp.Databases == nil || len(*resp.Databases) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No databases found for instance %s on project %s\n", model.InstanceId, projectLabel) + params.Printer.Info("No databases found for instance %s on project %s\n", model.InstanceId, projectLabel) return nil } databases := *resp.Databases @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { databases = databases[:*model.Limit] } - return outputResult(p, model.OutputFormat, databases) + return outputResult(params.Printer, model.OutputFormat, databases) }, } diff --git a/internal/cmd/beta/sqlserverflex/database/list/list_test.go b/internal/cmd/beta/sqlserverflex/database/list/list_test.go index 1b10b22a8..0aa4979f7 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -235,7 +236,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.databases); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 904b2f6f8..9003de50b 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -65,7 +66,7 @@ type inputModel struct { RetentionDays *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a SQLServer Flex instance", @@ -86,26 +87,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a SQLServer Flex instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -124,7 +125,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) if err != nil { @@ -133,7 +134,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(params.Printer, model, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go index eaf4a5463..851d3d1fd 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -251,7 +252,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -524,7 +525,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go index c0456b08d..2b5723c50 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a SQLServer Flex instance", @@ -41,26 +42,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) if err != nil { @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go index 753379175..ae971f31d 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -139,7 +140,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index c5d8e68e1..7dec66a7d 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a SQLServer Flex instance", @@ -45,12 +46,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -62,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read SQLServer Flex instance: %w", err) } - return outputResult(p, model.OutputFormat, resp.Item) + return outputResult(params.Printer, model.OutputFormat, resp.Item) }, } return cmd diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go index 29edcede2..7412418c6 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/instance/instance.go b/internal/cmd/beta/sqlserverflex/instance/instance.go index a74e41085..4ed452eb1 100644 --- a/internal/cmd/beta/sqlserverflex/instance/instance.go +++ b/internal/cmd/beta/sqlserverflex/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for SQLServer Flex instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 18666a7d5..3f9abdb22 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all SQLServer Flex instances", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,12 +67,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get SQLServer Flex instances: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } instances := *resp.Items @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go index 094774724..be4b5debe 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -211,7 +212,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index 39c5989dc..53921ea75 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -60,7 +61,7 @@ type inputModel struct { Version *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a SQLServer Flex instance", @@ -77,26 +78,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -115,7 +116,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) if err != nil { @@ -124,7 +125,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, instanceLabel, resp) + return outputResult(params.Printer, model, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update_test.go b/internal/cmd/beta/sqlserverflex/instance/update/update_test.go index 4c9c92dd5..5db0655ba 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -281,7 +282,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -520,7 +521,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index a4b815a44..d66f082c9 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -87,7 +88,7 @@ type instanceDBCompatibilities struct { DBCompatibilities []sqlserverflex.MssqlDatabaseCompatibility `json:"dbCompatibilities"` } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "options", Short: "Lists SQL Server Flex options", @@ -109,19 +110,19 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } // Call API - err = buildAndExecuteRequest(ctx, p, model, apiClient) + err = buildAndExecuteRequest(ctx, params.Printer, model, apiClient) if err != nil { return fmt.Errorf("get SQL Server Flex options: %w", err) } diff --git a/internal/cmd/beta/sqlserverflex/options/options_test.go b/internal/cmd/beta/sqlserverflex/options/options_test.go index 5e76ad539..1f527d85e 100644 --- a/internal/cmd/beta/sqlserverflex/options/options_test.go +++ b/internal/cmd/beta/sqlserverflex/options/options_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -263,7 +264,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -472,7 +473,7 @@ func TestBuildAndExecuteRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) p.Cmd = cmd client := &sqlServerFlexClientMocked{ listFlavorsFails: tt.listFlavorsFails, @@ -544,7 +545,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.flavors, tt.args.versions, tt.args.storages, tt.args.userRoles, tt.args.dbCollations, tt.args.dbCompatibilities); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/sqlserverflex.go b/internal/cmd/beta/sqlserverflex/sqlserverflex.go index a65ca22e8..51c93beb8 100644 --- a/internal/cmd/beta/sqlserverflex/sqlserverflex.go +++ b/internal/cmd/beta/sqlserverflex/sqlserverflex.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/options" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "sqlserverflex", Short: "Provides functionality for SQLServer Flex", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(database.NewCmd(p)) - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(options.NewCmd(p)) - cmd.AddCommand(user.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(database.NewCmd(params)) + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(options.NewCmd(params)) + cmd.AddCommand(user.NewCmd(params)) } diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 0cd99180c..501746b1e 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a SQLServer Flex user", @@ -58,26 +59,26 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } user := resp.Item - return outputResult(p, model, instanceLabel, user) + return outputResult(params.Printer, model, instanceLabel, user) }, } diff --git a/internal/cmd/beta/sqlserverflex/user/create/create_test.go b/internal/cmd/beta/sqlserverflex/user/create/create_test.go index a53878b3d..4c294d6d9 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -247,7 +248,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete.go b/internal/cmd/beta/sqlserverflex/user/delete/delete.go index b85272ba3..dea859e97 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", userIdArg), Short: "Deletes a SQLServer Flex user", @@ -46,32 +47,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := sqlserverflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete SQLServer Flex user: %w", err) } - p.Info("Deleted user %q of instance %q\n", userLabel, instanceLabel) + params.Printer.Info("Deleted user %q of instance %q\n", userLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go index 79053edf7..c4345ba6a 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -154,7 +155,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index e9822bdd0..7ccba07f1 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", userIdArg), Short: "Shows details of a SQLServer Flex user", @@ -54,13 +55,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get SQLServer Flex user: %w", err) } - return outputResult(p, model.OutputFormat, resp.Item) + return outputResult(params.Printer, model.OutputFormat, resp.Item) }, } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go index c0d6be049..8f44c6db7 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" @@ -153,7 +154,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -256,7 +257,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index c4fcd2152..29e2c803c 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all SQLServer Flex users of an instance", @@ -51,13 +52,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,10 +72,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if resp.Items == nil || len(*resp.Items) == 0 { instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } - p.Info("No users found for instance %q\n", instanceLabel) + params.Printer.Info("No users found for instance %q\n", instanceLabel) return nil } users := *resp.Items @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { users = users[:*model.Limit] } - return outputResult(p, model.OutputFormat, users) + return outputResult(params.Printer, model.OutputFormat, users) }, } diff --git a/internal/cmd/beta/sqlserverflex/user/list/list_test.go b/internal/cmd/beta/sqlserverflex/user/list/list_test.go index cc3dabc34..7ec60722f 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -228,7 +229,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index 182a9e147..ff560a2cf 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reset-password %s", userIdArg), Short: "Resets the password of a SQLServer Flex user", @@ -49,32 +50,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := sqlserverflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("reset SQLServer Flex user password: %w", err) } - return outputResult(p, model.OutputFormat, userLabel, instanceLabel, user.Item) + return outputResult(params.Printer, model.OutputFormat, userLabel, instanceLabel, user.Item) }, } diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go index 8eda0631f..eeeb230a1 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" @@ -153,7 +154,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -258,7 +259,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.userLabel, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/user/user.go b/internal/cmd/beta/sqlserverflex/user/user.go index 9426f3bbf..0c83d54e4 100644 --- a/internal/cmd/beta/sqlserverflex/user/user.go +++ b/internal/cmd/beta/sqlserverflex/user/user.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user/list" resetpassword "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user/reset-password" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "user", Short: "Provides functionality for SQLServer Flex users", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(resetpassword.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(resetpassword.NewCmd(params)) } diff --git a/internal/cmd/config/config.go b/internal/cmd/config/config.go index a96355a54..46b21b96a 100644 --- a/internal/cmd/config/config.go +++ b/internal/cmd/config/config.go @@ -7,14 +7,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile" "github.com/stackitcloud/stackit-cli/internal/cmd/config/set" "github.com/stackitcloud/stackit-cli/internal/cmd/config/unset" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "config", Short: "Provides functionality for CLI configuration options", @@ -28,13 +28,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(set.NewCmd(p)) - cmd.AddCommand(unset.NewCmd(p)) - cmd.AddCommand(profile.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(set.NewCmd(params)) + cmd.AddCommand(unset.NewCmd(params)) + cmd.AddCommand(profile.NewCmd(params)) } diff --git a/internal/cmd/config/list/list.go b/internal/cmd/config/list/list.go index 7fd7b51ce..6dbc78e7e 100644 --- a/internal/cmd/config/list/list.go +++ b/internal/cmd/config/list/list.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -25,7 +26,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists the current CLI configuration values", @@ -50,14 +51,14 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { configData := viper.AllSettings() - model := parseInput(p, cmd) + model := parseInput(params.Printer, cmd) activeProfile, err := config.GetProfile() if err != nil { return fmt.Errorf("get profile: %w", err) } - return outputResult(p, model.OutputFormat, configData, activeProfile) + return outputResult(params.Printer, model.OutputFormat, configData, activeProfile) }, } return cmd diff --git a/internal/cmd/config/list/list_test.go b/internal/cmd/config/list/list_test.go index d32d5d76a..936e5a76d 100644 --- a/internal/cmd/config/list/list_test.go +++ b/internal/cmd/config/list/list_test.go @@ -3,6 +3,7 @@ package list import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/print" ) @@ -24,7 +25,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.configData, tt.args.activeProfile); (err != nil) != tt.wantErr { diff --git a/internal/cmd/config/profile/create/create.go b/internal/cmd/config/profile/create/create.go index ceec4ee04..8ab83f574 100644 --- a/internal/cmd/config/profile/create/create.go +++ b/internal/cmd/config/profile/create/create.go @@ -3,6 +3,7 @@ package create import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -28,7 +29,7 @@ type inputModel struct { Profile string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", profileArg), Short: "Creates a CLI configuration profile", @@ -49,30 +50,30 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit config profile create my-profile --empty --no-set"), ), RunE: func(cmd *cobra.Command, args []string) error { - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } - err = config.CreateProfile(p, model.Profile, !model.NoSet, model.FromEmptyProfile) + err = config.CreateProfile(params.Printer, model.Profile, !model.NoSet, model.FromEmptyProfile) if err != nil { return fmt.Errorf("create profile: %w", err) } if model.NoSet { - p.Info("Successfully created profile %q\n", model.Profile) + params.Printer.Info("Successfully created profile %q\n", model.Profile) return nil } - p.Info("Successfully created and set active profile to %q\n", model.Profile) + params.Printer.Info("Successfully created and set active profile to %q\n", model.Profile) flow, err := auth.GetAuthFlow() if err != nil { - p.Debug(print.WarningLevel, "both keyring and text file storage failed to find a valid authentication flow for the active profile") - p.Warn("The active profile %q is not authenticated, please login using the 'stackit auth login' command.\n", model.Profile) + params.Printer.Debug(print.WarningLevel, "both keyring and text file storage failed to find a valid authentication flow for the active profile") + params.Printer.Warn("The active profile %q is not authenticated, please login using the 'stackit auth login' command.\n", model.Profile) return nil } - p.Debug(print.DebugLevel, "found valid authentication flow for active profile: %s", flow) + params.Printer.Debug(print.DebugLevel, "found valid authentication flow for active profile: %s", flow) return nil }, diff --git a/internal/cmd/config/profile/create/create_test.go b/internal/cmd/config/profile/create/create_test.go index 0cc32cc9d..097071947 100644 --- a/internal/cmd/config/profile/create/create_test.go +++ b/internal/cmd/config/profile/create/create_test.go @@ -3,6 +3,7 @@ package create import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -104,7 +105,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/config/profile/delete/delete.go b/internal/cmd/config/profile/delete/delete.go index 992750c29..88d00907f 100644 --- a/internal/cmd/config/profile/delete/delete.go +++ b/internal/cmd/config/profile/delete/delete.go @@ -3,6 +3,7 @@ package delete import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -23,7 +24,7 @@ type inputModel struct { Profile string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", profileArg), Short: "Delete a CLI configuration profile", @@ -38,7 +39,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit config profile delete my-profile"), ), RunE: func(cmd *cobra.Command, args []string) error { - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -60,18 +61,18 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get profile: %w", err) } if activeProfile == model.Profile { - p.Warn("The profile you are trying to delete is the active profile. The default profile will be set to active.\n") + params.Printer.Warn("The profile you are trying to delete is the active profile. The default profile will be set to active.\n") } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete profile %q? (This cannot be undone)", model.Profile) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } } - err = config.DeleteProfile(p, model.Profile) + err = config.DeleteProfile(params.Printer, model.Profile) if err != nil { return fmt.Errorf("delete profile: %w", err) } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete profile authentication: %w", err) } - p.Info("Successfully deleted profile %q\n", model.Profile) + params.Printer.Info("Successfully deleted profile %q\n", model.Profile) return nil }, diff --git a/internal/cmd/config/profile/delete/delete_test.go b/internal/cmd/config/profile/delete/delete_test.go index 3919460b7..018ded22a 100644 --- a/internal/cmd/config/profile/delete/delete_test.go +++ b/internal/cmd/config/profile/delete/delete_test.go @@ -3,6 +3,7 @@ package delete import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -80,7 +81,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/config/profile/export/export.go b/internal/cmd/config/profile/export/export.go index 9aa585971..59389b47a 100644 --- a/internal/cmd/config/profile/export/export.go +++ b/internal/cmd/config/profile/export/export.go @@ -4,6 +4,7 @@ import ( "fmt" "path/filepath" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { FilePath string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("export %s", profileNameArg), Short: "Exports a CLI configuration profile", @@ -45,17 +46,17 @@ func NewCmd(p *print.Printer) *cobra.Command { ), Args: args.SingleArg(profileNameArg, nil), RunE: func(cmd *cobra.Command, args []string) error { - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } - err = config.ExportProfile(p, model.ProfileName, model.FilePath) + err = config.ExportProfile(params.Printer, model.ProfileName, model.FilePath) if err != nil { return fmt.Errorf("could not export profile: %w", err) } - p.Info("Exported profile %q to %q\n", model.ProfileName, model.FilePath) + params.Printer.Info("Exported profile %q to %q\n", model.ProfileName, model.FilePath) return nil }, diff --git a/internal/cmd/config/profile/export/export_test.go b/internal/cmd/config/profile/export/export_test.go index 4dffd3a22..d15885813 100644 --- a/internal/cmd/config/profile/export/export_test.go +++ b/internal/cmd/config/profile/export/export_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -102,7 +103,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/config/profile/import/import.go b/internal/cmd/config/profile/import/import.go index d57cb1929..84bd9b3aa 100644 --- a/internal/cmd/config/profile/import/import.go +++ b/internal/cmd/config/profile/import/import.go @@ -2,6 +2,7 @@ package importProfile import ( "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -24,7 +25,7 @@ type inputModel struct { NoSet bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "import", Short: "Imports a CLI configuration profile", @@ -41,17 +42,17 @@ func NewCmd(p *print.Printer) *cobra.Command { ), Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } - err = config.ImportProfile(p, model.ProfileName, model.Config, !model.NoSet) + err = config.ImportProfile(params.Printer, model.ProfileName, model.Config, !model.NoSet) if err != nil { return err } - p.Info("Successfully imported profile %q\n", model.ProfileName) + params.Printer.Info("Successfully imported profile %q\n", model.ProfileName) return nil }, diff --git a/internal/cmd/config/profile/import/import_test.go b/internal/cmd/config/profile/import/import_test.go index 7e028ab59..121b7adb9 100644 --- a/internal/cmd/config/profile/import/import_test.go +++ b/internal/cmd/config/profile/import/import_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -75,7 +76,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/config/profile/list/list.go b/internal/cmd/config/profile/list/list.go index 10f2e239b..2a43aa417 100644 --- a/internal/cmd/config/profile/list/list.go +++ b/internal/cmd/config/profile/list/list.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -20,7 +21,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all CLI configuration profiles", @@ -35,7 +36,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit config profile list --output-format json"), ), RunE: func(cmd *cobra.Command, _ []string) error { - model := parseInput(p, cmd) + model := parseInput(params.Printer, cmd) profiles, err := config.ListProfiles() if err != nil { @@ -49,7 +50,7 @@ func NewCmd(p *print.Printer) *cobra.Command { outputProfiles := buildOutput(profiles, activeProfile) - return outputResult(p, model.OutputFormat, outputProfiles) + return outputResult(params.Printer, model.OutputFormat, outputProfiles) }, } return cmd diff --git a/internal/cmd/config/profile/list/list_test.go b/internal/cmd/config/profile/list/list_test.go index 80e080c56..8016b6071 100644 --- a/internal/cmd/config/profile/list/list_test.go +++ b/internal/cmd/config/profile/list/list_test.go @@ -3,6 +3,7 @@ package list import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/print" ) @@ -23,7 +24,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.profiles); (err != nil) != tt.wantErr { diff --git a/internal/cmd/config/profile/profile.go b/internal/cmd/config/profile/profile.go index 848a60382..f6ad03ece 100644 --- a/internal/cmd/config/profile/profile.go +++ b/internal/cmd/config/profile/profile.go @@ -10,14 +10,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/list" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/set" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/unset" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "profile", Short: "Manage the CLI configuration profiles", @@ -30,16 +30,16 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(set.NewCmd(p)) - cmd.AddCommand(unset.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(importProfile.NewCmd(p)) - cmd.AddCommand(export.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(set.NewCmd(params)) + cmd.AddCommand(unset.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(importProfile.NewCmd(params)) + cmd.AddCommand(export.NewCmd(params)) } diff --git a/internal/cmd/config/profile/set/set.go b/internal/cmd/config/profile/set/set.go index ac43977b3..0784d4654 100644 --- a/internal/cmd/config/profile/set/set.go +++ b/internal/cmd/config/profile/set/set.go @@ -3,6 +3,7 @@ package set import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -23,7 +24,7 @@ type inputModel struct { Profile string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("set %s", profileArg), Short: "Set a CLI configuration profile", @@ -40,7 +41,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit config profile set my-profile"), ), RunE: func(cmd *cobra.Command, args []string) error { - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -53,20 +54,20 @@ func NewCmd(p *print.Printer) *cobra.Command { return &errors.SetInexistentProfile{Profile: model.Profile} } - err = config.SetProfile(p, model.Profile) + err = config.SetProfile(params.Printer, model.Profile) if err != nil { return fmt.Errorf("set profile: %w", err) } - p.Info("Successfully set active profile to %q\n", model.Profile) + params.Printer.Info("Successfully set active profile to %q\n", model.Profile) flow, err := auth.GetAuthFlow() if err != nil { - p.Debug(print.WarningLevel, "both keyring and text file storage failed to find a valid authentication flow for the active profile") - p.Warn("The active profile %q is not authenticated, please login using the 'stackit auth login' command.\n", model.Profile) + params.Printer.Debug(print.WarningLevel, "both keyring and text file storage failed to find a valid authentication flow for the active profile") + params.Printer.Warn("The active profile %q is not authenticated, please login using the 'stackit auth login' command.\n", model.Profile) return nil } - p.Debug(print.DebugLevel, "found valid authentication flow for active profile: %s", flow) + params.Printer.Debug(print.DebugLevel, "found valid authentication flow for active profile: %s", flow) return nil }, diff --git a/internal/cmd/config/profile/set/set_test.go b/internal/cmd/config/profile/set/set_test.go index 47f56ca0b..a12b0f328 100644 --- a/internal/cmd/config/profile/set/set_test.go +++ b/internal/cmd/config/profile/set/set_test.go @@ -3,6 +3,7 @@ package set import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -80,7 +81,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/config/profile/unset/unset.go b/internal/cmd/config/profile/unset/unset.go index 4c06edb60..9c7f923cd 100644 --- a/internal/cmd/config/profile/unset/unset.go +++ b/internal/cmd/config/profile/unset/unset.go @@ -3,6 +3,7 @@ package unset import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -12,7 +13,7 @@ import ( "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "unset", Short: "Unset the current active CLI configuration profile", @@ -27,20 +28,20 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit config profile unset"), ), RunE: func(_ *cobra.Command, _ []string) error { - err := config.UnsetProfile(p) + err := config.UnsetProfile(params.Printer) if err != nil { return fmt.Errorf("unset profile: %w", err) } - p.Info("Profile unset successfully. The default profile will be used.\n") + params.Printer.Info("Profile unset successfully. The default profile will be used.\n") flow, err := auth.GetAuthFlow() if err != nil { - p.Debug(print.WarningLevel, "both keyring and text file storage failed to find a valid authentication flow for the active profile") - p.Warn("The default profile is not authenticated, please login using the 'stackit auth login' command.\n") + params.Printer.Debug(print.WarningLevel, "both keyring and text file storage failed to find a valid authentication flow for the active profile") + params.Printer.Warn("The default profile is not authenticated, please login using the 'stackit auth login' command.\n") return nil } - p.Debug(print.DebugLevel, "found valid authentication flow for active profile: %s", flow) + params.Printer.Debug(print.DebugLevel, "found valid authentication flow for active profile: %s", flow) return nil }, diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index b8defa692..54f9f527d 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -53,7 +54,7 @@ type inputModel struct { ProjectIdSet bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "set", Short: "Sets CLI configuration options", @@ -76,13 +77,13 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit config set --dns-custom-endpoint https://dns.stackit.cloud"), ), RunE: func(cmd *cobra.Command, _ []string) error { - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } if model.SessionTimeLimit != nil { - p.Warn("Authenticate again to apply changes to session time limit\n") + params.Printer.Warn("Authenticate again to apply changes to session time limit\n") viper.Set(config.SessionTimeLimitKey, *model.SessionTimeLimit) } diff --git a/internal/cmd/config/set/set_test.go b/internal/cmd/config/set/set_test.go index 9b317b5ad..e9647e268 100644 --- a/internal/cmd/config/set/set_test.go +++ b/internal/cmd/config/set/set_test.go @@ -3,6 +3,7 @@ package set import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -122,7 +123,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 72d79aeb3..a288be6a3 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -3,6 +3,7 @@ package unset import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -88,7 +89,7 @@ type inputModel struct { TokenCustomEndpoint bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "unset", Short: "Unsets CLI configuration options", @@ -106,7 +107,7 @@ func NewCmd(p *print.Printer) *cobra.Command { "$ stackit config unset --dns-custom-endpoint"), ), RunE: func(cmd *cobra.Command, _ []string) error { - model := parseInput(p, cmd) + model := parseInput(params.Printer, cmd) if model.Async { viper.Set(config.AsyncKey, config.AsyncDefault) diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index bc262c002..a977f8aa2 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/google/go-cmp/cmp" @@ -291,7 +292,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) for flag, value := range tt.flagValues { stringBool := fmt.Sprintf("%v", value) diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index 9959e50f1..15b79627a 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -45,7 +46,7 @@ type inputModel struct { OutputFile *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("curl %s", urlArg), Short: "Executes an authenticated HTTP request to an endpoint", @@ -70,12 +71,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), Args: args.SingleArg(urlArg, utils.ValidateURLDomain), RunE: func(cmd *cobra.Command, args []string) (err error) { - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } - bearerToken, err := getBearerToken(p) + bearerToken, err := getBearerToken(params.Printer) if err != nil { return err } @@ -99,7 +100,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } }() - err = outputResponse(p, model, resp) + err = outputResponse(params.Printer, model, resp) if err != nil { return err } diff --git a/internal/cmd/curl/curl_test.go b/internal/cmd/curl/curl_test.go index c7b4dcf4b..3fbab3cf4 100644 --- a/internal/cmd/curl/curl_test.go +++ b/internal/cmd/curl/curl_test.go @@ -13,6 +13,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -216,7 +217,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -447,7 +448,7 @@ func TestOutputResponse(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResponse(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/dns.go b/internal/cmd/dns/dns.go index a89e959c5..ccba3b66d 100644 --- a/internal/cmd/dns/dns.go +++ b/internal/cmd/dns/dns.go @@ -3,14 +3,14 @@ package dns import ( recordset "github.com/stackitcloud/stackit-cli/internal/cmd/dns/record-set" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "dns", Short: "Provides functionality for DNS", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(zone.NewCmd(p)) - cmd.AddCommand(recordset.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(zone.NewCmd(params)) + cmd.AddCommand(recordset.NewCmd(params)) } diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 65ea58911..8441db8ac 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -43,7 +44,7 @@ type inputModel struct { Type string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a DNS record set", @@ -56,26 +57,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) if err != nil { - p.Debug(print.ErrorLevel, "get zone name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) zoneLabel = model.ZoneId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a record set for zone %s?", zoneLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating record set") _, err = wait.CreateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, recordSetId).WaitWithContext(ctx) if err != nil { @@ -100,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, zoneLabel, resp) + return outputResult(params.Printer, model, zoneLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/dns/record-set/create/create_test.go b/internal/cmd/dns/record-set/create/create_test.go index eed9f9424..99a216aeb 100644 --- a/internal/cmd/dns/record-set/create/create_test.go +++ b/internal/cmd/dns/record-set/create/create_test.go @@ -9,6 +9,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -267,7 +268,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -395,7 +396,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.zoneLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/record-set/delete/delete.go b/internal/cmd/dns/record-set/delete/delete.go index 4bb3a1c88..a4026478f 100644 --- a/internal/cmd/dns/record-set/delete/delete.go +++ b/internal/cmd/dns/record-set/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { RecordSetId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", recordSetIdArg), Short: "Deletes a DNS record set", @@ -45,32 +46,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) if err != nil { - p.Debug(print.ErrorLevel, "get zone name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) zoneLabel = model.ZoneId } recordSetLabel, err := dnsUtils.GetRecordSetName(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId) if err != nil { - p.Debug(print.ErrorLevel, "get record set name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get record set name: %v", err) recordSetLabel = model.RecordSetId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete record set %s of zone %s? (This cannot be undone)", recordSetLabel, zoneLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting record set") _, err = wait.DeleteRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx) if err != nil { @@ -101,7 +102,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s record set %s of zone %s\n", operationState, recordSetLabel, zoneLabel) + params.Printer.Info("%s record set %s of zone %s\n", operationState, recordSetLabel, zoneLabel) return nil }, } diff --git a/internal/cmd/dns/record-set/delete/delete_test.go b/internal/cmd/dns/record-set/delete/delete_test.go index 137c85267..55b534fde 100644 --- a/internal/cmd/dns/record-set/delete/delete_test.go +++ b/internal/cmd/dns/record-set/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/dns/record-set/describe/describe.go b/internal/cmd/dns/record-set/describe/describe.go index 03a757a7a..8f80674b8 100644 --- a/internal/cmd/dns/record-set/describe/describe.go +++ b/internal/cmd/dns/record-set/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { RecordSetId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", recordSetIdArg), Short: "Shows details of a DNS record set", @@ -49,13 +50,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -68,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } recordSet := resp.Rrset - return outputResult(p, model.OutputFormat, recordSet) + return outputResult(params.Printer, model.OutputFormat, recordSet) }, } configureFlags(cmd) diff --git a/internal/cmd/dns/record-set/describe/describe_test.go b/internal/cmd/dns/record-set/describe/describe_test.go index a2cbc48e7..55a032bd8 100644 --- a/internal/cmd/dns/record-set/describe/describe_test.go +++ b/internal/cmd/dns/record-set/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/dns" @@ -164,7 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -269,7 +270,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.recordSet); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index 2062a7c84..99a07bb5a 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -9,6 +9,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -50,7 +51,7 @@ type inputModel struct { PageSize int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists DNS record sets", @@ -75,13 +76,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -94,13 +95,13 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(recordSets) == 0 { zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) if err != nil { - p.Debug(print.ErrorLevel, "get zone name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) zoneLabel = model.ZoneId } - p.Info("No record sets found for zone %s matching the criteria\n", zoneLabel) + params.Printer.Info("No record sets found for zone %s matching the criteria\n", zoneLabel) return nil } - return outputResult(p, model.OutputFormat, recordSets) + return outputResult(params.Printer, model.OutputFormat, recordSets) }, } diff --git a/internal/cmd/dns/record-set/list/list_test.go b/internal/cmd/dns/record-set/list/list_test.go index d41e1f304..122a2b29d 100644 --- a/internal/cmd/dns/record-set/list/list_test.go +++ b/internal/cmd/dns/record-set/list/list_test.go @@ -11,6 +11,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -214,7 +215,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -518,7 +519,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.recordSets); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/record-set/record_set.go b/internal/cmd/dns/record-set/record_set.go index 698750f4b..d00152da0 100644 --- a/internal/cmd/dns/record-set/record_set.go +++ b/internal/cmd/dns/record-set/record_set.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/dns/record-set/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/record-set/list" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/record-set/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "record-set", Short: "Provides functionality for DNS record set", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/dns/record-set/update/update.go b/internal/cmd/dns/record-set/update/update.go index 2b3d258aa..6d2a7ea06 100644 --- a/internal/cmd/dns/record-set/update/update.go +++ b/internal/cmd/dns/record-set/update/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -42,7 +43,7 @@ type inputModel struct { Type *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", recordSetIdArg), Short: "Updates a DNS record set", @@ -55,32 +56,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) if err != nil { - p.Debug(print.ErrorLevel, "get zone name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) zoneLabel = model.ZoneId } recordSetLabel, err := dnsUtils.GetRecordSetName(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId) if err != nil { - p.Debug(print.ErrorLevel, "get record set name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get record set name: %v", err) recordSetLabel = model.RecordSetId } typeLabel, err := dnsUtils.GetRecordSetType(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId) if err != nil { - p.Debug(print.ErrorLevel, "get record set type: %v", err) + params.Printer.Debug(print.ErrorLevel, "get record set type: %v", err) } model.Type = typeLabel @@ -93,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update record set %s of zone %s?", recordSetLabel, zoneLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -108,7 +109,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating record set") _, err = wait.PartialUpdateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx) if err != nil { @@ -121,7 +122,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s record set %s of zone %s\n", operationState, recordSetLabel, zoneLabel) + params.Printer.Info("%s record set %s of zone %s\n", operationState, recordSetLabel, zoneLabel) return nil }, } diff --git a/internal/cmd/dns/record-set/update/update_test.go b/internal/cmd/dns/record-set/update/update_test.go index 9b07ffabb..99e32d0f9 100644 --- a/internal/cmd/dns/record-set/update/update_test.go +++ b/internal/cmd/dns/record-set/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -253,7 +254,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index a7a4e42a0..1894b2291 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -39,7 +40,7 @@ type inputModel struct { ZoneId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("clone %s", zoneIdArg), Short: "Clones a DNS zone", @@ -58,26 +59,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) if err != nil { - p.Debug(print.ErrorLevel, "get zone name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) zoneLabel = model.ZoneId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to clone the zone %q?", zoneLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -93,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Cloning zone") _, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx) if err != nil { @@ -102,7 +103,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, zoneLabel, resp) + return outputResult(params.Printer, model, zoneLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/dns/zone/clone/clone_test.go b/internal/cmd/dns/zone/clone/clone_test.go index ea4f0621b..01f738f3a 100644 --- a/internal/cmd/dns/zone/clone/clone_test.go +++ b/internal/cmd/dns/zone/clone/clone_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -169,7 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -291,7 +292,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index fadfbd183..d23d35f39 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -55,7 +56,7 @@ type inputModel struct { ContactEmail *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a DNS zone", @@ -71,26 +72,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a zone for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -106,7 +107,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating zone") _, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx) if err != nil { @@ -115,7 +116,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(params.Printer, model, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/dns/zone/create/create_test.go b/internal/cmd/dns/zone/create/create_test.go index 5bcc8728a..39412b8ac 100644 --- a/internal/cmd/dns/zone/create/create_test.go +++ b/internal/cmd/dns/zone/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -216,7 +217,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -339,7 +340,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/zone/delete/delete.go b/internal/cmd/dns/zone/delete/delete.go index 2ad4373dd..8c5b01bd9 100644 --- a/internal/cmd/dns/zone/delete/delete.go +++ b/internal/cmd/dns/zone/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ZoneId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", zoneIdArg), Short: "Deletes a DNS zone", @@ -41,25 +42,25 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) if err != nil { - p.Debug(print.ErrorLevel, "get zone name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) zoneLabel = model.ZoneId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete zone %q? (This cannot be undone)", zoneLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting zone") _, err = wait.DeleteZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx) if err != nil { @@ -90,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s zone %s\n", operationState, zoneLabel) + params.Printer.Info("%s zone %s\n", operationState, zoneLabel) return nil }, } diff --git a/internal/cmd/dns/zone/delete/delete_test.go b/internal/cmd/dns/zone/delete/delete_test.go index 38c534910..77cb37649 100644 --- a/internal/cmd/dns/zone/delete/delete_test.go +++ b/internal/cmd/dns/zone/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/dns/zone/describe/describe.go b/internal/cmd/dns/zone/describe/describe.go index bd6ada66d..b97ba0445 100644 --- a/internal/cmd/dns/zone/describe/describe.go +++ b/internal/cmd/dns/zone/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ZoneId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", zoneIdArg), Short: "Shows details of a DNS zone", @@ -44,12 +45,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -62,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } zone := resp.Zone - return outputResult(p, model.OutputFormat, zone) + return outputResult(params.Printer, model.OutputFormat, zone) }, } return cmd diff --git a/internal/cmd/dns/zone/describe/describe_test.go b/internal/cmd/dns/zone/describe/describe_test.go index e97810889..ed58cbb14 100644 --- a/internal/cmd/dns/zone/describe/describe_test.go +++ b/internal/cmd/dns/zone/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/dns" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -242,7 +243,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.zone); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index 73239b2c3..017a171df 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -49,7 +50,7 @@ type inputModel struct { PageSize int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists DNS zones", @@ -71,13 +72,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -88,16 +89,16 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } if len(zones) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No zones found for project %q matching the criteria\n", projectLabel) + params.Printer.Info("No zones found for project %q matching the criteria\n", projectLabel) return nil } - return outputResult(p, model.OutputFormat, zones) + return outputResult(params.Printer, model.OutputFormat, zones) }, } configureFlags(cmd) diff --git a/internal/cmd/dns/zone/list/list_test.go b/internal/cmd/dns/zone/list/list_test.go index d96b980d7..844c2afa6 100644 --- a/internal/cmd/dns/zone/list/list_test.go +++ b/internal/cmd/dns/zone/list/list_test.go @@ -11,6 +11,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -209,7 +210,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -512,7 +513,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.zones); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/zone/update/update.go b/internal/cmd/dns/zone/update/update.go index 0e0a6b628..09c4036fd 100644 --- a/internal/cmd/dns/zone/update/update.go +++ b/internal/cmd/dns/zone/update/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -50,7 +51,7 @@ type inputModel struct { ContactEmail *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", zoneIdArg), Short: "Updates a DNS zone", @@ -63,26 +64,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) if err != nil { - p.Debug(print.ErrorLevel, "get zone name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) zoneLabel = model.ZoneId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update zone %s?", zoneLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -100,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating zone") _, err = wait.PartialUpdateZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx) if err != nil { @@ -113,7 +114,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s zone %s\n", operationState, zoneLabel) + params.Printer.Info("%s zone %s\n", operationState, zoneLabel) return nil }, } diff --git a/internal/cmd/dns/zone/update/update_test.go b/internal/cmd/dns/zone/update/update_test.go index 82222ad5d..adea3637d 100644 --- a/internal/cmd/dns/zone/update/update_test.go +++ b/internal/cmd/dns/zone/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -246,7 +247,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/dns/zone/zone.go b/internal/cmd/dns/zone/zone.go index 77247e3c4..b81a143ff 100644 --- a/internal/cmd/dns/zone/zone.go +++ b/internal/cmd/dns/zone/zone.go @@ -7,14 +7,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/list" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "zone", Short: "Provides functionality for DNS zones", @@ -22,15 +22,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(clone.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(clone.NewCmd(params)) } diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index b29048efb..704872c11 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -13,6 +13,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -81,7 +82,7 @@ type inputModel struct { NoProgressIndicator *bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates images", @@ -99,13 +100,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) (err error) { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -123,7 +124,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create the image %q?", model.Name) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -141,11 +142,11 @@ func NewCmd(p *print.Printer) *cobra.Command { if !ok { return fmt.Errorf("create image: no upload URL has been provided") } - if err := uploadAsync(ctx, p, model, file, url); err != nil { + if err := uploadAsync(ctx, params.Printer, model, file, url); err != nil { return err } - if err := outputResult(p, model, result); err != nil { + if err := outputResult(params.Printer, model, result); err != nil { return err } diff --git a/internal/cmd/image/create/create_test.go b/internal/cmd/image/create/create_test.go index 262dc029e..cdf15ce81 100644 --- a/internal/cmd/image/create/create_test.go +++ b/internal/cmd/image/create/create_test.go @@ -9,6 +9,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -273,7 +274,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -422,7 +423,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/image/delete/delete.go b/internal/cmd/image/delete/delete.go index 57ae4f026..456867bdd 100644 --- a/internal/cmd/image/delete/delete.go +++ b/internal/cmd/image/delete/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -24,7 +25,7 @@ type inputModel struct { const imageIdArg = "IMAGE_ID" -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", imageIdArg), Short: "Deletes an image", @@ -35,26 +36,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } imageName, err := iaasUtils.GetImageName(ctx, apiClient, model.ProjectId, model.ImageId) if err != nil { - p.Debug(print.ErrorLevel, "get image name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get image name: %v", err) imageName = model.ImageId } else if imageName == "" { imageName = model.ImageId @@ -62,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete the image %q for %q?", imageName, projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err := request.Execute(); err != nil { return fmt.Errorf("delete image: %w", err) } - p.Info("Deleted image %q for %q\n", imageName, projectLabel) + params.Printer.Info("Deleted image %q for %q\n", imageName, projectLabel) return nil }, diff --git a/internal/cmd/image/delete/delete_test.go b/internal/cmd/image/delete/delete_test.go index 1fa1ed5bc..93b2a656a 100644 --- a/internal/cmd/image/delete/delete_test.go +++ b/internal/cmd/image/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -105,7 +106,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/image/describe/describe.go b/internal/cmd/image/describe/describe.go index 20ab802fc..5c0b8a824 100644 --- a/internal/cmd/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { const imageIdArg = "IMAGE_ID" -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", imageIdArg), Short: "Describes image", @@ -37,13 +38,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -56,7 +57,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get image: %w", err) } - if err := outputResult(p, model.OutputFormat, image); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, image); err != nil { return err } diff --git a/internal/cmd/image/describe/describe_test.go b/internal/cmd/image/describe/describe_test.go index 036648fee..a5e421a9d 100644 --- a/internal/cmd/image/describe/describe_test.go +++ b/internal/cmd/image/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -217,7 +218,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/image/image.go b/internal/cmd/image/image.go index 899a62ce9..b722f2b91 100644 --- a/internal/cmd/image/image.go +++ b/internal/cmd/image/image.go @@ -6,15 +6,15 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/image/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/image/list" "github.com/stackitcloud/stackit-cli/internal/cmd/image/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "image", Short: "Manage server images", @@ -22,16 +22,16 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand( - create.NewCmd(p), - list.NewCmd(p), - delete.NewCmd(p), - describe.NewCmd(p), - update.NewCmd(p), + create.NewCmd(params), + list.NewCmd(params), + delete.NewCmd(params), + describe.NewCmd(params), + update.NewCmd(params), ) } diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index 47779fb83..eff221cba 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ const ( limitFlag = "limit" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists images", @@ -53,20 +54,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId @@ -81,12 +82,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if items := response.GetItems(); len(items) == 0 { - p.Info("No images found for project %q", projectLabel) + params.Printer.Info("No images found for project %q", projectLabel) } else { if model.Limit != nil && len(items) > int(*model.Limit) { items = (items)[:*model.Limit] } - if err := outputResult(p, model.OutputFormat, items); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, items); err != nil { return fmt.Errorf("output images: %w", err) } } diff --git a/internal/cmd/image/list/list_test.go b/internal/cmd/image/list/list_test.go index 49a27a16e..c357d3bc1 100644 --- a/internal/cmd/image/list/list_test.go +++ b/internal/cmd/image/list/list_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -124,7 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -239,7 +240,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index 8e6a8a2dd..e123d4fe1 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -101,7 +102,7 @@ const ( protectedFlag = "protected" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", imageIdArg), Short: "Updates an image", @@ -113,26 +114,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } imageLabel, err := iaasUtils.GetImageName(ctx, apiClient, model.ProjectId, model.Id) if err != nil { - p.Debug(print.WarningLevel, "cannot retrieve image name: %v", err) + params.Printer.Debug(print.WarningLevel, "cannot retrieve image name: %v", err) imageLabel = model.Id } else if imageLabel == "" { imageLabel = model.Id @@ -140,7 +141,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update the image %q?", imageLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -153,7 +154,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("update image: %w", err) } - p.Info("Updated image \"%v\" for %q\n", utils.PtrString(resp.Name), projectLabel) + params.Printer.Info("Updated image \"%v\" for %q\n", utils.PtrString(resp.Name), projectLabel) return nil }, diff --git a/internal/cmd/image/update/update_test.go b/internal/cmd/image/update/update_test.go index b08d3ceca..bb313b3c2 100644 --- a/internal/cmd/image/update/update_test.go +++ b/internal/cmd/image/update/update_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -302,7 +303,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } diff --git a/internal/cmd/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go index 0c96810ba..b59fe4fb0 100644 --- a/internal/cmd/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -30,7 +31,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a key pair", @@ -56,20 +57,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := "Are your sure you want to create a key pair?" - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create key pair: %w", err) } - return outputResult(p, model.GlobalFlagModel.OutputFormat, resp) + return outputResult(params.Printer, model.GlobalFlagModel.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/key-pair/create/create_test.go b/internal/cmd/key-pair/create/create_test.go index f912892d5..32a0516b6 100644 --- a/internal/cmd/key-pair/create/create_test.go +++ b/internal/cmd/key-pair/create/create_test.go @@ -5,6 +5,7 @@ import ( "os" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -123,7 +124,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -224,7 +225,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.item); (err != nil) != tt.wantErr { diff --git a/internal/cmd/key-pair/delete/delete.go b/internal/cmd/key-pair/delete/delete.go index ba9b5a9ce..8bccdd45d 100644 --- a/internal/cmd/key-pair/delete/delete.go +++ b/internal/cmd/key-pair/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -23,7 +24,7 @@ type inputModel struct { KeyPairName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", keyPairNameArg), Short: "Deletes a key pair", @@ -37,20 +38,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete key pair %q?", model.KeyPairName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete key pair: %w", err) } - p.Info("Deleted key pair %q\n", model.KeyPairName) + params.Printer.Info("Deleted key pair %q\n", model.KeyPairName) return nil }, diff --git a/internal/cmd/key-pair/delete/delete_test.go b/internal/cmd/key-pair/delete/delete_test.go index cfbcd29e8..c5c8dc913 100644 --- a/internal/cmd/key-pair/delete/delete_test.go +++ b/internal/cmd/key-pair/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -96,7 +97,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/key-pair/describe/describe.go b/internal/cmd/key-pair/describe/describe.go index f4ee01f94..b355e7433 100644 --- a/internal/cmd/key-pair/describe/describe.go +++ b/internal/cmd/key-pair/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -35,7 +36,7 @@ type inputModel struct { PublicKey bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", keyPairNameArg), Short: "Describes a key pair", @@ -53,13 +54,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -72,9 +73,9 @@ func NewCmd(p *print.Printer) *cobra.Command { } if keypair := resp; keypair != nil { - return outputResult(p, model.OutputFormat, model.PublicKey, *keypair) + return outputResult(params.Printer, model.OutputFormat, model.PublicKey, *keypair) } - p.Outputln("No keypair found.") + params.Printer.Outputln("No keypair found.") return nil }, } diff --git a/internal/cmd/key-pair/describe/describe_test.go b/internal/cmd/key-pair/describe/describe_test.go index 46374b3c8..c3dd4ffaa 100644 --- a/internal/cmd/key-pair/describe/describe_test.go +++ b/internal/cmd/key-pair/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -108,7 +109,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -209,7 +210,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.showOnlyPublicKey, tt.args.keyPair); (err != nil) != tt.wantErr { diff --git a/internal/cmd/key-pair/key-pair.go b/internal/cmd/key-pair/key-pair.go index 90bbd648b..44cc1fef8 100644 --- a/internal/cmd/key-pair/key-pair.go +++ b/internal/cmd/key-pair/key-pair.go @@ -8,11 +8,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/list" "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/update" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "key-pair", Short: "Provides functionality for SSH key pairs", @@ -20,14 +20,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: cobra.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/key-pair/list/list.go b/internal/cmd/key-pair/list/list.go index 8685edb36..980625695 100644 --- a/internal/cmd/key-pair/list/list.go +++ b/internal/cmd/key-pair/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -33,7 +34,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all key pairs", @@ -59,13 +60,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - p.Info("No key pairs found\n") + params.Printer.Info("No key pairs found\n") return nil } @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/key-pair/list/list_test.go b/internal/cmd/key-pair/list/list_test.go index 8fa0a948f..6679cee0d 100644 --- a/internal/cmd/key-pair/list/list_test.go +++ b/internal/cmd/key-pair/list/list_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -116,7 +117,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -212,7 +213,7 @@ func Test_outputResult(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) if err := outputResult(p, tt.args.outputFormat, tt.args.keyPairs); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) diff --git a/internal/cmd/key-pair/update/update.go b/internal/cmd/key-pair/update/update.go index 1a64875b5..3af038018 100644 --- a/internal/cmd/key-pair/update/update.go +++ b/internal/cmd/key-pair/update/update.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -29,7 +30,7 @@ type inputModel struct { KeyPairName *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", keyPairNameArg), Short: "Updates a key pair", @@ -43,17 +44,17 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model := parseInput(p, cmd, args) + model := parseInput(params.Printer, cmd, args) // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update key pair %q?", *model.KeyPairName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return fmt.Errorf("update key pair: %w", err) } @@ -69,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("response is nil") } - return outputResult(p, model, *resp) + return outputResult(params.Printer, model, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/key-pair/update/update_test.go b/internal/cmd/key-pair/update/update_test.go index 5743e2d60..2f5432deb 100644 --- a/internal/cmd/key-pair/update/update_test.go +++ b/internal/cmd/key-pair/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -109,7 +110,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -208,7 +209,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.keyPair); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index a0600f66d..541293bc2 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ var ( xRequestId = uuid.NewString() ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Load Balancer", @@ -59,26 +60,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a load balancer for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -93,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating load balancer") _, err = wait.CreateLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *model.Payload.Name).WaitWithContext(ctx) if err != nil { @@ -106,7 +107,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s load balancer with name %q \n", operationState, utils.PtrString(model.Payload.Name)) + params.Printer.Outputf("%s load balancer with name %q \n", operationState, utils.PtrString(model.Payload.Name)) return nil }, } diff --git a/internal/cmd/load-balancer/create/create_test.go b/internal/cmd/load-balancer/create/create_test.go index da7bfce83..eca1281a8 100644 --- a/internal/cmd/load-balancer/create/create_test.go +++ b/internal/cmd/load-balancer/create/create_test.go @@ -6,6 +6,7 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -277,7 +278,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/load-balancer/delete/delete.go b/internal/cmd/load-balancer/delete/delete.go index c2410db74..d5f3f6c75 100644 --- a/internal/cmd/load-balancer/delete/delete.go +++ b/internal/cmd/load-balancer/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { LoadBalancerName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", loadBalancerNameArg), Short: "Deletes a Load Balancer", @@ -39,19 +40,19 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete load balancer %q? (This cannot be undone)", model.LoadBalancerName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting load balancer") _, err = wait.DeleteLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.LoadBalancerName).WaitWithContext(ctx) if err != nil { @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s load balancer %q\n", operationState, model.LoadBalancerName) + params.Printer.Info("%s load balancer %q\n", operationState, model.LoadBalancerName) return nil }, } diff --git a/internal/cmd/load-balancer/delete/delete_test.go b/internal/cmd/load-balancer/delete/delete_test.go index 621113c56..17cca82cb 100644 --- a/internal/cmd/load-balancer/delete/delete_test.go +++ b/internal/cmd/load-balancer/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index 603bfd185..fe8669864 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { LoadBalancerName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", loadBalancerNameArg), Short: "Shows details of a Load Balancer", @@ -45,12 +46,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -62,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read load balancer: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/load-balancer/describe/describe_test.go b/internal/cmd/load-balancer/describe/describe_test.go index 821f942b7..2aebb5e61 100644 --- a/internal/cmd/load-balancer/describe/describe_test.go +++ b/internal/cmd/load-balancer/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -234,7 +235,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.loadBalancer); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index ba14de569..2fccfb37a 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -109,7 +110,7 @@ var ( } ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "generate-payload", Short: "Generates a payload to create/update a Load Balancer", @@ -135,20 +136,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if model.LoadBalancerName == nil { createPayload := DefaultCreateLoadBalancerPayload - return outputCreateResult(p, model.FilePath, &createPayload) + return outputCreateResult(params.Printer, model.FilePath, &createPayload) } req := buildRequest(ctx, model, apiClient) @@ -168,7 +169,7 @@ func NewCmd(p *print.Printer) *cobra.Command { TargetPools: resp.TargetPools, Version: resp.Version, } - return outputUpdateResult(p, model.FilePath, updatePayload) + return outputUpdateResult(params.Printer, model.FilePath, updatePayload) }, } configureFlags(cmd) diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go index 0e2ee4beb..5943215b8 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -132,7 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -337,7 +338,7 @@ func TestOutputCreateResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputCreateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { @@ -371,7 +372,7 @@ func TestOutputUpdateResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputUpdateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index a9611e137..5d23c5d2a 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Load Balancers", @@ -49,13 +50,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -68,12 +69,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.LoadBalancers == nil || (resp.LoadBalancers != nil && len(*resp.LoadBalancers) == 0) { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No load balancers found for project %q\n", projectLabel) + params.Printer.Info("No load balancers found for project %q\n", projectLabel) return nil } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { loadBalancers = loadBalancers[:*model.Limit] } - return outputResult(p, model.OutputFormat, loadBalancers) + return outputResult(params.Printer, model.OutputFormat, loadBalancers) }, } diff --git a/internal/cmd/load-balancer/list/list_test.go b/internal/cmd/load-balancer/list/list_test.go index d0210b9cb..f43d4ae62 100644 --- a/internal/cmd/load-balancer/list/list_test.go +++ b/internal/cmd/load-balancer/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -116,7 +117,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.loadBalancers); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/load_balancer.go b/internal/cmd/load-balancer/load_balancer.go index c6f6be2f5..4a2876453 100644 --- a/internal/cmd/load-balancer/load_balancer.go +++ b/internal/cmd/load-balancer/load_balancer.go @@ -10,15 +10,15 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/quota" targetpool "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/target-pool" "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "load-balancer", Aliases: []string{"lb"}, @@ -27,18 +27,18 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(generatepayload.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(quota.NewCmd(p)) - cmd.AddCommand(observabilitycredentials.NewCmd(p)) - cmd.AddCommand(targetpool.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(generatepayload.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(quota.NewCmd(params)) + cmd.AddCommand(observabilitycredentials.NewCmd(params)) + cmd.AddCommand(targetpool.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index a75b5e064..abbbd36a0 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Password *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "add", Short: "Adds observability credentials to Load Balancer", @@ -50,26 +51,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } // Prompt for password if not passed in as a flag if model.Password == nil { - pwd, err := p.PromptForPassword("Enter user password: ") + pwd, err := params.Printer.PromptForPassword("Enter user password: ") if err != nil { return fmt.Errorf("prompt for password: %w", err) } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to add observability credentials for Load Balancer on project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("add Load Balancer observability credentials: %w", err) } - return outputResult(p, model.OutputFormat, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/load-balancer/observability-credentials/add/add_test.go b/internal/cmd/load-balancer/observability-credentials/add/add_test.go index 57557613a..5ee5523f8 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add_test.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -125,7 +126,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -229,7 +230,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.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.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go index 28b560b2a..e69b3ae98 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -21,7 +22,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "cleanup", Short: "Deletes observability credentials unused by any Load Balancer", @@ -34,20 +35,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if len(credentials) == 0 { - p.Info("No unused observability credentials found on project %q\n", projectLabel) + params.Printer.Info("No unused observability credentials found on project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { prompt += fmt.Sprintf(" - %s (username: %q)\n", name, username) } prompt += fmt.Sprintf("Are you sure you want to delete unused observability credentials on project %q? (This cannot be undone)", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -100,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - p.Info("Deleted unused Load Balancer observability credentials on project %q\n", projectLabel) + params.Printer.Info("Deleted unused Load Balancer observability credentials on project %q\n", projectLabel) return nil }, } diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go index ae7b8e3c4..7154b55ee 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -116,7 +117,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete.go b/internal/cmd/load-balancer/observability-credentials/delete/delete.go index 73c9db46d..12b260489 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { CredentialsRef string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsRefArg), Short: "Deletes observability credentials for Load Balancer", @@ -39,32 +40,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } credentialsLabel, err := loadbalancerUtils.GetCredentialsDisplayName(ctx, apiClient, model.ProjectId, model.Region, model.CredentialsRef) if err != nil { - p.Debug(print.ErrorLevel, "get observability credentials display name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get observability credentials display name: %v", err) credentialsLabel = model.CredentialsRef } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete observability credentials %q on project %q?(This cannot be undone)", credentialsLabel, projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Load Balancer observability credentials: %w", err) } - p.Info("Deleted observability credentials %q on project %q\n", credentialsLabel, projectLabel) + params.Printer.Info("Deleted observability credentials %q on project %q\n", credentialsLabel, projectLabel) return nil }, } diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go b/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go index d4f22f799..4730f6a31 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index 9f622f750..a09a94685 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { CredentialsRef string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsRefArg), Short: "Shows details of observability credentials for Load Balancer", @@ -41,13 +42,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -59,7 +60,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe Load Balancer observability credentials: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go index a67979219..55335f68b 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -135,7 +136,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -245,7 +246,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 87e149053..92dcb9602 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Unused bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists observability credentials for Load Balancer", @@ -60,20 +61,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } @@ -105,7 +106,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } else if model.Unused { opLabel += "unused" } - p.Info("%s observability credentials found for Load Balancer on project %q\n", opLabel, projectLabel) + params.Printer.Info("%s observability credentials found for Load Balancer on project %q\n", opLabel, projectLabel) return nil } @@ -113,7 +114,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentials) }, } configureFlags(cmd) diff --git a/internal/cmd/load-balancer/observability-credentials/list/list_test.go b/internal/cmd/load-balancer/observability-credentials/list/list_test.go index ddf04272e..00d107c2e 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list_test.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" lbUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils" @@ -145,7 +146,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -297,7 +298,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/observability-credentials/observability-credentials.go b/internal/cmd/load-balancer/observability-credentials/observability-credentials.go index 390b83caf..03613a8de 100644 --- a/internal/cmd/load-balancer/observability-credentials/observability-credentials.go +++ b/internal/cmd/load-balancer/observability-credentials/observability-credentials.go @@ -7,14 +7,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/observability-credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/observability-credentials/list" "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/observability-credentials/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "observability-credentials", Short: "Provides functionality for Load Balancer observability credentials", @@ -23,15 +23,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Aliases: []string{"credentials"}, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(add.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(cleanup.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(add.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(cleanup.NewCmd(params)) } diff --git a/internal/cmd/load-balancer/observability-credentials/update/update.go b/internal/cmd/load-balancer/observability-credentials/update/update.go index 4c76da9f9..942c20131 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -45,7 +46,7 @@ type inputModel struct { Password *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", credentialsRefArg), Short: "Updates observability credentials for Load Balancer", @@ -61,32 +62,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } credentialsLabel, err := loadBalancerUtils.GetCredentialsDisplayName(ctx, apiClient, model.ProjectId, model.Region, model.CredentialsRef) if err != nil { - p.Debug(print.ErrorLevel, "get credentials display name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials display name: %v", err) credentialsLabel = model.CredentialsRef } // Prompt for password if not passed in as a flag if model.Password == nil { - pwd, err := p.PromptForPassword("Enter new password: ") + pwd, err := params.Printer.PromptForPassword("Enter new password: ") if err != nil { return fmt.Errorf("prompt for password: %w", err) } @@ -95,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update observability credentials %q for Load Balancer on project %q?", credentialsLabel, projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -112,7 +113,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update Load Balancer observability credentials: %w", err) } - p.Info("Updated observability credentials %q for Load Balancer on project %q\n", credentialsLabel, projectLabel) + params.Printer.Info("Updated observability credentials %q for Load Balancer on project %q\n", credentialsLabel, projectLabel) return nil }, } diff --git a/internal/cmd/load-balancer/observability-credentials/update/update_test.go b/internal/cmd/load-balancer/observability-credentials/update/update_test.go index 87677fa86..5aa4faa50 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update_test.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -180,7 +181,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index 9c2fb2840..fdb173fb0 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -22,7 +23,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "quota", Short: "Shows the configured Load Balancer quota", @@ -35,12 +36,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -52,7 +53,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get load balancer quota: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/load-balancer/quota/quota_test.go b/internal/cmd/load-balancer/quota/quota_test.go index e1ba5a893..16c14e857 100644 --- a/internal/cmd/load-balancer/quota/quota_test.go +++ b/internal/cmd/load-balancer/quota/quota_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -94,7 +95,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -194,7 +195,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.quota); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target.go b/internal/cmd/load-balancer/target-pool/add-target/add_target.go index 139dfda26..5dec7bfca 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { IP string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("add-target %s", ipArg), Short: "Adds a target to a target pool", @@ -49,20 +50,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to add a target with IP %q to target pool %q of load balancer %q?", model.IP, model.TargetPoolName, model.LBName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("add target to target pool: %w", err) } - p.Info("Added target to target pool of load balancer %q\n", model.LBName) + params.Printer.Info("Added target to target pool of load balancer %q\n", model.LBName) return nil }, } diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go b/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go index 6fd3da6c9..61d2fe4a6 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -260,7 +261,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index a4ffa6d65..b9699e7c0 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -9,6 +9,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { LBName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", targetPoolNameArg), Short: "Shows details of a target pool in a Load Balancer", @@ -50,12 +51,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { listener := lbUtils.FindLoadBalancerListenerByTargetPool(*resp.Listeners, *targetPool.Name) - return outputResult(p, model.OutputFormat, *targetPool, listener) + return outputResult(params.Printer, model.OutputFormat, *targetPool, listener) }, } configureFlags(cmd) diff --git a/internal/cmd/load-balancer/target-pool/describe/describe_test.go b/internal/cmd/load-balancer/target-pool/describe/describe_test.go index e1acadb53..d59a0fe6b 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe_test.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { @@ -244,7 +245,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.targetPool, tt.args.listener); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go index 2fbb0c447..5d8297665 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { IP string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("remove-target %s", ipArg), Short: "Removes a target from a target pool", @@ -45,26 +46,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } targetLabel, err := utils.GetTargetName(ctx, apiClient, model.ProjectId, model.Region, model.LBName, model.TargetPoolName, model.IP) if err != nil { - p.Debug(print.ErrorLevel, "get target name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get target name: %v", err) targetLabel = model.IP } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to remove target %q from target pool %q of load balancer %q?", targetLabel, model.TargetPoolName, model.LBName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("remove target from target pool: %w", err) } - p.Info("Removed target from target pool of load balancer %q\n", model.LBName) + params.Printer.Info("Removed target from target pool of load balancer %q\n", model.LBName) return nil }, } diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go index e961447d2..d945f3c8e 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -249,7 +250,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { diff --git a/internal/cmd/load-balancer/target-pool/target_pool.go b/internal/cmd/load-balancer/target-pool/target_pool.go index 78a8d50c7..da2e0f7fa 100644 --- a/internal/cmd/load-balancer/target-pool/target_pool.go +++ b/internal/cmd/load-balancer/target-pool/target_pool.go @@ -4,14 +4,14 @@ import ( addtarget "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/target-pool/add-target" "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/target-pool/describe" removetarget "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/target-pool/remove-target" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "target-pool", Short: "Provides functionality for target pools", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(addtarget.NewCmd(p)) - cmd.AddCommand(removetarget.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(addtarget.NewCmd(params)) + cmd.AddCommand(removetarget.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) } diff --git a/internal/cmd/load-balancer/update/update.go b/internal/cmd/load-balancer/update/update.go index 154e9d992..ab2a82d88 100644 --- a/internal/cmd/load-balancer/update/update.go +++ b/internal/cmd/load-balancer/update/update.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Payload loadbalancer.UpdateLoadBalancerPayload } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", loadBalancerNameArg), Short: "Updates a Load Balancer", @@ -53,20 +54,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update load balancer %q?", model.LoadBalancerName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // The API has no status to wait on, so async mode is default - p.Info("Updated load balancer with name %q\n", model.LoadBalancerName) + params.Printer.Info("Updated load balancer with name %q\n", model.LoadBalancerName) return nil }, } diff --git a/internal/cmd/load-balancer/update/update_test.go b/internal/cmd/load-balancer/update/update_test.go index b6c998138..9d97f07fc 100644 --- a/internal/cmd/load-balancer/update/update_test.go +++ b/internal/cmd/load-balancer/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -300,7 +301,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 61df00f15..80783e6da 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for a LogMe instance", @@ -46,26 +47,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := logmeUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create LogMe credentials: %w", err) } - return outputResult(p, model.OutputFormat, model.ShowPassword, instanceLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.ShowPassword, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/logme/credentials/create/create_test.go b/internal/cmd/logme/credentials/create/create_test.go index 3ad8aec16..d577d1422 100644 --- a/internal/cmd/logme/credentials/create/create_test.go +++ b/internal/cmd/logme/credentials/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -227,7 +228,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/credentials/credentials.go b/internal/cmd/logme/credentials/credentials.go index 1b884797a..9f7cd2d7e 100644 --- a/internal/cmd/logme/credentials/credentials.go +++ b/internal/cmd/logme/credentials/credentials.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/logme/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/credentials/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for LogMe credentials", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/logme/credentials/delete/delete.go b/internal/cmd/logme/credentials/delete/delete.go index 2f884ac0e..2295be928 100644 --- a/internal/cmd/logme/credentials/delete/delete.go +++ b/internal/cmd/logme/credentials/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of a LogMe instance", @@ -43,32 +44,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := logmeUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } credentialsLabel, err := logmeUtils.GetCredentialsUsername(ctx, apiClient, model.ProjectId, model.InstanceId, model.CredentialsId) if err != nil { - p.Debug(print.ErrorLevel, "get credentials username: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials username: %v", err) credentialsLabel = model.CredentialsId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete LogMe credentials: %w", err) } - p.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) + params.Printer.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/logme/credentials/delete/delete_test.go b/internal/cmd/logme/credentials/delete/delete_test.go index ea6d637f2..96aff20b2 100644 --- a/internal/cmd/logme/credentials/delete/delete_test.go +++ b/internal/cmd/logme/credentials/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/logme/credentials/describe/describe.go b/internal/cmd/logme/credentials/describe/describe.go index 2a73c9a15..faf1537b6 100644 --- a/internal/cmd/logme/credentials/describe/describe.go +++ b/internal/cmd/logme/credentials/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of a LogMe instance", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe LogMe credentials: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/logme/credentials/describe/describe_test.go b/internal/cmd/logme/credentials/describe/describe_test.go index 3ef166834..ae7f38696 100644 --- a/internal/cmd/logme/credentials/describe/describe_test.go +++ b/internal/cmd/logme/credentials/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -268,7 +269,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index a149a6090..107824d39 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for a LogMe instance", @@ -51,13 +52,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -72,10 +73,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(credentials) == 0 { instanceLabel, err := logmeUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - p.Info("No credentials found for instance %q\n", instanceLabel) + params.Printer.Info("No credentials found for instance %q\n", instanceLabel) return nil } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentials) }, } configureFlags(cmd) diff --git a/internal/cmd/logme/credentials/list/list_test.go b/internal/cmd/logme/credentials/list/list_test.go index dd9b71e66..55c522bbf 100644 --- a/internal/cmd/logme/credentials/list/list_test.go +++ b/internal/cmd/logme/credentials/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -239,7 +240,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index df11b20a2..89f2d9dc0 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -55,7 +56,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a LogMe instance", @@ -74,26 +75,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a LogMe instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -116,7 +117,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -125,7 +126,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/logme/instance/create/create_test.go b/internal/cmd/logme/instance/create/create_test.go index ac8928edf..9f452d086 100644 --- a/internal/cmd/logme/instance/create/create_test.go +++ b/internal/cmd/logme/instance/create/create_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -262,7 +263,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -490,7 +491,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/instance/delete/delete.go b/internal/cmd/logme/instance/delete/delete.go index 315a2b3be..25693c798 100644 --- a/internal/cmd/logme/instance/delete/delete.go +++ b/internal/cmd/logme/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a LogMe instance", @@ -41,26 +42,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := logmeUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/logme/instance/delete/delete_test.go b/internal/cmd/logme/instance/delete/delete_test.go index 607bc9bd2..dde9637bb 100644 --- a/internal/cmd/logme/instance/delete/delete_test.go +++ b/internal/cmd/logme/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/logme/instance/describe/describe.go b/internal/cmd/logme/instance/describe/describe.go index d32944bdf..29b86a0a7 100644 --- a/internal/cmd/logme/instance/describe/describe.go +++ b/internal/cmd/logme/instance/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a LogMe instance", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read LogMe instance: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/logme/instance/describe/describe_test.go b/internal/cmd/logme/instance/describe/describe_test.go index 3cc0b5e38..00041b4a9 100644 --- a/internal/cmd/logme/instance/describe/describe_test.go +++ b/internal/cmd/logme/instance/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/instance/instance.go b/internal/cmd/logme/instance/instance.go index 534151d57..aa86b4f08 100644 --- a/internal/cmd/logme/instance/instance.go +++ b/internal/cmd/logme/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/logme/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/instance/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for LogMe instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index e59d09cb6..821727852 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all LogMe instances", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/logme/instance/list/list_test.go b/internal/cmd/logme/instance/list/list_test.go index 97df7394c..0168ee409 100644 --- a/internal/cmd/logme/instance/list/list_test.go +++ b/internal/cmd/logme/instance/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/instance/update/update.go b/internal/cmd/logme/instance/update/update.go index 08972358e..79802ee58 100644 --- a/internal/cmd/logme/instance/update/update.go +++ b/internal/cmd/logme/instance/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -55,7 +56,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a LogMe instance", @@ -71,26 +72,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := logmeUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -113,7 +114,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -126,7 +127,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/logme/instance/update/update_test.go b/internal/cmd/logme/instance/update/update_test.go index 4577de0ec..dc3518985 100644 --- a/internal/cmd/logme/instance/update/update_test.go +++ b/internal/cmd/logme/instance/update/update_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -267,7 +268,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/logme/logme.go b/internal/cmd/logme/logme.go index 9dc8b77fd..a4e3f4715 100644 --- a/internal/cmd/logme/logme.go +++ b/internal/cmd/logme/logme.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/logme/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/plans" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "logme", Short: "Provides functionality for LogMe", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(plans.NewCmd(p)) - cmd.AddCommand(credentials.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(plans.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) } diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index ccfdc098b..2eb665d7e 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all LogMe service plans", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No plans found for project %q\n", projectLabel) + params.Printer.Info("No plans found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(p, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, plans) }, } diff --git a/internal/cmd/logme/plans/plans_test.go b/internal/cmd/logme/plans/plans_test.go index bc8c78bb7..6feb2a2a5 100644 --- a/internal/cmd/logme/plans/plans_test.go +++ b/internal/cmd/logme/plans/plans_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 880444860..7e4a8a592 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for a MariaDB instance", @@ -47,26 +48,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mariadbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create MariaDB credentials: %w", err) } - return outputResult(p, model.OutputFormat, model.ShowPassword, instanceLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.ShowPassword, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/mariadb/credentials/create/create_test.go b/internal/cmd/mariadb/credentials/create/create_test.go index d3202e596..5516a2415 100644 --- a/internal/cmd/mariadb/credentials/create/create_test.go +++ b/internal/cmd/mariadb/credentials/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -228,7 +229,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/credentials/credentials.go b/internal/cmd/mariadb/credentials/credentials.go index f8fb1c5d2..e23c3887f 100644 --- a/internal/cmd/mariadb/credentials/credentials.go +++ b/internal/cmd/mariadb/credentials/credentials.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/credentials/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for MariaDB credentials", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/mariadb/credentials/delete/delete.go b/internal/cmd/mariadb/credentials/delete/delete.go index 4e8185624..5df7736dc 100644 --- a/internal/cmd/mariadb/credentials/delete/delete.go +++ b/internal/cmd/mariadb/credentials/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of a MariaDB instance", @@ -43,32 +44,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mariadbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } credentialsLabel, err := mariadbUtils.GetCredentialsUsername(ctx, apiClient, model.ProjectId, model.InstanceId, model.CredentialsId) if err != nil { - p.Debug(print.ErrorLevel, "get credentials username: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials username: %v", err) credentialsLabel = model.CredentialsId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete MariaDB credentials: %w", err) } - p.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) + params.Printer.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/mariadb/credentials/delete/delete_test.go b/internal/cmd/mariadb/credentials/delete/delete_test.go index c1b2560e5..81da9d7b3 100644 --- a/internal/cmd/mariadb/credentials/delete/delete_test.go +++ b/internal/cmd/mariadb/credentials/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/mariadb/credentials/describe/describe.go b/internal/cmd/mariadb/credentials/describe/describe.go index 8e3e3f869..c868a7d60 100644 --- a/internal/cmd/mariadb/credentials/describe/describe.go +++ b/internal/cmd/mariadb/credentials/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of a MariaDB instance", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe MariaDB credentials: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/mariadb/credentials/describe/describe_test.go b/internal/cmd/mariadb/credentials/describe/describe_test.go index f822d88f4..522049aec 100644 --- a/internal/cmd/mariadb/credentials/describe/describe_test.go +++ b/internal/cmd/mariadb/credentials/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -269,7 +270,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index b854d6c66..acb97d02f 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for a MariaDB instance", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,10 +72,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(credentials) == 0 { instanceLabel, err := mariadbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - p.Info("No credentials found for instance %q\n", instanceLabel) + params.Printer.Info("No credentials found for instance %q\n", instanceLabel) return nil } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentials) }, } configureFlags(cmd) diff --git a/internal/cmd/mariadb/credentials/list/list_test.go b/internal/cmd/mariadb/credentials/list/list_test.go index 978210a9f..c4fbce7b2 100644 --- a/internal/cmd/mariadb/credentials/list/list_test.go +++ b/internal/cmd/mariadb/credentials/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -240,7 +241,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index 3a2a4e4fb..dae8ad6b3 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -55,7 +56,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a MariaDB instance", @@ -74,26 +75,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a MariaDB instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -116,7 +117,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -125,7 +126,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/mariadb/instance/create/create_test.go b/internal/cmd/mariadb/instance/create/create_test.go index 0e797ff1e..33dedf860 100644 --- a/internal/cmd/mariadb/instance/create/create_test.go +++ b/internal/cmd/mariadb/instance/create/create_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -262,7 +263,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -491,7 +492,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/instance/delete/delete.go b/internal/cmd/mariadb/instance/delete/delete.go index e28fb3593..7b7b2d6e5 100644 --- a/internal/cmd/mariadb/instance/delete/delete.go +++ b/internal/cmd/mariadb/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a MariaDB instance", @@ -41,26 +42,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mariadbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/mariadb/instance/delete/delete_test.go b/internal/cmd/mariadb/instance/delete/delete_test.go index 4dbac6693..737f2affc 100644 --- a/internal/cmd/mariadb/instance/delete/delete_test.go +++ b/internal/cmd/mariadb/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/mariadb/instance/describe/describe.go b/internal/cmd/mariadb/instance/describe/describe.go index b3b8013a6..978cdcf24 100644 --- a/internal/cmd/mariadb/instance/describe/describe.go +++ b/internal/cmd/mariadb/instance/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a MariaDB instance", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read MariaDB instance: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/mariadb/instance/describe/describe_test.go b/internal/cmd/mariadb/instance/describe/describe_test.go index 555f7bcbf..3d5cc03ec 100644 --- a/internal/cmd/mariadb/instance/describe/describe_test.go +++ b/internal/cmd/mariadb/instance/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -242,7 +243,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/instance/instance.go b/internal/cmd/mariadb/instance/instance.go index 71e25309a..3b16f4864 100644 --- a/internal/cmd/mariadb/instance/instance.go +++ b/internal/cmd/mariadb/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/instance/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for MariaDB instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index 2b2dbe70c..3bba56507 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all MariaDB instances", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/mariadb/instance/list/list_test.go b/internal/cmd/mariadb/instance/list/list_test.go index a7b29714f..7f199d16c 100644 --- a/internal/cmd/mariadb/instance/list/list_test.go +++ b/internal/cmd/mariadb/instance/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -219,7 +220,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/instance/update/update.go b/internal/cmd/mariadb/instance/update/update.go index a2b70759e..80cabdac5 100644 --- a/internal/cmd/mariadb/instance/update/update.go +++ b/internal/cmd/mariadb/instance/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -53,7 +54,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a MariaDB instance", @@ -69,26 +70,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mariadbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -111,7 +112,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -124,7 +125,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/mariadb/instance/update/update_test.go b/internal/cmd/mariadb/instance/update/update_test.go index 514820867..5fb7369c5 100644 --- a/internal/cmd/mariadb/instance/update/update_test.go +++ b/internal/cmd/mariadb/instance/update/update_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -278,7 +279,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/mariadb/mariadb.go b/internal/cmd/mariadb/mariadb.go index 7058813f9..602949253 100644 --- a/internal/cmd/mariadb/mariadb.go +++ b/internal/cmd/mariadb/mariadb.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/plans" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "mariadb", Short: "Provides functionality for MariaDB", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(plans.NewCmd(p)) - cmd.AddCommand(credentials.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(plans.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) } diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index e4d3bf021..5b342f29e 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all MariaDB service plans", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No plans found for project %q\n", projectLabel) + params.Printer.Info("No plans found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(p, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, plans) }, } diff --git a/internal/cmd/mariadb/plans/plans_test.go b/internal/cmd/mariadb/plans/plans_test.go index 3d8f56a28..f80f6c9cd 100644 --- a/internal/cmd/mariadb/plans/plans_test.go +++ b/internal/cmd/mariadb/plans/plans_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -219,7 +220,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/backup.go b/internal/cmd/mongodbflex/backup/backup.go index 738363d78..af716446b 100644 --- a/internal/cmd/mongodbflex/backup/backup.go +++ b/internal/cmd/mongodbflex/backup/backup.go @@ -7,14 +7,14 @@ import ( restorejobs "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/backup/restore-jobs" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/backup/schedule" updateschedule "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/backup/update-schedule" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "backup", Short: "Provides functionality for MongoDB Flex instance backups", @@ -22,15 +22,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(updateschedule.NewCmd(p)) - cmd.AddCommand(schedule.NewCmd(p)) - cmd.AddCommand(restore.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(restorejobs.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(updateschedule.NewCmd(params)) + cmd.AddCommand(schedule.NewCmd(params)) + cmd.AddCommand(restore.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(restorejobs.NewCmd(params)) } diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index a30fb3f63..43e8a0b81 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { BackupId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupIdArg), Short: "Shows details of a backup for a MongoDB Flex instance", @@ -49,20 +50,20 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(backupIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongoUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } restoreJobState := mongoUtils.GetRestoreStatus(model.BackupId, restoreJobs) - return outputResult(p, model.OutputFormat, restoreJobState, *resp.Item) + return outputResult(params.Printer, model.OutputFormat, restoreJobState, *resp.Item) }, } configureFlags(cmd) diff --git a/internal/cmd/mongodbflex/backup/describe/describe_test.go b/internal/cmd/mongodbflex/backup/describe/describe_test.go index 0b761904d..914f27259 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe_test.go +++ b/internal/cmd/mongodbflex/backup/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -159,7 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -263,7 +264,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.restoreStatus, tt.args.backup); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index b145685fb..75ddca216 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all backups which are available for a MongoDB Flex instance", @@ -52,20 +53,20 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { backups = backups[:*model.Limit] } - return outputResult(p, model.OutputFormat, backups, restoreJobs) + return outputResult(params.Printer, model.OutputFormat, backups, restoreJobs) }, } diff --git a/internal/cmd/mongodbflex/backup/list/list_test.go b/internal/cmd/mongodbflex/backup/list/list_test.go index 362b35c78..3328c6030 100644 --- a/internal/cmd/mongodbflex/backup/list/list_test.go +++ b/internal/cmd/mongodbflex/backup/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -248,7 +249,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.backups, tt.args.restoreJobs); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index 30a48be34..7119dccbb 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "restore-jobs", Short: "Lists all restore jobs which have been run for a MongoDB Flex instance", @@ -51,20 +52,20 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { restoreJobs = restoreJobs[:*model.Limit] } - return outputResult(p, model.OutputFormat, restoreJobs) + return outputResult(params.Printer, model.OutputFormat, restoreJobs) }, } diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go index 5135be262..61f911ea7 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -239,7 +240,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.restoreJobs); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index c8de137fc..067c0e56e 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Timestamp string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "restore", Short: "Restores a MongoDB Flex instance from a backup", @@ -58,26 +59,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to restore MongoDB Flex instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -99,7 +100,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Restoring instance") _, err = wait.RestoreInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.BackupId).WaitWithContext(ctx) if err != nil { @@ -108,7 +109,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - p.Outputf("Restored instance %q with backup %q\n", model.InstanceId, model.BackupId) + params.Printer.Outputf("Restored instance %q with backup %q\n", model.InstanceId, model.BackupId) return nil } @@ -120,7 +121,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Cloning instance") _, err = wait.CloneInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -129,7 +130,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - p.Outputf("Cloned instance %q from backup with timestamp %q\n", model.InstanceId, model.Timestamp) + params.Printer.Outputf("Cloned instance %q from backup with timestamp %q\n", model.InstanceId, model.Timestamp) return nil }, } diff --git a/internal/cmd/mongodbflex/backup/restore/restore_test.go b/internal/cmd/mongodbflex/backup/restore/restore_test.go index 63e06d9af..bffa02934 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore_test.go +++ b/internal/cmd/mongodbflex/backup/restore/restore_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -170,7 +171,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index b21167724..55272a544 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "schedule", Short: "Shows details of the backup schedule and retention policy of a MongoDB Flex instance", @@ -44,12 +45,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -61,7 +62,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read MongoDB Flex instance: %w", err) } - return outputResult(p, model.OutputFormat, resp.Item) + return outputResult(params.Printer, model.OutputFormat, resp.Item) }, } configureFlags(cmd) diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go index 018cefc28..705bd7432 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go index 8f75c6964..d417ccbf4 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go @@ -6,6 +6,7 @@ import ( "strconv" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -46,7 +47,7 @@ type inputModel struct { MonthlySnapshotRetentionMonths *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update-schedule", Short: "Updates the backup schedule and retention policy for a MongoDB Flex instance", @@ -69,26 +70,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongoDBflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update backup schedule of instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index c6c4d3322..2b8905364 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -56,7 +57,7 @@ type inputModel struct { Type *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a MongoDB Flex instance", @@ -76,26 +77,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a MongoDB Flex instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -123,7 +124,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -132,7 +133,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/mongodbflex/instance/create/create_test.go b/internal/cmd/mongodbflex/instance/create/create_test.go index 23fa109b7..72ab744b7 100644 --- a/internal/cmd/mongodbflex/instance/create/create_test.go +++ b/internal/cmd/mongodbflex/instance/create/create_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -250,7 +251,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -573,7 +574,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.createInstanceResponse); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/instance/delete/delete.go b/internal/cmd/mongodbflex/instance/delete/delete.go index 237681df0..86653c5a3 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete.go +++ b/internal/cmd/mongodbflex/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a MongoDB Flex instance", @@ -41,26 +42,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/mongodbflex/instance/delete/delete_test.go b/internal/cmd/mongodbflex/instance/delete/delete_test.go index ec3913381..1c02e7f87 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete_test.go +++ b/internal/cmd/mongodbflex/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index 79ca55b64..2b64e3432 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a MongoDB Flex instance", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read MongoDB Flex instance: %w", err) } - return outputResult(p, model.OutputFormat, resp.Item) + return outputResult(params.Printer, model.OutputFormat, resp.Item) }, } return cmd diff --git a/internal/cmd/mongodbflex/instance/describe/describe_test.go b/internal/cmd/mongodbflex/instance/describe/describe_test.go index 1238f7bc0..c933d86e4 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe_test.go +++ b/internal/cmd/mongodbflex/instance/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/instance/instance.go b/internal/cmd/mongodbflex/instance/instance.go index 1a770bcc1..a4cc5b231 100644 --- a/internal/cmd/mongodbflex/instance/instance.go +++ b/internal/cmd/mongodbflex/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/instance/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for MongoDB Flex instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index 5b65f8d5e..a016550cc 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all MongoDB Flex instances", @@ -49,13 +50,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get MongoDB Flex instances: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } instances := *resp.Items @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/mongodbflex/instance/list/list_test.go b/internal/cmd/mongodbflex/instance/list/list_test.go index e6a9c1416..e8a95d34c 100644 --- a/internal/cmd/mongodbflex/instance/list/list_test.go +++ b/internal/cmd/mongodbflex/instance/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instanceList); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index 5f854005c..e1882bfd9 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -54,7 +55,7 @@ type inputModel struct { Type *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a MongoDB Flex instance", @@ -71,26 +72,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -109,7 +110,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -118,7 +119,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, instanceLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/mongodbflex/instance/update/update_test.go b/internal/cmd/mongodbflex/instance/update/update_test.go index a36f33454..0379f2c0f 100644 --- a/internal/cmd/mongodbflex/instance/update/update_test.go +++ b/internal/cmd/mongodbflex/instance/update/update_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -280,7 +281,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -617,7 +618,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/mongodbflex.go b/internal/cmd/mongodbflex/mongodbflex.go index e7373b9b9..50ba29f78 100644 --- a/internal/cmd/mongodbflex/mongodbflex.go +++ b/internal/cmd/mongodbflex/mongodbflex.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/options" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/user" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "mongodbflex", Short: "Provides functionality for MongoDB Flex", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(user.NewCmd(p)) - cmd.AddCommand(options.NewCmd(p)) - cmd.AddCommand(backup.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(user.NewCmd(params)) + cmd.AddCommand(options.NewCmd(params)) + cmd.AddCommand(backup.NewCmd(params)) } diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 82b43cbc5..92c6c55bb 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -45,7 +47,7 @@ type flavorStorages struct { Storages *mongodbflex.ListStoragesResponse `json:"storages"` } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "options", Short: "Lists MongoDB Flex options", @@ -64,19 +66,19 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } // Call API - err = buildAndExecuteRequest(ctx, p, model, apiClient) + err = buildAndExecuteRequest(ctx, params.Printer, model, apiClient) if err != nil { return fmt.Errorf("get MongoDB Flex options: %w", err) } diff --git a/internal/cmd/mongodbflex/options/options_test.go b/internal/cmd/mongodbflex/options/options_test.go index 9b48a710b..dc1eb60c8 100644 --- a/internal/cmd/mongodbflex/options/options_test.go +++ b/internal/cmd/mongodbflex/options/options_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -167,7 +168,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -291,7 +292,7 @@ func TestBuildAndExecuteRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := &print.Printer{} - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) p.Cmd = cmd client := &mongoDBFlexClientMocked{ listFlavorsFails: tt.listFlavorsFails, @@ -406,7 +407,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.inputModel, tt.args.flavors, tt.args.versions, tt.args.storages); (err != nil) != tt.wantErr { @@ -455,7 +456,7 @@ func TestOutputResultAsTable(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResultAsTable(p, tt.args.model, tt.args.options); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index be494fcdb..afc26fe76 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -39,7 +40,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a MongoDB Flex user", @@ -60,26 +61,26 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -93,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } user := resp.Item - return outputResult(p, model.OutputFormat, instanceLabel, user) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, user) }, } diff --git a/internal/cmd/mongodbflex/user/create/create_test.go b/internal/cmd/mongodbflex/user/create/create_test.go index 73f184a65..75e02fef0 100644 --- a/internal/cmd/mongodbflex/user/create/create_test.go +++ b/internal/cmd/mongodbflex/user/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -270,7 +271,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/delete/delete.go b/internal/cmd/mongodbflex/user/delete/delete.go index 7eec0fbd5..d57879062 100644 --- a/internal/cmd/mongodbflex/user/delete/delete.go +++ b/internal/cmd/mongodbflex/user/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", userIdArg), Short: "Deletes a MongoDB Flex user", @@ -47,32 +48,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, utils.ValidateUUID), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) if err != nil { - p.Debug(print.ErrorLevel, "get user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete MongoDB Flex user: %w", err) } - p.Info("Deleted user %q of instance %q\n", userLabel, instanceLabel) + params.Printer.Info("Deleted user %q of instance %q\n", userLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/mongodbflex/user/delete/delete_test.go b/internal/cmd/mongodbflex/user/delete/delete_test.go index 36e356790..b373f7f56 100644 --- a/internal/cmd/mongodbflex/user/delete/delete_test.go +++ b/internal/cmd/mongodbflex/user/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/mongodbflex/user/describe/describe.go b/internal/cmd/mongodbflex/user/describe/describe.go index b94f4b453..89f919f7b 100644 --- a/internal/cmd/mongodbflex/user/describe/describe.go +++ b/internal/cmd/mongodbflex/user/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", userIdArg), Short: "Shows details of a MongoDB Flex user", @@ -53,13 +54,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, utils.ValidateUUID), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get MongoDB Flex user: %w", err) } - return outputResult(p, model.OutputFormat, *resp.Item) + return outputResult(params.Printer, model.OutputFormat, *resp.Item) }, } diff --git a/internal/cmd/mongodbflex/user/describe/describe_test.go b/internal/cmd/mongodbflex/user/describe/describe_test.go index 7d5201075..c151b4da0 100644 --- a/internal/cmd/mongodbflex/user/describe/describe_test.go +++ b/internal/cmd/mongodbflex/user/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -268,7 +269,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instanceResponseUser); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index ae690568b..299319462 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all MongoDB Flex users of an instance", @@ -52,13 +53,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -72,10 +73,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if resp.Items == nil || len(*resp.Items) == 0 { instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } - p.Info("No users found for instance %q\n", instanceLabel) + params.Printer.Info("No users found for instance %q\n", instanceLabel) return nil } users := *resp.Items @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { users = users[:*model.Limit] } - return outputResult(p, model.OutputFormat, users) + return outputResult(params.Printer, model.OutputFormat, users) }, } diff --git a/internal/cmd/mongodbflex/user/list/list_test.go b/internal/cmd/mongodbflex/user/list/list_test.go index 8cc901aef..18e9325f5 100644 --- a/internal/cmd/mongodbflex/user/list/list_test.go +++ b/internal/cmd/mongodbflex/user/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -235,7 +236,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index 5541b89a3..72d7ad9d4 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reset-password %s", userIdArg), Short: "Resets the password of a MongoDB Flex user", @@ -49,32 +50,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, utils.ValidateUUID), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) if err != nil { - p.Debug(print.ErrorLevel, "get user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("reset MongoDB Flex user password: %w", err) } - return outputResult(p, model.OutputFormat, userLabel, instanceLabel, user) + return outputResult(params.Printer, model.OutputFormat, userLabel, instanceLabel, user) }, } diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go index 98abb2136..d86e57206 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -270,7 +271,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.userLabel, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/update/update.go b/internal/cmd/mongodbflex/user/update/update.go index ee2a9ea1d..3ebdf4e6d 100644 --- a/internal/cmd/mongodbflex/user/update/update.go +++ b/internal/cmd/mongodbflex/user/update/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", userIdArg), Short: "Updates a MongoDB Flex user", @@ -48,32 +49,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, utils.ValidateUUID), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) if err != nil { - p.Debug(print.ErrorLevel, "get user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update user %q of instance %q?", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -86,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update MongoDB Flex user: %w", err) } - p.Info("Updated user %q of instance %q\n", userLabel, instanceLabel) + params.Printer.Info("Updated user %q of instance %q\n", userLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/mongodbflex/user/update/update_test.go b/internal/cmd/mongodbflex/user/update/update_test.go index fc2872c2d..e4f74eb0f 100644 --- a/internal/cmd/mongodbflex/user/update/update_test.go +++ b/internal/cmd/mongodbflex/user/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -197,7 +198,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/mongodbflex/user/user.go b/internal/cmd/mongodbflex/user/user.go index 614b7c2f9..0e0600ed6 100644 --- a/internal/cmd/mongodbflex/user/user.go +++ b/internal/cmd/mongodbflex/user/user.go @@ -7,14 +7,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/user/list" resetpassword "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/user/reset-password" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/user/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "user", Short: "Provides functionality for MongoDB Flex users", @@ -22,15 +22,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(resetpassword.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(resetpassword.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index 4ce917af7..80c14dc37 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -45,7 +46,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a STACKIT Network Area (SNA)", @@ -71,34 +72,34 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } var orgLabel string - rmApiClient, err := rmClient.ConfigureClient(p) + rmApiClient, err := rmClient.ConfigureClient(params.Printer) if err == nil { orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) if err != nil { - p.Debug(print.ErrorLevel, "get organization name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get organization name: %v", err) orgLabel = *model.OrganizationId } else if orgLabel == "" { orgLabel = *model.OrganizationId } } else { - p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) + params.Printer.Debug(print.ErrorLevel, "configure resource manager client: %v", err) } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a network area for organization %q?", orgLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -111,7 +112,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create network area: %w", err) } - return outputResult(p, model.OutputFormat, orgLabel, resp) + return outputResult(params.Printer, model.OutputFormat, orgLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/create/create_test.go b/internal/cmd/network-area/create/create_test.go index ee055ad5c..7b9d235cd 100644 --- a/internal/cmd/network-area/create/create_test.go +++ b/internal/cmd/network-area/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -193,7 +194,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -289,7 +290,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.orgLabel, tt.args.networkArea); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/delete/delete.go b/internal/cmd/network-area/delete/delete.go index d617d8496..49f618338 100644 --- a/internal/cmd/network-area/delete/delete.go +++ b/internal/cmd/network-area/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -30,7 +31,7 @@ type inputModel struct { AreaId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", areaIdArg), Short: "Deletes a STACKIT Network Area (SNA)", @@ -47,20 +48,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, model.AreaId) if err != nil { - p.Debug(print.ErrorLevel, "get network area name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = model.AreaId } else if networkAreaLabel == "" { networkAreaLabel = model.AreaId @@ -68,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete network area %q?", networkAreaLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting network area") _, err = wait.DeleteNetworkAreaWaitHandler(ctx, apiClient, *model.OrganizationId, model.AreaId).WaitWithContext(ctx) if err != nil { @@ -96,7 +97,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s STACKIT Network Area %q\n", operationState, networkAreaLabel) + params.Printer.Info("%s STACKIT Network Area %q\n", operationState, networkAreaLabel) return nil }, } diff --git a/internal/cmd/network-area/delete/delete_test.go b/internal/cmd/network-area/delete/delete_test.go index a3ff4f430..4b8077590 100644 --- a/internal/cmd/network-area/delete/delete_test.go +++ b/internal/cmd/network-area/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/network-area/describe/describe.go b/internal/cmd/network-area/describe/describe.go index 35be06f3c..6658b1feb 100644 --- a/internal/cmd/network-area/describe/describe.go +++ b/internal/cmd/network-area/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -34,7 +35,7 @@ type inputModel struct { ShowAttachedProjects bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", areaIdArg), Short: "Shows details of a STACKIT Network Area", @@ -56,13 +57,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - return outputResult(p, model.OutputFormat, resp, projects) + return outputResult(params.Printer, model.OutputFormat, resp, projects) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/describe/describe_test.go b/internal/cmd/network-area/describe/describe_test.go index 24c18cb06..7160f6a01 100644 --- a/internal/cmd/network-area/describe/describe_test.go +++ b/internal/cmd/network-area/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -149,7 +150,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -253,7 +254,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.networkArea, tt.args.attachedProjects); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/list/list.go b/internal/cmd/network-area/list/list.go index 4e112ae53..82147c17b 100644 --- a/internal/cmd/network-area/list/list.go +++ b/internal/cmd/network-area/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all STACKIT Network Areas (SNA) of an organization", @@ -60,13 +61,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -80,19 +81,19 @@ func NewCmd(p *print.Printer) *cobra.Command { if resp.Items == nil || len(*resp.Items) == 0 { var orgLabel string - rmApiClient, err := rmClient.ConfigureClient(p) + rmApiClient, err := rmClient.ConfigureClient(params.Printer) if err == nil { orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) if err != nil { - p.Debug(print.ErrorLevel, "get organization name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get organization name: %v", err) orgLabel = *model.OrganizationId } else if orgLabel == "" { orgLabel = *model.OrganizationId } } else { - p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) + params.Printer.Debug(print.ErrorLevel, "configure resource manager client: %v", err) } - p.Info("No STACKIT Network Areas found for organization %q\n", orgLabel) + params.Printer.Info("No STACKIT Network Areas found for organization %q\n", orgLabel) return nil } @@ -102,7 +103,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/list/list_test.go b/internal/cmd/network-area/list/list_test.go index 4b71b3dda..d41ae9ad8 100644 --- a/internal/cmd/network-area/list/list_test.go +++ b/internal/cmd/network-area/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -232,7 +233,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreas); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go index 98fa25a60..7d81e2358 100644 --- a/internal/cmd/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -32,7 +33,7 @@ type inputModel struct { NetworkRange *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a network range in a STACKIT Network Area (SNA)", @@ -46,13 +47,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -60,13 +61,13 @@ func NewCmd(p *print.Printer) *cobra.Command { // Get network area label networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { - p.Debug(print.ErrorLevel, "get network area name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a network range for STACKIT Network Area (SNA) %q?", networkAreaLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - return outputResult(p, model.OutputFormat, networkAreaLabel, networkRange) + return outputResult(params.Printer, model.OutputFormat, networkAreaLabel, networkRange) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/network-range/create/create_test.go b/internal/cmd/network-area/network-range/create/create_test.go index f3eb51bf1..478854cc2 100644 --- a/internal/cmd/network-area/network-range/create/create_test.go +++ b/internal/cmd/network-area/network-range/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -145,7 +146,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreaLabel, tt.args.networkRange); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/network-range/delete/delete.go b/internal/cmd/network-area/network-range/delete/delete.go index 4b4ab2eda..4b7397796 100644 --- a/internal/cmd/network-area/network-range/delete/delete.go +++ b/internal/cmd/network-area/network-range/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -31,7 +32,7 @@ type inputModel struct { NetworkRangeId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", networkRangeIdArg), Short: "Deletes a network range in a STACKIT Network Area (SNA)", @@ -45,27 +46,27 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { - p.Debug(print.ErrorLevel, "get network area name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId } else if networkAreaLabel == "" { networkAreaLabel = *model.NetworkAreaId } networkRangeLabel, err := iaasUtils.GetNetworkRangePrefix(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) if err != nil { - p.Debug(print.ErrorLevel, "get network range prefix: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network range prefix: %v", err) networkRangeLabel = model.NetworkRangeId } else if networkRangeLabel == "" { networkRangeLabel = model.NetworkRangeId @@ -73,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete network range %q on STACKIT Network Area (SNA) %q?", networkRangeLabel, networkAreaLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -86,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete network range: %w", err) } - p.Info("Deleted network range %q on SNA %q\n", networkRangeLabel, networkAreaLabel) + params.Printer.Info("Deleted network range %q on SNA %q\n", networkRangeLabel, networkAreaLabel) return nil }, diff --git a/internal/cmd/network-area/network-range/delete/delete_test.go b/internal/cmd/network-area/network-range/delete/delete_test.go index 5955ea316..5fb112ef6 100644 --- a/internal/cmd/network-area/network-range/delete/delete_test.go +++ b/internal/cmd/network-area/network-range/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -156,7 +157,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/network-area/network-range/describe/describe.go b/internal/cmd/network-area/network-range/describe/describe.go index 9f35dc145..45bcfa4e4 100644 --- a/internal/cmd/network-area/network-range/describe/describe.go +++ b/internal/cmd/network-area/network-range/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -33,7 +34,7 @@ type inputModel struct { NetworkRangeId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", networkRangeIdArg), Short: "Shows details of a network range in a STACKIT Network Area (SNA)", @@ -47,13 +48,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe network range: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/network-range/describe/describe_test.go b/internal/cmd/network-area/network-range/describe/describe_test.go index c03229238..a314d11ee 100644 --- a/internal/cmd/network-area/network-range/describe/describe_test.go +++ b/internal/cmd/network-area/network-range/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -156,7 +157,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -259,7 +260,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.networkRange); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go index b9b11d0e2..aed963ba0 100644 --- a/internal/cmd/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { NetworkAreaId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all network ranges in a STACKIT Network Area (SNA)", @@ -56,13 +57,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -78,12 +79,12 @@ func NewCmd(p *print.Printer) *cobra.Command { var networkAreaLabel string networkAreaLabel, err = iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { - p.Debug(print.ErrorLevel, "get organization name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get organization name: %v", err) networkAreaLabel = *model.NetworkAreaId } else if networkAreaLabel == "" { networkAreaLabel = *model.NetworkAreaId } - p.Info("No network ranges found for SNA %q\n", networkAreaLabel) + params.Printer.Info("No network ranges found for SNA %q\n", networkAreaLabel) return nil } @@ -93,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/network-range/list/list_test.go b/internal/cmd/network-area/network-range/list/list_test.go index 26efc608c..4e7b52627 100644 --- a/internal/cmd/network-area/network-range/list/list_test.go +++ b/internal/cmd/network-area/network-range/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -140,7 +141,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -242,7 +243,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.networkRanges); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/network-range/network_range.go b/internal/cmd/network-area/network-range/network_range.go index 71c849f17..1c52227a8 100644 --- a/internal/cmd/network-area/network-range/network_range.go +++ b/internal/cmd/network-area/network-range/network_range.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network-range", Aliases: []string{"range"}, @@ -21,13 +21,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/network-area/network_area.go b/internal/cmd/network-area/network_area.go index ef12c22a8..0b67ea3ea 100644 --- a/internal/cmd/network-area/network_area.go +++ b/internal/cmd/network-area/network_area.go @@ -8,14 +8,14 @@ import ( networkrange "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network-area", Short: "Provides functionality for STACKIT Network Area (SNA)", @@ -23,16 +23,16 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(networkrange.NewCmd(p)) - cmd.AddCommand(route.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(networkrange.NewCmd(params)) + cmd.AddCommand(route.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index 05a881052..56ac716b4 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -36,7 +37,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a static route in a STACKIT Network Area (SNA)", @@ -57,13 +58,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Get network area label networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { - p.Debug(print.ErrorLevel, "get network area name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId } else if networkAreaLabel == "" { networkAreaLabel = *model.NetworkAreaId @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a static route for STACKIT Network Area (SNA) %q?", networkAreaLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -101,7 +102,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } - return outputResult(p, model.OutputFormat, networkAreaLabel, route) + return outputResult(params.Printer, model.OutputFormat, networkAreaLabel, route) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/route/create/create_test.go b/internal/cmd/network-area/route/create/create_test.go index 4ffca7666..182555c0c 100644 --- a/internal/cmd/network-area/route/create/create_test.go +++ b/internal/cmd/network-area/route/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -180,7 +181,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -287,7 +288,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreaLabel, tt.args.route); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/route/delete/delete.go b/internal/cmd/network-area/route/delete/delete.go index 144647440..f455786d2 100644 --- a/internal/cmd/network-area/route/delete/delete.go +++ b/internal/cmd/network-area/route/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -31,7 +32,7 @@ type inputModel struct { RouteId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", routeIdArg), Short: "Deletes a static route in a STACKIT Network Area (SNA)", @@ -45,20 +46,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { - p.Debug(print.ErrorLevel, "get network area name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId } else if networkAreaLabel == "" { networkAreaLabel = *model.NetworkAreaId @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete static route %q on STACKIT Network Area (SNA) %q?", model.RouteId, networkAreaLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete static route: %w", err) } - p.Info("Deleted static route %q on SNA %q\n", model.RouteId, networkAreaLabel) + params.Printer.Info("Deleted static route %q on SNA %q\n", model.RouteId, networkAreaLabel) return nil }, } diff --git a/internal/cmd/network-area/route/delete/delete_test.go b/internal/cmd/network-area/route/delete/delete_test.go index 8a63e08c7..0358eba8c 100644 --- a/internal/cmd/network-area/route/delete/delete_test.go +++ b/internal/cmd/network-area/route/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -156,7 +157,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/network-area/route/describe/describe.go b/internal/cmd/network-area/route/describe/describe.go index 8708f12e1..8e48f1ee6 100644 --- a/internal/cmd/network-area/route/describe/describe.go +++ b/internal/cmd/network-area/route/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -34,7 +35,7 @@ type inputModel struct { RouteId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", routeIdArg), Short: "Shows details of a static route in a STACKIT Network Area (SNA)", @@ -52,13 +53,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe static route: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/route/describe/describe_test.go b/internal/cmd/network-area/route/describe/describe_test.go index d052d69f9..0c674de81 100644 --- a/internal/cmd/network-area/route/describe/describe_test.go +++ b/internal/cmd/network-area/route/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -156,7 +157,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -259,7 +260,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.route); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go index f8bada766..f8159617b 100644 --- a/internal/cmd/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { NetworkAreaId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all static routes in a STACKIT Network Area (SNA)", @@ -55,13 +56,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,12 +78,12 @@ func NewCmd(p *print.Printer) *cobra.Command { var networkAreaLabel string networkAreaLabel, err = iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { - p.Debug(print.ErrorLevel, "get network area name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId } else if networkAreaLabel == "" { networkAreaLabel = *model.NetworkAreaId } - p.Info("No static routes found for STACKIT Network Area %q\n", networkAreaLabel) + params.Printer.Info("No static routes found for STACKIT Network Area %q\n", networkAreaLabel) return nil } @@ -92,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/route/list/list_test.go b/internal/cmd/network-area/route/list/list_test.go index 573b332a8..2d66bad9f 100644 --- a/internal/cmd/network-area/route/list/list_test.go +++ b/internal/cmd/network-area/route/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -140,7 +141,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -242,7 +243,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.routes); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/route/routes.go b/internal/cmd/network-area/route/routes.go index 20fa115dd..1769f349e 100644 --- a/internal/cmd/network-area/route/routes.go +++ b/internal/cmd/network-area/route/routes.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/list" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "route", Short: "Provides functionality for static routes in STACKIT Network Areas", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go index b97c9b44d..ab4c8c860 100644 --- a/internal/cmd/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", routeIdArg), Short: "Updates a static route in a STACKIT Network Area (SNA)", @@ -53,13 +54,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Get network area label networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId) if err != nil { - p.Debug(print.ErrorLevel, "get network area name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId } else if networkAreaLabel == "" { networkAreaLabel = *model.NetworkAreaId @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create static route: %w", err) } - return outputResult(p, model.OutputFormat, networkAreaLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, networkAreaLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/route/update/update_test.go b/internal/cmd/network-area/route/update/update_test.go index 813deae4d..03bdf6da2 100644 --- a/internal/cmd/network-area/route/update/update_test.go +++ b/internal/cmd/network-area/route/update/update_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -189,7 +190,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -293,7 +294,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreaLabel, tt.args.route); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/update/update.go b/internal/cmd/network-area/update/update.go index 3a0c4f6f7..7e9615aff 100644 --- a/internal/cmd/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -45,7 +46,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", areaIdArg), Short: "Updates a STACKIT Network Area (SNA)", @@ -59,34 +60,34 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } var orgLabel string - rmApiClient, err := rmClient.ConfigureClient(p) + rmApiClient, err := rmClient.ConfigureClient(params.Printer) if err == nil { orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) if err != nil { - p.Debug(print.ErrorLevel, "get organization name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get organization name: %v", err) orgLabel = *model.OrganizationId } else if orgLabel == "" { orgLabel = *model.OrganizationId } } else { - p.Debug(print.ErrorLevel, "configure resource manager client: %v", err) + params.Printer.Debug(print.ErrorLevel, "configure resource manager client: %v", err) } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update a network area for organization %q?", orgLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -99,7 +100,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update network area: %w", err) } - return outputResult(p, model.OutputFormat, orgLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, orgLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network-area/update/update_test.go b/internal/cmd/network-area/update/update_test.go index 807ec124f..f25018286 100644 --- a/internal/cmd/network-area/update/update_test.go +++ b/internal/cmd/network-area/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -206,7 +207,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -310,7 +311,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.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.networkArea); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index a14e57b1e..08a8c7cac 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -49,7 +50,7 @@ type inputModel struct { SecurityGroups *[]string // = 36 characters + regex ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a network interface", @@ -67,20 +68,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a network interface for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -101,7 +102,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create network interface: %w", err) } - return outputResult(p, model.OutputFormat, model.ProjectId, resp) + return outputResult(params.Printer, model.OutputFormat, model.ProjectId, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network-interface/create/create_test.go b/internal/cmd/network-interface/create/create_test.go index 843b15f69..f05ed584e 100644 --- a/internal/cmd/network-interface/create/create_test.go +++ b/internal/cmd/network-interface/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -190,7 +191,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -286,7 +287,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.projectId, tt.args.nic); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-interface/delete/delete.go b/internal/cmd/network-interface/delete/delete.go index 4f2cd3302..925bf29b7 100644 --- a/internal/cmd/network-interface/delete/delete.go +++ b/internal/cmd/network-interface/delete/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -27,7 +28,7 @@ type inputModel struct { NicId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", nicIdArg), Short: "Deletes a network interface", @@ -41,20 +42,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete the network interface %q? (This cannot be undone)", model.NicId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete network interface: %w", err) } - p.Info("Deleted network interface %q\n", model.NicId) + params.Printer.Info("Deleted network interface %q\n", model.NicId) return nil }, diff --git a/internal/cmd/network-interface/delete/delete_test.go b/internal/cmd/network-interface/delete/delete_test.go index 4b9fdd56b..ac03d45f6 100644 --- a/internal/cmd/network-interface/delete/delete_test.go +++ b/internal/cmd/network-interface/delete/delete_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -122,7 +123,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/network-interface/describe/describe.go b/internal/cmd/network-interface/describe/describe.go index 89b04b9b3..aba9ed65a 100644 --- a/internal/cmd/network-interface/describe/describe.go +++ b/internal/cmd/network-interface/describe/describe.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { NicId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", nicIdArg), Short: "Describes a network interface", @@ -54,13 +55,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe network interface: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network-interface/describe/describe_test.go b/internal/cmd/network-interface/describe/describe_test.go index 967057b02..24163ac87 100644 --- a/internal/cmd/network-interface/describe/describe_test.go +++ b/internal/cmd/network-interface/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -122,7 +123,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -225,7 +226,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.nic); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go index 3164f956b..e7282358f 100644 --- a/internal/cmd/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { NetworkId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all network interfaces of a network", @@ -59,13 +60,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -80,12 +81,12 @@ func NewCmd(p *print.Printer) *cobra.Command { if resp.Items == nil || len(*resp.Items) == 0 { networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) if err != nil { - p.Debug(print.ErrorLevel, "get network name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = *model.NetworkId } else if networkLabel == "" { networkLabel = *model.NetworkId } - p.Info("No network interfaces found for network %q\n", networkLabel) + params.Printer.Info("No network interfaces found for network %q\n", networkLabel) return nil } @@ -95,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/network-interface/list/list_test.go b/internal/cmd/network-interface/list/list_test.go index 97610156a..3e976c5db 100644 --- a/internal/cmd/network-interface/list/list_test.go +++ b/internal/cmd/network-interface/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -135,7 +136,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -223,7 +224,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.nics); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-interface/network-interface.go b/internal/cmd/network-interface/network-interface.go index cada28596..f9bbca3fe 100644 --- a/internal/cmd/network-interface/network-interface.go +++ b/internal/cmd/network-interface/network-interface.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/list" "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network-interface", Short: "Provides functionality for network interfaces", @@ -20,14 +20,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go index 777f2f4b4..9cf746745 100644 --- a/internal/cmd/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -47,7 +48,7 @@ type inputModel struct { SecurityGroups *[]string // = 36 characters + regex ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", nicIdArg), Short: "Updates a network interface", @@ -69,20 +70,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update the network interface %q?", model.NicId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -95,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update network interface: %w", err) } - return outputResult(p, model.OutputFormat, model.ProjectId, resp) + return outputResult(params.Printer, model.OutputFormat, model.ProjectId, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network-interface/update/update_test.go b/internal/cmd/network-interface/update/update_test.go index 98987b829..03faa73ad 100644 --- a/internal/cmd/network-interface/update/update_test.go +++ b/internal/cmd/network-interface/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -213,7 +214,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -317,7 +318,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.projectId, tt.args.nic); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index b89f54f49..339025b74 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -55,7 +56,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a network", @@ -89,20 +90,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId @@ -110,7 +111,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a network for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -126,7 +127,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating network") _, err = wait.CreateNetworkWaitHandler(ctx, apiClient, model.ProjectId, networkId).WaitWithContext(ctx) if err != nil { @@ -135,7 +136,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/network/create/create_test.go b/internal/cmd/network/create/create_test.go index 19edc1d40..63c6a3635 100644 --- a/internal/cmd/network/create/create_test.go +++ b/internal/cmd/network/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -258,7 +259,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -467,7 +468,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.network); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network/delete/delete.go b/internal/cmd/network/delete/delete.go index c1608151e..a0adcb6d0 100644 --- a/internal/cmd/network/delete/delete.go +++ b/internal/cmd/network/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { NetworkId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", networkIdArg), Short: "Deletes a network", @@ -45,20 +46,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.NetworkId) if err != nil { - p.Debug(print.ErrorLevel, "get network name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = model.NetworkId } else if networkLabel == "" { networkLabel = model.NetworkId @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete network %q?", networkLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting network") _, err = wait.DeleteNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.NetworkId).WaitWithContext(ctx) if err != nil { @@ -94,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s network %q\n", operationState, networkLabel) + params.Printer.Info("%s network %q\n", operationState, networkLabel) return nil }, } diff --git a/internal/cmd/network/delete/delete_test.go b/internal/cmd/network/delete/delete_test.go index 726364502..630a0f3fb 100644 --- a/internal/cmd/network/delete/delete_test.go +++ b/internal/cmd/network/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/network/describe/describe.go b/internal/cmd/network/describe/describe.go index 13eb11133..129c52899 100644 --- a/internal/cmd/network/describe/describe.go +++ b/internal/cmd/network/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { NetworkId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", networkIdArg), Short: "Shows details of a network", @@ -47,13 +48,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read network: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/network/describe/describe_test.go b/internal/cmd/network/describe/describe_test.go index 451b518b3..9c3b62d35 100644 --- a/internal/cmd/network/describe/describe_test.go +++ b/internal/cmd/network/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.network); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network/list/list.go b/internal/cmd/network/list/list.go index 8b5577685..90e6efa0e 100644 --- a/internal/cmd/network/list/list.go +++ b/internal/cmd/network/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all networks of a project", @@ -58,13 +59,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,14 +78,14 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId } - p.Info("No networks found for project %q\n", projectLabel) + params.Printer.Info("No networks found for project %q\n", projectLabel) return nil } @@ -94,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/network/list/list_test.go b/internal/cmd/network/list/list_test.go index 9bc47dfb5..c0f1ac4c3 100644 --- a/internal/cmd/network/list/list_test.go +++ b/internal/cmd/network/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -132,7 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -229,7 +230,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.networks); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network/network.go b/internal/cmd/network/network.go index b95a496c7..5fbd7e77b 100644 --- a/internal/cmd/network/network.go +++ b/internal/cmd/network/network.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network/list" "github.com/stackitcloud/stackit-cli/internal/cmd/network/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network", Short: "Provides functionality for networks", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/network/update/update.go b/internal/cmd/network/update/update.go index 50be6c698..1b331a802 100644 --- a/internal/cmd/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -46,7 +47,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", networkIdArg), Short: "Updates a network", @@ -72,20 +73,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.NetworkId) if err != nil { - p.Debug(print.ErrorLevel, "get network name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = model.NetworkId } else if networkLabel == "" { networkLabel = model.NetworkId @@ -93,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update network %q?", networkLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -109,7 +110,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating network") _, err = wait.UpdateNetworkWaitHandler(ctx, apiClient, model.ProjectId, networkId).WaitWithContext(ctx) if err != nil { @@ -122,7 +123,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s network %q\n", operationState, networkLabel) + params.Printer.Info("%s network %q\n", operationState, networkLabel) return nil }, } diff --git a/internal/cmd/network/update/update_test.go b/internal/cmd/network/update/update_test.go index 7a1b243c5..d05624840 100644 --- a/internal/cmd/network/update/update_test.go +++ b/internal/cmd/network/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -241,7 +242,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/object-storage/bucket/bucket.go b/internal/cmd/object-storage/bucket/bucket.go index 701fc0934..62d928e54 100644 --- a/internal/cmd/object-storage/bucket/bucket.go +++ b/internal/cmd/object-storage/bucket/bucket.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/bucket/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/bucket/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/bucket/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "bucket", Short: "Provides functionality for Object Storage buckets", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index e96a4206c..f4337d7e3 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { BucketName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", bucketNameArg), Short: "Creates an Object Storage bucket", @@ -42,20 +43,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create bucket %q? (This cannot be undone)", model.BucketName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating bucket") _, err = wait.CreateBucketWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx) if err != nil { @@ -90,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, model.BucketName, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, model.BucketName, resp) }, } return cmd diff --git a/internal/cmd/object-storage/bucket/create/create_test.go b/internal/cmd/object-storage/bucket/create/create_test.go index 49a089342..344c228d5 100644 --- a/internal/cmd/object-storage/bucket/create/create_test.go +++ b/internal/cmd/object-storage/bucket/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.bucketName, tt.args.createBucketResponse); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/bucket/delete/delete.go b/internal/cmd/object-storage/bucket/delete/delete.go index 1c6edbf90..0b4174f47 100644 --- a/internal/cmd/object-storage/bucket/delete/delete.go +++ b/internal/cmd/object-storage/bucket/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { BucketName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", bucketNameArg), Short: "Deletes an Object Storage bucket", @@ -39,20 +40,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete bucket %q? (This cannot be undone)", model.BucketName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting bucket") _, err = wait.DeleteBucketWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx) if err != nil { @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s bucket %q\n", operationState, model.BucketName) + params.Printer.Info("%s bucket %q\n", operationState, model.BucketName) return nil }, } diff --git a/internal/cmd/object-storage/bucket/delete/delete_test.go b/internal/cmd/object-storage/bucket/delete/delete_test.go index be5bd0028..6e06d4adc 100644 --- a/internal/cmd/object-storage/bucket/delete/delete_test.go +++ b/internal/cmd/object-storage/bucket/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index 23a9e7011..c1fd344d6 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { BucketName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", bucketNameArg), Short: "Shows details of an Object Storage bucket", @@ -44,12 +45,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -61,7 +62,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read Object Storage bucket: %w", err) } - return outputResult(p, model.OutputFormat, resp.Bucket) + return outputResult(params.Printer, model.OutputFormat, resp.Bucket) }, } return cmd diff --git a/internal/cmd/object-storage/bucket/describe/describe_test.go b/internal/cmd/object-storage/bucket/describe/describe_test.go index d233fc17f..9e376132d 100644 --- a/internal/cmd/object-storage/bucket/describe/describe_test.go +++ b/internal/cmd/object-storage/bucket/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -239,7 +240,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.bucket); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index 19466184b..cbfa41574 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Object Storage buckets", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,12 +67,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get Object Storage buckets: %w", err) } if resp.Buckets == nil || len(*resp.Buckets) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No buckets found for project %s\n", projectLabel) + params.Printer.Info("No buckets found for project %s\n", projectLabel) return nil } buckets := *resp.Buckets @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { buckets = buckets[:*model.Limit] } - return outputResult(p, model.OutputFormat, buckets) + return outputResult(params.Printer, model.OutputFormat, buckets) }, } diff --git a/internal/cmd/object-storage/bucket/list/list_test.go b/internal/cmd/object-storage/bucket/list/list_test.go index 31664679f..eb50f0ca7 100644 --- a/internal/cmd/object-storage/bucket/list/list_test.go +++ b/internal/cmd/object-storage/bucket/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -215,7 +216,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.buckets); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index 55530ccc7..02dfba938 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { CredentialsGroupName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a credentials group to hold Object Storage access credentials", @@ -41,20 +42,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a credentials group with name %q?", model.CredentialsGroupName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Object Storage credentials group: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/object-storage/credentials-group/create/create_test.go b/internal/cmd/object-storage/credentials-group/create/create_test.go index 60dd53fbd..f23487603 100644 --- a/internal/cmd/object-storage/credentials-group/create/create_test.go +++ b/internal/cmd/object-storage/credentials-group/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -122,7 +123,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -226,7 +227,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.createCredentialsGroupResponse); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/credentials-group/credentials_group.go b/internal/cmd/object-storage/credentials-group/credentials_group.go index 0803796f4..9b9d05129 100644 --- a/internal/cmd/object-storage/credentials-group/credentials_group.go +++ b/internal/cmd/object-storage/credentials-group/credentials_group.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group/create" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials-group", Short: "Provides functionality for Object Storage credentials group", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/object-storage/credentials-group/delete/delete.go b/internal/cmd/object-storage/credentials-group/delete/delete.go index 27dda8460..11457da96 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { CredentialsGroupId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsGroupIdArg), Short: "Deletes a credentials group that holds Object Storage access credentials", @@ -39,26 +40,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get credentials group name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials group name: %v", err) credentialsGroupLabel = model.CredentialsGroupId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials group %q? (This cannot be undone)", credentialsGroupLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Object Storage credentials group: %w", err) } - p.Info("Deleted credentials group %q\n", credentialsGroupLabel) + params.Printer.Info("Deleted credentials group %q\n", credentialsGroupLabel) return nil }, } diff --git a/internal/cmd/object-storage/credentials-group/delete/delete_test.go b/internal/cmd/object-storage/credentials-group/delete/delete_test.go index 1711bd33c..a5097a0b7 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete_test.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -142,7 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index 876392113..e239167b0 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials groups that hold Object Storage access credentials", @@ -47,13 +48,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } credentialsGroups := *resp.CredentialsGroups if len(credentialsGroups) == 0 { - p.Info("No credentials groups found for your project") + params.Printer.Info("No credentials groups found for your project") return nil } @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentialsGroups) > int(*model.Limit) { credentialsGroups = credentialsGroups[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentialsGroups) + return outputResult(params.Printer, model.OutputFormat, credentialsGroups) }, } configureFlags(cmd) diff --git a/internal/cmd/object-storage/credentials-group/list/list_test.go b/internal/cmd/object-storage/credentials-group/list/list_test.go index 2a7ee01ff..b0570483b 100644 --- a/internal/cmd/object-storage/credentials-group/list/list_test.go +++ b/internal/cmd/object-storage/credentials-group/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -117,7 +118,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -219,7 +220,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentialsGroups); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index 71c854dd3..bce332f93 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { HidePassword bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for an Object Storage credentials group", @@ -49,26 +50,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get credentials group name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials group name: %v", err) credentialsGroupLabel = model.CredentialsGroupId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create credentials in group %q?", credentialsGroupLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Object Storage credentials: %w", err) } - return outputResult(p, model.OutputFormat, credentialsGroupLabel, resp) + return outputResult(params.Printer, model.OutputFormat, credentialsGroupLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/object-storage/credentials/create/create_test.go b/internal/cmd/object-storage/credentials/create/create_test.go index 03257beda..c2efbf566 100644 --- a/internal/cmd/object-storage/credentials/create/create_test.go +++ b/internal/cmd/object-storage/credentials/create/create_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -181,7 +182,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -277,7 +278,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentialsGroupLabel, tt.args.createAccessKeyResponse); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/credentials/credentials.go b/internal/cmd/object-storage/credentials/credentials.go index e96b86072..8654a6734 100644 --- a/internal/cmd/object-storage/credentials/credentials.go +++ b/internal/cmd/object-storage/credentials/credentials.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials/create" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for Object Storage credentials", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/object-storage/credentials/delete/delete.go b/internal/cmd/object-storage/credentials/delete/delete.go index ed7fedb5e..e8cc8a4e3 100644 --- a/internal/cmd/object-storage/credentials/delete/delete.go +++ b/internal/cmd/object-storage/credentials/delete/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of an Object Storage credentials group", @@ -40,32 +41,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get credentials group name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials group name: %v", err) credentialsGroupLabel = model.CredentialsGroupId } credentialsLabel, err := objectStorageUtils.GetCredentialsName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.CredentialsId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get credentials name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials name: %v", err) credentialsLabel = model.CredentialsId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials %q of credentials group %q? (This cannot be undone)", credentialsLabel, credentialsGroupLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Object Storage credentials: %w", err) } - p.Info("Deleted credentials %q of credentials group %q\n", credentialsLabel, credentialsGroupLabel) + params.Printer.Info("Deleted credentials %q of credentials group %q\n", credentialsLabel, credentialsGroupLabel) return nil }, } diff --git a/internal/cmd/object-storage/credentials/delete/delete_test.go b/internal/cmd/object-storage/credentials/delete/delete_test.go index 09ee7d04b..1ba508df1 100644 --- a/internal/cmd/object-storage/credentials/delete/delete_test.go +++ b/internal/cmd/object-storage/credentials/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -161,7 +162,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index c1a6d63dd..33a41860f 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials for an Object Storage credentials group", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,11 +72,11 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(credentials) == 0 { credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get credentials group name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials group name: %v", err) credentialsGroupLabel = model.CredentialsGroupId } - p.Info("No credentials found for credentials group %q\n", credentialsGroupLabel) + params.Printer.Info("No credentials found for credentials group %q\n", credentialsGroupLabel) return nil } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentials) }, } configureFlags(cmd) diff --git a/internal/cmd/object-storage/credentials/list/list_test.go b/internal/cmd/object-storage/credentials/list/list_test.go index a50921b69..6f6fb41a3 100644 --- a/internal/cmd/object-storage/credentials/list/list_test.go +++ b/internal/cmd/object-storage/credentials/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -142,7 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -244,7 +245,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/disable/disable.go b/internal/cmd/object-storage/disable/disable.go index 56e6f940d..0486e90ae 100644 --- a/internal/cmd/object-storage/disable/disable.go +++ b/internal/cmd/object-storage/disable/disable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -20,7 +21,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "disable", Short: "Disables Object Storage for a project", @@ -33,26 +34,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to disable Object Storage for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -69,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered disablement of" } - p.Info("%s Object Storage for project %q\n", operationState, projectLabel) + params.Printer.Info("%s Object Storage for project %q\n", operationState, projectLabel) return nil }, } diff --git a/internal/cmd/object-storage/enable/enable.go b/internal/cmd/object-storage/enable/enable.go index cec0d6e7d..00959bcfa 100644 --- a/internal/cmd/object-storage/enable/enable.go +++ b/internal/cmd/object-storage/enable/enable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -20,7 +21,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "enable", Short: "Enables Object Storage for a project", @@ -33,26 +34,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to enable Object Storage for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -69,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered enablement of" } - p.Info("%s Object Storage for project %q\n", operationState, projectLabel) + params.Printer.Info("%s Object Storage for project %q\n", operationState, projectLabel) return nil }, } diff --git a/internal/cmd/object-storage/object_storage.go b/internal/cmd/object-storage/object_storage.go index 0ba397592..2adfb7001 100644 --- a/internal/cmd/object-storage/object_storage.go +++ b/internal/cmd/object-storage/object_storage.go @@ -6,14 +6,14 @@ import ( credentialsGroup "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/disable" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "object-storage", Short: "Provides functionality for Object Storage", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(bucket.NewCmd(p)) - cmd.AddCommand(disable.NewCmd(p)) - cmd.AddCommand(enable.NewCmd(p)) - cmd.AddCommand(credentialsGroup.NewCmd(p)) - cmd.AddCommand(credentials.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(bucket.NewCmd(params)) + cmd.AddCommand(disable.NewCmd(params)) + cmd.AddCommand(enable.NewCmd(params)) + cmd.AddCommand(credentialsGroup.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) } diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index 9852ee352..f968f0a7e 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for an Observability instance.", @@ -44,26 +45,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create credentials for Observability instance: %w", err) } - return outputResult(p, model.OutputFormat, instanceLabel, resp) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/observability/credentials/create/create_test.go b/internal/cmd/observability/credentials/create/create_test.go index c261948c7..16fcc439d 100644 --- a/internal/cmd/observability/credentials/create/create_test.go +++ b/internal/cmd/observability/credentials/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/observability" @@ -224,7 +225,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/credentials/credentials.go b/internal/cmd/observability/credentials/credentials.go index fb84cf9d6..c4aa1e396 100644 --- a/internal/cmd/observability/credentials/credentials.go +++ b/internal/cmd/observability/credentials/credentials.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/create" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for Observability credentials", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/observability/credentials/delete/delete.go b/internal/cmd/observability/credentials/delete/delete.go index a501b949a..0c85bf2b6 100644 --- a/internal/cmd/observability/credentials/delete/delete.go +++ b/internal/cmd/observability/credentials/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Username string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", usernameArg), Short: "Deletes credentials of an Observability instance", @@ -42,26 +43,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials for username %q of instance %q? (This cannot be undone)", model.Username, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Observability credentials: %w", err) } - p.Info("Deleted credentials for username %q of instance %q\n", model.Username, instanceLabel) + params.Printer.Info("Deleted credentials for username %q of instance %q\n", model.Username, instanceLabel) return nil }, } diff --git a/internal/cmd/observability/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go index 9c9452832..3bf6bf231 100644 --- a/internal/cmd/observability/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists the usernames of all credentials for an Observability instance", @@ -51,13 +52,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -72,10 +73,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(credentials) == 0 { instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - p.Info("No credentials found for instance %q\n", instanceLabel) + params.Printer.Info("No credentials found for instance %q\n", instanceLabel) return nil } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentials) }, } configureFlags(cmd) diff --git a/internal/cmd/observability/credentials/list/list_test.go b/internal/cmd/observability/credentials/list/list_test.go index fa23d5dfe..64d92b12f 100644 --- a/internal/cmd/observability/credentials/list/list_test.go +++ b/internal/cmd/observability/credentials/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -238,7 +239,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index 9a364499c..bce33d2a6 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of the Grafana configuration of an Observability instance", @@ -54,13 +55,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get instance: %w", err) } - return outputResult(p, model.OutputFormat, model.ShowPassword, grafanaConfigsResp, instanceResp) + return outputResult(params.Printer, model.OutputFormat, model.ShowPassword, grafanaConfigsResp, instanceResp) }, } configureFlags(cmd) diff --git a/internal/cmd/observability/grafana/describe/describe_test.go b/internal/cmd/observability/grafana/describe/describe_test.go index f282c2964..d84af41cb 100644 --- a/internal/cmd/observability/grafana/describe/describe_test.go +++ b/internal/cmd/observability/grafana/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -169,7 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -322,7 +323,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, tt.args.grafanaConfig, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/grafana/grafana.go b/internal/cmd/observability/grafana/grafana.go index e9ad230d1..000da5eac 100644 --- a/internal/cmd/observability/grafana/grafana.go +++ b/internal/cmd/observability/grafana/grafana.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/describe" publicreadaccess "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access" singlesignon "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "grafana", Short: "Provides functionality for the Grafana configuration of Observability instances", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(publicreadaccess.NewCmd(p)) - cmd.AddCommand(singlesignon.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(publicreadaccess.NewCmd(params)) + cmd.AddCommand(singlesignon.NewCmd(params)) } diff --git a/internal/cmd/observability/grafana/public-read-access/disable/disable.go b/internal/cmd/observability/grafana/public-read-access/disable/disable.go index ac6cd80a4..0f122fc96 100644 --- a/internal/cmd/observability/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disable %s", instanceIdArg), Short: "Disables public read access for Grafana on Observability instances", @@ -42,13 +43,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -60,7 +61,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to disable Grafana public read access for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("disable grafana public read access: %w", err) } - p.Info("Disabled Grafana public read access for instance %q\n", instanceLabel) + params.Printer.Info("Disabled Grafana public read access for instance %q\n", instanceLabel) return nil }, } diff --git a/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go b/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go index 7e08ac647..a8db1bd9d 100644 --- a/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -186,7 +187,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/observability/grafana/public-read-access/enable/enable.go b/internal/cmd/observability/grafana/public-read-access/enable/enable.go index 9296a1f24..a13ae2c08 100644 --- a/internal/cmd/observability/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("enable %s", instanceIdArg), Short: "Enables public read access for Grafana on Observability instances", @@ -42,13 +43,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -60,7 +61,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to enable Grafana public read access for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("enable grafana public read access: %w", err) } - p.Info("Enabled Grafana public read access for instance %q\n", instanceLabel) + params.Printer.Info("Enabled Grafana public read access for instance %q\n", instanceLabel) return nil }, } diff --git a/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go b/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go index 57ebc5bc3..d425e7078 100644 --- a/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -186,7 +187,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/observability/grafana/public-read-access/public_read_access.go b/internal/cmd/observability/grafana/public-read-access/public_read_access.go index 8844e1279..94c27eb36 100644 --- a/internal/cmd/observability/grafana/public-read-access/public_read_access.go +++ b/internal/cmd/observability/grafana/public-read-access/public_read_access.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access/disable" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "public-read-access", Short: "Enable or disable public read access for Grafana in Observability instances", @@ -23,11 +23,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(enable.NewCmd(p)) - cmd.AddCommand(disable.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(enable.NewCmd(params)) + cmd.AddCommand(disable.NewCmd(params)) } diff --git a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go index 018d7827d..14084d154 100644 --- a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disable %s", instanceIdArg), Short: "Disables single sign-on for Grafana on Observability instances", @@ -42,13 +43,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -60,7 +61,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to disable single sign-on for Grafana for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("disable single sign-on for grafana: %w", err) } - p.Info("Disabled single sign-on for Grafana for instance %q\n", instanceLabel) + params.Printer.Info("Disabled single sign-on for Grafana for instance %q\n", instanceLabel) return nil }, } diff --git a/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go index 79653608e..53c087352 100644 --- a/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -186,7 +187,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go index 9a002b9f9..9956ebd9b 100644 --- a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("enable %s", instanceIdArg), Short: "Enables single sign-on for Grafana on Observability instances", @@ -42,13 +43,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -60,7 +61,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to enable single sign-on for Grafana for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("enable single sign-on for grafana: %w", err) } - p.Info("Enabled single sign-on for Grafana for instance %q\n", instanceLabel) + params.Printer.Info("Enabled single sign-on for Grafana for instance %q\n", instanceLabel) return nil }, } diff --git a/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go index e59f23828..cdc464409 100644 --- a/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" @@ -186,7 +187,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go b/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go index c53c4a5cf..c4a73ada2 100644 --- a/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go +++ b/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on/disable" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "single-sign-on", Aliases: []string{"sso"}, @@ -24,11 +24,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(enable.NewCmd(p)) - cmd.AddCommand(disable.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(enable.NewCmd(params)) + cmd.AddCommand(disable.NewCmd(params)) } diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 57e9d888f..5158941e5 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -38,7 +39,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an Observability instance", @@ -54,26 +55,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create an Observability instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -96,7 +97,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx) if err != nil { @@ -105,7 +106,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/observability/instance/create/create_test.go b/internal/cmd/observability/instance/create/create_test.go index f36d5ae8a..6cdeda809 100644 --- a/internal/cmd/observability/instance/create/create_test.go +++ b/internal/cmd/observability/instance/create/create_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -175,7 +176,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -361,7 +362,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/instance/delete/delete.go b/internal/cmd/observability/instance/delete/delete.go index abe93e2a0..eb1790ebd 100644 --- a/internal/cmd/observability/instance/delete/delete.go +++ b/internal/cmd/observability/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes an Observability instance", @@ -41,26 +42,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.InstanceId, model.ProjectId).WaitWithContext(ctx) if err != nil { @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/observability/instance/delete/delete_test.go b/internal/cmd/observability/instance/delete/delete_test.go index 8375214bb..d8432900f 100644 --- a/internal/cmd/observability/instance/delete/delete_test.go +++ b/internal/cmd/observability/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/observability/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go index 157bd28a4..7e03dbb03 100644 --- a/internal/cmd/observability/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of an Observability instance", @@ -44,12 +45,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -61,7 +62,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read Observability instance: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/observability/instance/describe/describe_test.go b/internal/cmd/observability/instance/describe/describe_test.go index c55020fa7..62f60d451 100644 --- a/internal/cmd/observability/instance/describe/describe_test.go +++ b/internal/cmd/observability/instance/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/instance/instance.go b/internal/cmd/observability/instance/instance.go index efd7d4974..47a84edf6 100644 --- a/internal/cmd/observability/instance/instance.go +++ b/internal/cmd/observability/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for Observability instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) } diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index b540bee32..e82c2254b 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Observability instances", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/observability/instance/list/list_test.go b/internal/cmd/observability/instance/list/list_test.go index e8a87f48a..33157c100 100644 --- a/internal/cmd/observability/instance/list/list_test.go +++ b/internal/cmd/observability/instance/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -217,7 +218,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/instance/update/update.go b/internal/cmd/observability/instance/update/update.go index 192c84366..90411dd26 100644 --- a/internal/cmd/observability/instance/update/update.go +++ b/internal/cmd/observability/instance/update/update.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -38,7 +39,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates an Observability instance", @@ -57,26 +58,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil || instanceLabel == "" { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -100,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.UpdateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx) if err != nil { @@ -113,7 +114,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/observability/instance/update/update_test.go b/internal/cmd/observability/instance/update/update_test.go index 0b5177b27..fd798093c 100644 --- a/internal/cmd/observability/instance/update/update_test.go +++ b/internal/cmd/observability/instance/update/update_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -240,7 +241,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/observability/observability.go b/internal/cmd/observability/observability.go index 8737a716e..136f29637 100644 --- a/internal/cmd/observability/observability.go +++ b/internal/cmd/observability/observability.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/plans" scrapeconfig "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "observability", Short: "Provides functionality for Observability", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(grafana.NewCmd(p)) - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(credentials.NewCmd(p)) - cmd.AddCommand(scrapeconfig.NewCmd(p)) - cmd.AddCommand(plans.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(grafana.NewCmd(params)) + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) + cmd.AddCommand(scrapeconfig.NewCmd(params)) + cmd.AddCommand(plans.NewCmd(params)) } diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index d42cfb8a0..90867c27a 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all Observability service plans", @@ -49,13 +50,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -68,12 +69,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } plans := *resp.Plans if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No plans found for project %q\n", projectLabel) + params.Printer.Info("No plans found for project %q\n", projectLabel) return nil } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(p, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, plans) }, } diff --git a/internal/cmd/observability/plans/plans_test.go b/internal/cmd/observability/plans/plans_test.go index 047c3c5f6..2228a0402 100644 --- a/internal/cmd/observability/plans/plans_test.go +++ b/internal/cmd/observability/plans/plans_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go index 0856e6b19..9bd89d9d7 100644 --- a/internal/cmd/observability/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Payload *observability.CreateScrapeConfigPayload } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a scrape configuration for an Observability instance", @@ -61,20 +62,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } @@ -89,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create scrape configuration %q on Observability instance %q?", *model.Payload.JobName, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -106,7 +107,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating scrape config") _, err = wait.CreateScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, *jobName, model.ProjectId).WaitWithContext(ctx) if err != nil { @@ -119,7 +120,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered creation of" } - p.Outputf("%s scrape configuration with name %q for Observability instance %q\n", operationState, utils.PtrString(jobName), instanceLabel) + params.Printer.Outputf("%s scrape configuration with name %q for Observability instance %q\n", operationState, utils.PtrString(jobName), instanceLabel) return nil }, } diff --git a/internal/cmd/observability/scrape-config/delete/delete.go b/internal/cmd/observability/scrape-config/delete/delete.go index de04c6fcc..0bc137b3b 100644 --- a/internal/cmd/observability/scrape-config/delete/delete.go +++ b/internal/cmd/observability/scrape-config/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", jobNameArg), Short: "Deletes a scrape configuration from an Observability instance", @@ -44,26 +45,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete scrape configuration %q on Observability instance %q? (This cannot be undone)", model.JobName, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting scrape config") _, err = wait.DeleteScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, model.JobName, model.ProjectId).WaitWithContext(ctx) if err != nil { @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s scrape configuration with name %q for Observability instance %q\n", operationState, model.JobName, instanceLabel) + params.Printer.Info("%s scrape configuration with name %q for Observability instance %q\n", operationState, model.JobName, instanceLabel) return nil }, } diff --git a/internal/cmd/observability/scrape-config/describe/describe.go b/internal/cmd/observability/scrape-config/describe/describe.go index 2687a72a3..2c6e24573 100644 --- a/internal/cmd/observability/scrape-config/describe/describe.go +++ b/internal/cmd/observability/scrape-config/describe/describe.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", jobNameArg), Short: "Shows details of a scrape configuration from an Observability instance", @@ -48,12 +49,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read scrape configuration: %w", err) } - return outputResult(p, model.OutputFormat, resp.Data) + return outputResult(params.Printer, model.OutputFormat, resp.Data) }, } configureFlags(cmd) diff --git a/internal/cmd/observability/scrape-config/describe/describe_test.go b/internal/cmd/observability/scrape-config/describe/describe_test.go index a0cf31413..d975ba82c 100644 --- a/internal/cmd/observability/scrape-config/describe/describe_test.go +++ b/internal/cmd/observability/scrape-config/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -257,7 +258,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.config); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go index fe8a9f5ec..3a1927114 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/fileutils" @@ -31,7 +32,7 @@ type inputModel struct { FilePath *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "generate-payload", Short: "Generates a payload to create/update scrape configurations for an Observability instance ", @@ -61,20 +62,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if model.JobName == nil { createPayload := observabilityUtils.DefaultCreateScrapeConfigPayload - return outputCreateResult(p, model.FilePath, &createPayload) + return outputCreateResult(params.Printer, model.FilePath, &createPayload) } req := buildRequest(ctx, model, apiClient) @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("map update scrape config payloads: %w", err) } - return outputUpdateResult(p, model.FilePath, payload) + return outputUpdateResult(params.Printer, model.FilePath, payload) }, } configureFlags(cmd) diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go index b8740da53..e9a3a076b 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -274,7 +275,7 @@ func TestOutputCreateResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputCreateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { @@ -308,7 +309,7 @@ func TestOutputUpdateResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputUpdateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go index 5dbdde095..b03ec740b 100644 --- a/internal/cmd/observability/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all scrape configurations of an Observability instance", @@ -52,13 +53,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -73,10 +74,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(configs) == 0 { instanceLabel, err := observabilityUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - p.Info("No scrape configurations found for instance %q\n", instanceLabel) + params.Printer.Info("No scrape configurations found for instance %q\n", instanceLabel) return nil } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { configs = configs[:*model.Limit] } - return outputResult(p, model.OutputFormat, configs) + return outputResult(params.Printer, model.OutputFormat, configs) }, } diff --git a/internal/cmd/observability/scrape-config/list/list_test.go b/internal/cmd/observability/scrape-config/list/list_test.go index 69e5b6ab5..35e53001b 100644 --- a/internal/cmd/observability/scrape-config/list/list_test.go +++ b/internal/cmd/observability/scrape-config/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.configs); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/scrape-config/scrape_config.go b/internal/cmd/observability/scrape-config/scrape_config.go index f056c6e60..d0934ff3b 100644 --- a/internal/cmd/observability/scrape-config/scrape_config.go +++ b/internal/cmd/observability/scrape-config/scrape_config.go @@ -7,14 +7,14 @@ import ( generatepayload "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/generate-payload" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/list" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "scrape-config", Short: "Provides functionality for scrape configurations in Observability", @@ -22,15 +22,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(generatepayload.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(generatepayload.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) } diff --git a/internal/cmd/observability/scrape-config/update/update.go b/internal/cmd/observability/scrape-config/update/update.go index d07e97e1b..25b423452 100644 --- a/internal/cmd/observability/scrape-config/update/update.go +++ b/internal/cmd/observability/scrape-config/update/update.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Payload observability.UpdateScrapeConfigPayload } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", jobNameArg), Short: "Updates a scrape configuration of an Observability instance", @@ -56,20 +57,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update scrape configuration %q?", model.JobName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // The API has no status to wait on, so async mode is default - p.Info("Updated Observability scrape configuration with name %q\n", model.JobName) + params.Printer.Info("Updated Observability scrape configuration with name %q\n", model.JobName) return nil }, } diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index 9a4174db8..ce5a1cf9b 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for an OpenSearch instance", @@ -46,26 +47,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create OpenSearch credentials: %w", err) } - return outputResult(p, model.OutputFormat, model.ShowPassword, instanceLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.ShowPassword, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/opensearch/credentials/create/create_test.go b/internal/cmd/opensearch/credentials/create/create_test.go index 1424c9729..6928feefc 100644 --- a/internal/cmd/opensearch/credentials/create/create_test.go +++ b/internal/cmd/opensearch/credentials/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -271,7 +272,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/credentials/credentials.go b/internal/cmd/opensearch/credentials/credentials.go index 4ea7f3f76..3e1c17ba8 100644 --- a/internal/cmd/opensearch/credentials/credentials.go +++ b/internal/cmd/opensearch/credentials/credentials.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/credentials/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for OpenSearch credentials", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/opensearch/credentials/delete/delete.go b/internal/cmd/opensearch/credentials/delete/delete.go index 1931ad0fc..97e2fc14b 100644 --- a/internal/cmd/opensearch/credentials/delete/delete.go +++ b/internal/cmd/opensearch/credentials/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of an OpenSearch instance", @@ -43,32 +44,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } credentialsLabel, err := opensearchUtils.GetCredentialsUsername(ctx, apiClient, model.ProjectId, model.InstanceId, model.CredentialsId) if err != nil { - p.Debug(print.ErrorLevel, "get credentials user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials user name: %v", err) credentialsLabel = model.CredentialsId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete OpenSearch credentials: %w", err) } - p.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) + params.Printer.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/opensearch/credentials/delete/delete_test.go b/internal/cmd/opensearch/credentials/delete/delete_test.go index 4dcdc9dfe..350175fd2 100644 --- a/internal/cmd/opensearch/credentials/delete/delete_test.go +++ b/internal/cmd/opensearch/credentials/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/opensearch/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index fb8012012..d70edf933 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of an OpenSearch instance", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe OpenSearch credentials: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/opensearch/credentials/describe/describe_test.go b/internal/cmd/opensearch/credentials/describe/describe_test.go index 3618a4cc7..50ce776b5 100644 --- a/internal/cmd/opensearch/credentials/describe/describe_test.go +++ b/internal/cmd/opensearch/credentials/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -268,7 +269,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index b58c99796..b4d200b1e 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for an OpenSearch instance", @@ -51,13 +52,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -72,10 +73,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(credentials) == 0 { instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - p.Info("No credentials found for instance %q\n", instanceLabel) + params.Printer.Info("No credentials found for instance %q\n", instanceLabel) return nil } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentials) }, } configureFlags(cmd) diff --git a/internal/cmd/opensearch/credentials/list/list_test.go b/internal/cmd/opensearch/credentials/list/list_test.go index d6b041f57..bfe0ea554 100644 --- a/internal/cmd/opensearch/credentials/list/list_test.go +++ b/internal/cmd/opensearch/credentials/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -239,7 +240,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index 62d447f82..336a2e5ab 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -57,7 +58,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an OpenSearch instance", @@ -76,26 +77,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create an OpenSearch instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -118,7 +119,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -127,7 +128,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, projectLabel, instanceId, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, instanceId, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/opensearch/instance/create/create_test.go b/internal/cmd/opensearch/instance/create/create_test.go index 3aceed814..e6028b4d9 100644 --- a/internal/cmd/opensearch/instance/create/create_test.go +++ b/internal/cmd/opensearch/instance/create/create_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -277,7 +278,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -516,7 +517,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/instance/delete/delete.go b/internal/cmd/opensearch/instance/delete/delete.go index 40dc60461..cd7f159d3 100644 --- a/internal/cmd/opensearch/instance/delete/delete.go +++ b/internal/cmd/opensearch/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes an OpenSearch instance", @@ -41,26 +42,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/opensearch/instance/delete/delete_test.go b/internal/cmd/opensearch/instance/delete/delete_test.go index 7454c04e0..217ff1b1d 100644 --- a/internal/cmd/opensearch/instance/delete/delete_test.go +++ b/internal/cmd/opensearch/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index 1358aef39..d8722d9d5 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of an OpenSearch instance", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read OpenSearch instance: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/opensearch/instance/describe/describe_test.go b/internal/cmd/opensearch/instance/describe/describe_test.go index d4b58656f..6e17a8e85 100644 --- a/internal/cmd/opensearch/instance/describe/describe_test.go +++ b/internal/cmd/opensearch/instance/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/instance/instance.go b/internal/cmd/opensearch/instance/instance.go index 649d439ce..05d92bbc6 100644 --- a/internal/cmd/opensearch/instance/instance.go +++ b/internal/cmd/opensearch/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/instance/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for OpenSearch instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index 024619beb..0b0aa93c8 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all OpenSearch instances", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/opensearch/instance/list/list_test.go b/internal/cmd/opensearch/instance/list/list_test.go index baa22ac9f..766115689 100644 --- a/internal/cmd/opensearch/instance/list/list_test.go +++ b/internal/cmd/opensearch/instance/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/instance/update/update.go b/internal/cmd/opensearch/instance/update/update.go index 57072b0a8..85ba3f133 100644 --- a/internal/cmd/opensearch/instance/update/update.go +++ b/internal/cmd/opensearch/instance/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -56,7 +57,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates an OpenSearch instance", @@ -72,26 +73,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -114,7 +115,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -127,7 +128,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/opensearch/instance/update/update_test.go b/internal/cmd/opensearch/instance/update/update_test.go index 478199985..70168bbc2 100644 --- a/internal/cmd/opensearch/instance/update/update_test.go +++ b/internal/cmd/opensearch/instance/update/update_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -294,7 +295,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/opensearch/opensearch.go b/internal/cmd/opensearch/opensearch.go index 08103e63c..766065ed2 100644 --- a/internal/cmd/opensearch/opensearch.go +++ b/internal/cmd/opensearch/opensearch.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/plans" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "opensearch", Short: "Provides functionality for OpenSearch", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(plans.NewCmd(p)) - cmd.AddCommand(credentials.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(plans.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) } diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index 013e486e1..e2678f163 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all OpenSearch service plans", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No plans found for project %q\n", projectLabel) + params.Printer.Info("No plans found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(p, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, plans) }, } diff --git a/internal/cmd/opensearch/plans/plans_test.go b/internal/cmd/opensearch/plans/plans_test.go index a1d162d4a..0b4f95cec 100644 --- a/internal/cmd/opensearch/plans/plans_test.go +++ b/internal/cmd/opensearch/plans/plans_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/organization/member/add/add.go b/internal/cmd/organization/member/add/add.go index b03ae495f..246a7f27f 100644 --- a/internal/cmd/organization/member/add/add.go +++ b/internal/cmd/organization/member/add/add.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -32,7 +33,7 @@ type inputModel struct { Role *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("add %s", subjectArg), Short: "Adds a member to an organization", @@ -51,21 +52,21 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to add the %s role to %s on organization with ID %q?", *model.Role, model.Subject, *model.OrganizationId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("add member: %w", err) } - p.Info("Member added") + params.Printer.Info("Member added") return nil }, } diff --git a/internal/cmd/organization/member/add/add_test.go b/internal/cmd/organization/member/add/add_test.go index 996439285..a98f06ecc 100644 --- a/internal/cmd/organization/member/add/add_test.go +++ b/internal/cmd/organization/member/add/add_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -125,7 +126,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index e3376d584..105f6b14a 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -38,7 +39,7 @@ type inputModel struct { SortBy string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists members of an organization", @@ -57,13 +58,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } members := *resp.Members if len(members) == 0 { - p.Info("No members found for organization with ID %q\n", *model.OrganizationId) + params.Printer.Info("No members found for organization with ID %q\n", *model.OrganizationId) return nil } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { members = members[:*model.Limit] } - return outputResult(p, model.OutputFormat, model.SortBy, members) + return outputResult(params.Printer, model.OutputFormat, model.SortBy, members) }, } configureFlags(cmd) diff --git a/internal/cmd/organization/member/list/list_test.go b/internal/cmd/organization/member/list/list_test.go index 2c73681c0..ff90898b2 100644 --- a/internal/cmd/organization/member/list/list_test.go +++ b/internal/cmd/organization/member/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -237,7 +238,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.sortBy, tt.args.members); (err != nil) != tt.wantErr { diff --git a/internal/cmd/organization/member/member.go b/internal/cmd/organization/member/member.go index cf7c515d8..fe2b67e5d 100644 --- a/internal/cmd/organization/member/member.go +++ b/internal/cmd/organization/member/member.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/organization/member/add" "github.com/stackitcloud/stackit-cli/internal/cmd/organization/member/list" "github.com/stackitcloud/stackit-cli/internal/cmd/organization/member/remove" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "member", Short: "Manages organization members", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(add.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(remove.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(add.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(remove.NewCmd(params)) } diff --git a/internal/cmd/organization/member/remove/remove.go b/internal/cmd/organization/member/remove/remove.go index de9a09ceb..7ff3c9147 100644 --- a/internal/cmd/organization/member/remove/remove.go +++ b/internal/cmd/organization/member/remove/remove.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -35,7 +36,7 @@ type inputModel struct { Force bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("remove %s", subjectArg), Short: "Removes a member from an organization", @@ -55,13 +56,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Force { prompt = fmt.Sprintf("%s This will also remove other roles of the subject that would stop the removal of the requested role", prompt) } - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("remove member: %w", err) } - p.Info("Member removed") + params.Printer.Info("Member removed") return nil }, } diff --git a/internal/cmd/organization/member/remove/remove_test.go b/internal/cmd/organization/member/remove/remove_test.go index fff1648f8..1b2a3e702 100644 --- a/internal/cmd/organization/member/remove/remove_test.go +++ b/internal/cmd/organization/member/remove/remove_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/organization/organization.go b/internal/cmd/organization/organization.go index 3d34090fd..e7d1376b5 100644 --- a/internal/cmd/organization/organization.go +++ b/internal/cmd/organization/organization.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/organization/member" "github.com/stackitcloud/stackit-cli/internal/cmd/organization/role" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "organization", Short: "Manages organizations", @@ -23,11 +23,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(member.NewCmd(p)) - cmd.AddCommand(role.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(member.NewCmd(params)) + cmd.AddCommand(role.NewCmd(params)) } diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index c9e175323..c8925c90e 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists roles and permissions of an organization", @@ -52,13 +53,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } roles := *resp.Roles if len(roles) == 0 { - p.Info("No roles found for organization with ID %q\n", *model.OrganizationId) + params.Printer.Info("No roles found for organization with ID %q\n", *model.OrganizationId) return nil } @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { roles = roles[:*model.Limit] } - return outputRolesResult(p, model.OutputFormat, roles) + return outputRolesResult(params.Printer, model.OutputFormat, roles) }, } configureFlags(cmd) diff --git a/internal/cmd/organization/role/list/list_test.go b/internal/cmd/organization/role/list/list_test.go index 1268fb039..5633b3f60 100644 --- a/internal/cmd/organization/role/list/list_test.go +++ b/internal/cmd/organization/role/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -199,7 +200,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputRolesResult(p, tt.args.outputFormat, tt.args.roles); (err != nil) != tt.wantErr { diff --git a/internal/cmd/organization/role/role.go b/internal/cmd/organization/role/role.go index f32189bf5..286783661 100644 --- a/internal/cmd/organization/role/role.go +++ b/internal/cmd/organization/role/role.go @@ -2,14 +2,14 @@ package role import ( "github.com/stackitcloud/stackit-cli/internal/cmd/organization/role/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "role", Short: "Manages organization roles", @@ -17,10 +17,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/params/cmd_params.go b/internal/cmd/params/cmd_params.go new file mode 100644 index 000000000..572c80706 --- /dev/null +++ b/internal/cmd/params/cmd_params.go @@ -0,0 +1,10 @@ +package params + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/print" +) + +type CmdParams struct { + Printer *print.Printer + CliVersion string +} diff --git a/internal/cmd/postgresflex/backup/backup.go b/internal/cmd/postgresflex/backup/backup.go index 85b08b5b2..bac6c4a72 100644 --- a/internal/cmd/postgresflex/backup/backup.go +++ b/internal/cmd/postgresflex/backup/backup.go @@ -1,17 +1,17 @@ package backup import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/backup/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/backup/list" updateschedule "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/backup/update-schedule" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "backup", Short: "Provides functionality for PostgreSQL Flex instance backups", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(updateschedule.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(updateschedule.NewCmd(params)) } diff --git a/internal/cmd/postgresflex/backup/describe/describe.go b/internal/cmd/postgresflex/backup/describe/describe.go index dbb8fe4ce..758fb955a 100644 --- a/internal/cmd/postgresflex/backup/describe/describe.go +++ b/internal/cmd/postgresflex/backup/describe/describe.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -37,7 +38,7 @@ type inputModel struct { BackupId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupIdArg), Short: "Shows details of a backup for a PostgreSQL Flex instance", @@ -53,13 +54,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(backupIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe backup for PostgreSQL Flex instance: %w", err) } - return outputResult(p, model.OutputFormat, *resp.Item) + return outputResult(params.Printer, model.OutputFormat, *resp.Item) }, } configureFlags(cmd) diff --git a/internal/cmd/postgresflex/backup/describe/describe_test.go b/internal/cmd/postgresflex/backup/describe/describe_test.go index 5c3479254..6e47eabb0 100644 --- a/internal/cmd/postgresflex/backup/describe/describe_test.go +++ b/internal/cmd/postgresflex/backup/describe/describe_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -262,7 +263,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index 7e1d6c398..3f463a670 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -38,7 +39,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all backups which are available for a PostgreSQL Flex instance", @@ -57,20 +58,20 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, *model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { backups = backups[:*model.Limit] } - return outputResult(p, model.OutputFormat, backups) + return outputResult(params.Printer, model.OutputFormat, backups) }, } diff --git a/internal/cmd/postgresflex/backup/list/list_test.go b/internal/cmd/postgresflex/backup/list/list_test.go index f34d184cf..9dee772fe 100644 --- a/internal/cmd/postgresflex/backup/list/list_test.go +++ b/internal/cmd/postgresflex/backup/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -243,7 +244,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go index 9d5ff6626..a9f3bb70d 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { BackupSchedule *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update-schedule", Short: "Updates backup schedule for a PostgreSQL Flex instance", @@ -43,26 +44,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, *model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update backup schedule of instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index 1d753cfeb..b8a31cd4e 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -40,7 +41,7 @@ type inputModel struct { RecoveryDate *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("clone %s", instanceIdArg), Short: "Clones a PostgreSQL Flex instance", @@ -61,26 +62,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to clone instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -99,7 +100,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Cloning instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) if err != nil { @@ -108,7 +109,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, instanceLabel, instanceId, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, instanceLabel, instanceId, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/postgresflex/instance/clone/clone_test.go b/internal/cmd/postgresflex/instance/clone/clone_test.go index eed05d8d3..04dbd1954 100644 --- a/internal/cmd/postgresflex/instance/clone/clone_test.go +++ b/internal/cmd/postgresflex/instance/clone/clone_test.go @@ -9,6 +9,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -302,7 +303,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -553,7 +554,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 191d982f5..32301a4d4 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -57,7 +58,7 @@ type inputModel struct { Type *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a PostgreSQL Flex instance", @@ -77,26 +78,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a PostgreSQL Flex instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -124,7 +125,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) if err != nil { @@ -133,7 +134,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, projectLabel, instanceId, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, instanceId, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/postgresflex/instance/create/create_test.go b/internal/cmd/postgresflex/instance/create/create_test.go index 6adbfb09b..32d63d5d8 100644 --- a/internal/cmd/postgresflex/instance/create/create_test.go +++ b/internal/cmd/postgresflex/instance/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -250,7 +251,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -547,7 +548,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/postgresflex/instance/delete/delete.go b/internal/cmd/postgresflex/instance/delete/delete.go index 4c9077a6a..acf78c5ba 100644 --- a/internal/cmd/postgresflex/instance/delete/delete.go +++ b/internal/cmd/postgresflex/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { ForceDelete bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a PostgreSQL Flex instance", @@ -52,26 +53,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -92,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -112,7 +113,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Forcing deletion of instance") _, err = wait.ForceDeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -132,7 +133,7 @@ func NewCmd(p *print.Printer) *cobra.Command { operationState = "Triggered forced deletion of" } } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/postgresflex/instance/delete/delete_test.go b/internal/cmd/postgresflex/instance/delete/delete_test.go index 23f662a5d..13f33bfbd 100644 --- a/internal/cmd/postgresflex/instance/delete/delete_test.go +++ b/internal/cmd/postgresflex/instance/delete/delete_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -171,7 +172,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/postgresflex/instance/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index 2d59f5306..13604fb58 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a PostgreSQL Flex instance", @@ -47,12 +48,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -64,7 +65,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read PostgreSQL Flex instance: %w", err) } - return outputResult(p, model.OutputFormat, resp.Item) + return outputResult(params.Printer, model.OutputFormat, resp.Item) }, } return cmd diff --git a/internal/cmd/postgresflex/instance/describe/describe_test.go b/internal/cmd/postgresflex/instance/describe/describe_test.go index c6945faa1..69e100822 100644 --- a/internal/cmd/postgresflex/instance/describe/describe_test.go +++ b/internal/cmd/postgresflex/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -259,7 +260,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/instance/instance.go b/internal/cmd/postgresflex/instance/instance.go index 4a005c13a..f43979195 100644 --- a/internal/cmd/postgresflex/instance/instance.go +++ b/internal/cmd/postgresflex/instance/instance.go @@ -1,6 +1,7 @@ package instance import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/clone" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/create" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/delete" @@ -8,13 +9,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for PostgreSQL Flex instances", @@ -22,15 +22,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(clone.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(clone.NewCmd(params)) } diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index 040a9de6b..d3870566b 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all PostgreSQL Flex instances", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -68,12 +69,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get PostgreSQL Flex instances: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } instances := *resp.Items @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/postgresflex/instance/list/list_test.go b/internal/cmd/postgresflex/instance/list/list_test.go index 09880f92c..3cfc85652 100644 --- a/internal/cmd/postgresflex/instance/list/list_test.go +++ b/internal/cmd/postgresflex/instance/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 66022fb1d..980a358df 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -54,7 +55,7 @@ type inputModel struct { Type *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a PostgreSQL Flex instance", @@ -71,26 +72,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q? (This may cause downtime)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -109,7 +110,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) if err != nil { @@ -118,7 +119,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, instanceLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/postgresflex/instance/update/update_test.go b/internal/cmd/postgresflex/instance/update/update_test.go index 46b157bbe..0c4ed96b6 100644 --- a/internal/cmd/postgresflex/instance/update/update_test.go +++ b/internal/cmd/postgresflex/instance/update/update_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -282,7 +283,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -620,7 +621,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index 8d53c2017..cbf87326d 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -45,7 +47,7 @@ type flavorStorages struct { Storages *postgresflex.ListStoragesResponse `json:"storages"` } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "options", Short: "Lists PostgreSQL Flex options", @@ -64,19 +66,19 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } // Call API - err = buildAndExecuteRequest(ctx, p, model, apiClient) + err = buildAndExecuteRequest(ctx, params.Printer, model, apiClient) if err != nil { return fmt.Errorf("get PostgreSQL Flex options: %w", err) } diff --git a/internal/cmd/postgresflex/options/options_test.go b/internal/cmd/postgresflex/options/options_test.go index 3854aeaca..7643dad69 100644 --- a/internal/cmd/postgresflex/options/options_test.go +++ b/internal/cmd/postgresflex/options/options_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -166,7 +167,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -290,7 +291,7 @@ func TestBuildAndExecuteRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := &print.Printer{} - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) p.Cmd = cmd client := &postgresFlexClientMocked{ listFlavorsFails: tt.listFlavorsFails, @@ -360,7 +361,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.flavors, tt.args.versions, tt.args.storages); (err != nil) != tt.wantErr { diff --git a/internal/cmd/postgresflex/postgresflex.go b/internal/cmd/postgresflex/postgresflex.go index 7820cded2..3a86086c2 100644 --- a/internal/cmd/postgresflex/postgresflex.go +++ b/internal/cmd/postgresflex/postgresflex.go @@ -1,18 +1,18 @@ package postgresflex import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/backup" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/options" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "postgresflex", Aliases: []string{"postgresqlflex"}, @@ -21,13 +21,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(user.NewCmd(p)) - cmd.AddCommand(options.NewCmd(p)) - cmd.AddCommand(backup.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(user.NewCmd(params)) + cmd.AddCommand(options.NewCmd(params)) + cmd.AddCommand(backup.NewCmd(params)) } diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index ce2912e3a..8808e676e 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -37,7 +38,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a PostgreSQL Flex user", @@ -58,26 +59,26 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -90,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create PostgreSQL Flex user: %w", err) } - return outputResult(p, model.OutputFormat, instanceLabel, resp) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, resp) }, } diff --git a/internal/cmd/postgresflex/user/create/create_test.go b/internal/cmd/postgresflex/user/create/create_test.go index 6c0fe71ba..e75d785e9 100644 --- a/internal/cmd/postgresflex/user/create/create_test.go +++ b/internal/cmd/postgresflex/user/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -258,7 +259,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/user/delete/delete.go b/internal/cmd/postgresflex/user/delete/delete.go index f9f166291..2ed42cd8f 100644 --- a/internal/cmd/postgresflex/user/delete/delete.go +++ b/internal/cmd/postgresflex/user/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", userIdArg), Short: "Deletes a PostgreSQL Flex user", @@ -47,32 +48,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId, model.UserId) if err != nil { - p.Debug(print.ErrorLevel, "get user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete PostgreSQL Flex user: %w", err) } - p.Info("Deleted user %q of instance %q\n", userLabel, instanceLabel) + params.Printer.Info("Deleted user %q of instance %q\n", userLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/postgresflex/user/delete/delete_test.go b/internal/cmd/postgresflex/user/delete/delete_test.go index cd6dfa986..867635736 100644 --- a/internal/cmd/postgresflex/user/delete/delete_test.go +++ b/internal/cmd/postgresflex/user/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -160,7 +161,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/postgresflex/user/describe/describe.go b/internal/cmd/postgresflex/user/describe/describe.go index cc02a616b..75e239d68 100644 --- a/internal/cmd/postgresflex/user/describe/describe.go +++ b/internal/cmd/postgresflex/user/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", userIdArg), Short: "Shows details of a PostgreSQL Flex user", @@ -52,13 +53,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get MongoDB Flex user: %w", err) } - return outputResult(p, model.OutputFormat, *resp.Item) + return outputResult(params.Printer, model.OutputFormat, *resp.Item) }, } diff --git a/internal/cmd/postgresflex/user/describe/describe_test.go b/internal/cmd/postgresflex/user/describe/describe_test.go index 4ff8819b9..8b91301b7 100644 --- a/internal/cmd/postgresflex/user/describe/describe_test.go +++ b/internal/cmd/postgresflex/user/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" @@ -159,7 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -259,7 +260,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index 0b530674d..3c8f79e77 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all PostgreSQL Flex users of an instance", @@ -51,13 +52,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,10 +72,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if resp.Items == nil || len(*resp.Items) == 0 { instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, *model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } - p.Info("No users found for instance %q\n", instanceLabel) + params.Printer.Info("No users found for instance %q\n", instanceLabel) return nil } users := *resp.Items @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { users = users[:*model.Limit] } - return outputResult(p, model.OutputFormat, users) + return outputResult(params.Printer, model.OutputFormat, users) }, } diff --git a/internal/cmd/postgresflex/user/list/list_test.go b/internal/cmd/postgresflex/user/list/list_test.go index ed82bbb26..20adc9e13 100644 --- a/internal/cmd/postgresflex/user/list/list_test.go +++ b/internal/cmd/postgresflex/user/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -222,7 +223,7 @@ func Test_outputResult(t *testing.T) { }}}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index d2d240585..0d324a07b 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reset-password %s", userIdArg), Short: "Resets the password of a PostgreSQL Flex user", @@ -48,32 +49,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId, model.UserId) if err != nil { - p.Debug(print.ErrorLevel, "get user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -86,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("reset PostgreSQL Flex user password: %w", err) } - return outputResult(p, model.OutputFormat, userLabel, instanceLabel, user) + return outputResult(params.Printer, model.OutputFormat, userLabel, instanceLabel, user) }, } diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go index 8cde43c41..b12c31d3a 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" @@ -159,7 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -260,7 +261,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/user/update/update.go b/internal/cmd/postgresflex/user/update/update.go index 47872ecc5..5466348d3 100644 --- a/internal/cmd/postgresflex/user/update/update.go +++ b/internal/cmd/postgresflex/user/update/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", userIdArg), Short: "Updates a PostgreSQL Flex user", @@ -45,32 +46,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, nil), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := postgresflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := postgresflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId, model.UserId) if err != nil { - p.Debug(print.ErrorLevel, "get user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update user %q of instance %q?", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update PostgreSQL Flex user: %w", err) } - p.Info("Updated user %q of instance %q\n", userLabel, instanceLabel) + params.Printer.Info("Updated user %q of instance %q\n", userLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/postgresflex/user/update/update_test.go b/internal/cmd/postgresflex/user/update/update_test.go index fb0fe9cd3..787dc992d 100644 --- a/internal/cmd/postgresflex/user/update/update_test.go +++ b/internal/cmd/postgresflex/user/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -169,7 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/postgresflex/user/user.go b/internal/cmd/postgresflex/user/user.go index 018244197..af9d371ef 100644 --- a/internal/cmd/postgresflex/user/user.go +++ b/internal/cmd/postgresflex/user/user.go @@ -1,6 +1,7 @@ package user import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/create" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/describe" @@ -8,13 +9,12 @@ import ( resetpassword "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/reset-password" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "user", Short: "Provides functionality for PostgreSQL Flex users", @@ -22,15 +22,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(resetpassword.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(resetpassword.NewCmd(params)) } diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index 99f62fadd..d8c687bbd 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -7,6 +7,7 @@ import ( "regexp" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -41,7 +42,7 @@ type inputModel struct { NetworkAreaId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a STACKIT project", @@ -66,20 +67,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a project under the parent with ID %q?", *model.ParentId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -95,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create project: %w", err) } - return outputResult(p, *model, resp) + return outputResult(params.Printer, *model, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/project/create/create_test.go b/internal/cmd/project/create/create_test.go index 8c977d3c6..f6cf9fbde 100644 --- a/internal/cmd/project/create/create_test.go +++ b/internal/cmd/project/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -177,7 +178,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -374,7 +375,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/project/delete/delete.go b/internal/cmd/project/delete/delete.go index 9b3178bce..c0d4e121e 100644 --- a/internal/cmd/project/delete/delete.go +++ b/internal/cmd/project/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -20,7 +21,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Short: "Deletes a STACKIT project", @@ -36,26 +37,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete the project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -68,8 +69,8 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete project: %w", err) } - p.Info("Deleted project %q\n", projectLabel) - p.Warn("%s", fmt.Sprintf("%s\n%s\n", + params.Printer.Info("Deleted project %q\n", projectLabel) + params.Printer.Warn("%s", fmt.Sprintf("%s\n%s\n", "If this was your default project, consider configuring a new project ID by running:", " $ stackit config set --project-id ", )) diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index 26162f859..7fe4c7b9b 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -31,7 +32,7 @@ type inputModel struct { IncludeParents bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "describe", Short: "Shows details of a STACKIT project", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -68,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read project details: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/project/describe/describe_test.go b/internal/cmd/project/describe/describe_test.go index 3c2e5f658..f32dbc491 100644 --- a/internal/cmd/project/describe/describe_test.go +++ b/internal/cmd/project/describe/describe_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -238,7 +239,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.project); (err != nil) != tt.wantErr { diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 4459558ad..c2aaccad5 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -43,7 +44,7 @@ type inputModel struct { PageSize int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists STACKIT projects", @@ -65,13 +66,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -82,11 +83,11 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } if len(projects) == 0 { - p.Info("No projects found matching the criteria\n") + params.Printer.Info("No projects found matching the criteria\n") return nil } - return outputResult(p, model.OutputFormat, projects) + return outputResult(params.Printer, model.OutputFormat, projects) }, } configureFlags(cmd) diff --git a/internal/cmd/project/list/list_test.go b/internal/cmd/project/list/list_test.go index 47db45bac..79397409f 100644 --- a/internal/cmd/project/list/list_test.go +++ b/internal/cmd/project/list/list_test.go @@ -12,6 +12,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -194,7 +195,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -539,7 +540,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/project/member/add/add.go b/internal/cmd/project/member/add/add.go index 23436f039..5f9456602 100644 --- a/internal/cmd/project/member/add/add.go +++ b/internal/cmd/project/member/add/add.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Role *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("add %s", subjectArg), Short: "Adds a member to a project", @@ -52,26 +53,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to add the role %q to %s on project %q?", *model.Role, model.Subject, projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("add member: %w", err) } - p.Info("Added the role %q to %s on project %q\n", utils.PtrString(model.Role), model.Subject, projectLabel) + params.Printer.Info("Added the role %q to %s on project %q\n", utils.PtrString(model.Role), model.Subject, projectLabel) return nil }, } diff --git a/internal/cmd/project/member/add/add_test.go b/internal/cmd/project/member/add/add_test.go index e9fc2b4d6..9d24461bf 100644 --- a/internal/cmd/project/member/add/add_test.go +++ b/internal/cmd/project/member/add/add_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -124,7 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index 861423dc5..c7c220121 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -37,7 +38,7 @@ type inputModel struct { SortBy string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists members of a project", @@ -56,13 +57,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -75,12 +76,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } members := *resp.Members if len(members) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No members found for project %q\n", projectLabel) + params.Printer.Info("No members found for project %q\n", projectLabel) return nil } @@ -89,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { members = members[:*model.Limit] } - return outputResult(p, *model, members) + return outputResult(params.Printer, *model, members) }, } configureFlags(cmd) diff --git a/internal/cmd/project/member/list/list_test.go b/internal/cmd/project/member/list/list_test.go index 4aecdee12..a710f7b5d 100644 --- a/internal/cmd/project/member/list/list_test.go +++ b/internal/cmd/project/member/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -240,7 +241,7 @@ func Test_outputResult(t *testing.T) { false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.members); (err != nil) != tt.wantErr { diff --git a/internal/cmd/project/member/member.go b/internal/cmd/project/member/member.go index 658f6ff7c..cef271820 100644 --- a/internal/cmd/project/member/member.go +++ b/internal/cmd/project/member/member.go @@ -1,17 +1,17 @@ package member import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/project/member/add" "github.com/stackitcloud/stackit-cli/internal/cmd/project/member/list" "github.com/stackitcloud/stackit-cli/internal/cmd/project/member/remove" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "member", Short: "Manages project members", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(add.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(remove.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(add.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(remove.NewCmd(params)) } diff --git a/internal/cmd/project/member/remove/remove.go b/internal/cmd/project/member/remove/remove.go index 56004a03b..9fc60a116 100644 --- a/internal/cmd/project/member/remove/remove.go +++ b/internal/cmd/project/member/remove/remove.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Force bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("remove %s", subjectArg), Short: "Removes a member from a project", @@ -55,20 +56,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Force { prompt = fmt.Sprintf("%s This will also remove other roles of the subject that would stop the removal of the requested role", prompt) } - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -90,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("remove member: %w", err) } - p.Info("Removed the role %q from %s on project %q\n", utils.PtrString(model.Role), model.Subject, projectLabel) + params.Printer.Info("Removed the role %q from %s on project %q\n", utils.PtrString(model.Role), model.Subject, projectLabel) return nil }, } diff --git a/internal/cmd/project/member/remove/remove_test.go b/internal/cmd/project/member/remove/remove_test.go index 626efe0d6..c3cb414e1 100644 --- a/internal/cmd/project/member/remove/remove_test.go +++ b/internal/cmd/project/member/remove/remove_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/project/project.go b/internal/cmd/project/project.go index ded8f8444..f888fbbc5 100644 --- a/internal/cmd/project/project.go +++ b/internal/cmd/project/project.go @@ -3,6 +3,7 @@ package project import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/project/create" "github.com/stackitcloud/stackit-cli/internal/cmd/project/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/project/describe" @@ -11,13 +12,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/project/role" "github.com/stackitcloud/stackit-cli/internal/cmd/project/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "project", Short: "Manages projects", @@ -28,16 +28,16 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(member.NewCmd(p)) - cmd.AddCommand(role.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(member.NewCmd(params)) + cmd.AddCommand(role.NewCmd(params)) } diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index 4b98bf977..9ffd80067 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists roles and permissions of a project", @@ -51,13 +52,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -70,12 +71,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } roles := *resp.Roles if len(roles) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No roles found for project %q\n", projectLabel) + params.Printer.Info("No roles found for project %q\n", projectLabel) return nil } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { roles = roles[:*model.Limit] } - return outputRolesResult(p, model.OutputFormat, roles) + return outputRolesResult(params.Printer, model.OutputFormat, roles) }, } configureFlags(cmd) diff --git a/internal/cmd/project/role/list/list_test.go b/internal/cmd/project/role/list/list_test.go index 4e8744528..b1f14f432 100644 --- a/internal/cmd/project/role/list/list_test.go +++ b/internal/cmd/project/role/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -196,7 +197,7 @@ func Test_outputRolesResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputRolesResult(p, tt.args.outputFormat, tt.args.roles); (err != nil) != tt.wantErr { diff --git a/internal/cmd/project/role/role.go b/internal/cmd/project/role/role.go index b460e54b7..bb0781f08 100644 --- a/internal/cmd/project/role/role.go +++ b/internal/cmd/project/role/role.go @@ -1,15 +1,15 @@ package role import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/project/role/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "role", Short: "Manages project roles", @@ -17,10 +17,10 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/project/update/update.go b/internal/cmd/project/update/update.go index ea91ccdae..e217f55f5 100644 --- a/internal/cmd/project/update/update.go +++ b/internal/cmd/project/update/update.go @@ -5,6 +5,7 @@ import ( "fmt" "regexp" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "Updates a STACKIT project", @@ -55,26 +56,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update project: %w", err) } - p.Info("Updated project %q\n", projectLabel) + params.Printer.Info("Updated project %q\n", projectLabel) return nil }, } diff --git a/internal/cmd/project/update/update_test.go b/internal/cmd/project/update/update_test.go index 836110963..289a3b752 100644 --- a/internal/cmd/project/update/update_test.go +++ b/internal/cmd/project/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -131,7 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/public-ip/associate/associate.go b/internal/cmd/public-ip/associate/associate.go index 9ce91a954..369efc526 100644 --- a/internal/cmd/public-ip/associate/associate.go +++ b/internal/cmd/public-ip/associate/associate.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { AssociatedResourceId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("associate %s", publicIpIdArg), Short: "Associates a Public IP with a network interface or a virtual IP", @@ -44,20 +45,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) if err != nil { - p.Debug(print.ErrorLevel, "get public IP: %v", err) + params.Printer.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId } else if publicIpLabel == "" { publicIpLabel = model.PublicIpId @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to associate public IP %q with resource %v?", publicIpLabel, *model.AssociatedResourceId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("associate public IP: %w", err) } - p.Outputf("Associated public IP %q with resource %v.\n", publicIpLabel, utils.PtrString(resp.GetNetworkInterface())) + params.Printer.Outputf("Associated public IP %q with resource %v.\n", publicIpLabel, utils.PtrString(resp.GetNetworkInterface())) return nil }, } diff --git a/internal/cmd/public-ip/associate/associate_test.go b/internal/cmd/public-ip/associate/associate_test.go index 99b51c3e6..bc2b890e7 100644 --- a/internal/cmd/public-ip/associate/associate_test.go +++ b/internal/cmd/public-ip/associate/associate_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index 0ba5c6a84..e072655db 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Public IP", @@ -52,20 +53,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId @@ -73,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a public IP for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -86,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create public IP: %w", err) } - return outputResult(p, model.OutputFormat, projectLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, projectLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/public-ip/create/create_test.go b/internal/cmd/public-ip/create/create_test.go index b204d561f..be2653938 100644 --- a/internal/cmd/public-ip/create/create_test.go +++ b/internal/cmd/public-ip/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -142,7 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -232,7 +233,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.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.publicIp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/public-ip/delete/delete.go b/internal/cmd/public-ip/delete/delete.go index 57a427dd6..5382526e7 100644 --- a/internal/cmd/public-ip/delete/delete.go +++ b/internal/cmd/public-ip/delete/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -25,7 +26,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", publicIpIdArg), Short: "Deletes a Public IP", @@ -42,20 +43,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) if err != nil { - p.Debug(print.ErrorLevel, "get public IP: %v", err) + params.Printer.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId } else if publicIpLabel == "" { publicIpLabel = model.PublicIpId @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete public IP %q? (This cannot be undone)", publicIpLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete public IP: %w", err) } - p.Info("Deleted public IP %q\n", publicIpLabel) + params.Printer.Info("Deleted public IP %q\n", publicIpLabel) return nil }, } diff --git a/internal/cmd/public-ip/delete/delete_test.go b/internal/cmd/public-ip/delete/delete_test.go index 1acd8b016..667578fb0 100644 --- a/internal/cmd/public-ip/delete/delete_test.go +++ b/internal/cmd/public-ip/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/public-ip/describe/describe.go b/internal/cmd/public-ip/describe/describe.go index 820d9ff61..18f96d46d 100644 --- a/internal/cmd/public-ip/describe/describe.go +++ b/internal/cmd/public-ip/describe/describe.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", publicIpIdArg), Short: "Shows details of a Public IP", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read public IP: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } return cmd diff --git a/internal/cmd/public-ip/describe/describe_test.go b/internal/cmd/public-ip/describe/describe_test.go index 44ab876ff..f69ba8dbb 100644 --- a/internal/cmd/public-ip/describe/describe_test.go +++ b/internal/cmd/public-ip/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -234,7 +235,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.publicIp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/public-ip/disassociate/disassociate.go b/internal/cmd/public-ip/disassociate/disassociate.go index f15bd7efd..cdd427605 100644 --- a/internal/cmd/public-ip/disassociate/disassociate.go +++ b/internal/cmd/public-ip/disassociate/disassociate.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disassociate %s", publicIpIdArg), Short: "Disassociates a Public IP from a network interface or a virtual IP", @@ -40,20 +41,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } publicIpLabel, associatedResourceId, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) if err != nil { - p.Debug(print.ErrorLevel, "get public IP: %v", err) + params.Printer.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId } else if publicIpLabel == "" { publicIpLabel = model.PublicIpId @@ -61,7 +62,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to disassociate public IP %q from the associated resource %q?", publicIpLabel, associatedResourceId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("disassociate public IP: %w", err) } - p.Outputf("Disassociated public IP %q from the associated resource %q.\n", publicIpLabel, associatedResourceId) + params.Printer.Outputf("Disassociated public IP %q from the associated resource %q.\n", publicIpLabel, associatedResourceId) return nil }, } diff --git a/internal/cmd/public-ip/disassociate/disassociate_test.go b/internal/cmd/public-ip/disassociate/disassociate_test.go index e4478b0c7..956be6b23 100644 --- a/internal/cmd/public-ip/disassociate/disassociate_test.go +++ b/internal/cmd/public-ip/disassociate/disassociate_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/google/go-cmp/cmp" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/public-ip/list/list.go b/internal/cmd/public-ip/list/list.go index 19c225198..df57f864c 100644 --- a/internal/cmd/public-ip/list/list.go +++ b/internal/cmd/public-ip/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Public IPs of a project", @@ -58,13 +59,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,14 +78,14 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId } - p.Info("No public IPs found for project %q\n", projectLabel) + params.Printer.Info("No public IPs found for project %q\n", projectLabel) return nil } @@ -94,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/public-ip/list/list_test.go b/internal/cmd/public-ip/list/list_test.go index 0644d83e8..a6fe99a48 100644 --- a/internal/cmd/public-ip/list/list_test.go +++ b/internal/cmd/public-ip/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -132,7 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -220,7 +221,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.publicIps); (err != nil) != tt.wantErr { diff --git a/internal/cmd/public-ip/public-ip.go b/internal/cmd/public-ip/public-ip.go index 6259759a8..3be1ac1c4 100644 --- a/internal/cmd/public-ip/public-ip.go +++ b/internal/cmd/public-ip/public-ip.go @@ -1,6 +1,7 @@ package publicip import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/associate" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/create" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/delete" @@ -9,13 +10,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/list" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "public-ip", Short: "Provides functionality for public IPs", @@ -23,16 +23,16 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(associate.NewCmd(p)) - cmd.AddCommand(disassociate.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(associate.NewCmd(params)) + cmd.AddCommand(disassociate.NewCmd(params)) } diff --git a/internal/cmd/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go index d3bd1a86c..0e9a2180a 100644 --- a/internal/cmd/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -33,7 +34,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", publicIpIdArg), Short: "Updates a Public IP", @@ -51,26 +52,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) if err != nil { - p.Debug(print.ErrorLevel, "get public IP: %v", err) + params.Printer.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update public IP %q?", publicIpLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update public IP: %w", err) } - return outputResult(p, model, publicIpLabel, resp) + return outputResult(params.Printer, model, publicIpLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/public-ip/update/update_test.go b/internal/cmd/public-ip/update/update_test.go index 9590a858a..87c598665 100644 --- a/internal/cmd/public-ip/update/update_test.go +++ b/internal/cmd/public-ip/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -145,7 +146,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/quota/list/list.go b/internal/cmd/quota/list/list.go index 2e7a307c4..756c10ff5 100644 --- a/internal/cmd/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -23,7 +24,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists quotas", @@ -37,20 +38,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } else if projectLabel == "" { projectLabel = model.ProjectId @@ -65,9 +66,9 @@ func NewCmd(p *print.Printer) *cobra.Command { } if items := response.Quotas; items == nil { - p.Info("No quotas found for project %q", projectLabel) + params.Printer.Info("No quotas found for project %q", projectLabel) } else { - if err := outputResult(p, model.OutputFormat, items); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, items); err != nil { return fmt.Errorf("output quotas: %w", err) } } diff --git a/internal/cmd/quota/list/list_test.go b/internal/cmd/quota/list/list_test.go index 1daa3fcff..ab2cdd8ea 100644 --- a/internal/cmd/quota/list/list_test.go +++ b/internal/cmd/quota/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -95,7 +96,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -187,7 +188,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.quotas); (err != nil) != tt.wantErr { diff --git a/internal/cmd/quota/quota.go b/internal/cmd/quota/quota.go index bd71be405..ff323e97e 100644 --- a/internal/cmd/quota/quota.go +++ b/internal/cmd/quota/quota.go @@ -1,16 +1,16 @@ package quota import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/quota/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "quota", Short: "Manage server quotas", @@ -18,12 +18,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand( - list.NewCmd(p), + list.NewCmd(params), ) } diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index bc4e069f4..0cbe75a6f 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for a RabbitMQ instance", @@ -46,26 +47,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := rabbitmqUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create RabbitMQ credentials: %w", err) } - return outputResult(p, *model, instanceLabel, resp) + return outputResult(params.Printer, *model, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/rabbitmq/credentials/create/create_test.go b/internal/cmd/rabbitmq/credentials/create/create_test.go index 1c053d029..84e65eaa0 100644 --- a/internal/cmd/rabbitmq/credentials/create/create_test.go +++ b/internal/cmd/rabbitmq/credentials/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -243,7 +244,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/credentials/credentials.go b/internal/cmd/rabbitmq/credentials/credentials.go index 38ec2c552..80c06fb8e 100644 --- a/internal/cmd/rabbitmq/credentials/credentials.go +++ b/internal/cmd/rabbitmq/credentials/credentials.go @@ -1,18 +1,18 @@ package credentials import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials/create" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for RabbitMQ credentials", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/rabbitmq/credentials/delete/delete.go b/internal/cmd/rabbitmq/credentials/delete/delete.go index 682a0eed8..433348260 100644 --- a/internal/cmd/rabbitmq/credentials/delete/delete.go +++ b/internal/cmd/rabbitmq/credentials/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of a RabbitMQ instance", @@ -43,32 +44,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := rabbitmqUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } credentialsLabel, err := rabbitmqUtils.GetCredentialsUsername(ctx, apiClient, model.ProjectId, model.InstanceId, model.CredentialsId) if err != nil { - p.Debug(print.ErrorLevel, "get credentials user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials user name: %v", err) credentialsLabel = model.CredentialsId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete RabbitMQ credentials: %w", err) } - p.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) + params.Printer.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/rabbitmq/credentials/delete/delete_test.go b/internal/cmd/rabbitmq/credentials/delete/delete_test.go index 24739b018..e716f7c72 100644 --- a/internal/cmd/rabbitmq/credentials/delete/delete_test.go +++ b/internal/cmd/rabbitmq/credentials/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/rabbitmq/credentials/describe/describe.go b/internal/cmd/rabbitmq/credentials/describe/describe.go index 85159848d..9ad4dcc9f 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of a RabbitMQ instance", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe RabbitMQ credentials: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/rabbitmq/credentials/describe/describe_test.go b/internal/cmd/rabbitmq/credentials/describe/describe_test.go index ef4d23107..a40cd610d 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe_test.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" @@ -164,7 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -270,7 +271,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index e9b03d199..6a06c9313 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for a RabbitMQ instance", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,10 +72,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(credentials) == 0 { instanceLabel, err := rabbitmqUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - p.Info("No credentials found for instance %q\n", instanceLabel) + params.Printer.Info("No credentials found for instance %q\n", instanceLabel) return nil } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentials) }, } configureFlags(cmd) diff --git a/internal/cmd/rabbitmq/credentials/list/list_test.go b/internal/cmd/rabbitmq/credentials/list/list_test.go index 431a51a08..77f7f2f5e 100644 --- a/internal/cmd/rabbitmq/credentials/list/list_test.go +++ b/internal/cmd/rabbitmq/credentials/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -234,7 +235,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index 3ea8bfda1..77f34ed7f 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -57,7 +58,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a RabbitMQ instance", @@ -76,26 +77,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create an RabbitMQ instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -118,7 +119,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -127,7 +128,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, instanceId, resp) + return outputResult(params.Printer, model, projectLabel, instanceId, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/rabbitmq/instance/create/create_test.go b/internal/cmd/rabbitmq/instance/create/create_test.go index 5faeb3257..aa39a62e8 100644 --- a/internal/cmd/rabbitmq/instance/create/create_test.go +++ b/internal/cmd/rabbitmq/instance/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -276,7 +277,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -521,7 +522,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, &tt.args.model, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/instance/delete/delete.go b/internal/cmd/rabbitmq/instance/delete/delete.go index 66a7b578e..992526969 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete.go +++ b/internal/cmd/rabbitmq/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a RabbitMQ instance", @@ -41,26 +42,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := rabbitmqUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/rabbitmq/instance/delete/delete_test.go b/internal/cmd/rabbitmq/instance/delete/delete_test.go index d9b32ef81..8064098ad 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete_test.go +++ b/internal/cmd/rabbitmq/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/rabbitmq/instance/describe/describe.go b/internal/cmd/rabbitmq/instance/describe/describe.go index c65f67ed3..e79f476fa 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe.go +++ b/internal/cmd/rabbitmq/instance/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a RabbitMQ instance", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read RabbitMQ instance: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/rabbitmq/instance/describe/describe_test.go b/internal/cmd/rabbitmq/instance/describe/describe_test.go index 4b9420995..8fe1f8288 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe_test.go +++ b/internal/cmd/rabbitmq/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -250,7 +251,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/instance/instance.go b/internal/cmd/rabbitmq/instance/instance.go index b9a73a3e0..2ad311846 100644 --- a/internal/cmd/rabbitmq/instance/instance.go +++ b/internal/cmd/rabbitmq/instance/instance.go @@ -1,19 +1,19 @@ package instance import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/create" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for RabbitMQ instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index 3ade03661..cad8afdb3 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all RabbitMQ instances", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/rabbitmq/instance/list/list_test.go b/internal/cmd/rabbitmq/instance/list/list_test.go index 50bdcf4bd..bbfefdfff 100644 --- a/internal/cmd/rabbitmq/instance/list/list_test.go +++ b/internal/cmd/rabbitmq/instance/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -213,7 +214,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/instance/update/update.go b/internal/cmd/rabbitmq/instance/update/update.go index 67144235d..f75c97cac 100644 --- a/internal/cmd/rabbitmq/instance/update/update.go +++ b/internal/cmd/rabbitmq/instance/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -56,7 +57,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a RabbitMQ instance", @@ -72,26 +73,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := rabbitmqUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -114,7 +115,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -127,7 +128,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/rabbitmq/instance/update/update_test.go b/internal/cmd/rabbitmq/instance/update/update_test.go index c2d92bc6f..50642481c 100644 --- a/internal/cmd/rabbitmq/instance/update/update_test.go +++ b/internal/cmd/rabbitmq/instance/update/update_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -294,7 +295,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index 1b84f3029..fc9276a93 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all RabbitMQ service plans", @@ -49,13 +50,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -68,12 +69,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No plans found for project %q\n", projectLabel) + params.Printer.Info("No plans found for project %q\n", projectLabel) return nil } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(p, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, plans) }, } diff --git a/internal/cmd/rabbitmq/plans/plans_test.go b/internal/cmd/rabbitmq/plans/plans_test.go index ab8966a20..d5f0f9aee 100644 --- a/internal/cmd/rabbitmq/plans/plans_test.go +++ b/internal/cmd/rabbitmq/plans/plans_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -213,7 +214,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/rabbitmq.go b/internal/cmd/rabbitmq/rabbitmq.go index 26b5db9bb..9dc5b76a3 100644 --- a/internal/cmd/rabbitmq/rabbitmq.go +++ b/internal/cmd/rabbitmq/rabbitmq.go @@ -1,17 +1,17 @@ package rabbitmq import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/plans" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "rabbitmq", Short: "Provides functionality for RabbitMQ", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(plans.NewCmd(p)) - cmd.AddCommand(credentials.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(plans.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) } diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index 9b2098344..17d6e4164 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for a Redis instance", @@ -47,26 +48,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := redisUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Redis credentials: %w", err) } - return outputResult(p, *model, instanceLabel, resp) + return outputResult(params.Printer, *model, instanceLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/redis/credentials/create/create_test.go b/internal/cmd/redis/credentials/create/create_test.go index 511b066ad..070229478 100644 --- a/internal/cmd/redis/credentials/create/create_test.go +++ b/internal/cmd/redis/credentials/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/redis" @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -223,7 +224,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/credentials/credentials.go b/internal/cmd/redis/credentials/credentials.go index 42e6226da..d1d8a4d7a 100644 --- a/internal/cmd/redis/credentials/credentials.go +++ b/internal/cmd/redis/credentials/credentials.go @@ -1,18 +1,18 @@ package credentials import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials/create" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for Redis credentials", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/redis/credentials/delete/delete.go b/internal/cmd/redis/credentials/delete/delete.go index 4012c6b3f..147ad731b 100644 --- a/internal/cmd/redis/credentials/delete/delete.go +++ b/internal/cmd/redis/credentials/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of a Redis instance", @@ -43,32 +44,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := redisUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } credentialsLabel, err := redisUtils.GetCredentialsUsername(ctx, apiClient, model.ProjectId, model.InstanceId, model.CredentialsId) if err != nil { - p.Debug(print.ErrorLevel, "get credentials user name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get credentials user name: %v", err) credentialsLabel = model.CredentialsId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Redis credentials: %w", err) } - p.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) + params.Printer.Info("Deleted credentials %s of instance %q\n", credentialsLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/redis/credentials/delete/delete_test.go b/internal/cmd/redis/credentials/delete/delete_test.go index 716bfedfe..d8b2c4632 100644 --- a/internal/cmd/redis/credentials/delete/delete_test.go +++ b/internal/cmd/redis/credentials/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/redis/credentials/describe/describe.go b/internal/cmd/redis/credentials/describe/describe.go index 7a6dc78e4..9ab0e9ab4 100644 --- a/internal/cmd/redis/credentials/describe/describe.go +++ b/internal/cmd/redis/credentials/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of a Redis instance", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe Redis credentials: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/redis/credentials/describe/describe_test.go b/internal/cmd/redis/credentials/describe/describe_test.go index c6f837491..fc8edb1b8 100644 --- a/internal/cmd/redis/credentials/describe/describe_test.go +++ b/internal/cmd/redis/credentials/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/redis" @@ -164,7 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -267,7 +268,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index a83492451..603dc86ed 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for a Redis instance", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,10 +72,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(credentials) == 0 { instanceLabel, err := redisUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - p.Info("No credentials found for instance %q\n", instanceLabel) + params.Printer.Info("No credentials found for instance %q\n", instanceLabel) return nil } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(p, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentials) }, } configureFlags(cmd) diff --git a/internal/cmd/redis/credentials/list/list_test.go b/internal/cmd/redis/credentials/list/list_test.go index b771823bf..a37f530c4 100644 --- a/internal/cmd/redis/credentials/list/list_test.go +++ b/internal/cmd/redis/credentials/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -234,7 +235,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index 87db67741..86fdec837 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -55,7 +56,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Redis instance", @@ -74,26 +75,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a Redis instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -116,7 +117,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating instance") _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -125,7 +126,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, instanceId, resp) + return outputResult(params.Printer, model, projectLabel, instanceId, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/redis/instance/create/create_test.go b/internal/cmd/redis/instance/create/create_test.go index 59ee4d259..814673259 100644 --- a/internal/cmd/redis/instance/create/create_test.go +++ b/internal/cmd/redis/instance/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -261,7 +262,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -496,7 +497,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/instance/delete/delete.go b/internal/cmd/redis/instance/delete/delete.go index 902e30ada..bb4efebda 100644 --- a/internal/cmd/redis/instance/delete/delete.go +++ b/internal/cmd/redis/instance/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a Redis instance", @@ -41,26 +42,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := redisUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting instance") _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) if err != nil { @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/redis/instance/delete/delete_test.go b/internal/cmd/redis/instance/delete/delete_test.go index 60dc78c89..bb0da281f 100644 --- a/internal/cmd/redis/instance/delete/delete_test.go +++ b/internal/cmd/redis/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/redis/instance/describe/describe.go b/internal/cmd/redis/instance/describe/describe.go index f91b4b1e6..c01d82ddd 100644 --- a/internal/cmd/redis/instance/describe/describe.go +++ b/internal/cmd/redis/instance/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a Redis instance", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read Redis instance: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/redis/instance/describe/describe_test.go b/internal/cmd/redis/instance/describe/describe_test.go index 1e12d6195..651164b98 100644 --- a/internal/cmd/redis/instance/describe/describe_test.go +++ b/internal/cmd/redis/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/redis" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -251,7 +252,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/instance/instance.go b/internal/cmd/redis/instance/instance.go index 3518921b5..a45e6bd96 100644 --- a/internal/cmd/redis/instance/instance.go +++ b/internal/cmd/redis/instance/instance.go @@ -1,19 +1,19 @@ package instance import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/create" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for Redis instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index 4b49c15fa..87f7b6d3e 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Redis instances", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/redis/instance/list/list_test.go b/internal/cmd/redis/instance/list/list_test.go index 0338bd8a7..aff5c8020 100644 --- a/internal/cmd/redis/instance/list/list_test.go +++ b/internal/cmd/redis/instance/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -212,7 +213,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/instance/update/update.go b/internal/cmd/redis/instance/update/update.go index 117dbe472..65e92c860 100644 --- a/internal/cmd/redis/instance/update/update.go +++ b/internal/cmd/redis/instance/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -53,7 +54,7 @@ type inputModel struct { PlanId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a Redis instance", @@ -69,26 +70,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := redisUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -111,7 +112,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating instance") _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) if err != nil { @@ -124,7 +125,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered update of" } - p.Info("%s instance %q\n", operationState, instanceLabel) + params.Printer.Info("%s instance %q\n", operationState, instanceLabel) return nil }, } diff --git a/internal/cmd/redis/instance/update/update_test.go b/internal/cmd/redis/instance/update/update_test.go index 30602e593..7c5df24d5 100644 --- a/internal/cmd/redis/instance/update/update_test.go +++ b/internal/cmd/redis/instance/update/update_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -278,7 +279,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 8ae785da6..7bcb60218 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all Redis service plans", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No plans found for project %q\n", projectLabel) + params.Printer.Info("No plans found for project %q\n", projectLabel) return nil } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(p, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, plans) }, } diff --git a/internal/cmd/redis/plans/plans_test.go b/internal/cmd/redis/plans/plans_test.go index f850de8a1..8ea65f786 100644 --- a/internal/cmd/redis/plans/plans_test.go +++ b/internal/cmd/redis/plans/plans_test.go @@ -8,6 +8,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -212,7 +213,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/redis.go b/internal/cmd/redis/redis.go index 3b07f00c9..4a45e9c33 100644 --- a/internal/cmd/redis/redis.go +++ b/internal/cmd/redis/redis.go @@ -1,17 +1,17 @@ package redis import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/plans" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "redis", Short: "Provides functionality for Redis", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(plans.NewCmd(p)) - cmd.AddCommand(credentials.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(plans.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) } diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 736c944f5..6da6491d6 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -6,6 +6,8 @@ import ( "strings" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + affinityGroups "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups" "github.com/stackitcloud/stackit-cli/internal/cmd/auth" "github.com/stackitcloud/stackit-cli/internal/cmd/beta" @@ -114,7 +116,10 @@ func NewRootCmd(version, date string, p *print.Printer) *cobra.Command { err := configureFlags(cmd) cobra.CheckErr(err) - addSubcommands(cmd, p) + addSubcommands(cmd, ¶ms.CmdParams{ + Printer: p, + CliVersion: version, + }) // Cobra creates the help flag with "help for " as the description // We want to override that message by capitalizing the first letter to match the other flag descriptions @@ -154,38 +159,38 @@ func configureFlags(cmd *cobra.Command) error { return nil } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(auth.NewCmd(p)) - cmd.AddCommand(configCmd.NewCmd(p)) - cmd.AddCommand(beta.NewCmd(p)) - cmd.AddCommand(curl.NewCmd(p)) - cmd.AddCommand(dns.NewCmd(p)) - cmd.AddCommand(loadbalancer.NewCmd(p)) - cmd.AddCommand(logme.NewCmd(p)) - cmd.AddCommand(mariadb.NewCmd(p)) - cmd.AddCommand(mongodbflex.NewCmd(p)) - cmd.AddCommand(objectstorage.NewCmd(p)) - cmd.AddCommand(observability.NewCmd(p)) - cmd.AddCommand(opensearch.NewCmd(p)) - cmd.AddCommand(organization.NewCmd(p)) - cmd.AddCommand(postgresflex.NewCmd(p)) - cmd.AddCommand(project.NewCmd(p)) - cmd.AddCommand(rabbitmq.NewCmd(p)) - cmd.AddCommand(redis.NewCmd(p)) - cmd.AddCommand(secretsmanager.NewCmd(p)) - cmd.AddCommand(serviceaccount.NewCmd(p)) - cmd.AddCommand(ske.NewCmd(p)) - cmd.AddCommand(server.NewCmd(p)) - cmd.AddCommand(networkArea.NewCmd(p)) - cmd.AddCommand(network.NewCmd(p)) - cmd.AddCommand(volume.NewCmd(p)) - cmd.AddCommand(networkinterface.NewCmd(p)) - cmd.AddCommand(publicip.NewCmd(p)) - cmd.AddCommand(securitygroup.NewCmd(p)) - cmd.AddCommand(keypair.NewCmd(p)) - cmd.AddCommand(image.NewCmd(p)) - cmd.AddCommand(quota.NewCmd(p)) - cmd.AddCommand(affinityGroups.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(auth.NewCmd(params)) + cmd.AddCommand(configCmd.NewCmd(params)) + cmd.AddCommand(beta.NewCmd(params)) + cmd.AddCommand(curl.NewCmd(params)) + cmd.AddCommand(dns.NewCmd(params)) + cmd.AddCommand(loadbalancer.NewCmd(params)) + cmd.AddCommand(logme.NewCmd(params)) + cmd.AddCommand(mariadb.NewCmd(params)) + cmd.AddCommand(mongodbflex.NewCmd(params)) + cmd.AddCommand(objectstorage.NewCmd(params)) + cmd.AddCommand(observability.NewCmd(params)) + cmd.AddCommand(opensearch.NewCmd(params)) + cmd.AddCommand(organization.NewCmd(params)) + cmd.AddCommand(postgresflex.NewCmd(params)) + cmd.AddCommand(project.NewCmd(params)) + cmd.AddCommand(rabbitmq.NewCmd(params)) + cmd.AddCommand(redis.NewCmd(params)) + cmd.AddCommand(secretsmanager.NewCmd(params)) + cmd.AddCommand(serviceaccount.NewCmd(params)) + cmd.AddCommand(ske.NewCmd(params)) + cmd.AddCommand(server.NewCmd(params)) + cmd.AddCommand(networkArea.NewCmd(params)) + cmd.AddCommand(network.NewCmd(params)) + cmd.AddCommand(volume.NewCmd(params)) + cmd.AddCommand(networkinterface.NewCmd(params)) + cmd.AddCommand(publicip.NewCmd(params)) + cmd.AddCommand(securitygroup.NewCmd(params)) + cmd.AddCommand(keypair.NewCmd(params)) + cmd.AddCommand(image.NewCmd(params)) + cmd.AddCommand(quota.NewCmd(params)) + cmd.AddCommand(affinityGroups.NewCmd(params)) } // traverseCommands calls f for c and all of its children. diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index 35c02682c..ad1a8195f 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Acls *[]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Secrets Manager instance", @@ -49,26 +50,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a Secrets Manager instance for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -94,7 +95,7 @@ If you want to retry configuring the ACLs, you can do it via: } } - return outputResult(p, model.OutputFormat, projectLabel, instanceId, resp) + return outputResult(params.Printer, model.OutputFormat, projectLabel, instanceId, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/secrets-manager/instance/create/create_test.go b/internal/cmd/secrets-manager/instance/create/create_test.go index 92b04ba79..02a895c01 100644 --- a/internal/cmd/secrets-manager/instance/create/create_test.go +++ b/internal/cmd/secrets-manager/instance/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -184,7 +185,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -329,7 +330,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.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.instanceId, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/instance/delete/delete.go b/internal/cmd/secrets-manager/instance/delete/delete.go index 960034165..dda64b620 100644 --- a/internal/cmd/secrets-manager/instance/delete/delete.go +++ b/internal/cmd/secrets-manager/instance/delete/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -25,7 +26,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a Secrets Manager instance", @@ -38,26 +39,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := secretsmanagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Secrets Manager instance: %w", err) } - p.Info("Deleted instance %q \n", model.InstanceId) + params.Printer.Info("Deleted instance %q \n", model.InstanceId) return nil }, } diff --git a/internal/cmd/secrets-manager/instance/delete/delete_test.go b/internal/cmd/secrets-manager/instance/delete/delete_test.go index b36eb87b8..fe6eae032 100644 --- a/internal/cmd/secrets-manager/instance/delete/delete_test.go +++ b/internal/cmd/secrets-manager/instance/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index 8551fa8bf..e794a2cce 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a Secrets Manager instance", @@ -45,12 +46,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -69,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read Secrets Manager instance ACLs: %w", err) } - return outputResult(p, model.OutputFormat, instance, aclList) + return outputResult(params.Printer, model.OutputFormat, instance, aclList) }, } return cmd diff --git a/internal/cmd/secrets-manager/instance/describe/describe_test.go b/internal/cmd/secrets-manager/instance/describe/describe_test.go index 212c825ab..2cadb3be2 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe_test.go +++ b/internal/cmd/secrets-manager/instance/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -146,7 +147,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -293,7 +294,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instance, tt.args.aclList); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/instance/instance.go b/internal/cmd/secrets-manager/instance/instance.go index cc38f6ca7..5617aeddc 100644 --- a/internal/cmd/secrets-manager/instance/instance.go +++ b/internal/cmd/secrets-manager/instance/instance.go @@ -1,19 +1,19 @@ package instance import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/create" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for Secrets Manager instances", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index 019aff8f6..cf6d4c745 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Secrets Manager instances", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,12 +68,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Instances == nil || len(*resp.Instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No instances found for project %q\n", projectLabel) + params.Printer.Info("No instances found for project %q\n", projectLabel) return nil } instances := *resp.Instances @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(p, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, instances) }, } diff --git a/internal/cmd/secrets-manager/instance/list/list_test.go b/internal/cmd/secrets-manager/instance/list/list_test.go index 3903b0210..6ea677137 100644 --- a/internal/cmd/secrets-manager/instance/list/list_test.go +++ b/internal/cmd/secrets-manager/instance/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -228,7 +229,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/instance/update/update.go b/internal/cmd/secrets-manager/instance/update/update.go index e013c1e73..371711e55 100644 --- a/internal/cmd/secrets-manager/instance/update/update.go +++ b/internal/cmd/secrets-manager/instance/update/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Acls *[]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a Secrets Manager instance", @@ -45,26 +46,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update Secrets Manager instance: %w", err) } - p.Info("Updated instance %q\n", instanceLabel) + params.Printer.Info("Updated instance %q\n", instanceLabel) return nil }, } diff --git a/internal/cmd/secrets-manager/instance/update/update_test.go b/internal/cmd/secrets-manager/instance/update/update_test.go index 8668d9ca1..1a60db361 100644 --- a/internal/cmd/secrets-manager/instance/update/update_test.go +++ b/internal/cmd/secrets-manager/instance/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -198,7 +199,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/secrets-manager/secrets_manager.go b/internal/cmd/secrets-manager/secrets_manager.go index d9c78f035..35745dfde 100644 --- a/internal/cmd/secrets-manager/secrets_manager.go +++ b/internal/cmd/secrets-manager/secrets_manager.go @@ -1,16 +1,16 @@ package secretsmanager import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "secrets-manager", Short: "Provides functionality for Secrets Manager", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(instance.NewCmd(p)) - cmd.AddCommand(user.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(user.NewCmd(params)) } diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 12a767cf4..62d54d9d7 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Write *bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Secrets Manager user", @@ -54,26 +55,26 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -86,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Secrets Manager user: %w", err) } - return outputResult(p, model.OutputFormat, instanceLabel, resp) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, resp) }, } diff --git a/internal/cmd/secrets-manager/user/create/create_test.go b/internal/cmd/secrets-manager/user/create/create_test.go index be5ae1a37..a64b826ba 100644 --- a/internal/cmd/secrets-manager/user/create/create_test.go +++ b/internal/cmd/secrets-manager/user/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -251,7 +252,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/user/delete/delete.go b/internal/cmd/secrets-manager/user/delete/delete.go index 6ed848d0e..fc3272435 100644 --- a/internal/cmd/secrets-manager/user/delete/delete.go +++ b/internal/cmd/secrets-manager/user/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", userIdArg), Short: "Deletes a Secrets Manager user", @@ -47,32 +48,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, utils.ValidateUUID), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := secretsManagerUtils.GetUserLabel(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) if err != nil { - p.Debug(print.ErrorLevel, "get user label: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user label: %v", err) userLabel = fmt.Sprintf("%q", model.UserId) } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete user %s of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Secrets Manager user: %w", err) } - p.Info("Deleted user %s of instance %q\n", userLabel, instanceLabel) + params.Printer.Info("Deleted user %s of instance %q\n", userLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/secrets-manager/user/delete/delete_test.go b/internal/cmd/secrets-manager/user/delete/delete_test.go index 8ad0a2bf2..0827ebf88 100644 --- a/internal/cmd/secrets-manager/user/delete/delete_test.go +++ b/internal/cmd/secrets-manager/user/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -153,7 +154,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/secrets-manager/user/describe/describe.go b/internal/cmd/secrets-manager/user/describe/describe.go index 2bfb18b08..c08e0ac32 100644 --- a/internal/cmd/secrets-manager/user/describe/describe.go +++ b/internal/cmd/secrets-manager/user/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { UserId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", userIdArg), Short: "Shows details of a Secrets Manager user", @@ -49,13 +50,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, utils.ValidateUUID), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get Secrets Manager user: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } diff --git a/internal/cmd/secrets-manager/user/describe/describe_test.go b/internal/cmd/secrets-manager/user/describe/describe_test.go index 46cd4b63e..53c14c586 100644 --- a/internal/cmd/secrets-manager/user/describe/describe_test.go +++ b/internal/cmd/secrets-manager/user/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -268,7 +269,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index 19ff7f8ea..b414e2cd9 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Secrets Manager users", @@ -51,13 +52,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,10 +72,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if resp.Users == nil || len(*resp.Users) == 0 { instanceLabel, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId } - p.Info("No users found for instance %q\n", instanceLabel) + params.Printer.Info("No users found for instance %q\n", instanceLabel) return nil } users := *resp.Users @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { users = users[:*model.Limit] } - return outputResult(p, model.OutputFormat, users) + return outputResult(params.Printer, model.OutputFormat, users) }, } diff --git a/internal/cmd/secrets-manager/user/list/list_test.go b/internal/cmd/secrets-manager/user/list/list_test.go index ac4c830a7..d2de82297 100644 --- a/internal/cmd/secrets-manager/user/list/list_test.go +++ b/internal/cmd/secrets-manager/user/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -235,7 +236,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/user/update/update.go b/internal/cmd/secrets-manager/user/update/update.go index 573076eb4..f0b6e35b9 100644 --- a/internal/cmd/secrets-manager/user/update/update.go +++ b/internal/cmd/secrets-manager/user/update/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { DisableWrite *bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", userIdArg), Short: "Updates the write privileges Secrets Manager user", @@ -51,32 +52,32 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.SingleArg(userIdArg, utils.ValidateUUID), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } instanceLabel, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { - p.Debug(print.ErrorLevel, "get instance name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } userLabel, err := secretsManagerUtils.GetUserLabel(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) if err != nil { - p.Debug(print.ErrorLevel, "get user label: %v", err) + params.Printer.Debug(print.ErrorLevel, "get user label: %v", err) userLabel = fmt.Sprintf("%q", model.UserId) } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update user %s of instance %q?", userLabel, instanceLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -93,7 +94,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update Secrets Manager user: %w", err) } - p.Info("Updated user %s of instance %q\n", userLabel, instanceLabel) + params.Printer.Info("Updated user %s of instance %q\n", userLabel, instanceLabel) return nil }, } diff --git a/internal/cmd/secrets-manager/user/update/update_test.go b/internal/cmd/secrets-manager/user/update/update_test.go index b3b8a67b0..5ae24676b 100644 --- a/internal/cmd/secrets-manager/user/update/update_test.go +++ b/internal/cmd/secrets-manager/user/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -189,7 +190,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/secrets-manager/user/user.go b/internal/cmd/secrets-manager/user/user.go index 8dcd68410..ae4e1c90f 100644 --- a/internal/cmd/secrets-manager/user/user.go +++ b/internal/cmd/secrets-manager/user/user.go @@ -2,10 +2,10 @@ package user import ( "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user/create" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user/describe" @@ -13,7 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user/update" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "user", Short: "Provides functionality for Secrets Manager users", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index 24f3da09c..891abccc9 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Stateful *bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates security groups", @@ -45,20 +46,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create the security group %q?", *model.Name) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create security group: %w", err) } - if err := outputResult(p, model.OutputFormat, *model.Name, *group); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, *model.Name, *group); err != nil { return err } diff --git a/internal/cmd/security-group/create/create_test.go b/internal/cmd/security-group/create/create_test.go index 6a6a02898..9b2561489 100644 --- a/internal/cmd/security-group/create/create_test.go +++ b/internal/cmd/security-group/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -168,7 +169,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -282,7 +283,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.name, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/delete/delete.go b/internal/cmd/security-group/delete/delete.go index 85781ae13..0d116da7e 100644 --- a/internal/cmd/security-group/delete/delete.go +++ b/internal/cmd/security-group/delete/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -24,7 +25,7 @@ type inputModel struct { const groupIdArg = "GROUP_ID" -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", groupIdArg), Short: "Deletes a security group", @@ -35,32 +36,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } groupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) if err != nil { - p.Warn("get security group name: %v", err) + params.Printer.Warn("get security group name: %v", err) groupLabel = model.SecurityGroupId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete the security group %q for %q?", groupLabel, projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err := request.Execute(); err != nil { return fmt.Errorf("delete security group: %w", err) } - p.Info("Deleted security group %q for %q\n", groupLabel, projectLabel) + params.Printer.Info("Deleted security group %q for %q\n", groupLabel, projectLabel) return nil }, diff --git a/internal/cmd/security-group/delete/delete_test.go b/internal/cmd/security-group/delete/delete_test.go index 7666e1585..ec7143cbf 100644 --- a/internal/cmd/security-group/delete/delete_test.go +++ b/internal/cmd/security-group/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -105,7 +106,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/security-group/describe/describe.go b/internal/cmd/security-group/describe/describe.go index 01d86df03..bde9cbc9f 100644 --- a/internal/cmd/security-group/describe/describe.go +++ b/internal/cmd/security-group/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { const groupIdArg = "GROUP_ID" -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", groupIdArg), Short: "Describes security groups", @@ -38,13 +39,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -57,7 +58,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get security group: %w", err) } - if err := outputResult(p, model.OutputFormat, group); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, group); err != nil { return err } diff --git a/internal/cmd/security-group/describe/describe_test.go b/internal/cmd/security-group/describe/describe_test.go index 6deaf042f..f9b5f7fba 100644 --- a/internal/cmd/security-group/describe/describe_test.go +++ b/internal/cmd/security-group/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -216,7 +217,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/list/list.go b/internal/cmd/security-group/list/list.go index 48caeddb3..592c65408 100644 --- a/internal/cmd/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ const ( labelSelectorFlag = "label-selector" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists security groups", @@ -42,20 +43,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } @@ -68,9 +69,9 @@ func NewCmd(p *print.Printer) *cobra.Command { } if items := response.GetItems(); len(items) == 0 { - p.Info("No security groups found for project %q", projectLabel) + params.Printer.Info("No security groups found for project %q", projectLabel) } else { - if err := outputResult(p, model.OutputFormat, items); err != nil { + if err := outputResult(params.Printer, model.OutputFormat, items); err != nil { return fmt.Errorf("output security groups: %w", err) } } diff --git a/internal/cmd/security-group/list/list_test.go b/internal/cmd/security-group/list/list_test.go index d19adf3a0..a78e3501a 100644 --- a/internal/cmd/security-group/list/list_test.go +++ b/internal/cmd/security-group/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -222,7 +223,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go index a330e98eb..a5b4bbc9d 100644 --- a/internal/cmd/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -52,7 +53,7 @@ type inputModel struct { ProtocolName *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a security group rule", @@ -78,32 +79,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) if err != nil { - p.Debug(print.ErrorLevel, "get security group name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get security group name: %v", err) securityGroupLabel = model.SecurityGroupId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a security group rule for security group %q for project %q?", securityGroupLabel, projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -116,7 +117,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create security group rule : %w", err) } - return outputResult(p, model, projectLabel, securityGroupLabel, resp) + return outputResult(params.Printer, model, projectLabel, securityGroupLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/security-group/rule/create/create_test.go b/internal/cmd/security-group/rule/create/create_test.go index 1a0024129..6c1521899 100644 --- a/internal/cmd/security-group/rule/create/create_test.go +++ b/internal/cmd/security-group/rule/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -243,7 +244,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -360,7 +361,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.securityGroupName, tt.args.securityGroupRule); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/rule/delete/delete.go b/internal/cmd/security-group/rule/delete/delete.go index 247caed8a..adca9d3eb 100644 --- a/internal/cmd/security-group/rule/delete/delete.go +++ b/internal/cmd/security-group/rule/delete/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { SecurityGroupId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", securityGroupRuleIdArg), Short: "Deletes a security group rule", @@ -46,32 +47,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, *model.SecurityGroupId) if err != nil { - p.Debug(print.ErrorLevel, "get security group name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get security group name: %v", err) securityGroupLabel = *model.SecurityGroupId } securityGroupRuleLabel, err := iaasUtils.GetSecurityGroupRuleName(ctx, apiClient, model.ProjectId, model.SecurityGroupRuleId, *model.SecurityGroupId) if err != nil { - p.Debug(print.ErrorLevel, "get security group rule name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get security group rule name: %v", err) securityGroupRuleLabel = model.SecurityGroupRuleId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete security group rule %q from security group %q?", securityGroupRuleLabel, securityGroupLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete security group rule: %w", err) } - p.Info("Deleted security group rule %q from security group %q\n", securityGroupRuleLabel, securityGroupLabel) + params.Printer.Info("Deleted security group rule %q from security group %q\n", securityGroupRuleLabel, securityGroupLabel) return nil }, } diff --git a/internal/cmd/security-group/rule/delete/delete_test.go b/internal/cmd/security-group/rule/delete/delete_test.go index e8d36d7f6..ebf83035c 100644 --- a/internal/cmd/security-group/rule/delete/delete_test.go +++ b/internal/cmd/security-group/rule/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -155,7 +156,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/security-group/rule/describe/describe.go b/internal/cmd/security-group/rule/describe/describe.go index 8e8bd0508..feefb5d54 100644 --- a/internal/cmd/security-group/rule/describe/describe.go +++ b/internal/cmd/security-group/rule/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { SecurityGroupId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", securityGroupRuleIdArg), Short: "Shows details of a security group rule", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -68,7 +69,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read security group rule: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/security-group/rule/describe/describe_test.go b/internal/cmd/security-group/rule/describe/describe_test.go index 03060fcb2..66b536f5c 100644 --- a/internal/cmd/security-group/rule/describe/describe_test.go +++ b/internal/cmd/security-group/rule/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -268,7 +269,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.securityGroupRule); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/rule/list/list.go b/internal/cmd/security-group/rule/list/list.go index 84c83ece4..50304378e 100644 --- a/internal/cmd/security-group/rule/list/list.go +++ b/internal/cmd/security-group/rule/list/list.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { SecurityGroupId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all security group rules in a security group of a project", @@ -56,13 +57,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,16 +78,16 @@ func NewCmd(p *print.Printer) *cobra.Command { if resp.Items == nil || len(*resp.Items) == 0 { securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, *model.SecurityGroupId) if err != nil { - p.Debug(print.ErrorLevel, "get security group name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get security group name: %v", err) securityGroupLabel = *model.SecurityGroupId } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No rules found in security group %q for project %q\n", securityGroupLabel, projectLabel) + params.Printer.Info("No rules found in security group %q for project %q\n", securityGroupLabel, projectLabel) return nil } @@ -96,7 +97,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/security-group/rule/list/list_test.go b/internal/cmd/security-group/rule/list/list_test.go index f72f89897..0b7a49b25 100644 --- a/internal/cmd/security-group/rule/list/list_test.go +++ b/internal/cmd/security-group/rule/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -141,7 +142,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -229,7 +230,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.securityGroupRules); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/rule/security_group_rule.go b/internal/cmd/security-group/rule/security_group_rule.go index c1e133841..75f394384 100644 --- a/internal/cmd/security-group/rule/security_group_rule.go +++ b/internal/cmd/security-group/rule/security_group_rule.go @@ -1,18 +1,18 @@ package rule import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/create" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "rule", Short: "Provides functionality for security group rules", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/security-group/security_group.go b/internal/cmd/security-group/security_group.go index f20679d57..952da976c 100644 --- a/internal/cmd/security-group/security_group.go +++ b/internal/cmd/security-group/security_group.go @@ -1,6 +1,7 @@ package security_group import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/create" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/describe" @@ -8,14 +9,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "security-group", Short: "Manage security groups", @@ -23,17 +23,17 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand( - rule.NewCmd(p), - create.NewCmd(p), - delete.NewCmd(p), - describe.NewCmd(p), - list.NewCmd(p), - update.NewCmd(p), + rule.NewCmd(params), + create.NewCmd(params), + delete.NewCmd(params), + describe.NewCmd(params), + list.NewCmd(params), + update.NewCmd(params), ) } diff --git a/internal/cmd/security-group/update/update.go b/internal/cmd/security-group/update/update.go index ddff90e23..a91c07971 100644 --- a/internal/cmd/security-group/update/update.go +++ b/internal/cmd/security-group/update/update.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ const ( labelsArg = "labels" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", groupNameArg), Short: "Updates a security group", @@ -46,32 +47,32 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } groupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) if err != nil { - p.Warn("cannot retrieve groupname: %v", err) + params.Printer.Warn("cannot retrieve groupname: %v", err) groupLabel = model.SecurityGroupId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update the security group %q?", groupLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("update security group: %w", err) } - p.Info("Updated security group \"%v\" for %q\n", utils.PtrString(resp.Name), projectLabel) + params.Printer.Info("Updated security group \"%v\" for %q\n", utils.PtrString(resp.Name), projectLabel) return nil }, diff --git a/internal/cmd/security-group/update/update_test.go b/internal/cmd/security-group/update/update_test.go index f27cbfc25..3bc10055a 100644 --- a/internal/cmd/security-group/update/update_test.go +++ b/internal/cmd/security-group/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -204,7 +205,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } diff --git a/internal/cmd/server/backup/backup.go b/internal/cmd/server/backup/backup.go index 8936ae65f..e29887143 100644 --- a/internal/cmd/server/backup/backup.go +++ b/internal/cmd/server/backup/backup.go @@ -1,6 +1,7 @@ package backup import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/create" del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/describe" @@ -11,13 +12,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule" volumebackup "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "backup", Short: "Provides functionality for server backups", @@ -25,18 +25,18 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(enable.NewCmd(p)) - cmd.AddCommand(disable.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(schedule.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(restore.NewCmd(p)) - cmd.AddCommand(del.NewCmd(p)) - cmd.AddCommand(volumebackup.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(enable.NewCmd(params)) + cmd.AddCommand(disable.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(schedule.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(restore.NewCmd(params)) + cmd.AddCommand(del.NewCmd(params)) + cmd.AddCommand(volumebackup.NewCmd(params)) } diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index 28243cdc8..ba2aa95c5 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -39,7 +40,7 @@ type inputModel struct { BackupVolumeIds []string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server Backup.", @@ -56,23 +57,23 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a Backup for server %s?", model.ServerId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -96,7 +97,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server Backup: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/backup/create/create_test.go b/internal/cmd/server/backup/create/create_test.go index b0d547f44..71a50ff6b 100644 --- a/internal/cmd/server/backup/create/create_test.go +++ b/internal/cmd/server/backup/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -131,7 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -228,7 +229,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/delete/delete.go b/internal/cmd/server/backup/delete/delete.go index 7805d20c0..a30dec646 100644 --- a/internal/cmd/server/backup/delete/delete.go +++ b/internal/cmd/server/backup/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", backupIdArg), Short: "Deletes a Server Backup.", @@ -41,20 +42,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete server backup %q? (This cannot be undone)", model.BackupId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Server Backup: %w", err) } - p.Info("Triggered deletion of server backup %q\n", model.BackupId) + params.Printer.Info("Triggered deletion of server backup %q\n", model.BackupId) return nil }, } diff --git a/internal/cmd/server/backup/delete/delete_test.go b/internal/cmd/server/backup/delete/delete_test.go index d1f455b3d..d1de3562f 100644 --- a/internal/cmd/server/backup/delete/delete_test.go +++ b/internal/cmd/server/backup/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/backup/describe/describe.go b/internal/cmd/server/backup/describe/describe.go index b1fe36663..9b3ad9247 100644 --- a/internal/cmd/server/backup/describe/describe.go +++ b/internal/cmd/server/backup/describe/describe.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { BackupId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupIdArg), Short: "Shows details of a Server Backup", @@ -48,12 +49,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server backup: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/backup/describe/describe_test.go b/internal/cmd/server/backup/describe/describe_test.go index 2760e7e7c..c706734f1 100644 --- a/internal/cmd/server/backup/describe/describe_test.go +++ b/internal/cmd/server/backup/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -236,7 +237,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.backup); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go index 0a76151a5..a61dce696 100644 --- a/internal/cmd/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "disable", Short: "Disables Server Backup service", @@ -41,23 +42,23 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -68,13 +69,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return err } if !canDisable { - p.Info("Cannot disable backup service for server %s - existing backups or existing backup schedules found\n", serverLabel) + params.Printer.Info("Cannot disable backup service for server %s - existing backups or existing backup schedules found\n", serverLabel) return nil } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to disable the backup service for server %s?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("disable server backup service: %w", err) } - p.Info("Disabled Server Backup service for server %s\n", serverLabel) + params.Printer.Info("Disabled Server Backup service for server %s\n", serverLabel) return nil }, } diff --git a/internal/cmd/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go index 9f0f48e1b..89265e748 100644 --- a/internal/cmd/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "enable", Short: "Enables Server Backup service", @@ -41,23 +42,23 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to enable the Server Backup service for server %s?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - p.Info("Enabled backup service for server %s\n", serverLabel) + params.Printer.Info("Enabled backup service for server %s\n", serverLabel) return nil }, } diff --git a/internal/cmd/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go index d7cbfeb6f..ccd29a624 100644 --- a/internal/cmd/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server backups", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -69,15 +70,15 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(backups) == 0 { serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } } - p.Info("No backups found for server %s\n", serverLabel) + params.Printer.Info("No backups found for server %s\n", serverLabel) return nil } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(backups) > int(*model.Limit) { backups = backups[:*model.Limit] } - return outputResult(p, model.OutputFormat, backups) + return outputResult(params.Printer, model.OutputFormat, backups) }, } configureFlags(cmd) diff --git a/internal/cmd/server/backup/list/list_test.go b/internal/cmd/server/backup/list/list_test.go index c9f5b9c2e..218a17c6e 100644 --- a/internal/cmd/server/backup/list/list_test.go +++ b/internal/cmd/server/backup/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -117,7 +118,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -214,7 +215,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.backups); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/restore/restore.go b/internal/cmd/server/backup/restore/restore.go index 67bbff395..445680053 100644 --- a/internal/cmd/server/backup/restore/restore.go +++ b/internal/cmd/server/backup/restore/restore.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { BackupVolumeIds []string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("restore %s", backupIdArg), Short: "Restores a Server Backup.", @@ -50,20 +51,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to restore server backup %q? (This cannot be undone)", model.BackupId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("restore Server Backup: %w", err) } - p.Info("Triggered restoring of server backup %q\n", model.BackupId) + params.Printer.Info("Triggered restoring of server backup %q\n", model.BackupId) return nil }, } diff --git a/internal/cmd/server/backup/restore/restore_test.go b/internal/cmd/server/backup/restore/restore_test.go index c352d56cd..ff14455c2 100644 --- a/internal/cmd/server/backup/restore/restore_test.go +++ b/internal/cmd/server/backup/restore/restore_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -132,7 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index 716e0d5c0..09b834c50 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -47,7 +48,7 @@ type inputModel struct { BackupVolumeIds []string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server Backup Schedule", @@ -64,23 +65,23 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -88,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a Backup Schedule for server %s?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -104,7 +105,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server Backup Schedule: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/backup/schedule/create/create_test.go b/internal/cmd/server/backup/schedule/create/create_test.go index 00ec85560..ceb92188b 100644 --- a/internal/cmd/server/backup/schedule/create/create_test.go +++ b/internal/cmd/server/backup/schedule/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -142,7 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -238,7 +239,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/schedule/delete/delete.go b/internal/cmd/server/backup/schedule/delete/delete.go index e2dcaa7a0..69dc81579 100644 --- a/internal/cmd/server/backup/schedule/delete/delete.go +++ b/internal/cmd/server/backup/schedule/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", scheduleIdArg), Short: "Deletes a Server Backup Schedule", @@ -42,23 +43,23 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete server backup schedule %q? (This cannot be undone)", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Server Backup Schedule: %w", err) } - p.Info("Deleted server backup schedule %q\n", model.ScheduleId) + params.Printer.Info("Deleted server backup schedule %q\n", model.ScheduleId) return nil }, } diff --git a/internal/cmd/server/backup/schedule/delete/delete_test.go b/internal/cmd/server/backup/schedule/delete/delete_test.go index 7915f1c07..26c218485 100644 --- a/internal/cmd/server/backup/schedule/delete/delete_test.go +++ b/internal/cmd/server/backup/schedule/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/backup/schedule/describe/describe.go b/internal/cmd/server/backup/schedule/describe/describe.go index 990032499..cc838e0a8 100644 --- a/internal/cmd/server/backup/schedule/describe/describe.go +++ b/internal/cmd/server/backup/schedule/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { BackupScheduleId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupScheduleIdArg), Short: "Shows details of a Server Backup Schedule", @@ -47,12 +48,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -64,7 +65,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server backup schedule: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/backup/schedule/describe/describe_test.go b/internal/cmd/server/backup/schedule/describe/describe_test.go index f94627dc3..edc952d18 100644 --- a/internal/cmd/server/backup/schedule/describe/describe_test.go +++ b/internal/cmd/server/backup/schedule/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -263,7 +264,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.schedule); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go index 2920e9853..3ad1c840e 100644 --- a/internal/cmd/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server backup schedules", @@ -48,23 +49,23 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } schedules := *resp.Items if len(schedules) == 0 { - p.Info("No backup schedules found for server %s\n", serverLabel) + params.Printer.Info("No backup schedules found for server %s\n", serverLabel) return nil } @@ -86,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(schedules) > int(*model.Limit) { schedules = schedules[:*model.Limit] } - return outputResult(p, model.OutputFormat, schedules) + return outputResult(params.Printer, model.OutputFormat, schedules) }, } configureFlags(cmd) diff --git a/internal/cmd/server/backup/schedule/list/list_test.go b/internal/cmd/server/backup/schedule/list/list_test.go index 6c055bcef..c88ec459e 100644 --- a/internal/cmd/server/backup/schedule/list/list_test.go +++ b/internal/cmd/server/backup/schedule/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -117,7 +118,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -225,7 +226,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.schedules); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/schedule/schedule.go b/internal/cmd/server/backup/schedule/schedule.go index 423486fde..1ce797c4f 100644 --- a/internal/cmd/server/backup/schedule/schedule.go +++ b/internal/cmd/server/backup/schedule/schedule.go @@ -1,19 +1,19 @@ package schedule import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/create" del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "schedule", Short: "Provides functionality for Server Backup Schedule", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(del.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(del.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/server/backup/schedule/update/update.go b/internal/cmd/server/backup/schedule/update/update.go index 9885cc2a1..4bc895fc0 100644 --- a/internal/cmd/server/backup/schedule/update/update.go +++ b/internal/cmd/server/backup/schedule/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -48,7 +49,7 @@ type inputModel struct { BackupVolumeIds []string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", scheduleIdArg), Short: "Updates a Server Backup Schedule", @@ -65,26 +66,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } currentBackupSchedule, err := apiClient.GetBackupScheduleExecute(ctx, model.ProjectId, model.ServerId, model.Region, model.BackupScheduleId) if err != nil { - p.Debug(print.ErrorLevel, "get current server backup schedule: %v", err) + params.Printer.Debug(print.ErrorLevel, "get current server backup schedule: %v", err) return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update Server Backup Schedule %q?", model.BackupScheduleId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -100,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update Server Backup Schedule: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/backup/schedule/update/update_test.go b/internal/cmd/server/backup/schedule/update/update_test.go index 8b127b235..263a9188a 100644 --- a/internal/cmd/server/backup/schedule/update/update_test.go +++ b/internal/cmd/server/backup/schedule/update/update_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -183,7 +184,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -295,7 +296,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/volume-backup/delete/delete.go b/internal/cmd/server/backup/volume-backup/delete/delete.go index 9e3de47a8..1b924fe85 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", volumeBackupIdArg), Short: "Deletes a Server Volume Backup.", @@ -43,20 +44,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete server volume backup %q? (This cannot be undone)", model.VolumeId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -69,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Server Volume Backup: %w", err) } - p.Info("Triggered deletion of server volume backup %q\n", model.VolumeId) + params.Printer.Info("Triggered deletion of server volume backup %q\n", model.VolumeId) return nil }, } diff --git a/internal/cmd/server/backup/volume-backup/delete/delete_test.go b/internal/cmd/server/backup/volume-backup/delete/delete_test.go index 59af68770..34859934a 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete_test.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -133,7 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/backup/volume-backup/restore/restore.go b/internal/cmd/server/backup/volume-backup/restore/restore.go index 8e0881d1f..db7c6b543 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { RestoreVolumeId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("restore %s", volumeBackupIdArg), Short: "Restore a Server Volume Backup to a volume.", @@ -45,20 +46,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to restore volume backup %q? (This cannot be undone)", model.VolumeBackupId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("restore Server Volume Backup: %w", err) } - p.Info("Triggered restoring of server volume backup %q\n", model.VolumeBackupId) + params.Printer.Info("Triggered restoring of server volume backup %q\n", model.VolumeBackupId) return nil }, } diff --git a/internal/cmd/server/backup/volume-backup/restore/restore_test.go b/internal/cmd/server/backup/volume-backup/restore/restore_test.go index cb3701baa..21da9b128 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore_test.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -139,7 +140,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/backup/volume-backup/volumebackup.go b/internal/cmd/server/backup/volume-backup/volumebackup.go index 7a4024eb4..e0d3b6d62 100644 --- a/internal/cmd/server/backup/volume-backup/volumebackup.go +++ b/internal/cmd/server/backup/volume-backup/volumebackup.go @@ -1,16 +1,16 @@ package volumebackup import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup/restore" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "volume-backup", Short: "Provides functionality for Server Backup Volume Backups", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(del.NewCmd(p)) - cmd.AddCommand(restore.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(del.NewCmd(params)) + cmd.AddCommand(restore.NewCmd(params)) } diff --git a/internal/cmd/server/command/command.go b/internal/cmd/server/command/command.go index 9347fb111..e6c2d79a8 100644 --- a/internal/cmd/server/command/command.go +++ b/internal/cmd/server/command/command.go @@ -1,18 +1,18 @@ package command import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/create" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "command", Short: "Provides functionality for Server Command", @@ -20,13 +20,13 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(template.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(template.NewCmd(params)) } diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index ed65528ac..748d50b9b 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Params *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server Command", @@ -52,23 +53,23 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a Command for server %s?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -92,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server Command: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/command/create/create_test.go b/internal/cmd/server/command/create/create_test.go index b7b3657ca..eed029584 100644 --- a/internal/cmd/server/command/create/create_test.go +++ b/internal/cmd/server/command/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -127,7 +128,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -223,7 +224,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/describe/describe.go b/internal/cmd/server/command/describe/describe.go index 6eb4359c7..a93d66988 100644 --- a/internal/cmd/server/command/describe/describe.go +++ b/internal/cmd/server/command/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { CommandId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", commandIdArg), Short: "Shows details of a Server Command", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server command: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/command/describe/describe_test.go b/internal/cmd/server/command/describe/describe_test.go index c9d1f3d86..59363f0e7 100644 --- a/internal/cmd/server/command/describe/describe_test.go +++ b/internal/cmd/server/command/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -163,7 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -261,7 +262,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.command); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/list/list.go b/internal/cmd/server/command/list/list.go index 4a00abf57..f5deb62d1 100644 --- a/internal/cmd/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server commands", @@ -48,23 +49,23 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("list server commands: %w", err) } if commands := resp.Items; commands == nil || len(*commands) == 0 { - p.Info("No commands found for server %s\n", serverLabel) + params.Printer.Info("No commands found for server %s\n", serverLabel) return nil } commands := *resp.Items @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(commands) > int(*model.Limit) { commands = commands[:*model.Limit] } - return outputResult(p, model.OutputFormat, commands) + return outputResult(params.Printer, model.OutputFormat, commands) }, } configureFlags(cmd) diff --git a/internal/cmd/server/command/list/list_test.go b/internal/cmd/server/command/list/list_test.go index 6740fac38..7d6ce40fb 100644 --- a/internal/cmd/server/command/list/list_test.go +++ b/internal/cmd/server/command/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -208,7 +209,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.commands); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/template/describe/describe.go b/internal/cmd/server/command/template/describe/describe.go index 816bfa8be..a694b9cad 100644 --- a/internal/cmd/server/command/template/describe/describe.go +++ b/internal/cmd/server/command/template/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { CommandTemplateName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", commandTemplateNameArg), Short: "Shows details of a Server Command Template", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server command template: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/command/template/describe/describe_test.go b/internal/cmd/server/command/template/describe/describe_test.go index 85b97a8ea..9fa7ba208 100644 --- a/internal/cmd/server/command/template/describe/describe_test.go +++ b/internal/cmd/server/command/template/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -163,7 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -261,7 +262,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.commandTemplate); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/template/list/list.go b/internal/cmd/server/command/template/list/list.go index 079c4f5f7..439df690d 100644 --- a/internal/cmd/server/command/template/list/list.go +++ b/internal/cmd/server/command/template/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server command templates", @@ -44,13 +45,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -62,7 +63,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("list server command templates: %w", err) } if templates := resp.Items; templates == nil || len(*templates) == 0 { - p.Info("No commands templates found\n") + params.Printer.Info("No commands templates found\n") return nil } templates := *resp.Items @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(templates) > int(*model.Limit) { templates = templates[:*model.Limit] } - return outputResult(p, model.OutputFormat, templates) + return outputResult(params.Printer, model.OutputFormat, templates) }, } configureFlags(cmd) diff --git a/internal/cmd/server/command/template/list/list_test.go b/internal/cmd/server/command/template/list/list_test.go index 309716c16..0ff491e5d 100644 --- a/internal/cmd/server/command/template/list/list_test.go +++ b/internal/cmd/server/command/template/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -111,7 +112,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -207,7 +208,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.templates); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/template/template.go b/internal/cmd/server/command/template/template.go index 03f9b13da..6b41f434b 100644 --- a/internal/cmd/server/command/template/template.go +++ b/internal/cmd/server/command/template/template.go @@ -1,16 +1,16 @@ package template import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "template", Short: "Provides functionality for Server Command Template", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/server/console/console.go b/internal/cmd/server/console/console.go index a9964619c..35e5f814a 100644 --- a/internal/cmd/server/console/console.go +++ b/internal/cmd/server/console/console.go @@ -7,6 +7,7 @@ import ( "net/url" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("console %s", serverIdArg), Short: "Gets a URL for server remote console", @@ -47,20 +48,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -73,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("server console: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, serverLabel, *resp) }, } return cmd diff --git a/internal/cmd/server/console/console_test.go b/internal/cmd/server/console/console_test.go index 4d9b9e6c1..9b6c0413c 100644 --- a/internal/cmd/server/console/console_test.go +++ b/internal/cmd/server/console/console_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -234,7 +235,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.serverUrl); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 69cfc627b..25544b3c8 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -65,7 +66,7 @@ type inputModel struct { Volumes *[]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a server", @@ -111,26 +112,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a server for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -146,7 +147,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating server") _, err = wait.CreateServerWaitHandler(ctx, apiClient, model.ProjectId, serverId).WaitWithContext(ctx) if err != nil { @@ -155,7 +156,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/create/create_test.go b/internal/cmd/server/create/create_test.go index bf8f815d5..1548691d4 100644 --- a/internal/cmd/server/create/create_test.go +++ b/internal/cmd/server/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -326,7 +327,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -434,7 +435,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.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.server); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/deallocate/deallocate.go b/internal/cmd/server/deallocate/deallocate.go index 53a01de69..f51fab931 100644 --- a/internal/cmd/server/deallocate/deallocate.go +++ b/internal/cmd/server/deallocate/deallocate.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("deallocate %s", serverIdArg), Short: "Deallocates an existing server", @@ -42,20 +43,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to deallocate server %q?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deallocating server") _, err = wait.DeallocateServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) if err != nil { @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deallocation of" } - p.Info("%s server %q\n", operationState, serverLabel) + params.Printer.Info("%s server %q\n", operationState, serverLabel) return nil }, diff --git a/internal/cmd/server/deallocate/deallocate_test.go b/internal/cmd/server/deallocate/deallocate_test.go index 6ededf983..379fc3a58 100644 --- a/internal/cmd/server/deallocate/deallocate_test.go +++ b/internal/cmd/server/deallocate/deallocate_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -128,7 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/delete/delete.go b/internal/cmd/server/delete/delete.go index 77ad35479..d9a366c2e 100644 --- a/internal/cmd/server/delete/delete.go +++ b/internal/cmd/server/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", serverIdArg), Short: "Deletes a server", @@ -45,20 +46,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ProjectId @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete server %q?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting server") _, err = wait.DeleteServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) if err != nil { @@ -94,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s server %q\n", operationState, serverLabel) + params.Printer.Info("%s server %q\n", operationState, serverLabel) return nil }, } diff --git a/internal/cmd/server/delete/delete_test.go b/internal/cmd/server/delete/delete_test.go index 3b7c0ba31..1c04e26cb 100644 --- a/internal/cmd/server/delete/delete_test.go +++ b/internal/cmd/server/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/describe/describe.go b/internal/cmd/server/describe/describe.go index d45086fb2..4873e688c 100644 --- a/internal/cmd/server/describe/describe.go +++ b/internal/cmd/server/describe/describe.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", serverIdArg), Short: "Shows details of a server", @@ -47,13 +48,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/server/describe/describe_test.go b/internal/cmd/server/describe/describe_test.go index d16a3ec04..86052e8b7 100644 --- a/internal/cmd/server/describe/describe_test.go +++ b/internal/cmd/server/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -139,7 +140,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -243,7 +244,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.server); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/list/list.go b/internal/cmd/server/list/list.go index db72cdb26..867a0e233 100644 --- a/internal/cmd/server/list/list.go +++ b/internal/cmd/server/list/list.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all servers of a project", @@ -58,13 +59,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,12 +78,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No servers found for project %q\n", projectLabel) + params.Printer.Info("No servers found for project %q\n", projectLabel) return nil } @@ -92,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/server/list/list_test.go b/internal/cmd/server/list/list_test.go index a8dfe0e1e..64fe0ddb4 100644 --- a/internal/cmd/server/list/list_test.go +++ b/internal/cmd/server/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -133,7 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -221,7 +222,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.servers); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/log/log.go b/internal/cmd/server/log/log.go index 646417b42..76e80cc67 100644 --- a/internal/cmd/server/log/log.go +++ b/internal/cmd/server/log/log.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Length *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("log %s", serverIdArg), Short: "Gets server console log", @@ -56,20 +57,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -88,10 +89,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(lines) > int(*model.Length) { // Truncate output and show most recent logs start := len(lines) - int(*model.Length) - return outputResult(p, model.OutputFormat, serverLabel, strings.Join(lines[start:], "\n")) + return outputResult(params.Printer, model.OutputFormat, serverLabel, strings.Join(lines[start:], "\n")) } - return outputResult(p, model.OutputFormat, serverLabel, log) + return outputResult(params.Printer, model.OutputFormat, serverLabel, log) }, } configureFlags(cmd) diff --git a/internal/cmd/server/log/log_test.go b/internal/cmd/server/log/log_test.go index 50ce7c723..0ebc57bdc 100644 --- a/internal/cmd/server/log/log_test.go +++ b/internal/cmd/server/log/log_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -142,7 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -239,7 +240,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.log); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/machine-type/describe/describe.go b/internal/cmd/server/machine-type/describe/describe.go index 8c5d99e38..018bf0ad7 100644 --- a/internal/cmd/server/machine-type/describe/describe.go +++ b/internal/cmd/server/machine-type/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { MachineType string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", machineTypeArg), Short: "Shows details of a server machine type", @@ -47,13 +48,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server machine type: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/server/machine-type/describe/describe_test.go b/internal/cmd/server/machine-type/describe/describe_test.go index 32f6d9a0b..20e47affc 100644 --- a/internal/cmd/server/machine-type/describe/describe_test.go +++ b/internal/cmd/server/machine-type/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -126,7 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -222,7 +223,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.machineType); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go index 19be072d3..2e5a20bde 100644 --- a/internal/cmd/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ const ( limitFlag = "limit" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Get list of all machine types available in a project", @@ -52,13 +53,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,12 +72,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No machine-types found for project %q\n", projectLabel) + params.Printer.Info("No machine-types found for project %q\n", projectLabel) return nil } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { *resp.Items = (*resp.Items)[:*model.Limit] } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } diff --git a/internal/cmd/server/machine-type/list/list_test.go b/internal/cmd/server/machine-type/list/list_test.go index a38d4f386..8472b596d 100644 --- a/internal/cmd/server/machine-type/list/list_test.go +++ b/internal/cmd/server/machine-type/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -118,7 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -206,7 +207,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.machineTypes); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/machine-type/machine-type.go b/internal/cmd/server/machine-type/machine-type.go index 51c33d236..9482a6143 100644 --- a/internal/cmd/server/machine-type/machine-type.go +++ b/internal/cmd/server/machine-type/machine-type.go @@ -1,16 +1,16 @@ package machinetype import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/machine-type/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/machine-type/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "machine-type", Short: "Provides functionality for server machine types available inside a project", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/server/network-interface/attach/attach.go b/internal/cmd/server/network-interface/attach/attach.go index b2f987f27..68e670159 100644 --- a/internal/cmd/server/network-interface/attach/attach.go +++ b/internal/cmd/server/network-interface/attach/attach.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -35,7 +36,7 @@ type inputModel struct { Create *bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "attach", Short: "Attaches a network interface to a server", @@ -53,20 +54,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } @@ -74,12 +75,12 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Create != nil && *model.Create { networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) if err != nil { - p.Debug(print.ErrorLevel, "get network name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = *model.NetworkId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a network interface for network %q and attach it to server %q?", networkLabel, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -90,13 +91,13 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("create and attach network interface: %w", err) } - p.Info("Created a network interface for network %q and attached it to server %q\n", networkLabel, serverLabel) + params.Printer.Info("Created a network interface for network %q and attached it to server %q\n", networkLabel, serverLabel) return nil } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to attach network interface %q to server %q?", *model.NicId, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -107,7 +108,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("attach network interface: %w", err) } - p.Info("Attached network interface %q to server %q\n", utils.PtrString(model.NicId), serverLabel) + params.Printer.Info("Attached network interface %q to server %q\n", utils.PtrString(model.NicId), serverLabel) return nil }, diff --git a/internal/cmd/server/network-interface/attach/attach_test.go b/internal/cmd/server/network-interface/attach/attach_test.go index 2adeff447..6e5a00011 100644 --- a/internal/cmd/server/network-interface/attach/attach_test.go +++ b/internal/cmd/server/network-interface/attach/attach_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -199,7 +200,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/network-interface/detach/detach.go b/internal/cmd/server/network-interface/detach/detach.go index f0c735cb1..6a2517e50 100644 --- a/internal/cmd/server/network-interface/detach/detach.go +++ b/internal/cmd/server/network-interface/detach/detach.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -35,7 +36,7 @@ type inputModel struct { Delete *bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "detach", Short: "Detaches a network interface from a server", @@ -53,20 +54,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -76,12 +77,12 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Delete != nil && *model.Delete { networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) if err != nil { - p.Debug(print.ErrorLevel, "get network name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = *model.NetworkId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to detach and delete all network interfaces of network %q from server %q? (This cannot be undone)", networkLabel, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -92,13 +93,13 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("detach and delete network interfaces: %w", err) } - p.Info("Detached and deleted all network interfaces of network %q from server %q\n", networkLabel, serverLabel) + params.Printer.Info("Detached and deleted all network interfaces of network %q from server %q\n", networkLabel, serverLabel) return nil } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to detach network interface %q from server %q?", *model.NicId, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -109,7 +110,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("detach network interface: %w", err) } - p.Info("Detached network interface %q from server %q\n", utils.PtrString(model.NicId), serverLabel) + params.Printer.Info("Detached network interface %q from server %q\n", utils.PtrString(model.NicId), serverLabel) return nil }, diff --git a/internal/cmd/server/network-interface/detach/detach_test.go b/internal/cmd/server/network-interface/detach/detach_test.go index df408bbb8..cc60c9912 100644 --- a/internal/cmd/server/network-interface/detach/detach_test.go +++ b/internal/cmd/server/network-interface/detach/detach_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -199,7 +200,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/network-interface/list/list.go b/internal/cmd/server/network-interface/list/list.go index eb3210cf4..62d4f6c8b 100644 --- a/internal/cmd/server/network-interface/list/list.go +++ b/internal/cmd/server/network-interface/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all attached network interfaces of a server", @@ -53,13 +54,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -74,12 +75,12 @@ func NewCmd(p *print.Printer) *cobra.Command { if resp.Items == nil || len(*resp.Items) == 0 { serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId } - p.Info("No attached network interfaces found for server %q\n", serverLabel) + params.Printer.Info("No attached network interfaces found for server %q\n", serverLabel) return nil } @@ -89,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, *model.ServerId, items) + return outputResult(params.Printer, model.OutputFormat, *model.ServerId, items) }, } configureFlags(cmd) diff --git a/internal/cmd/server/network-interface/list/list_test.go b/internal/cmd/server/network-interface/list/list_test.go index f627b1d19..8d2c90f86 100644 --- a/internal/cmd/server/network-interface/list/list_test.go +++ b/internal/cmd/server/network-interface/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -235,7 +236,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverId, tt.args.serverNics); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/network-interface/network-interface.go b/internal/cmd/server/network-interface/network-interface.go index 703e48eba..998ee07d3 100644 --- a/internal/cmd/server/network-interface/network-interface.go +++ b/internal/cmd/server/network-interface/network-interface.go @@ -1,17 +1,17 @@ package networkinterface import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/attach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/detach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network-interface", Short: "Allows attaching/detaching network interfaces to servers", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(attach.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(detach.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(attach.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(detach.NewCmd(params)) } diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index 71845bc2a..0bb65907d 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { MaintenanceWindow int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server os-update.", @@ -51,23 +52,23 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a os-update for server %s?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server os-update: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/os-update/create/create_test.go b/internal/cmd/server/os-update/create/create_test.go index 9dd635e70..78e914882 100644 --- a/internal/cmd/server/os-update/create/create_test.go +++ b/internal/cmd/server/os-update/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -226,7 +227,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/describe/describe.go b/internal/cmd/server/os-update/describe/describe.go index 7260131ff..e722e3994 100644 --- a/internal/cmd/server/os-update/describe/describe.go +++ b/internal/cmd/server/os-update/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { UpdateId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", updateIdArg), Short: "Shows details of a Server os-update", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server os-update: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/os-update/describe/describe_test.go b/internal/cmd/server/os-update/describe/describe_test.go index 741bbe6dc..0a859c415 100644 --- a/internal/cmd/server/os-update/describe/describe_test.go +++ b/internal/cmd/server/os-update/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -133,7 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -231,7 +232,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.update); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go index f0270b0cd..153754db3 100644 --- a/internal/cmd/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "disable", Short: "Disables server os-update service", @@ -40,23 +41,23 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -64,7 +65,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to disable the os-update service for server %s?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("disable server os-update service: %w", err) } - p.Info("Disabled Server os-update service for server %s\n", serverLabel) + params.Printer.Info("Disabled Server os-update service for server %s\n", serverLabel) return nil }, } diff --git a/internal/cmd/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go index c255c778e..ad0467bb5 100644 --- a/internal/cmd/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "enable", Short: "Enables Server os-update service", @@ -41,23 +42,23 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to enable the server os-update service for server %s?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - p.Info("Enabled os-update service for server %s\n", serverLabel) + params.Printer.Info("Enabled os-update service for server %s\n", serverLabel) return nil }, } diff --git a/internal/cmd/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go index e1435badc..ed7f183b7 100644 --- a/internal/cmd/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "strconv" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server os-updates", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -71,15 +72,15 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(updates) == 0 { serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } } - p.Info("No os-updates found for server %s\n", serverLabel) + params.Printer.Info("No os-updates found for server %s\n", serverLabel) return nil } @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(updates) > int(*model.Limit) { updates = updates[:*model.Limit] } - return outputResult(p, model.OutputFormat, updates) + return outputResult(params.Printer, model.OutputFormat, updates) }, } configureFlags(cmd) diff --git a/internal/cmd/server/os-update/list/list_test.go b/internal/cmd/server/os-update/list/list_test.go index 36205f88d..078f7ca0a 100644 --- a/internal/cmd/server/os-update/list/list_test.go +++ b/internal/cmd/server/os-update/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -208,7 +209,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.updates); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/os-update.go b/internal/cmd/server/os-update/os-update.go index a9d3ec8fc..516d7ce06 100644 --- a/internal/cmd/server/os-update/os-update.go +++ b/internal/cmd/server/os-update/os-update.go @@ -1,6 +1,7 @@ package osupdate import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/create" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/disable" @@ -8,13 +9,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "os-update", Short: "Provides functionality for managed server updates", @@ -22,15 +22,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(enable.NewCmd(p)) - cmd.AddCommand(disable.NewCmd(p)) - cmd.AddCommand(schedule.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(enable.NewCmd(params)) + cmd.AddCommand(disable.NewCmd(params)) + cmd.AddCommand(schedule.NewCmd(params)) } diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index 2f30e876f..f64b10728 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -43,7 +44,7 @@ type inputModel struct { MaintenanceWindow int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server os-update Schedule", @@ -60,23 +61,23 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a os-update Schedule for server %s?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -100,7 +101,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create Server os-update Schedule: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/os-update/schedule/create/create_test.go b/internal/cmd/server/os-update/schedule/create/create_test.go index 7d084516e..2cdb00f75 100644 --- a/internal/cmd/server/os-update/schedule/create/create_test.go +++ b/internal/cmd/server/os-update/schedule/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -136,7 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -233,7 +234,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/schedule/delete/delete.go b/internal/cmd/server/os-update/schedule/delete/delete.go index 855690fa4..a439bf76a 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete.go +++ b/internal/cmd/server/os-update/schedule/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", scheduleIdArg), Short: "Deletes a Server os-update Schedule", @@ -40,20 +41,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete server os-update schedule %q? (This cannot be undone)", model.ScheduleId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete Server os-update Schedule: %w", err) } - p.Info("Deleted server os-update schedule %q\n", model.ScheduleId) + params.Printer.Info("Deleted server os-update schedule %q\n", model.ScheduleId) return nil }, } diff --git a/internal/cmd/server/os-update/schedule/delete/delete_test.go b/internal/cmd/server/os-update/schedule/delete/delete_test.go index 040aa61f7..eb005e164 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete_test.go +++ b/internal/cmd/server/os-update/schedule/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -133,7 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/os-update/schedule/describe/describe.go b/internal/cmd/server/os-update/schedule/describe/describe.go index 60aa9431c..f66c9b5d2 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/server/os-update/schedule/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { ScheduleId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", scheduleIdArg), Short: "Shows details of a Server os-update Schedule", @@ -46,12 +47,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read server os-update schedule: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/os-update/schedule/describe/describe_test.go b/internal/cmd/server/os-update/schedule/describe/describe_test.go index 5928e712b..178585383 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe_test.go +++ b/internal/cmd/server/os-update/schedule/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -133,7 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -231,7 +232,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.schedule); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go index 562b30665..b14299303 100644 --- a/internal/cmd/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server os-update schedules", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -69,15 +70,15 @@ func NewCmd(p *print.Printer) *cobra.Command { if len(schedules) == 0 { serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(p); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { serverLabel = serverName } } - p.Info("No os-update schedules found for server %s\n", serverLabel) + params.Printer.Info("No os-update schedules found for server %s\n", serverLabel) return nil } @@ -85,7 +86,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Limit != nil && len(schedules) > int(*model.Limit) { schedules = schedules[:*model.Limit] } - return outputResult(p, model.OutputFormat, schedules) + return outputResult(params.Printer, model.OutputFormat, schedules) }, } configureFlags(cmd) diff --git a/internal/cmd/server/os-update/schedule/list/list_test.go b/internal/cmd/server/os-update/schedule/list/list_test.go index d29d3dd5f..57aa1c0dc 100644 --- a/internal/cmd/server/os-update/schedule/list/list_test.go +++ b/internal/cmd/server/os-update/schedule/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -120,7 +121,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -208,7 +209,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.schedules); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/schedule/schedule.go b/internal/cmd/server/os-update/schedule/schedule.go index 9f051ced0..3ffeb36ea 100644 --- a/internal/cmd/server/os-update/schedule/schedule.go +++ b/internal/cmd/server/os-update/schedule/schedule.go @@ -1,19 +1,19 @@ package schedule import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/create" del "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "schedule", Short: "Provides functionality for Server os-update Schedule", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(del.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(del.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/server/os-update/schedule/update/update.go b/internal/cmd/server/os-update/schedule/update/update.go index e698f21f7..bae09473e 100644 --- a/internal/cmd/server/os-update/schedule/update/update.go +++ b/internal/cmd/server/os-update/schedule/update/update.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -43,7 +44,7 @@ type inputModel struct { MaintenanceWindow *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", scheduleIdArg), Short: "Updates a Server os-update Schedule", @@ -57,26 +58,26 @@ func NewCmd(p *print.Printer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } currentSchedule, err := apiClient.GetUpdateScheduleExecute(ctx, model.ProjectId, model.ServerId, model.ScheduleId, model.Region) if err != nil { - p.Debug(print.ErrorLevel, "get current server os-update schedule: %v", err) + params.Printer.Debug(print.ErrorLevel, "get current server os-update schedule: %v", err) return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update Server os-update Schedule %q?", model.ScheduleId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -92,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update Server os-update Schedule: %w", err) } - return outputResult(p, model.OutputFormat, *resp) + return outputResult(params.Printer, model.OutputFormat, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/os-update/schedule/update/update_test.go b/internal/cmd/server/os-update/schedule/update/update_test.go index 63ab21239..a19c77958 100644 --- a/internal/cmd/server/os-update/schedule/update/update_test.go +++ b/internal/cmd/server/os-update/schedule/update/update_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -173,7 +174,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -285,7 +286,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/public-ip/attach/attach.go b/internal/cmd/server/public-ip/attach/attach.go index 848a913b4..8caecd342 100644 --- a/internal/cmd/server/public-ip/attach/attach.go +++ b/internal/cmd/server/public-ip/attach/attach.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("attach %s", publicIpIdArg), Short: "Attaches a public IP to a server", @@ -42,20 +43,20 @@ func NewCmd(p *print.Printer) *cobra.Command { )), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) if err != nil { - p.Debug(print.ErrorLevel, "get public ip name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get public ip name: %v", err) publicIpLabel = model.PublicIpId } else if publicIpLabel == "" { publicIpLabel = model.PublicIpId @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -71,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to attach public IP %q to server %q?", publicIpLabel, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("attach server to public ip: %w", err) } - p.Info("Attached public IP %q to server %q\n", publicIpLabel, serverLabel) + params.Printer.Info("Attached public IP %q to server %q\n", publicIpLabel, serverLabel) return nil }, } diff --git a/internal/cmd/server/public-ip/attach/attach_test.go b/internal/cmd/server/public-ip/attach/attach_test.go index b8a80d6b2..c58f7b280 100644 --- a/internal/cmd/server/public-ip/attach/attach_test.go +++ b/internal/cmd/server/public-ip/attach/attach_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -147,7 +148,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/public-ip/detach/detach.go b/internal/cmd/server/public-ip/detach/detach.go index 809b76759..c8066db67 100644 --- a/internal/cmd/server/public-ip/detach/detach.go +++ b/internal/cmd/server/public-ip/detach/detach.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("detach %s", publicIpIdArg), Short: "Detaches a public IP from a server", @@ -43,20 +44,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) if err != nil { - p.Debug(print.ErrorLevel, "get public ip: %v", err) + params.Printer.Debug(print.ErrorLevel, "get public ip: %v", err) publicIpLabel = model.PublicIpId } else if publicIpLabel == "" { publicIpLabel = model.PublicIpId @@ -64,7 +65,7 @@ func NewCmd(p *print.Printer) *cobra.Command { serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to detach public IP %q from server %q?", publicIpLabel, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("detach public ip from server: %w", err) } - p.Info("Detached public IP %q from server %q\n", publicIpLabel, serverLabel) + params.Printer.Info("Detached public IP %q from server %q\n", publicIpLabel, serverLabel) return nil }, diff --git a/internal/cmd/server/public-ip/detach/detach_test.go b/internal/cmd/server/public-ip/detach/detach_test.go index b7ed5c286..8a46591a7 100644 --- a/internal/cmd/server/public-ip/detach/detach_test.go +++ b/internal/cmd/server/public-ip/detach/detach_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -146,7 +147,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/public-ip/public_ip.go b/internal/cmd/server/public-ip/public_ip.go index 0bfafbcbd..494993ce8 100644 --- a/internal/cmd/server/public-ip/public_ip.go +++ b/internal/cmd/server/public-ip/public_ip.go @@ -1,16 +1,16 @@ package publicip import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/public-ip/attach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/public-ip/detach" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "public-ip", Short: "Allows attaching/detaching public IPs to servers", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(attach.NewCmd(p)) - cmd.AddCommand(detach.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(attach.NewCmd(params)) + cmd.AddCommand(detach.NewCmd(params)) } diff --git a/internal/cmd/server/reboot/reboot.go b/internal/cmd/server/reboot/reboot.go index 80aed47b3..465adaaa1 100644 --- a/internal/cmd/server/reboot/reboot.go +++ b/internal/cmd/server/reboot/reboot.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { HardReboot bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reboot %s", serverIdArg), Short: "Reboots a server", @@ -50,27 +51,27 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to reboot server %q?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("server reboot: %w", err) } - p.Info("Server %q rebooted\n", serverLabel) + params.Printer.Info("Server %q rebooted\n", serverLabel) return nil }, diff --git a/internal/cmd/server/reboot/reboot_test.go b/internal/cmd/server/reboot/reboot_test.go index c4444fa85..77e99f506 100644 --- a/internal/cmd/server/reboot/reboot_test.go +++ b/internal/cmd/server/reboot/reboot_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -130,7 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/rescue/rescue.go b/internal/cmd/server/rescue/rescue.go index 81eabcab2..73aeae948 100644 --- a/internal/cmd/server/rescue/rescue.go +++ b/internal/cmd/server/rescue/rescue.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { ImageId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("rescue %s", serverIdArg), Short: "Rescues an existing server", @@ -46,20 +47,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to rescue server %q?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Rescuing server") _, err = wait.RescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) if err != nil { @@ -95,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered rescue of" } - p.Info("%s server %q. Image %q is used as temporary boot image\n", operationState, serverLabel, utils.PtrString(model.ImageId)) + params.Printer.Info("%s server %q. Image %q is used as temporary boot image\n", operationState, serverLabel, utils.PtrString(model.ImageId)) return nil }, diff --git a/internal/cmd/server/rescue/rescue_test.go b/internal/cmd/server/rescue/rescue_test.go index 9d17daf78..8a5695fd9 100644 --- a/internal/cmd/server/rescue/rescue_test.go +++ b/internal/cmd/server/rescue/rescue_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -145,7 +146,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/resize/resize.go b/internal/cmd/server/resize/resize.go index d0112b723..8d3f19b3e 100644 --- a/internal/cmd/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { MachineType *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("resize %s", serverIdArg), Short: "Resizes the server to the given machine type", @@ -46,20 +47,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to resize server %q to machine type %q?", serverLabel, *model.MachineType) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Resizing server") _, err = wait.ResizeServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) if err != nil { @@ -95,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered resize of" } - p.Info("%s server %q\n", operationState, serverLabel) + params.Printer.Info("%s server %q\n", operationState, serverLabel) return nil }, diff --git a/internal/cmd/server/resize/resize_test.go b/internal/cmd/server/resize/resize_test.go index a93d8fdc1..ee94cfe6e 100644 --- a/internal/cmd/server/resize/resize_test.go +++ b/internal/cmd/server/resize/resize_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -144,7 +145,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/server.go b/internal/cmd/server/server.go index 209b19e1b..ac3101b41 100644 --- a/internal/cmd/server/server.go +++ b/internal/cmd/server/server.go @@ -1,6 +1,7 @@ package server import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command" "github.com/stackitcloud/stackit-cli/internal/cmd/server/console" @@ -25,13 +26,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "server", Short: "Provides functionality for servers", @@ -39,31 +39,31 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(backup.NewCmd(p)) - cmd.AddCommand(command.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(publicip.NewCmd(p)) - cmd.AddCommand(serviceaccount.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(volume.NewCmd(p)) - cmd.AddCommand(networkinterface.NewCmd(p)) - cmd.AddCommand(console.NewCmd(p)) - cmd.AddCommand(log.NewCmd(p)) - cmd.AddCommand(start.NewCmd(p)) - cmd.AddCommand(stop.NewCmd(p)) - cmd.AddCommand(reboot.NewCmd(p)) - cmd.AddCommand(deallocate.NewCmd(p)) - cmd.AddCommand(resize.NewCmd(p)) - cmd.AddCommand(rescue.NewCmd(p)) - cmd.AddCommand(unrescue.NewCmd(p)) - cmd.AddCommand(osUpdate.NewCmd(p)) - cmd.AddCommand(machinetype.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(backup.NewCmd(params)) + cmd.AddCommand(command.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(publicip.NewCmd(params)) + cmd.AddCommand(serviceaccount.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(volume.NewCmd(params)) + cmd.AddCommand(networkinterface.NewCmd(params)) + cmd.AddCommand(console.NewCmd(params)) + cmd.AddCommand(log.NewCmd(params)) + cmd.AddCommand(start.NewCmd(params)) + cmd.AddCommand(stop.NewCmd(params)) + cmd.AddCommand(reboot.NewCmd(params)) + cmd.AddCommand(deallocate.NewCmd(params)) + cmd.AddCommand(resize.NewCmd(params)) + cmd.AddCommand(rescue.NewCmd(params)) + cmd.AddCommand(unrescue.NewCmd(params)) + cmd.AddCommand(osUpdate.NewCmd(params)) + cmd.AddCommand(machinetype.NewCmd(params)) } diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 49f7a1aa4..e4e29042c 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { ServiceAccMail string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("attach %s", serviceAccMailArg), Short: "Attach a service account to a server", @@ -45,19 +46,19 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to attach service account %q to server %q?", model.ServiceAccMail, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("attach service account to server: %w", err) } - return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, model.ServiceAccMail, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/service-account/attach/attach_test.go b/internal/cmd/server/service-account/attach/attach_test.go index fddde577b..96ed151ce 100644 --- a/internal/cmd/server/service-account/attach/attach_test.go +++ b/internal/cmd/server/service-account/attach/attach_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -146,7 +147,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -244,7 +245,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serviceAccMail, tt.args.serverLabel, tt.args.serviceAccounts); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index aa3983c58..6b79c6998 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { ServiceAccMail string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("detach %s", serviceAccMailArg), Short: "Detach a service account from a server", @@ -45,19 +46,19 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -65,7 +66,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are your sure you want to detach service account %q from a server %q?", model.ServiceAccMail, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("detach service account request: %w", err) } - return outputResult(p, model.OutputFormat, model.ServiceAccMail, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, model.ServiceAccMail, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/service-account/detach/detach_test.go b/internal/cmd/server/service-account/detach/detach_test.go index ffee083d4..acfd02802 100644 --- a/internal/cmd/server/service-account/detach/detach_test.go +++ b/internal/cmd/server/service-account/detach/detach_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -146,7 +147,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -244,7 +245,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serviceAccMail, tt.args.serverLabel, tt.args.service); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/service-account/list/list.go b/internal/cmd/server/service-account/list/list.go index d9288a246..5c90714fd 100644 --- a/internal/cmd/server/service-account/list/list.go +++ b/internal/cmd/server/service-account/list/list.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -30,7 +31,7 @@ type inputModel struct { ServerId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "List all attached service accounts for a server", @@ -52,20 +53,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverName, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverName = *model.ServerId } else if serverName == "" { serverName = *model.ServerId @@ -79,7 +80,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } serviceAccounts := *resp.Items if len(serviceAccounts) == 0 { - p.Info("No service accounts found for server %s\n", serverName) + params.Printer.Info("No service accounts found for server %s\n", serverName) return nil } @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { serviceAccounts = serviceAccounts[:int(*model.Limit)] } - return outputResult(p, model.OutputFormat, *model.ServerId, serverName, serviceAccounts) + return outputResult(params.Printer, model.OutputFormat, *model.ServerId, serverName, serviceAccounts) }, } configureFlags(cmd) diff --git a/internal/cmd/server/service-account/list/list_test.go b/internal/cmd/server/service-account/list/list_test.go index 961ba2a0a..9ba1d281a 100644 --- a/internal/cmd/server/service-account/list/list_test.go +++ b/internal/cmd/server/service-account/list/list_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -149,7 +150,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -248,7 +249,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverId, tt.args.serverName, tt.args.serviceAccounts); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/service-account/service-account.go b/internal/cmd/server/service-account/service-account.go index 0739d29a7..b9455c563 100644 --- a/internal/cmd/server/service-account/service-account.go +++ b/internal/cmd/server/service-account/service-account.go @@ -3,15 +3,15 @@ package serviceaccount import ( "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/attach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/detach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/list" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "service-account", Short: "Allows attaching/detaching service accounts to servers", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: cobra.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(attach.NewCmd(p)) - cmd.AddCommand(detach.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(attach.NewCmd(params)) + cmd.AddCommand(detach.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/server/start/start.go b/internal/cmd/server/start/start.go index 7daec696f..918bab2a3 100644 --- a/internal/cmd/server/start/start.go +++ b/internal/cmd/server/start/start.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("start %s", serverIdArg), Short: "Starts an existing server or allocates the server if deallocated", @@ -42,20 +43,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Starting server") _, err = wait.StartServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) if err != nil { @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered start of" } - p.Info("%s server %q\n", operationState, serverLabel) + params.Printer.Info("%s server %q\n", operationState, serverLabel) return nil }, diff --git a/internal/cmd/server/start/start_test.go b/internal/cmd/server/start/start_test.go index f90b6048d..2776c77e7 100644 --- a/internal/cmd/server/start/start_test.go +++ b/internal/cmd/server/start/start_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -128,7 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/stop/stop.go b/internal/cmd/server/stop/stop.go index 1201c778b..ccb21bedc 100644 --- a/internal/cmd/server/stop/stop.go +++ b/internal/cmd/server/stop/stop.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("stop %s", serverIdArg), Short: "Stops an existing server", @@ -42,20 +43,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to stop server %q?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Stopping server") _, err = wait.StopServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) if err != nil { @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered stop of" } - p.Info("%s server %q\n", operationState, serverLabel) + params.Printer.Info("%s server %q\n", operationState, serverLabel) return nil }, diff --git a/internal/cmd/server/stop/stop_test.go b/internal/cmd/server/stop/stop_test.go index a4e889181..bbaefddba 100644 --- a/internal/cmd/server/stop/stop_test.go +++ b/internal/cmd/server/stop/stop_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -128,7 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/unrescue/unrescue.go b/internal/cmd/server/unrescue/unrescue.go index 5fc2d7c42..181ab88bc 100644 --- a/internal/cmd/server/unrescue/unrescue.go +++ b/internal/cmd/server/unrescue/unrescue.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("unrescue %s", serverIdArg), Short: "Unrescues an existing server", @@ -42,20 +43,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -63,7 +64,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to unrescue server %q?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Unrescuing server") _, err = wait.UnrescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) if err != nil { @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered unrescue of" } - p.Info("%s server %q\n", operationState, serverLabel) + params.Printer.Info("%s server %q\n", operationState, serverLabel) return nil }, diff --git a/internal/cmd/server/unrescue/unrescue_test.go b/internal/cmd/server/unrescue/unrescue_test.go index 82f75a370..1f2d95712 100644 --- a/internal/cmd/server/unrescue/unrescue_test.go +++ b/internal/cmd/server/unrescue/unrescue_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -128,7 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/update/update.go b/internal/cmd/server/update/update.go index d7e06d95a..2b8b35985 100644 --- a/internal/cmd/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", serverIdArg), Short: "Updates a server", @@ -52,20 +53,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId } else if serverLabel == "" { serverLabel = model.ServerId @@ -73,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update server %q?", serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -86,7 +87,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update server: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, resp) + return outputResult(params.Printer, model.OutputFormat, serverLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/update/update_test.go b/internal/cmd/server/update/update_test.go index 5286eb70f..63398311e 100644 --- a/internal/cmd/server/update/update_test.go +++ b/internal/cmd/server/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -172,7 +173,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -269,7 +270,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.server); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go index 61eab4ba0..fee7c9097 100644 --- a/internal/cmd/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { DeleteOnTermination *bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("attach %s", volumeIdArg), Short: "Attaches a volume to a server", @@ -53,20 +54,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { - p.Debug(print.ErrorLevel, "get volume name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } else if volumeLabel == "" { volumeLabel = model.VolumeId @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -82,7 +83,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to attach volume %q to server %q?", volumeLabel, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -95,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("attach server volume: %w", err) } - return outputResult(p, model.OutputFormat, volumeLabel, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, volumeLabel, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/volume/attach/attach_test.go b/internal/cmd/server/volume/attach/attach_test.go index 29dd0ff1f..9a180a4c0 100644 --- a/internal/cmd/server/volume/attach/attach_test.go +++ b/internal/cmd/server/volume/attach/attach_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -171,7 +172,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -269,7 +270,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.volumeLabel, tt.args.serverLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/describe/describe.go b/internal/cmd/server/volume/describe/describe.go index 9336183a5..87ebac142 100644 --- a/internal/cmd/server/volume/describe/describe.go +++ b/internal/cmd/server/volume/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { VolumeId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", volumeIdArg), Short: "Describes a server volume attachment", @@ -53,20 +54,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { - p.Debug(print.ErrorLevel, "get volume name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } else if volumeLabel == "" { volumeLabel = model.VolumeId @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("describe server volume: %w", err) } - return outputResult(p, model.OutputFormat, serverLabel, volumeLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, serverLabel, volumeLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/volume/describe/describe_test.go b/internal/cmd/server/volume/describe/describe_test.go index c86b57259..f2182f04c 100644 --- a/internal/cmd/server/volume/describe/describe_test.go +++ b/internal/cmd/server/volume/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -147,7 +148,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -245,7 +246,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.volumeLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/detach/detach.go b/internal/cmd/server/volume/detach/detach.go index 826f1881c..e557fc383 100644 --- a/internal/cmd/server/volume/detach/detach.go +++ b/internal/cmd/server/volume/detach/detach.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { VolumeId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("detach %s", volumeIdArg), Short: "Detaches a volume from a server", @@ -43,20 +44,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { - p.Debug(print.ErrorLevel, "get volume name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } else if volumeLabel == "" { volumeLabel = model.VolumeId @@ -64,7 +65,7 @@ func NewCmd(p *print.Printer) *cobra.Command { serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to detach volume %q from server %q?", volumeLabel, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("detach server volume: %w", err) } - p.Info("Detached volume %q from server %q\n", volumeLabel, serverLabel) + params.Printer.Info("Detached volume %q from server %q\n", volumeLabel, serverLabel) return nil }, diff --git a/internal/cmd/server/volume/detach/detach_test.go b/internal/cmd/server/volume/detach/detach_test.go index dd2032277..4934e778d 100644 --- a/internal/cmd/server/volume/detach/detach_test.go +++ b/internal/cmd/server/volume/detach/detach_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -146,7 +147,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go index dd7509d7f..f3ac90101 100644 --- a/internal/cmd/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { ServerId *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server volumes", @@ -45,20 +46,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } volumes := *resp.Items if len(volumes) == 0 { - p.Info("No volumes found for server %s\n", serverLabel) + params.Printer.Info("No volumes found for server %s\n", serverLabel) return nil } @@ -81,12 +82,12 @@ func NewCmd(p *print.Printer) *cobra.Command { for i := range volumes { volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, *volumes[i].VolumeId) if err != nil { - p.Debug(print.ErrorLevel, "get volume name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) } volumeNames = append(volumeNames, volumeLabel) } - return outputResult(p, model.OutputFormat, serverLabel, volumeNames, volumes) + return outputResult(params.Printer, model.OutputFormat, serverLabel, volumeNames, volumes) }, } configureFlags(cmd) diff --git a/internal/cmd/server/volume/list/list_test.go b/internal/cmd/server/volume/list/list_test.go index b9c37814f..a337fc247 100644 --- a/internal/cmd/server/volume/list/list_test.go +++ b/internal/cmd/server/volume/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -121,7 +122,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -220,7 +221,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serverLabel, tt.args.volumeNames, tt.args.volumes); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go index 5722808ef..e4795996d 100644 --- a/internal/cmd/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { DeleteOnTermination *bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", volumeIdArg), Short: "Updates an attached volume of a server", @@ -49,20 +50,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { - p.Debug(print.ErrorLevel, "get volume name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } else if volumeLabel == "" { volumeLabel = model.VolumeId @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) if err != nil { - p.Debug(print.ErrorLevel, "get server name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId } else if serverLabel == "" { serverLabel = *model.ServerId @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update attached volume %q of server %q?", volumeLabel, serverLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update server volume: %w", err) } - return outputResult(p, model.OutputFormat, volumeLabel, serverLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, volumeLabel, serverLabel, *resp) }, } configureFlags(cmd) diff --git a/internal/cmd/server/volume/update/update_test.go b/internal/cmd/server/volume/update/update_test.go index 46d5a0d20..1f820cff2 100644 --- a/internal/cmd/server/volume/update/update_test.go +++ b/internal/cmd/server/volume/update/update_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -170,7 +171,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -268,7 +269,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.volumeLabel, tt.args.serverLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/volume.go b/internal/cmd/server/volume/volume.go index c851bbcd7..15dd14ef7 100644 --- a/internal/cmd/server/volume/volume.go +++ b/internal/cmd/server/volume/volume.go @@ -1,19 +1,19 @@ package volume import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/attach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/detach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "volume", Short: "Provides functionality for server volumes", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(attach.NewCmd(p)) - cmd.AddCommand(detach.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(attach.NewCmd(params)) + cmd.AddCommand(detach.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) } diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index eedf109aa..fba36dfeb 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Name *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a service account", @@ -42,26 +43,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a service account for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create service account: %w", err) } - return outputResult(p, model.OutputFormat, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/service-account/create/create_test.go b/internal/cmd/service-account/create/create_test.go index d74e9ad3f..1c3fac895 100644 --- a/internal/cmd/service-account/create/create_test.go +++ b/internal/cmd/service-account/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -117,7 +118,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -213,7 +214,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.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.serviceAccount); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/delete/delete.go b/internal/cmd/service-account/delete/delete.go index 3bb571f87..829d6ac4c 100644 --- a/internal/cmd/service-account/delete/delete.go +++ b/internal/cmd/service-account/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -24,7 +25,7 @@ type inputModel struct { Email string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", emailArg), Short: "Deletes a service account", @@ -37,20 +38,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete service account %s? (This cannot be undone)", model.Email) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete service account: %w", err) } - p.Info("Service account %s deleted\n", model.Email) + params.Printer.Info("Service account %s deleted\n", model.Email) return nil }, } diff --git a/internal/cmd/service-account/delete/delete_test.go b/internal/cmd/service-account/delete/delete_test.go index a48cf2998..9a0dc74ef 100644 --- a/internal/cmd/service-account/delete/delete_test.go +++ b/internal/cmd/service-account/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -126,7 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/service-account/get-jwks/get_jwks.go b/internal/cmd/service-account/get-jwks/get_jwks.go index e86858c3e..641cba592 100644 --- a/internal/cmd/service-account/get-jwks/get_jwks.go +++ b/internal/cmd/service-account/get-jwks/get_jwks.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -22,7 +23,7 @@ type inputModel struct { Email string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("get-jwks %s", emailArg), Short: "Shows the JWKS for a service account", @@ -35,13 +36,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -54,11 +55,11 @@ func NewCmd(p *print.Printer) *cobra.Command { } jwks := *resp.Keys if len(jwks) == 0 { - p.Info("Empty JWKS for service account %s\n", model.Email) + params.Printer.Info("Empty JWKS for service account %s\n", model.Email) return nil } - return outputResult(p, jwks) + return outputResult(params.Printer, jwks) }, } diff --git a/internal/cmd/service-account/get-jwks/get_jwks_test.go b/internal/cmd/service-account/get-jwks/get_jwks_test.go index 93b049d14..c418ffb22 100644 --- a/internal/cmd/service-account/get-jwks/get_jwks_test.go +++ b/internal/cmd/service-account/get-jwks/get_jwks_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -69,7 +70,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -168,7 +169,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.serviceAccounts); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/key/create/create.go b/internal/cmd/service-account/key/create/create.go index 8cf058592..6d99a38fb 100644 --- a/internal/cmd/service-account/key/create/create.go +++ b/internal/cmd/service-account/key/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { PublicKey *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a service account key", @@ -56,13 +57,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -73,7 +74,7 @@ func NewCmd(p *print.Printer) *cobra.Command { validUntilInfo = fmt.Sprintf("The key will be valid for %d days", *model.ExpiresInDays) } prompt := fmt.Sprintf("Are you sure you want to create a key for service account %s? %s", model.ServiceAccountEmail, validUntilInfo) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -86,13 +87,13 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create service account key: %w", err) } - p.Info("Created key for service account %s with ID %q\n", model.ServiceAccountEmail, *resp.Id) + params.Printer.Info("Created key for service account %s with ID %q\n", model.ServiceAccountEmail, *resp.Id) key, err := json.MarshalIndent(resp, "", " ") if err != nil { return fmt.Errorf("marshal key: %w", err) } - p.Outputln(string(key)) + params.Printer.Outputln(string(key)) return nil }, } diff --git a/internal/cmd/service-account/key/create/create_test.go b/internal/cmd/service-account/key/create/create_test.go index f2ded7df9..8f07ed01f 100644 --- a/internal/cmd/service-account/key/create/create_test.go +++ b/internal/cmd/service-account/key/create/create_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -142,7 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/service-account/key/delete/delete.go b/internal/cmd/service-account/key/delete/delete.go index 20e79fa74..ffd77b76a 100644 --- a/internal/cmd/service-account/key/delete/delete.go +++ b/internal/cmd/service-account/key/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { KeyId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", keyIdArg), Short: "Deletes a service account key", @@ -43,20 +44,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete the key %s from service account %s?", model.KeyId, model.ServiceAccountEmail) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -69,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("delete key: %w", err) } - p.Info("Deleted key %s from service account %s\n", model.KeyId, model.ServiceAccountEmail) + params.Printer.Info("Deleted key %s from service account %s\n", model.KeyId, model.ServiceAccountEmail) return nil }, } diff --git a/internal/cmd/service-account/key/delete/delete_test.go b/internal/cmd/service-account/key/delete/delete_test.go index ca808acd5..9e811b0a6 100644 --- a/internal/cmd/service-account/key/delete/delete_test.go +++ b/internal/cmd/service-account/key/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -149,7 +150,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/service-account/key/describe/describe.go b/internal/cmd/service-account/key/describe/describe.go index 61bc9af84..3b7c16ca4 100644 --- a/internal/cmd/service-account/key/describe/describe.go +++ b/internal/cmd/service-account/key/describe/describe.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { KeyId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", keyIdArg), Short: "Shows details of a service account key", @@ -44,12 +45,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -61,7 +62,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read service account key: %w", err) } - return outputResult(p, resp) + return outputResult(params.Printer, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/service-account/key/describe/describe_test.go b/internal/cmd/service-account/key/describe/describe_test.go index 18cd60082..7111fa0a6 100644 --- a/internal/cmd/service-account/key/describe/describe_test.go +++ b/internal/cmd/service-account/key/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -149,7 +150,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -253,7 +254,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.key); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/key/key.go b/internal/cmd/service-account/key/key.go index 969e3df91..b91d31b6a 100644 --- a/internal/cmd/service-account/key/key.go +++ b/internal/cmd/service-account/key/key.go @@ -1,19 +1,19 @@ package key import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/create" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/list" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "key", Short: "Provides functionality for service account keys", @@ -21,14 +21,14 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index 66c7fafcb..194c66486 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all service account keys", @@ -50,13 +51,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -69,7 +70,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } keys := *resp.Items if len(keys) == 0 { - p.Info("No keys found for service account %s\n", model.ServiceAccountEmail) + params.Printer.Info("No keys found for service account %s\n", model.ServiceAccountEmail) return nil } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { keys = keys[:*model.Limit] } - return outputResult(p, model.OutputFormat, keys) + return outputResult(params.Printer, model.OutputFormat, keys) }, } diff --git a/internal/cmd/service-account/key/list/list_test.go b/internal/cmd/service-account/key/list/list_test.go index 46933a70c..ebde67439 100644 --- a/internal/cmd/service-account/key/list/list_test.go +++ b/internal/cmd/service-account/key/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -228,7 +229,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.keys); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/key/update/update.go b/internal/cmd/service-account/key/update/update.go index 5aba23b81..9df30b2a9 100644 --- a/internal/cmd/service-account/key/update/update.go +++ b/internal/cmd/service-account/key/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -38,7 +39,7 @@ type inputModel struct { Deactivate bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", keyIdArg), Short: "Updates a service account key", @@ -60,20 +61,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update the key with ID %q?", model.KeyId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -90,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("marshal key: %w", err) } - p.Info("%s", string(key)) + params.Printer.Info("%s", string(key)) return nil }, } diff --git a/internal/cmd/service-account/key/update/update_test.go b/internal/cmd/service-account/key/update/update_test.go index 706739579..84dde9c6d 100644 --- a/internal/cmd/service-account/key/update/update_test.go +++ b/internal/cmd/service-account/key/update/update_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -196,7 +197,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index c4ea786d2..063e4176a 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all service accounts", @@ -42,13 +43,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -61,12 +62,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } serviceAccounts := *resp.Items if len(serviceAccounts) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No service accounts found for project %q\n", projectLabel) + params.Printer.Info("No service accounts found for project %q\n", projectLabel) return nil } @@ -75,7 +76,7 @@ func NewCmd(p *print.Printer) *cobra.Command { serviceAccounts = serviceAccounts[:*model.Limit] } - return outputResult(p, model.OutputFormat, serviceAccounts) + return outputResult(params.Printer, model.OutputFormat, serviceAccounts) }, } diff --git a/internal/cmd/service-account/list/list_test.go b/internal/cmd/service-account/list/list_test.go index d212eabc8..161f050e2 100644 --- a/internal/cmd/service-account/list/list_test.go +++ b/internal/cmd/service-account/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serviceAccounts); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/service_account.go b/internal/cmd/service-account/service_account.go index 8a4f4634d..9c2462bfa 100644 --- a/internal/cmd/service-account/service_account.go +++ b/internal/cmd/service-account/service_account.go @@ -1,6 +1,7 @@ package serviceaccount import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/create" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/delete" getjwks "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/get-jwks" @@ -8,13 +9,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/list" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/token" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "service-account", Short: "Provides functionality for service accounts", @@ -22,16 +22,16 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(getjwks.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(getjwks.NewCmd(params)) - cmd.AddCommand(key.NewCmd(p)) - cmd.AddCommand(token.NewCmd(p)) + cmd.AddCommand(key.NewCmd(params)) + cmd.AddCommand(token.NewCmd(params)) } diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index 8f96b4002..83c249644 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { TTLDays *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an access token for a service account", @@ -52,20 +53,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create an access token for service account %s?", model.ServiceAccountEmail) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -78,7 +79,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create access token: %w", err) } - return outputResult(p, model.OutputFormat, model.ServiceAccountEmail, token) + return outputResult(params.Printer, model.OutputFormat, model.ServiceAccountEmail, token) }, } diff --git a/internal/cmd/service-account/token/create/create_test.go b/internal/cmd/service-account/token/create/create_test.go index d5d18e3e9..ffa760ce5 100644 --- a/internal/cmd/service-account/token/create/create_test.go +++ b/internal/cmd/service-account/token/create/create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -121,7 +122,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -219,7 +220,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.serviceAccountEmail, tt.args.token); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index 48b793f42..5a51b0ab7 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists access tokens of a service account", @@ -55,13 +56,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } tokensMetadata := *resp.Items if len(tokensMetadata) == 0 { - p.Info("No tokens found for service account with email %q\n", model.ServiceAccountEmail) + params.Printer.Info("No tokens found for service account with email %q\n", model.ServiceAccountEmail) return nil } @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { tokensMetadata = tokensMetadata[:*model.Limit] } - return outputResult(p, model.OutputFormat, tokensMetadata) + return outputResult(params.Printer, model.OutputFormat, tokensMetadata) }, } diff --git a/internal/cmd/service-account/token/list/list_test.go b/internal/cmd/service-account/token/list/list_test.go index fc3f5b54b..e03ee657f 100644 --- a/internal/cmd/service-account/token/list/list_test.go +++ b/internal/cmd/service-account/token/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -228,7 +229,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.tokensMetadata); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/token/revoke/revoke.go b/internal/cmd/service-account/token/revoke/revoke.go index 212f5c2a6..18dfe9fb1 100644 --- a/internal/cmd/service-account/token/revoke/revoke.go +++ b/internal/cmd/service-account/token/revoke/revoke.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { TokenId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("revoke %s", tokenIdArg), Short: "Revokes an access token of a service account", @@ -46,20 +47,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to revoke the access token with ID %q?", model.TokenId) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -72,7 +73,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("revoke access token: %w", err) } - p.Info("Revoked access token with ID %q\n", model.TokenId) + params.Printer.Info("Revoked access token with ID %q\n", model.TokenId) return nil }, } diff --git a/internal/cmd/service-account/token/revoke/revoke_test.go b/internal/cmd/service-account/token/revoke/revoke_test.go index 3cf5b1246..17387aceb 100644 --- a/internal/cmd/service-account/token/revoke/revoke_test.go +++ b/internal/cmd/service-account/token/revoke/revoke_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -149,7 +150,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/service-account/token/token.go b/internal/cmd/service-account/token/token.go index 45570ea97..ce4b4eac6 100644 --- a/internal/cmd/service-account/token/token.go +++ b/internal/cmd/service-account/token/token.go @@ -1,17 +1,17 @@ package token import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/token/create" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/token/list" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/token/revoke" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "token", Short: "Provides functionality for service account tokens", @@ -19,12 +19,12 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(revoke.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(revoke.NewCmd(params)) } diff --git a/internal/cmd/ske/cluster/cluster.go b/internal/cmd/ske/cluster/cluster.go index c5bb7b36b..0158b7173 100644 --- a/internal/cmd/ske/cluster/cluster.go +++ b/internal/cmd/ske/cluster/cluster.go @@ -1,6 +1,7 @@ package cluster import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/create" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/describe" @@ -8,13 +9,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/list" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "cluster", Short: "Provides functionality for SKE cluster", @@ -22,15 +22,15 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(generatepayload.NewCmd(p)) - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(generatepayload.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 195b343ca..5c017d90d 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { Payload *ske.CreateOrUpdateClusterPayload } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", clusterNameArg), Short: "Creates an SKE cluster", @@ -64,33 +65,33 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a cluster for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } } // Configure ServiceEnable API client - serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(p) + serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(params.Printer) if err != nil { return err } @@ -134,7 +135,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating cluster") _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient, model.ProjectId, name).WaitWithContext(ctx) if err != nil { @@ -143,7 +144,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/ske/cluster/create/create_test.go b/internal/cmd/ske/cluster/create/create_test.go index 6e2e92b3f..3cc543398 100644 --- a/internal/cmd/ske/cluster/create/create_test.go +++ b/internal/cmd/ske/cluster/create/create_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -228,7 +229,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -342,7 +343,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.cluster); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/delete/delete.go b/internal/cmd/ske/cluster/delete/delete.go index 657001abe..b78925dd5 100644 --- a/internal/cmd/ske/cluster/delete/delete.go +++ b/internal/cmd/ske/cluster/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { ClusterName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", clusterNameArg), Short: "Deletes a SKE cluster", @@ -39,20 +40,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete cluster %q? (This cannot be undone)", model.ClusterName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -67,7 +68,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting cluster") _, err = wait.DeleteClusterWaitHandler(ctx, apiClient, model.ProjectId, model.ClusterName).WaitWithContext(ctx) if err != nil { @@ -80,7 +81,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s cluster %q\n", operationState, model.ClusterName) + params.Printer.Info("%s cluster %q\n", operationState, model.ClusterName) return nil }, } diff --git a/internal/cmd/ske/cluster/delete/delete_test.go b/internal/cmd/ske/cluster/delete/delete_test.go index b15c7254c..b51e559ad 100644 --- a/internal/cmd/ske/cluster/delete/delete_test.go +++ b/internal/cmd/ske/cluster/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -126,7 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 52fb7af4d..1b6d08dc8 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { ClusterName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", clusterNameArg), Short: "Shows details of a SKE cluster", @@ -43,12 +44,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -60,7 +61,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read SKE cluster: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/ske/cluster/describe/describe_test.go b/internal/cmd/ske/cluster/describe/describe_test.go index 99e644af4..13a1b9468 100644 --- a/internal/cmd/ske/cluster/describe/describe_test.go +++ b/internal/cmd/ske/cluster/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -126,7 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -231,7 +232,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.cluster); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload.go b/internal/cmd/ske/cluster/generate-payload/generate_payload.go index 299b5e9ab..b3a94f2ef 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { FilePath *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "generate-payload", Short: "Generates a payload to create/update SKE clusters", @@ -56,13 +57,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -89,7 +90,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } } - return outputResult(p, model.FilePath, payload) + return outputResult(params.Printer, model.FilePath, payload) }, } configureFlags(cmd) diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go index 5516ccf26..ac758cd1d 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 7b5389454..a3cde587f 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all SKE clusters", @@ -51,19 +52,19 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } // Configure ServiceEnable API client - serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(p) + serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(params.Printer) if err != nil { return err } @@ -85,12 +86,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } clusters := *resp.Items if len(clusters) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No clusters found for project %q\n", projectLabel) + params.Printer.Info("No clusters found for project %q\n", projectLabel) return nil } @@ -99,7 +100,7 @@ func NewCmd(p *print.Printer) *cobra.Command { clusters = clusters[:*model.Limit] } - return outputResult(p, model.OutputFormat, clusters) + return outputResult(params.Printer, model.OutputFormat, clusters) }, } diff --git a/internal/cmd/ske/cluster/list/list_test.go b/internal/cmd/ske/cluster/list/list_test.go index 2959d6be6..c7eb8a01a 100644 --- a/internal/cmd/ske/cluster/list/list_test.go +++ b/internal/cmd/ske/cluster/list/list_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.clusters); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index c407b7fb8..aea878064 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Payload ske.CreateOrUpdateClusterPayload } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", clusterNameArg), Short: "Updates an SKE cluster", @@ -58,20 +59,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update cluster %q?", model.ClusterName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -96,7 +97,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Updating cluster") _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient, model.ProjectId, name).WaitWithContext(ctx) if err != nil { @@ -105,7 +106,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model.OutputFormat, model.Async, model.ClusterName, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, model.ClusterName, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/ske/cluster/update/update_test.go b/internal/cmd/ske/cluster/update/update_test.go index 53bce8b78..e4ec07b3f 100644 --- a/internal/cmd/ske/cluster/update/update_test.go +++ b/internal/cmd/ske/cluster/update/update_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -216,7 +217,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -322,7 +323,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.clusterName, tt.args.cluster); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go index f9936692e..69dd87211 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { ClusterName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("complete-rotation %s", clusterNameArg), Short: "Completes the rotation of the credentials associated to a SKE cluster", @@ -56,20 +57,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to complete the rotation of the credentials for SKE cluster %q?", model.ClusterName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -84,7 +85,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Completing credentials rotation") _, err = wait.CompleteCredentialsRotationWaitHandler(ctx, apiClient, model.ProjectId, model.ClusterName).WaitWithContext(ctx) if err != nil { @@ -97,8 +98,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered completion of credentials rotation" } - p.Info("%s for cluster %q\n", operationState, model.ClusterName) - p.Warn("Consider updating your kubeconfig with the new credentials, create a new kubeconfig by running:\n $ stackit ske kubeconfig create %s\n", model.ClusterName) + params.Printer.Info("%s for cluster %q\n", operationState, model.ClusterName) + params.Printer.Warn("Consider updating your kubeconfig with the new credentials, create a new kubeconfig by running:\n $ stackit ske kubeconfig create %s\n", model.ClusterName) return nil }, } diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go index 6b840c3e7..35e773133 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -126,7 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/ske/credentials/credentials.go b/internal/cmd/ske/credentials/credentials.go index 6fdfb1fc3..2770f349a 100644 --- a/internal/cmd/ske/credentials/credentials.go +++ b/internal/cmd/ske/credentials/credentials.go @@ -1,16 +1,16 @@ package credentials import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" completerotation "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials/complete-rotation" startrotation "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials/start-rotation" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for SKE credentials", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(startrotation.NewCmd(p)) - cmd.AddCommand(completerotation.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(startrotation.NewCmd(params)) + cmd.AddCommand(completerotation.NewCmd(params)) } diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation.go b/internal/cmd/ske/credentials/start-rotation/start_rotation.go index b11c42623..485e26a10 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { ClusterName string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("start-rotation %s", clusterNameArg), Short: "Starts the rotation of the credentials associated to a SKE cluster", @@ -59,20 +60,20 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to start the rotation of the credentials for SKE cluster %q?", model.ClusterName) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -87,7 +88,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Starting credentials rotation") _, err = wait.StartCredentialsRotationWaitHandler(ctx, apiClient, model.ProjectId, model.ClusterName).WaitWithContext(ctx) if err != nil { @@ -100,8 +101,8 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered start of credentials rotation" } - p.Info("%s for cluster %q\n", operationState, model.ClusterName) - p.Info("Complete the rotation by running:\n $ stackit ske credentials complete-rotation %s\n", model.ClusterName) + params.Printer.Info("%s for cluster %q\n", operationState, model.ClusterName) + params.Printer.Info("Complete the rotation by running:\n $ stackit ske credentials complete-rotation %s\n", model.ClusterName) return nil }, } diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go b/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go index dc5643eaa..29f2825ac 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -126,7 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index 6694b04a7..06522d5fb 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -23,7 +24,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "describe", Short: "Shows overall details regarding SKE", @@ -36,12 +37,12 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -53,7 +54,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read SKE project details: %w", err) } - return outputResult(p, model.OutputFormat, resp, model.ProjectId) + return outputResult(params.Printer, model.OutputFormat, resp, model.ProjectId) }, } return cmd diff --git a/internal/cmd/ske/describe/describe_test.go b/internal/cmd/ske/describe/describe_test.go index 839ae512e..4fb7cbb64 100644 --- a/internal/cmd/ske/describe/describe_test.go +++ b/internal/cmd/ske/describe/describe_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" serviceEnablementUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.project, tt.args.projectId); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index d00a56715..12685a580 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -23,7 +24,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "disable", Short: "Disables SKE for a project", @@ -36,26 +37,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to disable SKE for project %q? (This will delete all associated clusters)", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Disabling SKE") _, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) if err != nil { @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered disablement of" } - p.Info("%s SKE for project %q\n", operationState, projectLabel) + params.Printer.Info("%s SKE for project %q\n", operationState, projectLabel) return nil }, } diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index 9ab8ed7bf..7701c3bf5 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -23,7 +24,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "enable", Short: "Enables SKE for a project", @@ -36,26 +37,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to enable SKE for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Enabling SKE") _, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) if err != nil { @@ -83,7 +84,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered enablement of" } - p.Info("%s SKE for project %q\n", operationState, projectLabel) + params.Printer.Info("%s SKE for project %q\n", operationState, projectLabel) return nil }, } diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index 8677b033c..e7a252456 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -40,7 +41,7 @@ type inputModel struct { Overwrite bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", clusterNameArg), Short: "Creates or update a kubeconfig for an SKE cluster", @@ -77,13 +78,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -95,7 +96,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } else { prompt = fmt.Sprintf("Are you sure you want to update your kubeconfig for SKE cluster %q? This will update your kubeconfig file. \nIf it the kubeconfig file doesn't exists, it will create a new one.", model.ClusterName) } - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -156,10 +157,10 @@ func NewCmd(p *print.Printer) *cobra.Command { if err != nil { return fmt.Errorf("write kubeconfig file: %w", err) } - p.Outputf("\nSet kubectl context to %s with: kubectl config use-context %s\n", model.ClusterName, model.ClusterName) + params.Printer.Outputf("\nSet kubectl context to %s with: kubectl config use-context %s\n", model.ClusterName, model.ClusterName) } - return outputResult(p, model.OutputFormat, model.ClusterName, kubeconfigPath, respKubeconfig, respLogin) + return outputResult(params.Printer, model.OutputFormat, model.ClusterName, kubeconfigPath, respKubeconfig, respLogin) }, } configureFlags(cmd) diff --git a/internal/cmd/ske/kubeconfig/create/create_test.go b/internal/cmd/ske/kubeconfig/create/create_test.go index 9743067f8..558d273e5 100644 --- a/internal/cmd/ske/kubeconfig/create/create_test.go +++ b/internal/cmd/ske/kubeconfig/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -203,7 +204,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -324,7 +325,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.clusterName, tt.args.kubeconfigPath, tt.args.respKubeconfig, tt.args.respLogin); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/kubeconfig/kubeconfig.go b/internal/cmd/ske/kubeconfig/kubeconfig.go index 44803f14b..ad5482dbe 100644 --- a/internal/cmd/ske/kubeconfig/kubeconfig.go +++ b/internal/cmd/ske/kubeconfig/kubeconfig.go @@ -1,16 +1,16 @@ package kubeconfig import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/kubeconfig/create" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/kubeconfig/login" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "kubeconfig", Short: "Provides functionality for SKE kubeconfig", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(login.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(login.NewCmd(params)) } diff --git a/internal/cmd/ske/kubeconfig/login/login.go b/internal/cmd/ske/kubeconfig/login/login.go index 817b33ca4..ce748d242 100644 --- a/internal/cmd/ske/kubeconfig/login/login.go +++ b/internal/cmd/ske/kubeconfig/login/login.go @@ -12,6 +12,7 @@ import ( "strconv" "time" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/cache" "k8s.io/client-go/rest" @@ -34,7 +35,7 @@ const ( refreshBeforeDuration = 15 * time.Minute // 15 min ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "login", Short: "Login plugin for kubernetes clients", @@ -74,7 +75,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -82,33 +83,33 @@ func NewCmd(p *print.Printer) *cobra.Command { cachedKubeconfig := getCachedKubeConfig(clusterConfig.cacheKey) if cachedKubeconfig == nil { - return GetAndOutputKubeconfig(ctx, p, apiClient, clusterConfig, false, nil) + return GetAndOutputKubeconfig(ctx, params.Printer, apiClient, clusterConfig, false, nil) } certPem, _ := pem.Decode(cachedKubeconfig.CertData) if certPem == nil { _ = cache.DeleteObject(clusterConfig.cacheKey) - return GetAndOutputKubeconfig(ctx, p, apiClient, clusterConfig, false, nil) + return GetAndOutputKubeconfig(ctx, params.Printer, apiClient, clusterConfig, false, nil) } certificate, err := x509.ParseCertificate(certPem.Bytes) if err != nil { _ = cache.DeleteObject(clusterConfig.cacheKey) - return GetAndOutputKubeconfig(ctx, p, apiClient, clusterConfig, false, nil) + return GetAndOutputKubeconfig(ctx, params.Printer, apiClient, clusterConfig, false, nil) } // cert is expired, request new if time.Now().After(certificate.NotAfter.UTC()) { _ = cache.DeleteObject(clusterConfig.cacheKey) - return GetAndOutputKubeconfig(ctx, p, apiClient, clusterConfig, false, nil) + return GetAndOutputKubeconfig(ctx, params.Printer, apiClient, clusterConfig, false, nil) } // cert expires within the next 15min, refresh (try to get a new, use cache on failure) if time.Now().Add(refreshBeforeDuration).After(certificate.NotAfter.UTC()) { - return GetAndOutputKubeconfig(ctx, p, apiClient, clusterConfig, true, cachedKubeconfig) + return GetAndOutputKubeconfig(ctx, params.Printer, apiClient, clusterConfig, true, cachedKubeconfig) } // cert not expired, nor will it expire in the next 15min; therefore, use the cached kubeconfig - if err := output(p, clusterConfig.cacheKey, cachedKubeconfig); err != nil { + if err := output(params.Printer, clusterConfig.cacheKey, cachedKubeconfig); err != nil { return err } return nil diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index 419721d29..6aed48591 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -9,6 +9,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -37,7 +38,7 @@ type inputModel struct { VolumeTypes bool } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "options", Short: "Lists SKE provider options", @@ -59,13 +60,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("get SKE provider options: %w", err) } - return outputResult(p, model, resp) + return outputResult(params.Printer, model, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/ske/options/options_test.go b/internal/cmd/ske/options/options_test.go index 6b1c1ae93..b2181ef5b 100644 --- a/internal/cmd/ske/options/options_test.go +++ b/internal/cmd/ske/options/options_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -118,7 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -238,7 +239,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.options); (err != nil) != tt.wantErr { @@ -271,7 +272,7 @@ func TestOutputResultAsTable(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResultAsTable(p, tt.args.options); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/ske.go b/internal/cmd/ske/ske.go index 04438af65..137165e06 100644 --- a/internal/cmd/ske/ske.go +++ b/internal/cmd/ske/ske.go @@ -1,6 +1,7 @@ package ske import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/describe" @@ -9,13 +10,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/ske/kubeconfig" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/options" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "ske", Short: "Provides functionality for SKE", @@ -23,16 +23,16 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(enable.NewCmd(p)) - cmd.AddCommand(kubeconfig.NewCmd(p)) - cmd.AddCommand(disable.NewCmd(p)) - cmd.AddCommand(cluster.NewCmd(p)) - cmd.AddCommand(credentials.NewCmd(p)) - cmd.AddCommand(options.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(enable.NewCmd(params)) + cmd.AddCommand(kubeconfig.NewCmd(params)) + cmd.AddCommand(disable.NewCmd(params)) + cmd.AddCommand(cluster.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) + cmd.AddCommand(options.NewCmd(params)) } diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index 90b20d813..06c7da8e8 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -45,7 +46,7 @@ type inputModel struct { SourceType *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a volume", @@ -71,26 +72,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to create a volume for project %q?", projectLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -106,7 +107,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Creating volume") _, err = wait.CreateVolumeWaitHandler(ctx, apiClient, model.ProjectId, volumeId).WaitWithContext(ctx) if err != nil { @@ -115,7 +116,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, resp) + return outputResult(params.Printer, model, projectLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/volume/create/create_test.go b/internal/cmd/volume/create/create_test.go index 71f3e1697..716daaad2 100644 --- a/internal/cmd/volume/create/create_test.go +++ b/internal/cmd/volume/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -202,7 +203,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -310,7 +311,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go index d07a9e8f5..e9730faf9 100644 --- a/internal/cmd/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { VolumeId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", volumeIdArg), Short: "Deletes a volume", @@ -45,13 +46,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -59,14 +60,14 @@ func NewCmd(p *print.Printer) *cobra.Command { volumeLabel := model.VolumeId volumeName, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { - p.Debug(print.ErrorLevel, "get volume name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) } else if volumeName != "" { volumeLabel = volumeName } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to delete volume %q?", volumeLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(p *print.Printer) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p) + s := spinner.New(params.Printer) s.Start("Deleting volume") _, err = wait.DeleteVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.VolumeId).WaitWithContext(ctx) if err != nil { @@ -94,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { if model.Async { operationState = "Triggered deletion of" } - p.Info("%s volume %q\n", operationState, volumeLabel) + params.Printer.Info("%s volume %q\n", operationState, volumeLabel) return nil }, } diff --git a/internal/cmd/volume/delete/delete_test.go b/internal/cmd/volume/delete/delete_test.go index 5648c374c..58d10c79c 100644 --- a/internal/cmd/volume/delete/delete_test.go +++ b/internal/cmd/volume/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -138,7 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/volume/describe/describe.go b/internal/cmd/volume/describe/describe.go index e77073ea2..c8b787456 100644 --- a/internal/cmd/volume/describe/describe.go +++ b/internal/cmd/volume/describe/describe.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { VolumeId string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", volumeIdArg), Short: "Shows details of a volume", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read volume: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/volume/describe/describe_test.go b/internal/cmd/volume/describe/describe_test.go index 3de0f688b..aa0a0754f 100644 --- a/internal/cmd/volume/describe/describe_test.go +++ b/internal/cmd/volume/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -240,7 +241,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/list/list.go b/internal/cmd/volume/list/list.go index 02c643014..feffde80e 100644 --- a/internal/cmd/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -7,6 +7,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all volumes of a project", @@ -57,13 +58,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -76,12 +77,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No volumes found for project %q\n", projectLabel) + params.Printer.Info("No volumes found for project %q\n", projectLabel) return nil } @@ -91,7 +92,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/volume/list/list_test.go b/internal/cmd/volume/list/list_test.go index 77cc3808b..daa736ff1 100644 --- a/internal/cmd/volume/list/list_test.go +++ b/internal/cmd/volume/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -131,7 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -226,7 +227,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.volumes); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/performance-class/describe/describe.go b/internal/cmd/volume/performance-class/describe/describe.go index ade26f34a..3105e4fcc 100644 --- a/internal/cmd/volume/performance-class/describe/describe.go +++ b/internal/cmd/volume/performance-class/describe/describe.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { VolumePerformanceClass string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", volumePerformanceClassArg), Short: "Shows details of a volume performance class", @@ -48,13 +49,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("read volume performance class: %w", err) } - return outputResult(p, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } return cmd diff --git a/internal/cmd/volume/performance-class/describe/describe_test.go b/internal/cmd/volume/performance-class/describe/describe_test.go index 90ba0da3c..b5bf0cf3c 100644 --- a/internal/cmd/volume/performance-class/describe/describe_test.go +++ b/internal/cmd/volume/performance-class/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -131,7 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -234,7 +235,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.performanceClass); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/performance-class/list/list.go b/internal/cmd/volume/performance-class/list/list.go index 4449a5f3e..b48f399f6 100644 --- a/internal/cmd/volume/performance-class/list/list.go +++ b/internal/cmd/volume/performance-class/list/list.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all volume performance classes for a project", @@ -58,13 +59,13 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() - model, err := parseInput(p, cmd) + model, err := parseInput(params.Printer, cmd) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } @@ -77,12 +78,12 @@ func NewCmd(p *print.Printer) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, p, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) if err != nil { - p.Debug(print.ErrorLevel, "get project name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - p.Info("No volume performance class found for project %q\n", projectLabel) + params.Printer.Info("No volume performance class found for project %q\n", projectLabel) return nil } @@ -92,7 +93,7 @@ func NewCmd(p *print.Printer) *cobra.Command { items = items[:*model.Limit] } - return outputResult(p, model.OutputFormat, items) + return outputResult(params.Printer, model.OutputFormat, items) }, } configureFlags(cmd) diff --git a/internal/cmd/volume/performance-class/list/list_test.go b/internal/cmd/volume/performance-class/list/list_test.go index 9e23bbdfd..6e877390d 100644 --- a/internal/cmd/volume/performance-class/list/list_test.go +++ b/internal/cmd/volume/performance-class/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -131,7 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -226,7 +227,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.performanceClasses); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/performance-class/performance_class.go b/internal/cmd/volume/performance-class/performance_class.go index 4f159606e..6ed86618a 100644 --- a/internal/cmd/volume/performance-class/performance_class.go +++ b/internal/cmd/volume/performance-class/performance_class.go @@ -1,16 +1,16 @@ package performanceclass import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/performance-class/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/performance-class/list" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "performance-class", Short: "Provides functionality for volume performance classes available inside a project", @@ -18,11 +18,11 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/volume/resize/resize.go b/internal/cmd/volume/resize/resize.go index 7f966a2e3..afef2a7a3 100644 --- a/internal/cmd/volume/resize/resize.go +++ b/internal/cmd/volume/resize/resize.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Size *int64 } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("resize %s", volumeIdArg), Short: "Resizes a volume", @@ -44,26 +45,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { - p.Debug(print.ErrorLevel, "get volume name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to resize volume %q?", volumeLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -76,7 +77,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("resize volume: %w", err) } - p.Outputf("Resized volume %q.\n", volumeLabel) + params.Printer.Outputf("Resized volume %q.\n", volumeLabel) return nil }, } diff --git a/internal/cmd/volume/resize/resize_test.go b/internal/cmd/volume/resize/resize_test.go index 15dd9c757..54d02a47f 100644 --- a/internal/cmd/volume/resize/resize_test.go +++ b/internal/cmd/volume/resize/resize_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -152,7 +153,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/volume/update/update.go b/internal/cmd/volume/update/update.go index f7afad38a..0c57f6185 100644 --- a/internal/cmd/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -8,6 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", volumeIdArg), Short: "Updates a volume", @@ -58,26 +59,26 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(p, cmd, args) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } // Configure API client - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(params.Printer) if err != nil { return err } volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { - p.Debug(print.ErrorLevel, "get volume name: %v", err) + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } if !model.AssumeYes { prompt := fmt.Sprintf("Are you sure you want to update volume %q?", volumeLabel) - err = p.PromptForConfirmation(prompt) + err = params.Printer.PromptForConfirmation(prompt) if err != nil { return err } @@ -90,7 +91,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("update volume: %w", err) } - return outputResult(p, model.OutputFormat, volumeLabel, resp) + return outputResult(params.Printer, model.OutputFormat, volumeLabel, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/volume/update/update_test.go b/internal/cmd/volume/update/update_test.go index cdfed4017..1628bf26a 100644 --- a/internal/cmd/volume/update/update_test.go +++ b/internal/cmd/volume/update/update_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -176,7 +177,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(p) + cmd := NewCmd(¶ms.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -280,7 +281,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(p) + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResult(p, tt.args.outputFormat, tt.args.volumeLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/volume.go b/internal/cmd/volume/volume.go index fe334cb6f..1e876e85b 100644 --- a/internal/cmd/volume/volume.go +++ b/internal/cmd/volume/volume.go @@ -1,6 +1,7 @@ package volume import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/create" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/describe" @@ -9,13 +10,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/volume/resize" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(p *print.Printer) *cobra.Command { +func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "volume", Short: "Provides functionality for volumes", @@ -23,16 +23,16 @@ func NewCmd(p *print.Printer) *cobra.Command { Args: args.NoArgs, Run: utils.CmdHelp, } - addSubcommands(cmd, p) + addSubcommands(cmd, params) return cmd } -func addSubcommands(cmd *cobra.Command, p *print.Printer) { - cmd.AddCommand(create.NewCmd(p)) - cmd.AddCommand(delete.NewCmd(p)) - cmd.AddCommand(describe.NewCmd(p)) - cmd.AddCommand(list.NewCmd(p)) - cmd.AddCommand(update.NewCmd(p)) - cmd.AddCommand(resize.NewCmd(p)) - cmd.AddCommand(performanceclass.NewCmd(p)) +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(resize.NewCmd(params)) + cmd.AddCommand(performanceclass.NewCmd(params)) } From 2cac3074a7175162fef680030add84ad001422ec Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 12 May 2025 07:55:27 +0200 Subject: [PATCH 296/619] fix(deps): update stackit sdk modules (#740) Co-authored-by: Renovate Bot --- go.mod | 46 ++++++++++++++-------------- go.sum | 96 ++++++++++++++++++++++++++++------------------------------ 2 files changed, 69 insertions(+), 73 deletions(-) diff --git a/go.mod b/go.mod index 3e5f0a4b2..d4fa80e97 100644 --- a/go.mod +++ b/go.mod @@ -16,22 +16,22 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.1 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.2 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.2 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.1 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.3 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.2 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.1 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.2 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.2 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.3 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.1 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.3 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.2 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.3 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.3 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.30.0 @@ -235,13 +235,13 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.2 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.1 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.33.0 // indirect diff --git a/go.sum b/go.sum index 43889808a..8735251de 100644 --- a/go.sum +++ b/go.sum @@ -564,52 +564,52 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJSjtaGnUI7UE7ITb5IT0= github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.2 h1:7PIcO05sveIb0CNfJiwsWhcR7tc+9/e4p580Hm398ww= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.2/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.2 h1:erpN0BM7lTkV/zhxka5fTYHssQaOqdGjj76c2FWMec0= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.2/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2 h1:6rb3EM0yXuMIBd1U6WsJoMzEiVaHC3WQFWFvT23OE4Y= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1 h1:JXcLcbVesTtwVVb+jJjU3o0FmSpXBRnOw6PVETaeK+E= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2 h1:5rVt3n7kDJvJQxFCtxfx8uZI9PGkvJY9fVJ4yar10Uc= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1 h1:ZeEuUf0DrTTU/acHOg+pQcpLZV1NF9SZbqI6ogjdLao= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1 h1:bdfgwsFNJRqCDUu/r4ZYyACzHCo1bD3y8fGFLYvX9C4= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.1/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.0 h1:kUdCkqVFEOP1GCUoLwdkMi9o+qtghvBT+grIE0nvvlc= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.2 h1:h+EwnBOflLAKTZTlnl9YoB/z3ilvW34uezJO8YNG6Bo= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.2/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1 h1:BIMl8ISsDGsFB6dBqfxQMPFVyS5gB5EcwM4Jzpg65XE= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.1/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.1 h1:yukHymULIXiSu7RQSnYOaPlBXegFR3ICMXdQzG8v14g= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.1/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.3 h1:IFXdEoN92c7qpvzeXqMnhz9OsiLR7Hiub7UkxK8luWo= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.3/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1 h1:CHRxxDBW+4VrpZDyXabOJCF7LY0i+PNYY5QWE0kwGIo= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.1/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.1 h1:bYIczS7iJNSQGkoSghicCC3F657TqLl4CelCgyt3tbw= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.1/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.2 h1:k+Nr9JBzBBy6di7T0pmQGEKqjPkbv8goRFdWo6BaIhQ= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.2/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.1 h1:VUoD+yQKwWFfgYAZd9JkjgKQCWjs0dDuf6ZgNYcXi6Y= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.1/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3 h1:L8uFydvDVJBdXLSQdgRwztbQewwNtTtuPhM1L1ehIvA= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.3/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.2 h1:mf4ej9oTc45huZxRe231DAPY9MOgm9qV1gflXdYQN4Q= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.2/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2 h1:MCHMaS3hRTEYu+rWIDOas9tVn5+ddaulXzcE2porMek= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.2/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2 h1:SdQ9VqDmamOhnTp6fd0QYKhCcoxB2GP938o7hGAubqg= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.2/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.2 h1:KsfdYvi24Mli50gEDuruXk5lg5mQIFqr/hfLfHHFJXU= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.2/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2 h1:SYX9IXg+2YAIdiUzLyqs9ga+S+bjhZs8WYeqU3GK3hk= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.2/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2 h1:uNwgJMHRuihWJJbnCw2FiJ9zZB9ZaE9YJ8e7ytZG1Pc= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.2/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.3 h1:JVRsMN5uKPxy9ynsxmhGfAecz87LjqN5G5Vg8MRwyRc= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.3/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 h1:aXVMNdiHCtT07bro52KjnxEBMDNK9DweJBlk+G4ElCM= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3 h1:WJnA6YTOlBxMJf9PRuxkXduxj+fyWi+wOks69PvN1qI= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 h1:zh6e2eHgqex++fr6N0RK7wMMBGesC3QhBd42FdTq2Z8= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3 h1:StQg5p4h1aLFwIHQWWe5l44aFue+ZvQMGDbypP1DMYw= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2 h1:wM/Gop6sG/fkpzsZGhrPN2AzkKxHup175WaFBGaeQ7s= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2 h1:JoPz34UT1Gx7TV6GpOzWdNBq78co7MV12jynADI4AMc= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.1 h1:CBGVT+5ilIFVtz5gDnQ58zNapFCLpjOftuVeATdg1qo= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.1/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 h1:RFe45uLzTSmd69yaQe5zLDY3+1hYi6/lSZUVcjbb6+c= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2 h1:anITBRTlQoneEawVg4hHjs4IceFJLFq9KdDU+d5y5DU= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2 h1:p1bub8QayR+NkYtGd8DNSjxlRmoyR7Dr97LiwWVW1Ow= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 h1:AIQueG1oSdKbxK8ASZZYkmqzJ7NhKzKcR5AQsndoF18= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.2 h1:++lyru25B7J8cKaEBCw9ZKgXDIJGmQvmFXR+BpAcR4g= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.2/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2 h1:KKANO+wsLVkuH8N+xuYrEx+rDcliv48zYk3I7QzdX3A= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.3 h1:4DNnEZj4uSyE+gDS+j9MCUuax9nfnttfro+JJE8QRSE= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.3/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.2 h1:+YwMWWvZlUtw6TEfTqXPdUyN9hbkECU4DULwgIMu6A0= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.2/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4 h1:UCX1qy44q22bDGv7BhLtOrWCzriS9m4MQsIOX6n+lgM= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.3 h1:OR5CZnxZMbGXsYPOZL00En3RhXeUuEJcZVN9iSxxTs8= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.3/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 h1:iLyXsBF+lP7iE4rnoK3hO8l4wHcgySRXD65oeUgt6Jc= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3 h1:qCn6ZS/oJEqA4PBMLMDvvctQ4eQEoCQSSWES394+AcQ= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3 h1:rDsIPzaNJ4bnKJp9XFNzna+pXylGYVHUBPl5hqBWhX8= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.3 h1:dN6MOgb9CXaZ9hsdCIrrNGyw7EggPvE5kaTvNKvrEzI= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.3/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3 h1:MF46ffu+A8eu17N7LGFG2T50PhjDw2L0f68Uu316r8U= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -792,8 +792,6 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -961,8 +959,6 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 4f7804790e9f3306c2d3ea770f674239bbaea3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 12 May 2025 16:40:31 +0200 Subject: [PATCH 297/619] feat(cli): set custom user-agent header for STACKIT API calls (#741) relates to STACKITCLI-180 --- .github/docs/contribution-guide/client.go | 30 ++++++++++---- .github/docs/contribution-guide/cmd.go | 15 +++---- CONTRIBUTION.md | 4 +- internal/cmd/affinity-groups/create/create.go | 2 +- internal/cmd/affinity-groups/delete/delete.go | 4 +- .../cmd/affinity-groups/describe/describe.go | 2 +- internal/cmd/affinity-groups/list/list.go | 2 +- internal/cmd/beta/alb/create/create.go | 4 +- internal/cmd/beta/alb/delete/delete.go | 4 +- internal/cmd/beta/alb/describe/describe.go | 2 +- internal/cmd/beta/alb/list/list.go | 4 +- .../alb/observability-credentials/add/add.go | 2 +- .../delete/delete.go | 2 +- .../describe/describe.go | 2 +- .../observability-credentials/list/list.go | 2 +- .../update/update.go | 4 +- internal/cmd/beta/alb/plans/plans.go | 4 +- internal/cmd/beta/alb/pool/update/update.go | 4 +- internal/cmd/beta/alb/quotas/quotas.go | 2 +- internal/cmd/beta/alb/update/update.go | 4 +- .../sqlserverflex/database/create/create.go | 2 +- .../sqlserverflex/database/delete/delete.go | 2 +- .../database/describe/describe.go | 2 +- .../beta/sqlserverflex/database/list/list.go | 4 +- .../sqlserverflex/instance/create/create.go | 4 +- .../sqlserverflex/instance/delete/delete.go | 2 +- .../instance/describe/describe.go | 2 +- .../beta/sqlserverflex/instance/list/list.go | 4 +- .../sqlserverflex/instance/update/update.go | 2 +- .../cmd/beta/sqlserverflex/options/options.go | 2 +- .../beta/sqlserverflex/user/create/create.go | 2 +- .../beta/sqlserverflex/user/delete/delete.go | 2 +- .../sqlserverflex/user/describe/describe.go | 2 +- .../cmd/beta/sqlserverflex/user/list/list.go | 2 +- .../user/reset-password/reset_password.go | 2 +- internal/cmd/config/list/list_test.go | 1 + internal/cmd/config/profile/create/create.go | 1 + .../cmd/config/profile/create/create_test.go | 1 + internal/cmd/config/profile/delete/delete.go | 1 + .../cmd/config/profile/delete/delete_test.go | 1 + .../cmd/config/profile/export/export_test.go | 1 + internal/cmd/config/profile/list/list.go | 1 + internal/cmd/config/profile/set/set_test.go | 1 + internal/cmd/config/set/set_test.go | 1 + internal/cmd/config/unset/unset_test.go | 1 + internal/cmd/dns/record-set/create/create.go | 2 +- internal/cmd/dns/record-set/delete/delete.go | 2 +- .../cmd/dns/record-set/describe/describe.go | 2 +- internal/cmd/dns/record-set/list/list.go | 2 +- internal/cmd/dns/record-set/update/update.go | 2 +- .../cmd/dns/record-set/update/update_test.go | 1 + internal/cmd/dns/zone/clone/clone.go | 2 +- internal/cmd/dns/zone/create/create.go | 4 +- internal/cmd/dns/zone/delete/delete.go | 2 +- internal/cmd/dns/zone/describe/describe.go | 2 +- internal/cmd/dns/zone/list/list.go | 4 +- internal/cmd/dns/zone/update/update.go | 2 +- internal/cmd/image/create/create.go | 2 +- internal/cmd/image/delete/delete.go | 4 +- internal/cmd/image/describe/describe.go | 2 +- internal/cmd/image/list/list.go | 4 +- internal/cmd/image/update/update.go | 4 +- internal/cmd/key-pair/create/create.go | 2 +- internal/cmd/key-pair/delete/delete.go | 2 +- internal/cmd/key-pair/describe/describe.go | 2 +- internal/cmd/key-pair/list/list.go | 2 +- internal/cmd/key-pair/update/update.go | 2 +- internal/cmd/load-balancer/create/create.go | 4 +- internal/cmd/load-balancer/delete/delete.go | 2 +- .../cmd/load-balancer/describe/describe.go | 2 +- .../generate-payload/generate_payload.go | 2 +- internal/cmd/load-balancer/list/list.go | 4 +- .../observability-credentials/add/add.go | 4 +- .../cleanup/cleanup.go | 4 +- .../delete/delete.go | 4 +- .../describe/describe.go | 2 +- .../observability-credentials/list/list.go | 4 +- .../update/update.go | 4 +- internal/cmd/load-balancer/quota/quota.go | 2 +- .../target-pool/add-target/add_target.go | 2 +- .../target-pool/describe/describe.go | 2 +- .../remove-target/remove_target.go | 2 +- internal/cmd/load-balancer/update/update.go | 2 +- .../cmd/logme/credentials/create/create.go | 2 +- .../cmd/logme/credentials/delete/delete.go | 2 +- .../logme/credentials/describe/describe.go | 2 +- internal/cmd/logme/credentials/list/list.go | 2 +- internal/cmd/logme/instance/create/create.go | 4 +- internal/cmd/logme/instance/delete/delete.go | 2 +- .../cmd/logme/instance/describe/describe.go | 2 +- internal/cmd/logme/instance/list/list.go | 4 +- internal/cmd/logme/instance/update/update.go | 2 +- internal/cmd/logme/plans/plans.go | 4 +- .../cmd/mariadb/credentials/create/create.go | 2 +- .../cmd/mariadb/credentials/delete/delete.go | 2 +- .../mariadb/credentials/describe/describe.go | 2 +- internal/cmd/mariadb/credentials/list/list.go | 2 +- .../cmd/mariadb/instance/create/create.go | 4 +- .../cmd/mariadb/instance/delete/delete.go | 2 +- .../cmd/mariadb/instance/describe/describe.go | 2 +- internal/cmd/mariadb/instance/list/list.go | 4 +- .../cmd/mariadb/instance/update/update.go | 2 +- internal/cmd/mariadb/plans/plans.go | 4 +- .../mongodbflex/backup/describe/describe.go | 2 +- internal/cmd/mongodbflex/backup/list/list.go | 2 +- .../backup/restore-jobs/restore_jobs.go | 2 +- .../cmd/mongodbflex/backup/restore/restore.go | 2 +- .../mongodbflex/backup/schedule/schedule.go | 2 +- .../backup/update-schedule/update_schedule.go | 2 +- .../cmd/mongodbflex/instance/create/create.go | 4 +- .../cmd/mongodbflex/instance/delete/delete.go | 2 +- .../mongodbflex/instance/describe/describe.go | 2 +- .../cmd/mongodbflex/instance/list/list.go | 4 +- .../cmd/mongodbflex/instance/update/update.go | 2 +- internal/cmd/mongodbflex/options/options.go | 2 +- .../cmd/mongodbflex/user/create/create.go | 2 +- .../cmd/mongodbflex/user/delete/delete.go | 2 +- .../cmd/mongodbflex/user/describe/describe.go | 2 +- internal/cmd/mongodbflex/user/list/list.go | 2 +- .../user/reset-password/reset_password.go | 2 +- .../cmd/mongodbflex/user/update/update.go | 2 +- internal/cmd/network-area/create/create.go | 4 +- internal/cmd/network-area/delete/delete.go | 2 +- .../cmd/network-area/describe/describe.go | 2 +- internal/cmd/network-area/list/list.go | 7 ++-- .../network-range/create/create.go | 2 +- .../network-range/delete/delete.go | 2 +- .../network-range/describe/describe.go | 2 +- .../network-area/network-range/list/list.go | 2 +- .../cmd/network-area/route/create/create.go | 2 +- .../cmd/network-area/route/delete/delete.go | 2 +- .../network-area/route/describe/describe.go | 2 +- internal/cmd/network-area/route/list/list.go | 2 +- .../cmd/network-area/route/update/update.go | 2 +- internal/cmd/network-area/update/update.go | 7 ++-- .../cmd/network-interface/create/create.go | 4 +- .../cmd/network-interface/delete/delete.go | 2 +- .../network-interface/describe/describe.go | 2 +- internal/cmd/network-interface/list/list.go | 2 +- .../cmd/network-interface/update/update.go | 2 +- internal/cmd/network/create/create.go | 4 +- internal/cmd/network/delete/delete.go | 2 +- internal/cmd/network/describe/describe.go | 2 +- internal/cmd/network/list/list.go | 4 +- internal/cmd/network/update/update.go | 2 +- .../object-storage/bucket/create/create.go | 2 +- .../object-storage/bucket/delete/delete.go | 2 +- .../bucket/describe/describe.go | 2 +- .../cmd/object-storage/bucket/list/list.go | 4 +- .../credentials-group/create/create.go | 2 +- .../credentials-group/delete/delete.go | 2 +- .../credentials-group/list/list.go | 2 +- .../credentials/create/create.go | 2 +- .../credentials/delete/delete.go | 2 +- .../object-storage/credentials/list/list.go | 2 +- .../cmd/object-storage/disable/disable.go | 4 +- internal/cmd/object-storage/enable/enable.go | 4 +- .../credentials/create/create.go | 2 +- .../credentials/delete/delete.go | 2 +- .../observability/credentials/list/list.go | 2 +- .../grafana/describe/describe.go | 2 +- .../public-read-access/disable/disable.go | 2 +- .../public-read-access/enable/enable.go | 2 +- .../grafana/single-sign-on/disable/disable.go | 2 +- .../grafana/single-sign-on/enable/enable.go | 2 +- .../observability/instance/create/create.go | 4 +- .../observability/instance/delete/delete.go | 2 +- .../instance/describe/describe.go | 2 +- .../cmd/observability/instance/list/list.go | 4 +- .../observability/instance/update/update.go | 2 +- internal/cmd/observability/plans/plans.go | 4 +- .../scrape-config/create/create.go | 2 +- .../scrape-config/delete/delete.go | 2 +- .../scrape-config/describe/describe.go | 2 +- .../generate-payload/generate_payload.go | 2 +- .../observability/scrape-config/list/list.go | 2 +- .../scrape-config/update/update.go | 2 +- .../opensearch/credentials/create/create.go | 2 +- .../opensearch/credentials/delete/delete.go | 2 +- .../credentials/describe/describe.go | 2 +- .../cmd/opensearch/credentials/list/list.go | 2 +- .../cmd/opensearch/instance/create/create.go | 4 +- .../cmd/opensearch/instance/delete/delete.go | 2 +- .../opensearch/instance/describe/describe.go | 2 +- internal/cmd/opensearch/instance/list/list.go | 4 +- .../cmd/opensearch/instance/update/update.go | 2 +- internal/cmd/opensearch/plans/plans.go | 4 +- internal/cmd/organization/member/add/add.go | 2 +- internal/cmd/organization/member/list/list.go | 2 +- .../cmd/organization/member/remove/remove.go | 2 +- internal/cmd/organization/role/list/list.go | 2 +- .../postgresflex/backup/describe/describe.go | 2 +- internal/cmd/postgresflex/backup/list/list.go | 2 +- .../backup/update-schedule/update_schedule.go | 2 +- .../cmd/postgresflex/instance/clone/clone.go | 2 +- .../postgresflex/instance/create/create.go | 4 +- .../postgresflex/instance/delete/delete.go | 2 +- .../instance/describe/describe.go | 2 +- .../cmd/postgresflex/instance/list/list.go | 4 +- .../postgresflex/instance/update/update.go | 2 +- internal/cmd/postgresflex/options/options.go | 2 +- .../cmd/postgresflex/user/create/create.go | 2 +- .../cmd/postgresflex/user/delete/delete.go | 2 +- .../postgresflex/user/describe/describe.go | 2 +- internal/cmd/postgresflex/user/list/list.go | 2 +- .../user/reset-password/reset_password.go | 2 +- .../cmd/postgresflex/user/update/update.go | 2 +- internal/cmd/project/create/create.go | 2 +- internal/cmd/project/delete/delete.go | 4 +- internal/cmd/project/describe/describe.go | 2 +- internal/cmd/project/list/list.go | 2 +- internal/cmd/project/member/add/add.go | 4 +- internal/cmd/project/member/list/list.go | 4 +- internal/cmd/project/member/remove/remove.go | 4 +- internal/cmd/project/role/list/list.go | 4 +- internal/cmd/project/update/update.go | 4 +- internal/cmd/public-ip/associate/associate.go | 2 +- internal/cmd/public-ip/create/create.go | 4 +- internal/cmd/public-ip/delete/delete.go | 2 +- internal/cmd/public-ip/describe/describe.go | 2 +- .../public-ip/disassociate/disassociate.go | 2 +- internal/cmd/public-ip/list/list.go | 4 +- internal/cmd/public-ip/update/update.go | 2 +- internal/cmd/quota/list/list.go | 4 +- .../cmd/rabbitmq/credentials/create/create.go | 2 +- .../cmd/rabbitmq/credentials/delete/delete.go | 2 +- .../rabbitmq/credentials/describe/describe.go | 2 +- .../cmd/rabbitmq/credentials/list/list.go | 2 +- .../cmd/rabbitmq/instance/create/create.go | 4 +- .../cmd/rabbitmq/instance/delete/delete.go | 2 +- .../rabbitmq/instance/describe/describe.go | 2 +- internal/cmd/rabbitmq/instance/list/list.go | 4 +- .../cmd/rabbitmq/instance/update/update.go | 2 +- internal/cmd/rabbitmq/plans/plans.go | 4 +- .../cmd/redis/credentials/create/create.go | 2 +- .../cmd/redis/credentials/delete/delete.go | 2 +- .../redis/credentials/describe/describe.go | 2 +- internal/cmd/redis/credentials/list/list.go | 2 +- internal/cmd/redis/instance/create/create.go | 4 +- internal/cmd/redis/instance/delete/delete.go | 2 +- .../cmd/redis/instance/describe/describe.go | 2 +- internal/cmd/redis/instance/list/list.go | 4 +- internal/cmd/redis/instance/update/update.go | 2 +- internal/cmd/redis/plans/plans.go | 4 +- .../secrets-manager/instance/create/create.go | 4 +- .../secrets-manager/instance/delete/delete.go | 2 +- .../instance/describe/describe.go | 2 +- .../cmd/secrets-manager/instance/list/list.go | 4 +- .../secrets-manager/instance/update/update.go | 2 +- .../cmd/secrets-manager/user/create/create.go | 2 +- .../cmd/secrets-manager/user/delete/delete.go | 2 +- .../secrets-manager/user/describe/describe.go | 2 +- .../cmd/secrets-manager/user/list/list.go | 2 +- .../cmd/secrets-manager/user/update/update.go | 2 +- internal/cmd/security-group/create/create.go | 2 +- internal/cmd/security-group/delete/delete.go | 4 +- .../cmd/security-group/describe/describe.go | 2 +- internal/cmd/security-group/list/list.go | 4 +- .../cmd/security-group/rule/create/create.go | 4 +- .../cmd/security-group/rule/delete/delete.go | 2 +- .../security-group/rule/describe/describe.go | 2 +- internal/cmd/security-group/rule/list/list.go | 4 +- internal/cmd/security-group/update/update.go | 4 +- internal/cmd/server/backup/create/create.go | 7 ++-- internal/cmd/server/backup/delete/delete.go | 2 +- .../cmd/server/backup/describe/describe.go | 2 +- internal/cmd/server/backup/disable/disable.go | 4 +- internal/cmd/server/backup/enable/enable.go | 4 +- internal/cmd/server/backup/list/list.go | 7 ++-- internal/cmd/server/backup/restore/restore.go | 2 +- .../server/backup/schedule/create/create.go | 7 ++-- .../server/backup/schedule/delete/delete.go | 4 +- .../backup/schedule/describe/describe.go | 2 +- .../cmd/server/backup/schedule/list/list.go | 7 ++-- .../server/backup/schedule/update/update.go | 2 +- .../backup/volume-backup/delete/delete.go | 2 +- .../backup/volume-backup/restore/restore.go | 2 +- internal/cmd/server/command/create/create.go | 7 ++-- .../cmd/server/command/describe/describe.go | 2 +- internal/cmd/server/command/list/list.go | 7 ++-- .../command/template/describe/describe.go | 2 +- .../cmd/server/command/template/list/list.go | 2 +- internal/cmd/server/console/console.go | 2 +- internal/cmd/server/create/create.go | 4 +- internal/cmd/server/deallocate/deallocate.go | 2 +- internal/cmd/server/delete/delete.go | 2 +- internal/cmd/server/describe/describe.go | 2 +- internal/cmd/server/list/list.go | 4 +- internal/cmd/server/log/log.go | 2 +- .../server/machine-type/describe/describe.go | 2 +- internal/cmd/server/machine-type/list/list.go | 4 +- .../server/network-interface/attach/attach.go | 2 +- .../server/network-interface/detach/detach.go | 2 +- .../cmd/server/network-interface/list/list.go | 2 +- .../cmd/server/os-update/create/create.go | 7 ++-- .../cmd/server/os-update/describe/describe.go | 2 +- .../cmd/server/os-update/disable/disable.go | 4 +- .../cmd/server/os-update/enable/enable.go | 4 +- internal/cmd/server/os-update/list/list.go | 4 +- .../os-update/schedule/create/create.go | 4 +- .../os-update/schedule/delete/delete.go | 2 +- .../os-update/schedule/describe/describe.go | 2 +- .../server/os-update/schedule/list/list.go | 7 ++-- .../os-update/schedule/update/update.go | 2 +- .../cmd/server/public-ip/attach/attach.go | 2 +- .../cmd/server/public-ip/detach/detach.go | 2 +- internal/cmd/server/reboot/reboot.go | 2 +- internal/cmd/server/rescue/rescue.go | 2 +- internal/cmd/server/resize/resize.go | 2 +- .../server/service-account/attach/attach.go | 2 +- .../server/service-account/detach/detach.go | 2 +- .../cmd/server/service-account/list/list.go | 2 +- internal/cmd/server/start/start.go | 2 +- internal/cmd/server/stop/stop.go | 2 +- internal/cmd/server/unrescue/unrescue.go | 2 +- internal/cmd/server/update/update.go | 2 +- internal/cmd/server/volume/attach/attach.go | 2 +- .../cmd/server/volume/describe/describe.go | 2 +- internal/cmd/server/volume/detach/detach.go | 2 +- internal/cmd/server/volume/list/list.go | 2 +- internal/cmd/server/volume/update/update.go | 2 +- internal/cmd/service-account/create/create.go | 4 +- internal/cmd/service-account/delete/delete.go | 2 +- .../cmd/service-account/get-jwks/get_jwks.go | 2 +- .../cmd/service-account/key/create/create.go | 2 +- .../cmd/service-account/key/delete/delete.go | 2 +- .../service-account/key/describe/describe.go | 2 +- internal/cmd/service-account/key/list/list.go | 2 +- .../cmd/service-account/key/update/update.go | 2 +- internal/cmd/service-account/list/list.go | 4 +- .../service-account/token/create/create.go | 2 +- .../cmd/service-account/token/list/list.go | 2 +- .../service-account/token/revoke/revoke.go | 2 +- internal/cmd/ske/cluster/create/create.go | 6 +-- internal/cmd/ske/cluster/delete/delete.go | 2 +- internal/cmd/ske/cluster/describe/describe.go | 2 +- .../generate-payload/generate_payload.go | 2 +- internal/cmd/ske/cluster/list/list.go | 6 +-- internal/cmd/ske/cluster/update/update.go | 2 +- .../complete-rotation/complete_rotation.go | 2 +- .../start-rotation/start_rotation.go | 2 +- internal/cmd/ske/describe/describe.go | 2 +- internal/cmd/ske/disable/disable.go | 4 +- internal/cmd/ske/enable/enable.go | 4 +- internal/cmd/ske/kubeconfig/create/create.go | 2 +- internal/cmd/ske/kubeconfig/login/login.go | 2 +- internal/cmd/ske/options/options.go | 2 +- internal/cmd/volume/create/create.go | 4 +- internal/cmd/volume/delete/delete.go | 2 +- internal/cmd/volume/describe/describe.go | 2 +- internal/cmd/volume/list/list.go | 4 +- .../performance-class/describe/describe.go | 2 +- .../cmd/volume/performance-class/list/list.go | 4 +- internal/cmd/volume/resize/resize.go | 2 +- internal/cmd/volume/update/update.go | 2 +- internal/pkg/projectname/project_name.go | 4 +- internal/pkg/projectname/project_name_test.go | 2 +- internal/pkg/services/alb/client/client.go | 16 ++++---- .../services/authorization/client/client.go | 14 +++---- internal/pkg/services/dns/client/client.go | 15 +++---- internal/pkg/services/iaas/client/client.go | 14 +++---- .../services/load-balancer/client/client.go | 16 ++++---- internal/pkg/services/logme/client/client.go | 15 +++---- .../pkg/services/mariadb/client/client.go | 15 +++---- .../pkg/services/mongodbflex/client/client.go | 15 +++---- .../services/object-storage/client/client.go | 16 ++++---- .../services/observability/client/client.go | 15 +++---- .../pkg/services/opensearch/client/client.go | 15 +++---- .../services/postgresflex/client/client.go | 15 +++---- .../pkg/services/rabbitmq/client/client.go | 15 +++---- internal/pkg/services/redis/client/client.go | 15 +++---- .../services/resourcemanager/client/client.go | 14 +++---- .../pkg/services/runcommand/client/client.go | 14 +++---- .../services/secrets-manager/client/client.go | 15 +++---- .../services/serverbackup/client/client.go | 14 +++---- .../services/serverosupdate/client/client.go | 13 +++--- .../services/service-account/client/client.go | 14 +++---- .../service-enablement/client/client.go | 14 +++---- internal/pkg/services/ske/client/client.go | 14 +++---- .../services/sqlserverflex/client/client.go | 14 +++---- internal/pkg/utils/utils.go | 5 +++ internal/pkg/utils/utils_test.go | 41 +++++++++++++++++++ 382 files changed, 724 insertions(+), 635 deletions(-) diff --git a/.github/docs/contribution-guide/client.go b/.github/docs/contribution-guide/client.go index 4b84a6538..3fdda371b 100644 --- a/.github/docs/contribution-guide/client.go +++ b/.github/docs/contribution-guide/client.go @@ -1,24 +1,29 @@ package client import ( - "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/foo" // (...) ) -func ConfigureClient(cmd *cobra.Command) (*foo.APIClient, error) { - var err error - var apiClient foo.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - - authCfgOption, err := auth.AuthenticationConfig(cmd, auth.AuthorizeUser) +func ConfigureClient(p *print.Printer, cliVersion string) (*foo.APIClient, error) { + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) // Configuring region is needed if "foo" is a regional API + + region := viper.GetString(config.RegionKey) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), // Configuring region is needed if "foo" is a regional API + authCfgOption, + } customEndpoint := viper.GetString(config.fooCustomEndpointKey) @@ -26,8 +31,15 @@ func ConfigureClient(cmd *cobra.Command) (*foo.APIClient, error) { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } - apiClient, err = foo.NewAPIClient(cfgOptions...) + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err := foo.NewAPIClient(cfgOptions...) if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} } diff --git a/.github/docs/contribution-guide/cmd.go b/.github/docs/contribution-guide/cmd.go index 5fb05d2f4..175a9a6d3 100644 --- a/.github/docs/contribution-guide/cmd.go +++ b/.github/docs/contribution-guide/cmd.go @@ -12,6 +12,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" @@ -54,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer, cmd) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -66,7 +67,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("(...): %w", err) } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + projectLabel, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd) if err != nil { projectLabel = model.ProjectId } @@ -86,14 +87,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { // Configure command flags (type, default value, and description) func configureFlags(cmd *cobra.Command) { - cmd.Flags().StringP(myFlag, "defaultValue", "My flag description") + cmd.Flags().StringP(someFlag, "shorthand", "defaultValue", "My flag description") } // Parse user input (arguments and/or flags) func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { myArg := inputArgs[0] - globalFlags := globalflags.Parse(cmd) + globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} } @@ -101,7 +102,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, MyArg: myArg, - MyFlag: flags.FlagToStringPointer(cmd, myFlag), + MyFlag: flags.FlagToStringPointer(p, cmd, someFlag), } // Write the input model to the debug logs @@ -119,7 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu // Build request to the API func buildRequest(ctx context.Context, model *inputModel, apiClient *foo.APIClient) foo.ApiListInstancesRequest { - req := apiClient.GetBar(ctx, model.ProjectId, model.MyArg, someParam) + req := apiClient.GetBar(ctx, model.ProjectId, model.MyArg, someArg) return req } @@ -147,7 +148,7 @@ func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, res resource := resources[i] table.AddRow(*resource.ResourceId, *resource.Name, *resource.State) } - err := table.Display(cmd) + err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) } diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index d182c6534..e380d0458 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -53,7 +53,7 @@ Please remember to run `make generate-docs` after your changes to keep the comma Below is a typical structure of a CLI command: -https://github.com/stackitcloud/stackit-cli/blob/6f762bd56407ed232080efabc4d2bf87f260b71d/.github/docs/contribution-guide/cmd.go#L23-L156 +https://github.com/stackitcloud/stackit-cli/blob/85ce44cd18d11169f2548d8657031b5fc6f94740/.github/docs/contribution-guide/cmd.go#L23-L156 Please remember to always add unit tests for `parseInput`, `buildRequest` (in `bar_test.go`), and any other util functions used. @@ -83,7 +83,7 @@ If you want to add a command that uses a STACKIT service `foo` that was not yet 1. This is done in `internal/pkg/services/foo/client/client.go` 2. Below is an example of a typical `client.go` file structure: -https://github.com/stackitcloud/stackit-cli/blob/6f762bd56407ed232080efabc4d2bf87f260b71d/.github/docs/contribution-guide/client.go#L12-L35 +https://github.com/stackitcloud/stackit-cli/blob/85ce44cd18d11169f2548d8657031b5fc6f94740/.github/docs/contribution-guide/client.go#L12-L35 ### Local development diff --git a/internal/cmd/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go index fc8482ea8..60b14fdd1 100644 --- a/internal/cmd/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/affinity-groups/delete/delete.go b/internal/cmd/affinity-groups/delete/delete.go index f36371648..eab65fd66 100644 --- a/internal/cmd/affinity-groups/delete/delete.go +++ b/internal/cmd/affinity-groups/delete/delete.go @@ -47,12 +47,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/affinity-groups/describe/describe.go b/internal/cmd/affinity-groups/describe/describe.go index 566e42d5e..6abd3980c 100644 --- a/internal/cmd/affinity-groups/describe/describe.go +++ b/internal/cmd/affinity-groups/describe/describe.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/affinity-groups/list/list.go b/internal/cmd/affinity-groups/list/list.go index cb06a6612..5665a970c 100644 --- a/internal/cmd/affinity-groups/list/list.go +++ b/internal/cmd/affinity-groups/list/list.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go index 4d5abe3c1..2622a3ce4 100644 --- a/internal/cmd/beta/alb/create/create.go +++ b/internal/cmd/beta/alb/create/create.go @@ -54,12 +54,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/alb/delete/delete.go b/internal/cmd/beta/alb/delete/delete.go index 0c443d593..25886cd40 100644 --- a/internal/cmd/beta/alb/delete/delete.go +++ b/internal/cmd/beta/alb/delete/delete.go @@ -45,12 +45,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/alb/describe/describe.go b/internal/cmd/beta/alb/describe/describe.go index db4418ddf..67a10bf4a 100644 --- a/internal/cmd/beta/alb/describe/describe.go +++ b/internal/cmd/beta/alb/describe/describe.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go index cf1d478c5..6df67a81a 100644 --- a/internal/cmd/beta/alb/list/list.go +++ b/internal/cmd/beta/alb/list/list.go @@ -55,12 +55,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/alb/observability-credentials/add/add.go b/internal/cmd/beta/alb/observability-credentials/add/add.go index e0eff7449..86b6ac2b9 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete.go b/internal/cmd/beta/alb/observability-credentials/delete/delete.go index df9f462f0..ccf998580 100644 --- a/internal/cmd/beta/alb/observability-credentials/delete/delete.go +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete.go @@ -44,7 +44,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe.go b/internal/cmd/beta/alb/observability-credentials/describe/describe.go index 4081421ca..001e20278 100644 --- a/internal/cmd/beta/alb/observability-credentials/describe/describe.go +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/alb/observability-credentials/list/list.go b/internal/cmd/beta/alb/observability-credentials/list/list.go index bbbdd6db4..32baa31c6 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/alb/observability-credentials/update/update.go b/internal/cmd/beta/alb/observability-credentials/update/update.go index 3231f0d95..18b68ccb4 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { model := parseInput(params.Printer, cmd, args) // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/alb/plans/plans.go b/internal/cmd/beta/alb/plans/plans.go index f7d09bec6..d131422ad 100644 --- a/internal/cmd/beta/alb/plans/plans.go +++ b/internal/cmd/beta/alb/plans/plans.go @@ -44,12 +44,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/alb/pool/update/update.go b/internal/cmd/beta/alb/pool/update/update.go index 94bdd2872..2dc8cd3a2 100644 --- a/internal/cmd/beta/alb/pool/update/update.go +++ b/internal/cmd/beta/alb/pool/update/update.go @@ -54,12 +54,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/alb/quotas/quotas.go b/internal/cmd/beta/alb/quotas/quotas.go index 09735a914..c0ce6948b 100644 --- a/internal/cmd/beta/alb/quotas/quotas.go +++ b/internal/cmd/beta/alb/quotas/quotas.go @@ -43,7 +43,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go index 10e0b9bc5..2dcfddbb1 100644 --- a/internal/cmd/beta/alb/update/update.go +++ b/internal/cmd/beta/alb/update/update.go @@ -55,12 +55,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index ac7e345a8..f8ae03ccd 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete.go b/internal/cmd/beta/sqlserverflex/database/delete/delete.go index b1950aa86..0f2b221f7 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index 3ddbfa086..377d90476 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index ba22c593e..707922ef9 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -69,7 +69,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("get SQLServer Flex databases: %w", err) } if resp.Databases == nil || len(*resp.Databases) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 9003de50b..b30d7615c 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -93,12 +93,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go index 2b5723c50..ab1742879 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index 7dec66a7d..d8e3a60c3 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 3f9abdb22..945eb5024 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -67,7 +67,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("get SQLServer Flex instances: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index 53921ea75..c857aba35 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -84,7 +84,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index d66f082c9..d5d62c10b 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -116,7 +116,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 501746b1e..7cd803ec7 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete.go b/internal/cmd/beta/sqlserverflex/user/delete/delete.go index dea859e97..8250b1b01 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index 7ccba07f1..1d94890ac 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -61,7 +61,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index 29e2c803c..c45317bf2 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index ff560a2cf..35ef24063 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/config/list/list_test.go b/internal/cmd/config/list/list_test.go index 936e5a76d..cbdab8410 100644 --- a/internal/cmd/config/list/list_test.go +++ b/internal/cmd/config/list/list_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" ) diff --git a/internal/cmd/config/profile/create/create.go b/internal/cmd/config/profile/create/create.go index 8ab83f574..4d93bdd72 100644 --- a/internal/cmd/config/profile/create/create.go +++ b/internal/cmd/config/profile/create/create.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" diff --git a/internal/cmd/config/profile/create/create_test.go b/internal/cmd/config/profile/create/create_test.go index 097071947..6bf77a7ae 100644 --- a/internal/cmd/config/profile/create/create_test.go +++ b/internal/cmd/config/profile/create/create_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" diff --git a/internal/cmd/config/profile/delete/delete.go b/internal/cmd/config/profile/delete/delete.go index 88d00907f..02c04e64a 100644 --- a/internal/cmd/config/profile/delete/delete.go +++ b/internal/cmd/config/profile/delete/delete.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" diff --git a/internal/cmd/config/profile/delete/delete_test.go b/internal/cmd/config/profile/delete/delete_test.go index 018ded22a..66374b69d 100644 --- a/internal/cmd/config/profile/delete/delete_test.go +++ b/internal/cmd/config/profile/delete/delete_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" diff --git a/internal/cmd/config/profile/export/export_test.go b/internal/cmd/config/profile/export/export_test.go index d15885813..5975cf783 100644 --- a/internal/cmd/config/profile/export/export_test.go +++ b/internal/cmd/config/profile/export/export_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" diff --git a/internal/cmd/config/profile/list/list.go b/internal/cmd/config/profile/list/list.go index 2a43aa417..86e2f3341 100644 --- a/internal/cmd/config/profile/list/list.go +++ b/internal/cmd/config/profile/list/list.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" diff --git a/internal/cmd/config/profile/set/set_test.go b/internal/cmd/config/profile/set/set_test.go index a12b0f328..67b5f0789 100644 --- a/internal/cmd/config/profile/set/set_test.go +++ b/internal/cmd/config/profile/set/set_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" diff --git a/internal/cmd/config/set/set_test.go b/internal/cmd/config/set/set_test.go index e9647e268..8015fddff 100644 --- a/internal/cmd/config/set/set_test.go +++ b/internal/cmd/config/set/set_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index a977f8aa2..246696f15 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/google/go-cmp/cmp" diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 8441db8ac..49db52860 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/dns/record-set/delete/delete.go b/internal/cmd/dns/record-set/delete/delete.go index a4026478f..015b8019d 100644 --- a/internal/cmd/dns/record-set/delete/delete.go +++ b/internal/cmd/dns/record-set/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/dns/record-set/describe/describe.go b/internal/cmd/dns/record-set/describe/describe.go index 8f80674b8..c7d5e8c52 100644 --- a/internal/cmd/dns/record-set/describe/describe.go +++ b/internal/cmd/dns/record-set/describe/describe.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index 99a07bb5a..a1b59553b 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -82,7 +82,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/dns/record-set/update/update.go b/internal/cmd/dns/record-set/update/update.go index 6d2a7ea06..74630d455 100644 --- a/internal/cmd/dns/record-set/update/update.go +++ b/internal/cmd/dns/record-set/update/update.go @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/dns/record-set/update/update_test.go b/internal/cmd/dns/record-set/update/update_test.go index 99e32d0f9..228b4b956 100644 --- a/internal/cmd/dns/record-set/update/update_test.go +++ b/internal/cmd/dns/record-set/update/update_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index 1894b2291..7d81f13f8 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index d23d35f39..4855e4337 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -78,12 +78,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/dns/zone/delete/delete.go b/internal/cmd/dns/zone/delete/delete.go index 8c5b01bd9..443bbf186 100644 --- a/internal/cmd/dns/zone/delete/delete.go +++ b/internal/cmd/dns/zone/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/dns/zone/describe/describe.go b/internal/cmd/dns/zone/describe/describe.go index b97ba0445..d68bbb177 100644 --- a/internal/cmd/dns/zone/describe/describe.go +++ b/internal/cmd/dns/zone/describe/describe.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index 017a171df..c3de2d640 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -89,7 +89,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } if len(zones) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/dns/zone/update/update.go b/internal/cmd/dns/zone/update/update.go index 09c4036fd..d7575c609 100644 --- a/internal/cmd/dns/zone/update/update.go +++ b/internal/cmd/dns/zone/update/update.go @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 704872c11..930811f51 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -106,7 +106,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/image/delete/delete.go b/internal/cmd/image/delete/delete.go index 456867bdd..bfce6ae4c 100644 --- a/internal/cmd/image/delete/delete.go +++ b/internal/cmd/image/delete/delete.go @@ -42,12 +42,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/image/describe/describe.go b/internal/cmd/image/describe/describe.go index 5c0b8a824..d1c945b81 100644 --- a/internal/cmd/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -44,7 +44,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index eff221cba..00f28b066 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -60,12 +60,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index e123d4fe1..e46e90790 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -120,12 +120,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go index b59fe4fb0..5c4fb9196 100644 --- a/internal/cmd/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/key-pair/delete/delete.go b/internal/cmd/key-pair/delete/delete.go index 8bccdd45d..376d21174 100644 --- a/internal/cmd/key-pair/delete/delete.go +++ b/internal/cmd/key-pair/delete/delete.go @@ -44,7 +44,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/key-pair/describe/describe.go b/internal/cmd/key-pair/describe/describe.go index b355e7433..8de535589 100644 --- a/internal/cmd/key-pair/describe/describe.go +++ b/internal/cmd/key-pair/describe/describe.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/key-pair/list/list.go b/internal/cmd/key-pair/list/list.go index 980625695..b614cf5c1 100644 --- a/internal/cmd/key-pair/list/list.go +++ b/internal/cmd/key-pair/list/list.go @@ -66,7 +66,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/key-pair/update/update.go b/internal/cmd/key-pair/update/update.go index 3af038018..c34c1362b 100644 --- a/internal/cmd/key-pair/update/update.go +++ b/internal/cmd/key-pair/update/update.go @@ -47,7 +47,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { model := parseInput(params.Printer, cmd, args) // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index 541293bc2..f59683a47 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -66,12 +66,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/load-balancer/delete/delete.go b/internal/cmd/load-balancer/delete/delete.go index d5f3f6c75..84146f875 100644 --- a/internal/cmd/load-balancer/delete/delete.go +++ b/internal/cmd/load-balancer/delete/delete.go @@ -45,7 +45,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index fe8669864..2b5ff659d 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index 2fccfb37a..1197cf7a9 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -142,7 +142,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index 5d23c5d2a..02a1f30ed 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -69,7 +69,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.LoadBalancers == nil || (resp.LoadBalancers != nil && len(*resp.LoadBalancers) == 0) { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index abbbd36a0..533a222f4 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -57,12 +57,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go index e69b3ae98..3bcf0190a 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go @@ -41,12 +41,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete.go b/internal/cmd/load-balancer/observability-credentials/delete/delete.go index 12b260489..bef2362b9 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete.go @@ -46,12 +46,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index a09a94685..85c32ba7f 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 92dcb9602..714364c47 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -67,12 +67,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/load-balancer/observability-credentials/update/update.go b/internal/cmd/load-balancer/observability-credentials/update/update.go index 942c20131..29761043e 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update.go @@ -68,12 +68,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index fdb173fb0..2925d7f52 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -41,7 +41,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target.go b/internal/cmd/load-balancer/target-pool/add-target/add_target.go index 5dec7bfca..46faf8bb9 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index b9699e7c0..ea0f6dace 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go index 5d8297665..3ca65c79b 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/load-balancer/update/update.go b/internal/cmd/load-balancer/update/update.go index ab2a82d88..db183702d 100644 --- a/internal/cmd/load-balancer/update/update.go +++ b/internal/cmd/load-balancer/update/update.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 80783e6da..c1e44ccff 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/logme/credentials/delete/delete.go b/internal/cmd/logme/credentials/delete/delete.go index 2295be928..fabd2b838 100644 --- a/internal/cmd/logme/credentials/delete/delete.go +++ b/internal/cmd/logme/credentials/delete/delete.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/logme/credentials/describe/describe.go b/internal/cmd/logme/credentials/describe/describe.go index faf1537b6..240df0f81 100644 --- a/internal/cmd/logme/credentials/describe/describe.go +++ b/internal/cmd/logme/credentials/describe/describe.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index 107824d39..218dff2d1 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index 89f2d9dc0..ca00f4cdc 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -81,12 +81,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/logme/instance/delete/delete.go b/internal/cmd/logme/instance/delete/delete.go index 25693c798..905c51bed 100644 --- a/internal/cmd/logme/instance/delete/delete.go +++ b/internal/cmd/logme/instance/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/logme/instance/describe/describe.go b/internal/cmd/logme/instance/describe/describe.go index 29b86a0a7..bf7892373 100644 --- a/internal/cmd/logme/instance/describe/describe.go +++ b/internal/cmd/logme/instance/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index 821727852..e325aee95 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/logme/instance/update/update.go b/internal/cmd/logme/instance/update/update.go index 79802ee58..a7e3ec443 100644 --- a/internal/cmd/logme/instance/update/update.go +++ b/internal/cmd/logme/instance/update/update.go @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index 2eb665d7e..8c339a1ee 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 7e4a8a592..cf42e1ca2 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mariadb/credentials/delete/delete.go b/internal/cmd/mariadb/credentials/delete/delete.go index 5df7736dc..cbce0078d 100644 --- a/internal/cmd/mariadb/credentials/delete/delete.go +++ b/internal/cmd/mariadb/credentials/delete/delete.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mariadb/credentials/describe/describe.go b/internal/cmd/mariadb/credentials/describe/describe.go index c868a7d60..7a03a4377 100644 --- a/internal/cmd/mariadb/credentials/describe/describe.go +++ b/internal/cmd/mariadb/credentials/describe/describe.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index acb97d02f..f9a3f43d7 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index dae8ad6b3..b84368fa2 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -81,12 +81,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/mariadb/instance/delete/delete.go b/internal/cmd/mariadb/instance/delete/delete.go index 7b7b2d6e5..eaca7989a 100644 --- a/internal/cmd/mariadb/instance/delete/delete.go +++ b/internal/cmd/mariadb/instance/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mariadb/instance/describe/describe.go b/internal/cmd/mariadb/instance/describe/describe.go index 978cdcf24..58f07db66 100644 --- a/internal/cmd/mariadb/instance/describe/describe.go +++ b/internal/cmd/mariadb/instance/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index 3bba56507..7e5b8e0d6 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/mariadb/instance/update/update.go b/internal/cmd/mariadb/instance/update/update.go index 80cabdac5..26059ff6f 100644 --- a/internal/cmd/mariadb/instance/update/update.go +++ b/internal/cmd/mariadb/instance/update/update.go @@ -76,7 +76,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index 5b342f29e..c54703a1e 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index 43e8a0b81..f565aebd4 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index 75ddca216..f2e40bd83 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index 7119dccbb..81c5853c8 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index 067c0e56e..ed86d7c61 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index 55272a544..16cd47d24 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go index d417ccbf4..e93f557ea 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go @@ -76,7 +76,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 2b8905364..05df2b9e5 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -83,12 +83,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/mongodbflex/instance/delete/delete.go b/internal/cmd/mongodbflex/instance/delete/delete.go index 86653c5a3..609307fbd 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete.go +++ b/internal/cmd/mongodbflex/instance/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index 2b64e3432..65765a540 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index a016550cc..633caee2c 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("get MongoDB Flex instances: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index e1882bfd9..b861cc423 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 92c6c55bb..10e9f6f5c 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index afc26fe76..095077242 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -67,7 +67,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/user/delete/delete.go b/internal/cmd/mongodbflex/user/delete/delete.go index d57879062..1d0818522 100644 --- a/internal/cmd/mongodbflex/user/delete/delete.go +++ b/internal/cmd/mongodbflex/user/delete/delete.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/user/describe/describe.go b/internal/cmd/mongodbflex/user/describe/describe.go index 89f919f7b..67eb3d84b 100644 --- a/internal/cmd/mongodbflex/user/describe/describe.go +++ b/internal/cmd/mongodbflex/user/describe/describe.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index 299319462..ffdb6f10a 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index 72d7ad9d4..0144a20b5 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/mongodbflex/user/update/update.go b/internal/cmd/mongodbflex/user/update/update.go index 3ebdf4e6d..8dded41b0 100644 --- a/internal/cmd/mongodbflex/user/update/update.go +++ b/internal/cmd/mongodbflex/user/update/update.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index 80c14dc37..0bc3ae47a 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -78,13 +78,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } var orgLabel string - rmApiClient, err := rmClient.ConfigureClient(params.Printer) + rmApiClient, err := rmClient.ConfigureClient(params.Printer, params.CliVersion) if err == nil { orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) if err != nil { diff --git a/internal/cmd/network-area/delete/delete.go b/internal/cmd/network-area/delete/delete.go index 49f618338..9664f8305 100644 --- a/internal/cmd/network-area/delete/delete.go +++ b/internal/cmd/network-area/delete/delete.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/describe/describe.go b/internal/cmd/network-area/describe/describe.go index 6658b1feb..45c2cc4dc 100644 --- a/internal/cmd/network-area/describe/describe.go +++ b/internal/cmd/network-area/describe/describe.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/list/list.go b/internal/cmd/network-area/list/list.go index 82147c17b..aef31e48b 100644 --- a/internal/cmd/network-area/list/list.go +++ b/internal/cmd/network-area/list/list.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -15,7 +17,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" rmUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -67,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -81,7 +82,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if resp.Items == nil || len(*resp.Items) == 0 { var orgLabel string - rmApiClient, err := rmClient.ConfigureClient(params.Printer) + rmApiClient, err := rmClient.ConfigureClient(params.Printer, params.CliVersion) if err == nil { orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) if err != nil { diff --git a/internal/cmd/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go index 7d81e2358..cdc54b800 100644 --- a/internal/cmd/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/network-range/delete/delete.go b/internal/cmd/network-area/network-range/delete/delete.go index 4b7397796..fb4f53de0 100644 --- a/internal/cmd/network-area/network-range/delete/delete.go +++ b/internal/cmd/network-area/network-range/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/network-range/describe/describe.go b/internal/cmd/network-area/network-range/describe/describe.go index 45bcfa4e4..d594ebb64 100644 --- a/internal/cmd/network-area/network-range/describe/describe.go +++ b/internal/cmd/network-area/network-range/describe/describe.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go index aed963ba0..e7acd42e8 100644 --- a/internal/cmd/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index 56ac716b4..4cd29e663 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -64,7 +64,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/route/delete/delete.go b/internal/cmd/network-area/route/delete/delete.go index f455786d2..11e36eff8 100644 --- a/internal/cmd/network-area/route/delete/delete.go +++ b/internal/cmd/network-area/route/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/route/describe/describe.go b/internal/cmd/network-area/route/describe/describe.go index 8e48f1ee6..e58a3a2d5 100644 --- a/internal/cmd/network-area/route/describe/describe.go +++ b/internal/cmd/network-area/route/describe/describe.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go index f8159617b..2c099c3f8 100644 --- a/internal/cmd/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go index ab4c8c860..1fb9f13f6 100644 --- a/internal/cmd/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-area/update/update.go b/internal/cmd/network-area/update/update.go index 7e9615aff..122e94f33 100644 --- a/internal/cmd/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" + "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -13,7 +15,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" rmUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -66,13 +67,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } var orgLabel string - rmApiClient, err := rmClient.ConfigureClient(params.Printer) + rmApiClient, err := rmClient.ConfigureClient(params.Printer, params.CliVersion) if err == nil { orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) if err != nil { diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index 08a8c7cac..f1024f844 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -74,12 +74,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/network-interface/delete/delete.go b/internal/cmd/network-interface/delete/delete.go index 925bf29b7..8450f5abc 100644 --- a/internal/cmd/network-interface/delete/delete.go +++ b/internal/cmd/network-interface/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-interface/describe/describe.go b/internal/cmd/network-interface/describe/describe.go index aba9ed65a..b221a0b1b 100644 --- a/internal/cmd/network-interface/describe/describe.go +++ b/internal/cmd/network-interface/describe/describe.go @@ -61,7 +61,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go index e7282358f..eeb3c9be6 100644 --- a/internal/cmd/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -66,7 +66,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go index 9cf746745..e92c5b8be 100644 --- a/internal/cmd/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -76,7 +76,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index 339025b74..08e4e20b2 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -96,12 +96,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/network/delete/delete.go b/internal/cmd/network/delete/delete.go index a0adcb6d0..005c3e312 100644 --- a/internal/cmd/network/delete/delete.go +++ b/internal/cmd/network/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network/describe/describe.go b/internal/cmd/network/describe/describe.go index 129c52899..b4c12a317 100644 --- a/internal/cmd/network/describe/describe.go +++ b/internal/cmd/network/describe/describe.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/network/list/list.go b/internal/cmd/network/list/list.go index 90e6efa0e..2584d7fd7 100644 --- a/internal/cmd/network/list/list.go +++ b/internal/cmd/network/list/list.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/network/update/update.go b/internal/cmd/network/update/update.go index 1b331a802..22a8cf87a 100644 --- a/internal/cmd/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -79,7 +79,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index f4337d7e3..fd899a4d2 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/bucket/delete/delete.go b/internal/cmd/object-storage/bucket/delete/delete.go index 0b4174f47..fa4e68e99 100644 --- a/internal/cmd/object-storage/bucket/delete/delete.go +++ b/internal/cmd/object-storage/bucket/delete/delete.go @@ -46,7 +46,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index c1fd344d6..4112c0674 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index cbfa41574..8060094c1 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -67,7 +67,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("get Object Storage buckets: %w", err) } if resp.Buckets == nil || len(*resp.Buckets) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index 02dfba938..dac9c248c 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/credentials-group/delete/delete.go b/internal/cmd/object-storage/credentials-group/delete/delete.go index 11457da96..ff880c0f7 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete.go @@ -46,7 +46,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index e239167b0..ccea6fc84 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index bce332f93..eaef679f5 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/credentials/delete/delete.go b/internal/cmd/object-storage/credentials/delete/delete.go index e8cc8a4e3..dea8797b0 100644 --- a/internal/cmd/object-storage/credentials/delete/delete.go +++ b/internal/cmd/object-storage/credentials/delete/delete.go @@ -47,7 +47,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index 33a41860f..211ac8d77 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/object-storage/disable/disable.go b/internal/cmd/object-storage/disable/disable.go index 0486e90ae..f6b8ee848 100644 --- a/internal/cmd/object-storage/disable/disable.go +++ b/internal/cmd/object-storage/disable/disable.go @@ -40,12 +40,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/object-storage/enable/enable.go b/internal/cmd/object-storage/enable/enable.go index 00959bcfa..6a064bb3c 100644 --- a/internal/cmd/object-storage/enable/enable.go +++ b/internal/cmd/object-storage/enable/enable.go @@ -40,12 +40,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index f968f0a7e..139ed39dd 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/credentials/delete/delete.go b/internal/cmd/observability/credentials/delete/delete.go index 0c85bf2b6..eeb00d2b9 100644 --- a/internal/cmd/observability/credentials/delete/delete.go +++ b/internal/cmd/observability/credentials/delete/delete.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go index 3bf6bf231..d5cc513fe 100644 --- a/internal/cmd/observability/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index bce33d2a6..2ad9103e6 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -61,7 +61,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/grafana/public-read-access/disable/disable.go b/internal/cmd/observability/grafana/public-read-access/disable/disable.go index 0f122fc96..5696bf623 100644 --- a/internal/cmd/observability/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/grafana/public-read-access/enable/enable.go b/internal/cmd/observability/grafana/public-read-access/enable/enable.go index a13ae2c08..7cd00b9e2 100644 --- a/internal/cmd/observability/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go index 14084d154..bf6de05a4 100644 --- a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go index 9956ebd9b..84b2bc0c4 100644 --- a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 5158941e5..37f3a8114 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -61,12 +61,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/observability/instance/delete/delete.go b/internal/cmd/observability/instance/delete/delete.go index eb1790ebd..ff0d1bd62 100644 --- a/internal/cmd/observability/instance/delete/delete.go +++ b/internal/cmd/observability/instance/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go index 7e03dbb03..506bdcbc1 100644 --- a/internal/cmd/observability/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index e82c2254b..011842a4e 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/observability/instance/update/update.go b/internal/cmd/observability/instance/update/update.go index 90411dd26..b314a6ecc 100644 --- a/internal/cmd/observability/instance/update/update.go +++ b/internal/cmd/observability/instance/update/update.go @@ -64,7 +64,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index 90867c27a..7fe3feabf 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -69,7 +69,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } plans := *resp.Plans if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/observability/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go index 9bd89d9d7..d11d4b575 100644 --- a/internal/cmd/observability/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/scrape-config/delete/delete.go b/internal/cmd/observability/scrape-config/delete/delete.go index 0bc137b3b..5ec7e3931 100644 --- a/internal/cmd/observability/scrape-config/delete/delete.go +++ b/internal/cmd/observability/scrape-config/delete/delete.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/scrape-config/describe/describe.go b/internal/cmd/observability/scrape-config/describe/describe.go index 2c6e24573..0b7eb0eb5 100644 --- a/internal/cmd/observability/scrape-config/describe/describe.go +++ b/internal/cmd/observability/scrape-config/describe/describe.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go index 3a1927114..487fa32b3 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go index b03ec740b..95a9770cc 100644 --- a/internal/cmd/observability/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/observability/scrape-config/update/update.go b/internal/cmd/observability/scrape-config/update/update.go index 25b423452..ab39ea9e0 100644 --- a/internal/cmd/observability/scrape-config/update/update.go +++ b/internal/cmd/observability/scrape-config/update/update.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index ce5a1cf9b..fdc2760f7 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/opensearch/credentials/delete/delete.go b/internal/cmd/opensearch/credentials/delete/delete.go index 97e2fc14b..faccd169e 100644 --- a/internal/cmd/opensearch/credentials/delete/delete.go +++ b/internal/cmd/opensearch/credentials/delete/delete.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/opensearch/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index d70edf933..92bdf6350 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index b4d200b1e..0efb58d37 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index 336a2e5ab..bc41bfbed 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -83,12 +83,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/opensearch/instance/delete/delete.go b/internal/cmd/opensearch/instance/delete/delete.go index cd7f159d3..e0ed0db20 100644 --- a/internal/cmd/opensearch/instance/delete/delete.go +++ b/internal/cmd/opensearch/instance/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index d8722d9d5..da181a5a4 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index 0b0aa93c8..e32b425e5 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/opensearch/instance/update/update.go b/internal/cmd/opensearch/instance/update/update.go index 85ba3f133..254a9a41b 100644 --- a/internal/cmd/opensearch/instance/update/update.go +++ b/internal/cmd/opensearch/instance/update/update.go @@ -79,7 +79,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index e2678f163..c096fb230 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/organization/member/add/add.go b/internal/cmd/organization/member/add/add.go index 246a7f27f..d3dd1f81b 100644 --- a/internal/cmd/organization/member/add/add.go +++ b/internal/cmd/organization/member/add/add.go @@ -66,7 +66,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index 105f6b14a..6e414d257 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -64,7 +64,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/organization/member/remove/remove.go b/internal/cmd/organization/member/remove/remove.go index 7ff3c9147..6281b4214 100644 --- a/internal/cmd/organization/member/remove/remove.go +++ b/internal/cmd/organization/member/remove/remove.go @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index c8925c90e..c16d145c2 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/backup/describe/describe.go b/internal/cmd/postgresflex/backup/describe/describe.go index 758fb955a..5e0ecf5c9 100644 --- a/internal/cmd/postgresflex/backup/describe/describe.go +++ b/internal/cmd/postgresflex/backup/describe/describe.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index 3f463a670..5527343ad 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -64,7 +64,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go index a9f3bb70d..376b04bae 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index b8a31cd4e..2967fdbb3 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 32301a4d4..7def7878c 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -84,12 +84,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/postgresflex/instance/delete/delete.go b/internal/cmd/postgresflex/instance/delete/delete.go index acf78c5ba..1c892657d 100644 --- a/internal/cmd/postgresflex/instance/delete/delete.go +++ b/internal/cmd/postgresflex/instance/delete/delete.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/instance/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index 13604fb58..9d58c781b 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index d3870566b..2431afa89 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -69,7 +69,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("get PostgreSQL Flex instances: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 980a358df..3a50f8dfa 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index cbf87326d..66535e387 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 8808e676e..00e214089 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/user/delete/delete.go b/internal/cmd/postgresflex/user/delete/delete.go index 2ed42cd8f..925453632 100644 --- a/internal/cmd/postgresflex/user/delete/delete.go +++ b/internal/cmd/postgresflex/user/delete/delete.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/user/describe/describe.go b/internal/cmd/postgresflex/user/describe/describe.go index 75e239d68..fb18ff889 100644 --- a/internal/cmd/postgresflex/user/describe/describe.go +++ b/internal/cmd/postgresflex/user/describe/describe.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index 3c8f79e77..a493855e2 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index 0d324a07b..45255b988 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/postgresflex/user/update/update.go b/internal/cmd/postgresflex/user/update/update.go index 5466348d3..4149a3b78 100644 --- a/internal/cmd/postgresflex/user/update/update.go +++ b/internal/cmd/postgresflex/user/update/update.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index d8c687bbd..17e9e950e 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -73,7 +73,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/project/delete/delete.go b/internal/cmd/project/delete/delete.go index c0d4e121e..4e83d9324 100644 --- a/internal/cmd/project/delete/delete.go +++ b/internal/cmd/project/delete/delete.go @@ -43,12 +43,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index 7fe4c7b9b..edd17d483 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index c2aaccad5..364458a7c 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/project/member/add/add.go b/internal/cmd/project/member/add/add.go index 5f9456602..1d40c0ec5 100644 --- a/internal/cmd/project/member/add/add.go +++ b/internal/cmd/project/member/add/add.go @@ -59,12 +59,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index c7c220121..673b4f755 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -76,7 +76,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } members := *resp.Members if len(members) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/project/member/remove/remove.go b/internal/cmd/project/member/remove/remove.go index 9fc60a116..b4030199f 100644 --- a/internal/cmd/project/member/remove/remove.go +++ b/internal/cmd/project/member/remove/remove.go @@ -62,12 +62,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index 9ffd80067..2f49ba18b 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -71,7 +71,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } roles := *resp.Roles if len(roles) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/project/update/update.go b/internal/cmd/project/update/update.go index e217f55f5..b46641ec4 100644 --- a/internal/cmd/project/update/update.go +++ b/internal/cmd/project/update/update.go @@ -62,12 +62,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/public-ip/associate/associate.go b/internal/cmd/public-ip/associate/associate.go index 369efc526..82de08fcb 100644 --- a/internal/cmd/public-ip/associate/associate.go +++ b/internal/cmd/public-ip/associate/associate.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index e072655db..68252751f 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -59,12 +59,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/public-ip/delete/delete.go b/internal/cmd/public-ip/delete/delete.go index 5382526e7..9cb01d38e 100644 --- a/internal/cmd/public-ip/delete/delete.go +++ b/internal/cmd/public-ip/delete/delete.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/public-ip/describe/describe.go b/internal/cmd/public-ip/describe/describe.go index 18f96d46d..db2ac5050 100644 --- a/internal/cmd/public-ip/describe/describe.go +++ b/internal/cmd/public-ip/describe/describe.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/public-ip/disassociate/disassociate.go b/internal/cmd/public-ip/disassociate/disassociate.go index cdd427605..7630ce7c5 100644 --- a/internal/cmd/public-ip/disassociate/disassociate.go +++ b/internal/cmd/public-ip/disassociate/disassociate.go @@ -47,7 +47,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/public-ip/list/list.go b/internal/cmd/public-ip/list/list.go index df57f864c..37756c8c2 100644 --- a/internal/cmd/public-ip/list/list.go +++ b/internal/cmd/public-ip/list/list.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go index 0e9a2180a..939b91ccf 100644 --- a/internal/cmd/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/quota/list/list.go b/internal/cmd/quota/list/list.go index 756c10ff5..81397affc 100644 --- a/internal/cmd/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -44,12 +44,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index 0cbe75a6f..6195ec768 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/rabbitmq/credentials/delete/delete.go b/internal/cmd/rabbitmq/credentials/delete/delete.go index 433348260..9421e898e 100644 --- a/internal/cmd/rabbitmq/credentials/delete/delete.go +++ b/internal/cmd/rabbitmq/credentials/delete/delete.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/rabbitmq/credentials/describe/describe.go b/internal/cmd/rabbitmq/credentials/describe/describe.go index 9ad4dcc9f..e04eb1c2e 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index 6a06c9313..d31efe256 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index 77f34ed7f..a5ea1b7af 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -83,12 +83,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/rabbitmq/instance/delete/delete.go b/internal/cmd/rabbitmq/instance/delete/delete.go index 992526969..852fa0d2e 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete.go +++ b/internal/cmd/rabbitmq/instance/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/rabbitmq/instance/describe/describe.go b/internal/cmd/rabbitmq/instance/describe/describe.go index e79f476fa..734bd97ce 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe.go +++ b/internal/cmd/rabbitmq/instance/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index cad8afdb3..4556f201f 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/rabbitmq/instance/update/update.go b/internal/cmd/rabbitmq/instance/update/update.go index f75c97cac..b86b9f969 100644 --- a/internal/cmd/rabbitmq/instance/update/update.go +++ b/internal/cmd/rabbitmq/instance/update/update.go @@ -79,7 +79,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index fc9276a93..996cea081 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -69,7 +69,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index 17d6e4164..3e6d2d961 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/redis/credentials/delete/delete.go b/internal/cmd/redis/credentials/delete/delete.go index 147ad731b..4d438bfba 100644 --- a/internal/cmd/redis/credentials/delete/delete.go +++ b/internal/cmd/redis/credentials/delete/delete.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/redis/credentials/describe/describe.go b/internal/cmd/redis/credentials/describe/describe.go index 9ab0e9ab4..028554868 100644 --- a/internal/cmd/redis/credentials/describe/describe.go +++ b/internal/cmd/redis/credentials/describe/describe.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index 603dc86ed..d7edc501e 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index 86fdec837..bece1146e 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -81,12 +81,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/redis/instance/delete/delete.go b/internal/cmd/redis/instance/delete/delete.go index bb4efebda..01fa78218 100644 --- a/internal/cmd/redis/instance/delete/delete.go +++ b/internal/cmd/redis/instance/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/redis/instance/describe/describe.go b/internal/cmd/redis/instance/describe/describe.go index c01d82ddd..22e9e4805 100644 --- a/internal/cmd/redis/instance/describe/describe.go +++ b/internal/cmd/redis/instance/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index 87f7b6d3e..cc2bcacbd 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } instances := *resp.Instances if len(instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/redis/instance/update/update.go b/internal/cmd/redis/instance/update/update.go index 65e92c860..6d2e919f7 100644 --- a/internal/cmd/redis/instance/update/update.go +++ b/internal/cmd/redis/instance/update/update.go @@ -76,7 +76,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 7bcb60218..7e663c8c3 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } plans := *resp.Offerings if len(plans) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index ad1a8195f..cd0cfd175 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -56,12 +56,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/secrets-manager/instance/delete/delete.go b/internal/cmd/secrets-manager/instance/delete/delete.go index dda64b620..121d5427d 100644 --- a/internal/cmd/secrets-manager/instance/delete/delete.go +++ b/internal/cmd/secrets-manager/instance/delete/delete.go @@ -45,7 +45,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index e794a2cce..3aed94fd5 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index cf6d4c745..4098a7d76 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Instances == nil || len(*resp.Instances) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/secrets-manager/instance/update/update.go b/internal/cmd/secrets-manager/instance/update/update.go index 371711e55..b460360e2 100644 --- a/internal/cmd/secrets-manager/instance/update/update.go +++ b/internal/cmd/secrets-manager/instance/update/update.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 62d54d9d7..5e8e3e25f 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -61,7 +61,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/secrets-manager/user/delete/delete.go b/internal/cmd/secrets-manager/user/delete/delete.go index fc3272435..571ef6130 100644 --- a/internal/cmd/secrets-manager/user/delete/delete.go +++ b/internal/cmd/secrets-manager/user/delete/delete.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/secrets-manager/user/describe/describe.go b/internal/cmd/secrets-manager/user/describe/describe.go index c08e0ac32..b11949417 100644 --- a/internal/cmd/secrets-manager/user/describe/describe.go +++ b/internal/cmd/secrets-manager/user/describe/describe.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index b414e2cd9..7040d69a6 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/secrets-manager/user/update/update.go b/internal/cmd/secrets-manager/user/update/update.go index f0b6e35b9..07e9b6edd 100644 --- a/internal/cmd/secrets-manager/user/update/update.go +++ b/internal/cmd/secrets-manager/user/update/update.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index 891abccc9..54f521d26 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/security-group/delete/delete.go b/internal/cmd/security-group/delete/delete.go index 0d116da7e..329e4b026 100644 --- a/internal/cmd/security-group/delete/delete.go +++ b/internal/cmd/security-group/delete/delete.go @@ -42,12 +42,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/security-group/describe/describe.go b/internal/cmd/security-group/describe/describe.go index bde9cbc9f..1ea5bf64d 100644 --- a/internal/cmd/security-group/describe/describe.go +++ b/internal/cmd/security-group/describe/describe.go @@ -45,7 +45,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/security-group/list/list.go b/internal/cmd/security-group/list/list.go index 592c65408..1459a3c11 100644 --- a/internal/cmd/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -49,12 +49,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go index a5b4bbc9d..d0e7bb008 100644 --- a/internal/cmd/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -85,12 +85,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/security-group/rule/delete/delete.go b/internal/cmd/security-group/rule/delete/delete.go index adca9d3eb..6acae57c7 100644 --- a/internal/cmd/security-group/rule/delete/delete.go +++ b/internal/cmd/security-group/rule/delete/delete.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/security-group/rule/describe/describe.go b/internal/cmd/security-group/rule/describe/describe.go index feefb5d54..47cd0e554 100644 --- a/internal/cmd/security-group/rule/describe/describe.go +++ b/internal/cmd/security-group/rule/describe/describe.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/security-group/rule/list/list.go b/internal/cmd/security-group/rule/list/list.go index 50304378e..c0bec27c6 100644 --- a/internal/cmd/security-group/rule/list/list.go +++ b/internal/cmd/security-group/rule/list/list.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -82,7 +82,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { securityGroupLabel = *model.SecurityGroupId } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/security-group/update/update.go b/internal/cmd/security-group/update/update.go index a91c07971..083470467 100644 --- a/internal/cmd/security-group/update/update.go +++ b/internal/cmd/security-group/update/update.go @@ -53,12 +53,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index ba2aa95c5..ccabadb65 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -13,7 +15,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -63,14 +64,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/backup/delete/delete.go b/internal/cmd/server/backup/delete/delete.go index a30dec646..5fed34276 100644 --- a/internal/cmd/server/backup/delete/delete.go +++ b/internal/cmd/server/backup/delete/delete.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/backup/describe/describe.go b/internal/cmd/server/backup/describe/describe.go index 9b3ad9247..b44ec3fbe 100644 --- a/internal/cmd/server/backup/describe/describe.go +++ b/internal/cmd/server/backup/describe/describe.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go index a61dce696..f456647ba 100644 --- a/internal/cmd/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -48,14 +48,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go index 89265e748..c4a4402b6 100644 --- a/internal/cmd/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -48,14 +48,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go index ccd29a624..775f88198 100644 --- a/internal/cmd/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -14,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" @@ -55,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if len(backups) == 0 { serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/backup/restore/restore.go b/internal/cmd/server/backup/restore/restore.go index 445680053..db9a48bac 100644 --- a/internal/cmd/server/backup/restore/restore.go +++ b/internal/cmd/server/backup/restore/restore.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index 09b834c50..c400e4e06 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -13,7 +15,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -71,14 +72,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/backup/schedule/delete/delete.go b/internal/cmd/server/backup/schedule/delete/delete.go index 69dc81579..fbf35a733 100644 --- a/internal/cmd/server/backup/schedule/delete/delete.go +++ b/internal/cmd/server/backup/schedule/delete/delete.go @@ -49,14 +49,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/backup/schedule/describe/describe.go b/internal/cmd/server/backup/schedule/describe/describe.go index cc838e0a8..49c5fd5ee 100644 --- a/internal/cmd/server/backup/schedule/describe/describe.go +++ b/internal/cmd/server/backup/schedule/describe/describe.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go index 3ad1c840e..edb0c4411 100644 --- a/internal/cmd/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -14,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverbackup/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" @@ -55,14 +56,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/backup/schedule/update/update.go b/internal/cmd/server/backup/schedule/update/update.go index 4bc895fc0..bdb3d8040 100644 --- a/internal/cmd/server/backup/schedule/update/update.go +++ b/internal/cmd/server/backup/schedule/update/update.go @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/backup/volume-backup/delete/delete.go b/internal/cmd/server/backup/volume-backup/delete/delete.go index 1b924fe85..d6e040d56 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/backup/volume-backup/restore/restore.go b/internal/cmd/server/backup/volume-backup/restore/restore.go index db7c6b543..4d3dd8bc9 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index 748d50b9b..1a766ef46 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -14,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" runcommandUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/utils" @@ -59,14 +60,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/command/describe/describe.go b/internal/cmd/server/command/describe/describe.go index a93d66988..ba09d2575 100644 --- a/internal/cmd/server/command/describe/describe.go +++ b/internal/cmd/server/command/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/command/list/list.go b/internal/cmd/server/command/list/list.go index f5deb62d1..a05d1a034 100644 --- a/internal/cmd/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -14,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/runcommand/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" @@ -55,14 +56,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/command/template/describe/describe.go b/internal/cmd/server/command/template/describe/describe.go index a694b9cad..7a83bf609 100644 --- a/internal/cmd/server/command/template/describe/describe.go +++ b/internal/cmd/server/command/template/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/command/template/list/list.go b/internal/cmd/server/command/template/list/list.go index 439df690d..a085c3210 100644 --- a/internal/cmd/server/command/template/list/list.go +++ b/internal/cmd/server/command/template/list/list.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/console/console.go b/internal/cmd/server/console/console.go index 35e5f814a..1462a97ac 100644 --- a/internal/cmd/server/console/console.go +++ b/internal/cmd/server/console/console.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 25544b3c8..33b20c247 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -118,12 +118,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/server/deallocate/deallocate.go b/internal/cmd/server/deallocate/deallocate.go index f51fab931..b614ba471 100644 --- a/internal/cmd/server/deallocate/deallocate.go +++ b/internal/cmd/server/deallocate/deallocate.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/delete/delete.go b/internal/cmd/server/delete/delete.go index d9a366c2e..c5aae8216 100644 --- a/internal/cmd/server/delete/delete.go +++ b/internal/cmd/server/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/describe/describe.go b/internal/cmd/server/describe/describe.go index 4873e688c..85444e6ec 100644 --- a/internal/cmd/server/describe/describe.go +++ b/internal/cmd/server/describe/describe.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/list/list.go b/internal/cmd/server/list/list.go index 867a0e233..29eb51222 100644 --- a/internal/cmd/server/list/list.go +++ b/internal/cmd/server/list/list.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/server/log/log.go b/internal/cmd/server/log/log.go index 76e80cc67..11bbfe006 100644 --- a/internal/cmd/server/log/log.go +++ b/internal/cmd/server/log/log.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/machine-type/describe/describe.go b/internal/cmd/server/machine-type/describe/describe.go index 018bf0ad7..522d13bd3 100644 --- a/internal/cmd/server/machine-type/describe/describe.go +++ b/internal/cmd/server/machine-type/describe/describe.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go index 2e5a20bde..5ec90d0c4 100644 --- a/internal/cmd/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/server/network-interface/attach/attach.go b/internal/cmd/server/network-interface/attach/attach.go index 68e670159..6f2a64163 100644 --- a/internal/cmd/server/network-interface/attach/attach.go +++ b/internal/cmd/server/network-interface/attach/attach.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/network-interface/detach/detach.go b/internal/cmd/server/network-interface/detach/detach.go index 6a2517e50..58024dc3e 100644 --- a/internal/cmd/server/network-interface/detach/detach.go +++ b/internal/cmd/server/network-interface/detach/detach.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/network-interface/list/list.go b/internal/cmd/server/network-interface/list/list.go index 62d4f6c8b..c3d9769c3 100644 --- a/internal/cmd/server/network-interface/list/list.go +++ b/internal/cmd/server/network-interface/list/list.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index 0bb65907d..76d97cc01 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -13,7 +15,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -58,14 +59,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/os-update/describe/describe.go b/internal/cmd/server/os-update/describe/describe.go index e722e3994..3c8de58ee 100644 --- a/internal/cmd/server/os-update/describe/describe.go +++ b/internal/cmd/server/os-update/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go index 153754db3..510411798 100644 --- a/internal/cmd/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -47,14 +47,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go index ad0467bb5..e796767c6 100644 --- a/internal/cmd/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -48,14 +48,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go index ed7f183b7..4092be38a 100644 --- a/internal/cmd/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if len(updates) == 0 { serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index f64b10728..cae0f7377 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -67,14 +67,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/os-update/schedule/delete/delete.go b/internal/cmd/server/os-update/schedule/delete/delete.go index a439bf76a..0d2762d65 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete.go +++ b/internal/cmd/server/os-update/schedule/delete/delete.go @@ -47,7 +47,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/os-update/schedule/describe/describe.go b/internal/cmd/server/os-update/schedule/describe/describe.go index f66c9b5d2..89aaba7b0 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/server/os-update/schedule/describe/describe.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go index b14299303..3f8eeb6cb 100644 --- a/internal/cmd/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -5,6 +5,8 @@ import ( "encoding/json" "fmt" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -14,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/services/serverosupdate/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" @@ -55,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -70,7 +71,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if len(schedules) == 0 { serverLabel := model.ServerId // Get server name - if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer); err == nil { + if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) diff --git a/internal/cmd/server/os-update/schedule/update/update.go b/internal/cmd/server/os-update/schedule/update/update.go index bae09473e..3394ba5ba 100644 --- a/internal/cmd/server/os-update/schedule/update/update.go +++ b/internal/cmd/server/os-update/schedule/update/update.go @@ -64,7 +64,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/public-ip/attach/attach.go b/internal/cmd/server/public-ip/attach/attach.go index 8caecd342..843c030e7 100644 --- a/internal/cmd/server/public-ip/attach/attach.go +++ b/internal/cmd/server/public-ip/attach/attach.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/public-ip/detach/detach.go b/internal/cmd/server/public-ip/detach/detach.go index c8066db67..3c1aa6687 100644 --- a/internal/cmd/server/public-ip/detach/detach.go +++ b/internal/cmd/server/public-ip/detach/detach.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/reboot/reboot.go b/internal/cmd/server/reboot/reboot.go index 465adaaa1..dbdc10ef1 100644 --- a/internal/cmd/server/reboot/reboot.go +++ b/internal/cmd/server/reboot/reboot.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/rescue/rescue.go b/internal/cmd/server/rescue/rescue.go index 73aeae948..5c4efea4f 100644 --- a/internal/cmd/server/rescue/rescue.go +++ b/internal/cmd/server/rescue/rescue.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/resize/resize.go b/internal/cmd/server/resize/resize.go index 8d3f19b3e..57e6ebe1b 100644 --- a/internal/cmd/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index e4e29042c..89232fa88 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 6b79c6998..69bc5e4fe 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/service-account/list/list.go b/internal/cmd/server/service-account/list/list.go index 5c90714fd..19bfc8fa0 100644 --- a/internal/cmd/server/service-account/list/list.go +++ b/internal/cmd/server/service-account/list/list.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/start/start.go b/internal/cmd/server/start/start.go index 918bab2a3..5a6f9d02a 100644 --- a/internal/cmd/server/start/start.go +++ b/internal/cmd/server/start/start.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/stop/stop.go b/internal/cmd/server/stop/stop.go index ccb21bedc..aa510ef01 100644 --- a/internal/cmd/server/stop/stop.go +++ b/internal/cmd/server/stop/stop.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/unrescue/unrescue.go b/internal/cmd/server/unrescue/unrescue.go index 181ab88bc..44bf3ace1 100644 --- a/internal/cmd/server/unrescue/unrescue.go +++ b/internal/cmd/server/unrescue/unrescue.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/update/update.go b/internal/cmd/server/update/update.go index 2b8b35985..7d4c56241 100644 --- a/internal/cmd/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go index fee7c9097..e4c714531 100644 --- a/internal/cmd/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/volume/describe/describe.go b/internal/cmd/server/volume/describe/describe.go index 87ebac142..5b46ced73 100644 --- a/internal/cmd/server/volume/describe/describe.go +++ b/internal/cmd/server/volume/describe/describe.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/volume/detach/detach.go b/internal/cmd/server/volume/detach/detach.go index e557fc383..d794ddcf8 100644 --- a/internal/cmd/server/volume/detach/detach.go +++ b/internal/cmd/server/volume/detach/detach.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go index f3ac90101..93263daf2 100644 --- a/internal/cmd/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go index e4795996d..768643d36 100644 --- a/internal/cmd/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index fba36dfeb..c998de0f8 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -49,12 +49,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/service-account/delete/delete.go b/internal/cmd/service-account/delete/delete.go index 829d6ac4c..a92acdb4f 100644 --- a/internal/cmd/service-account/delete/delete.go +++ b/internal/cmd/service-account/delete/delete.go @@ -44,7 +44,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/get-jwks/get_jwks.go b/internal/cmd/service-account/get-jwks/get_jwks.go index 641cba592..441851bac 100644 --- a/internal/cmd/service-account/get-jwks/get_jwks.go +++ b/internal/cmd/service-account/get-jwks/get_jwks.go @@ -42,7 +42,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/key/create/create.go b/internal/cmd/service-account/key/create/create.go index 6d99a38fb..1b58d12b8 100644 --- a/internal/cmd/service-account/key/create/create.go +++ b/internal/cmd/service-account/key/create/create.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/key/delete/delete.go b/internal/cmd/service-account/key/delete/delete.go index ffd77b76a..e780ddd33 100644 --- a/internal/cmd/service-account/key/delete/delete.go +++ b/internal/cmd/service-account/key/delete/delete.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/key/describe/describe.go b/internal/cmd/service-account/key/describe/describe.go index 3b7c16ca4..ecf541f3f 100644 --- a/internal/cmd/service-account/key/describe/describe.go +++ b/internal/cmd/service-account/key/describe/describe.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index 194c66486..a39782f56 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/key/update/update.go b/internal/cmd/service-account/key/update/update.go index 9df30b2a9..62183d56f 100644 --- a/internal/cmd/service-account/key/update/update.go +++ b/internal/cmd/service-account/key/update/update.go @@ -67,7 +67,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index 063e4176a..121b5216d 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } serviceAccounts := *resp.Items if len(serviceAccounts) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index 83c249644..5b74fdae7 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index 5a51b0ab7..956b79908 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/service-account/token/revoke/revoke.go b/internal/cmd/service-account/token/revoke/revoke.go index 18dfe9fb1..0ac624a89 100644 --- a/internal/cmd/service-account/token/revoke/revoke.go +++ b/internal/cmd/service-account/token/revoke/revoke.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 5c017d90d..3f7f9a802 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -71,12 +71,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 @@ -91,7 +91,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure ServiceEnable API client - serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(params.Printer) + serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/cluster/delete/delete.go b/internal/cmd/ske/cluster/delete/delete.go index b78925dd5..8a6e5c9cc 100644 --- a/internal/cmd/ske/cluster/delete/delete.go +++ b/internal/cmd/ske/cluster/delete/delete.go @@ -46,7 +46,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 1b6d08dc8..703ce9b0f 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload.go b/internal/cmd/ske/cluster/generate-payload/generate_payload.go index b3a94f2ef..14400f175 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index a3cde587f..6674be931 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -58,13 +58,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } // Configure ServiceEnable API client - serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(params.Printer) + serviceEnablementApiClient, err := serviceEnablementClient.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -86,7 +86,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } clusters := *resp.Items if len(clusters) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index aea878064..8ce6568e9 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go index 69dd87211..4b9dfa1d6 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation.go b/internal/cmd/ske/credentials/start-rotation/start_rotation.go index 485e26a10..4e34c9ebe 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation.go @@ -66,7 +66,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index 06522d5fb..da717570e 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -42,7 +42,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index 12685a580..ea355ada1 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -43,12 +43,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index 7701c3bf5..91431b5e3 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -43,12 +43,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index e7a252456..c4565223c 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -84,7 +84,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/kubeconfig/login/login.go b/internal/cmd/ske/kubeconfig/login/login.go index ce748d242..058197418 100644 --- a/internal/cmd/ske/kubeconfig/login/login.go +++ b/internal/cmd/ske/kubeconfig/login/login.go @@ -75,7 +75,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index 6aed48591..0608e5a7d 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -66,7 +66,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index 06c7da8e8..258e0752a 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -78,12 +78,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go index e9730faf9..910e849b4 100644 --- a/internal/cmd/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/volume/describe/describe.go b/internal/cmd/volume/describe/describe.go index c8b787456..9d4c06538 100644 --- a/internal/cmd/volume/describe/describe.go +++ b/internal/cmd/volume/describe/describe.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/volume/list/list.go b/internal/cmd/volume/list/list.go index feffde80e..7534bb4a3 100644 --- a/internal/cmd/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -64,7 +64,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -77,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/volume/performance-class/describe/describe.go b/internal/cmd/volume/performance-class/describe/describe.go index 3105e4fcc..dc7b25ad5 100644 --- a/internal/cmd/volume/performance-class/describe/describe.go +++ b/internal/cmd/volume/performance-class/describe/describe.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/volume/performance-class/list/list.go b/internal/cmd/volume/performance-class/list/list.go index b48f399f6..a6490e75e 100644 --- a/internal/cmd/volume/performance-class/list/list.go +++ b/internal/cmd/volume/performance-class/list/list.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - projectLabel, err := projectname.GetProjectName(ctx, params.Printer, cmd) + 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 diff --git a/internal/cmd/volume/resize/resize.go b/internal/cmd/volume/resize/resize.go index afef2a7a3..f86f10546 100644 --- a/internal/cmd/volume/resize/resize.go +++ b/internal/cmd/volume/resize/resize.go @@ -51,7 +51,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/volume/update/update.go b/internal/cmd/volume/update/update.go index 0c57f6185..80e137987 100644 --- a/internal/cmd/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/pkg/projectname/project_name.go b/internal/pkg/projectname/project_name.go index b50239b9f..84381a8c6 100644 --- a/internal/pkg/projectname/project_name.go +++ b/internal/pkg/projectname/project_name.go @@ -19,7 +19,7 @@ import ( // Returns the project name associated to the project ID set in config // // Uses the one stored in config if it's valid, otherwise gets it from the API -func GetProjectName(ctx context.Context, p *print.Printer, cmd *cobra.Command) (string, error) { +func GetProjectName(ctx context.Context, p *print.Printer, cliVersion string, cmd *cobra.Command) (string, error) { // If we can use the project name from config, return it if useProjectNameFromConfig(p, cmd) { return viper.GetString(config.ProjectNameKey), nil @@ -30,7 +30,7 @@ func GetProjectName(ctx context.Context, p *print.Printer, cmd *cobra.Command) ( return "", fmt.Errorf("found empty project ID and name") } - apiClient, err := client.ConfigureClient(p) + apiClient, err := client.ConfigureClient(p, cliVersion) if err != nil { return "", fmt.Errorf("configure resource manager client: %w", err) } diff --git a/internal/pkg/projectname/project_name_test.go b/internal/pkg/projectname/project_name_test.go index 25239c8f4..ae6d79251 100644 --- a/internal/pkg/projectname/project_name_test.go +++ b/internal/pkg/projectname/project_name_test.go @@ -42,7 +42,7 @@ func TestGetProjectName(t *testing.T) { p := print.NewPrinter() cmd := &cobra.Command{} - projectName, err := GetProjectName(context.Background(), p, cmd) + projectName, err := GetProjectName(context.Background(), p, "0.0.0-dummy", cmd) if err != nil { if tt.isValid { t.Fatalf("unexpected error: %v", err) diff --git a/internal/pkg/services/alb/client/client.go b/internal/pkg/services/alb/client/client.go index c29f9eddb..866a76ad5 100644 --- a/internal/pkg/services/alb/client/client.go +++ b/internal/pkg/services/alb/client/client.go @@ -5,29 +5,27 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) -func ConfigureClient(p *print.Printer) (*alb.APIClient, error) { - var err error - var apiClient *alb.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*alb.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.IaaSCustomEndpointKey) if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } else { - cfgOptions = append(cfgOptions, authCfgOption) } if p.IsVerbosityDebug() { @@ -36,7 +34,7 @@ func ConfigureClient(p *print.Printer) (*alb.APIClient, error) { ) } - apiClient, err = alb.NewAPIClient(cfgOptions...) + apiClient, err := alb.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/authorization/client/client.go b/internal/pkg/services/authorization/client/client.go index 19c13d663..7deb26b12 100644 --- a/internal/pkg/services/authorization/client/client.go +++ b/internal/pkg/services/authorization/client/client.go @@ -5,23 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) -func ConfigureClient(p *print.Printer) (*authorization.APIClient, error) { - var err error - var apiClient *authorization.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*authorization.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.AuthorizationCustomEndpointKey) @@ -35,7 +35,7 @@ func ConfigureClient(p *print.Printer) (*authorization.APIClient, error) { ) } - apiClient, err = authorization.NewAPIClient(cfgOptions...) + apiClient, err := authorization.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/dns/client/client.go b/internal/pkg/services/dns/client/client.go index 384bc2cca..15b824da3 100644 --- a/internal/pkg/services/dns/client/client.go +++ b/internal/pkg/services/dns/client/client.go @@ -1,6 +1,8 @@ package client import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -11,17 +13,16 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -func ConfigureClient(p *print.Printer) (*dns.APIClient, error) { - var err error - var apiClient *dns.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*dns.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.DNSCustomEndpointKey) @@ -35,7 +36,7 @@ func ConfigureClient(p *print.Printer) (*dns.APIClient, error) { ) } - apiClient, err = dns.NewAPIClient(cfgOptions...) + apiClient, err := dns.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/iaas/client/client.go b/internal/pkg/services/iaas/client/client.go index 4f37168e7..e32d15b4c 100644 --- a/internal/pkg/services/iaas/client/client.go +++ b/internal/pkg/services/iaas/client/client.go @@ -5,23 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -func ConfigureClient(p *print.Printer) (*iaas.APIClient, error) { - var err error - var apiClient *iaas.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*iaas.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.IaaSCustomEndpointKey) if customEndpoint != "" { @@ -37,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*iaas.APIClient, error) { ) } - apiClient, err = iaas.NewAPIClient(cfgOptions...) + apiClient, err := iaas.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/load-balancer/client/client.go b/internal/pkg/services/load-balancer/client/client.go index 94d0b0a17..402498c70 100644 --- a/internal/pkg/services/load-balancer/client/client.go +++ b/internal/pkg/services/load-balancer/client/client.go @@ -5,29 +5,27 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) -func ConfigureClient(p *print.Printer) (*loadbalancer.APIClient, error) { - var err error - var apiClient *loadbalancer.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*loadbalancer.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.LoadBalancerCustomEndpointKey) if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } else { - cfgOptions = append(cfgOptions, authCfgOption) } if p.IsVerbosityDebug() { @@ -36,7 +34,7 @@ func ConfigureClient(p *print.Printer) (*loadbalancer.APIClient, error) { ) } - apiClient, err = loadbalancer.NewAPIClient(cfgOptions...) + apiClient, err := loadbalancer.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/logme/client/client.go b/internal/pkg/services/logme/client/client.go index fb3ba17a0..71a750c7f 100644 --- a/internal/pkg/services/logme/client/client.go +++ b/internal/pkg/services/logme/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/logme" ) -func ConfigureClient(p *print.Printer) (*logme.APIClient, error) { - var err error - var apiClient *logme.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*logme.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.LogMeCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*logme.APIClient, error) { ) } - apiClient, err = logme.NewAPIClient(cfgOptions...) + apiClient, err := logme.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/mariadb/client/client.go b/internal/pkg/services/mariadb/client/client.go index d21e32f03..7a7fb9f78 100644 --- a/internal/pkg/services/mariadb/client/client.go +++ b/internal/pkg/services/mariadb/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) -func ConfigureClient(p *print.Printer) (*mariadb.APIClient, error) { - var err error - var apiClient *mariadb.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*mariadb.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.MariaDBCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*mariadb.APIClient, error) { ) } - apiClient, err = mariadb.NewAPIClient(cfgOptions...) + apiClient, err := mariadb.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/mongodbflex/client/client.go b/internal/pkg/services/mongodbflex/client/client.go index 65f9ec696..b69cc40bf 100644 --- a/internal/pkg/services/mongodbflex/client/client.go +++ b/internal/pkg/services/mongodbflex/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -func ConfigureClient(p *print.Printer) (*mongodbflex.APIClient, error) { - var err error - var apiClient *mongodbflex.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*mongodbflex.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.MongoDBFlexCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*mongodbflex.APIClient, error) { ) } - apiClient, err = mongodbflex.NewAPIClient(cfgOptions...) + apiClient, err := mongodbflex.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/object-storage/client/client.go b/internal/pkg/services/object-storage/client/client.go index 13ca5c470..5eab52238 100644 --- a/internal/pkg/services/object-storage/client/client.go +++ b/internal/pkg/services/object-storage/client/client.go @@ -5,24 +5,26 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -func ConfigureClient(p *print.Printer) (*objectstorage.APIClient, error) { - var err error - var apiClient *objectstorage.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*objectstorage.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.ObjectStorageCustomEndpointKey) @@ -36,7 +38,7 @@ func ConfigureClient(p *print.Printer) (*objectstorage.APIClient, error) { ) } - apiClient, err = objectstorage.NewAPIClient(cfgOptions...) + apiClient, err := objectstorage.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/observability/client/client.go b/internal/pkg/services/observability/client/client.go index e629915d3..23698b5ff 100644 --- a/internal/pkg/services/observability/client/client.go +++ b/internal/pkg/services/observability/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/observability" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" ) -func ConfigureClient(p *print.Printer) (*observability.APIClient, error) { - var err error - var apiClient *observability.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*observability.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.ObservabilityCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*observability.APIClient, error) { ) } - apiClient, err = observability.NewAPIClient(cfgOptions...) + apiClient, err := observability.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/opensearch/client/client.go b/internal/pkg/services/opensearch/client/client.go index ce7a8f188..b1948a389 100644 --- a/internal/pkg/services/opensearch/client/client.go +++ b/internal/pkg/services/opensearch/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -func ConfigureClient(p *print.Printer) (*opensearch.APIClient, error) { - var err error - var apiClient *opensearch.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*opensearch.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.OpenSearchCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*opensearch.APIClient, error) { ) } - apiClient, err = opensearch.NewAPIClient(cfgOptions...) + apiClient, err := opensearch.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/postgresflex/client/client.go b/internal/pkg/services/postgresflex/client/client.go index d40584a4f..ad125cd0c 100644 --- a/internal/pkg/services/postgresflex/client/client.go +++ b/internal/pkg/services/postgresflex/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) -func ConfigureClient(p *print.Printer) (*postgresflex.APIClient, error) { - var err error - var apiClient *postgresflex.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*postgresflex.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.PostgresFlexCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*postgresflex.APIClient, error) { ) } - apiClient, err = postgresflex.NewAPIClient(cfgOptions...) + apiClient, err := postgresflex.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/rabbitmq/client/client.go b/internal/pkg/services/rabbitmq/client/client.go index a4a7778ac..90c4df9fa 100644 --- a/internal/pkg/services/rabbitmq/client/client.go +++ b/internal/pkg/services/rabbitmq/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -func ConfigureClient(p *print.Printer) (*rabbitmq.APIClient, error) { - var err error - var apiClient *rabbitmq.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*rabbitmq.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.RabbitMQCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*rabbitmq.APIClient, error) { ) } - apiClient, err = rabbitmq.NewAPIClient(cfgOptions...) + apiClient, err := rabbitmq.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/redis/client/client.go b/internal/pkg/services/redis/client/client.go index 039da32f7..1966b0ad2 100644 --- a/internal/pkg/services/redis/client/client.go +++ b/internal/pkg/services/redis/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) -func ConfigureClient(p *print.Printer) (*redis.APIClient, error) { - var err error - var apiClient *redis.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*redis.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.RedisCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*redis.APIClient, error) { ) } - apiClient, err = redis.NewAPIClient(cfgOptions...) + apiClient, err := redis.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/resourcemanager/client/client.go b/internal/pkg/services/resourcemanager/client/client.go index ce1ae5620..5cca3a34b 100644 --- a/internal/pkg/services/resourcemanager/client/client.go +++ b/internal/pkg/services/resourcemanager/client/client.go @@ -5,23 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" ) -func ConfigureClient(p *print.Printer) (*resourcemanager.APIClient, error) { - var err error - var apiClient *resourcemanager.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*resourcemanager.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.ResourceManagerEndpointKey) @@ -35,7 +35,7 @@ func ConfigureClient(p *print.Printer) (*resourcemanager.APIClient, error) { ) } - apiClient, err = resourcemanager.NewAPIClient(cfgOptions...) + apiClient, err := resourcemanager.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/runcommand/client/client.go b/internal/pkg/services/runcommand/client/client.go index 254978f4d..86f6d3d5d 100644 --- a/internal/pkg/services/runcommand/client/client.go +++ b/internal/pkg/services/runcommand/client/client.go @@ -5,23 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) -func ConfigureClient(p *print.Printer) (*runcommand.APIClient, error) { - var err error - var apiClient *runcommand.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*runcommand.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.RunCommandCustomEndpointKey) if customEndpoint != "" { @@ -36,7 +36,7 @@ func ConfigureClient(p *print.Printer) (*runcommand.APIClient, error) { ) } - apiClient, err = runcommand.NewAPIClient(cfgOptions...) + apiClient, err := runcommand.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/secrets-manager/client/client.go b/internal/pkg/services/secrets-manager/client/client.go index ad1d8136f..3ef6e1402 100644 --- a/internal/pkg/services/secrets-manager/client/client.go +++ b/internal/pkg/services/secrets-manager/client/client.go @@ -5,24 +5,25 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/secretsmanager" ) -func ConfigureClient(p *print.Printer) (*secretsmanager.APIClient, error) { - var err error - var apiClient *secretsmanager.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*secretsmanager.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + sdkConfig.WithRegion(region), + authCfgOption, + } customEndpoint := viper.GetString(config.SecretsManagerCustomEndpointKey) @@ -36,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*secretsmanager.APIClient, error) { ) } - apiClient, err = secretsmanager.NewAPIClient(cfgOptions...) + apiClient, err := secretsmanager.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/serverbackup/client/client.go b/internal/pkg/services/serverbackup/client/client.go index 589166e13..1184ce684 100644 --- a/internal/pkg/services/serverbackup/client/client.go +++ b/internal/pkg/services/serverbackup/client/client.go @@ -5,23 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) -func ConfigureClient(p *print.Printer) (*serverbackup.APIClient, error) { - var err error - var apiClient *serverbackup.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*serverbackup.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.ServerBackupCustomEndpointKey) if customEndpoint != "" { @@ -37,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*serverbackup.APIClient, error) { ) } - apiClient, err = serverbackup.NewAPIClient(cfgOptions...) + apiClient, err := serverbackup.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/serverosupdate/client/client.go b/internal/pkg/services/serverosupdate/client/client.go index 1f1f2033e..ec39a5477 100644 --- a/internal/pkg/services/serverosupdate/client/client.go +++ b/internal/pkg/services/serverosupdate/client/client.go @@ -5,22 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) -func ConfigureClient(p *print.Printer) (*serverupdate.APIClient, error) { - var apiClient *serverupdate.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*serverupdate.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.ServerOsUpdateCustomEndpointKey) if customEndpoint != "" { @@ -35,7 +36,7 @@ func ConfigureClient(p *print.Printer) (*serverupdate.APIClient, error) { ) } - apiClient, err = serverupdate.NewAPIClient(cfgOptions...) + apiClient, err := serverupdate.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/service-account/client/client.go b/internal/pkg/services/service-account/client/client.go index b4ba6919d..cb35d2c4d 100644 --- a/internal/pkg/services/service-account/client/client.go +++ b/internal/pkg/services/service-account/client/client.go @@ -5,23 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" ) -func ConfigureClient(p *print.Printer) (*serviceaccount.APIClient, error) { - var err error - var apiClient *serviceaccount.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*serviceaccount.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.ServiceAccountCustomEndpointKey) @@ -35,7 +35,7 @@ func ConfigureClient(p *print.Printer) (*serviceaccount.APIClient, error) { ) } - apiClient, err = serviceaccount.NewAPIClient(cfgOptions...) + apiClient, err := serviceaccount.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/service-enablement/client/client.go b/internal/pkg/services/service-enablement/client/client.go index 8fad8c06b..66b952376 100644 --- a/internal/pkg/services/service-enablement/client/client.go +++ b/internal/pkg/services/service-enablement/client/client.go @@ -6,22 +6,22 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" ) -func ConfigureClient(p *print.Printer) (*serviceenablement.APIClient, error) { - var err error - var apiClient *serviceenablement.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*serviceenablement.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.ServiceEnablementCustomEndpointKey) if customEndpoint != "" { @@ -37,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*serviceenablement.APIClient, error) { ) } - apiClient, err = serviceenablement.NewAPIClient(cfgOptions...) + apiClient, err := serviceenablement.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/ske/client/client.go b/internal/pkg/services/ske/client/client.go index 788fcb4c3..a361f73d2 100644 --- a/internal/pkg/services/ske/client/client.go +++ b/internal/pkg/services/ske/client/client.go @@ -5,23 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) -func ConfigureClient(p *print.Printer) (*ske.APIClient, error) { - var err error - var apiClient *ske.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*ske.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.SKECustomEndpointKey) if customEndpoint != "" { @@ -37,7 +37,7 @@ func ConfigureClient(p *print.Printer) (*ske.APIClient, error) { ) } - apiClient, err = ske.NewAPIClient(cfgOptions...) + apiClient, err := ske.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/services/sqlserverflex/client/client.go b/internal/pkg/services/sqlserverflex/client/client.go index 2767ae937..30e937f59 100644 --- a/internal/pkg/services/sqlserverflex/client/client.go +++ b/internal/pkg/services/sqlserverflex/client/client.go @@ -5,23 +5,23 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) -func ConfigureClient(p *print.Printer) (*sqlserverflex.APIClient, error) { - var err error - var apiClient *sqlserverflex.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - +func ConfigureClient(p *print.Printer, cliVersion string) (*sqlserverflex.APIClient, error) { authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) if err != nil { p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - cfgOptions = append(cfgOptions, authCfgOption) + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } customEndpoint := viper.GetString(config.SQLServerFlexCustomEndpointKey) @@ -35,7 +35,7 @@ func ConfigureClient(p *print.Printer) (*sqlserverflex.APIClient, error) { ) } - apiClient, err = sqlserverflex.NewAPIClient(cfgOptions...) + apiClient, err := sqlserverflex.NewAPIClient(cfgOptions...) if err != nil { p.Debug(print.ErrorLevel, "create new API client: %v", err) return nil, &errors.AuthError{} diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index 5649155cd..7aff6e713 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -12,6 +12,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/config" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" ) // Ptr Returns the pointer to any type T @@ -124,3 +125,7 @@ func Base64Encode(message []byte) string { base64.StdEncoding.Encode(b, message) return string(b) } + +func UserAgentConfigOption(cliVersion string) sdkConfig.ConfigurationOption { + return sdkConfig.WithUserAgent(fmt.Sprintf("stackit-cli/%s", cliVersion)) +} diff --git a/internal/pkg/utils/utils_test.go b/internal/pkg/utils/utils_test.go index 6ef165d9b..894f4f2e2 100644 --- a/internal/pkg/utils/utils_test.go +++ b/internal/pkg/utils/utils_test.go @@ -1,8 +1,11 @@ package utils import ( + "reflect" "testing" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/config" ) @@ -108,3 +111,41 @@ func TestValidateURLDomain(t *testing.T) { }) } } + +func TestUserAgentConfigOption(t *testing.T) { + type args struct { + providerVersion string + } + tests := []struct { + name string + args args + want sdkConfig.ConfigurationOption + }{ + { + name: "TestUserAgentConfigOption", + args: args{ + providerVersion: "1.0.0", + }, + want: sdkConfig.WithUserAgent("stackit-cli/1.0.0"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + clientConfigActual := sdkConfig.Configuration{} + err := tt.want(&clientConfigActual) + if err != nil { + t.Errorf("error configuring client: %v", err) + } + + clientConfigExpected := sdkConfig.Configuration{} + err = UserAgentConfigOption(tt.args.providerVersion)(&clientConfigExpected) + if err != nil { + t.Errorf("error configuring client: %v", err) + } + + if !reflect.DeepEqual(clientConfigActual, clientConfigExpected) { + t.Errorf("UserAgentConfigOption() = %v, want %v", clientConfigActual, clientConfigExpected) + } + }) + } +} From 1bb3c3379e956a76e7b167044107301263b8e227 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 13 May 2025 11:39:11 +0200 Subject: [PATCH 298/619] chore(deps): update renovatebot/github-action action to v42.0.2 (#743) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 952f88e2f..92e3fbd8c 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v42.0.1 + uses: renovatebot/github-action@v42.0.2 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 09684be711d6e62513fdc50647b59742a5ec3b0f Mon Sep 17 00:00:00 2001 From: Pere Manent Date: Tue, 13 May 2025 13:10:45 +0200 Subject: [PATCH 299/619] Add stackit git commands: list, describe, create and delete. (#725) * Add stackit git commands: list, describe, create and delete. * Add stackit git list instances command * Add stackit git list instances command * Git. Move list package and add describe command * Stackit Git create instance command * Add delete command to the stackit git cli * Stop using new variables for the globalflags.ProjectIdFlag and Docs generation * Stop using new variables for the globalflags.ProjectIdFlag and minor issues * Add docs of the stackit git instance command * Stackit git: add vertical table on describe and limit list command * Delete toolchain opetion from go.mod file * Get go.mod and go.sum from main --- docs/stackit.md | 1 + docs/stackit_git.md | 37 +++ docs/stackit_git_create.md | 41 +++ docs/stackit_git_delete.md | 40 +++ docs/stackit_git_describe.md | 40 +++ docs/stackit_git_list.md | 44 +++ go.mod | 1 + go.sum | 2 + internal/cmd/git/create/create.go | 167 ++++++++++++ internal/cmd/git/create/create_test.go | 257 ++++++++++++++++++ internal/cmd/git/delete/delete.go | 132 +++++++++ internal/cmd/git/delete/delete_test.go | 182 +++++++++++++ internal/cmd/git/describe/describe.go | 152 +++++++++++ internal/cmd/git/describe/describe_test.go | 226 +++++++++++++++ internal/cmd/git/git.go | 34 +++ internal/cmd/git/list/list.go | 163 +++++++++++ internal/cmd/git/list/list_test.go | 237 ++++++++++++++++ internal/cmd/root.go | 2 + internal/pkg/config/config.go | 3 + internal/pkg/services/git/client/client.go | 45 +++ internal/pkg/services/git/utils/utils.go | 23 ++ internal/pkg/services/git/utils/utils_test.go | 66 +++++ 22 files changed, 1895 insertions(+) create mode 100644 docs/stackit_git.md create mode 100644 docs/stackit_git_create.md create mode 100644 docs/stackit_git_delete.md create mode 100644 docs/stackit_git_describe.md create mode 100644 docs/stackit_git_list.md create mode 100644 internal/cmd/git/create/create.go create mode 100644 internal/cmd/git/create/create_test.go create mode 100644 internal/cmd/git/delete/delete.go create mode 100644 internal/cmd/git/delete/delete_test.go create mode 100644 internal/cmd/git/describe/describe.go create mode 100644 internal/cmd/git/describe/describe_test.go create mode 100644 internal/cmd/git/git.go create mode 100644 internal/cmd/git/list/list.go create mode 100644 internal/cmd/git/list/list_test.go create mode 100644 internal/pkg/services/git/client/client.go create mode 100644 internal/pkg/services/git/utils/utils.go create mode 100644 internal/pkg/services/git/utils/utils_test.go diff --git a/docs/stackit.md b/docs/stackit.md index 2dc456b83..3cc35f2f9 100644 --- a/docs/stackit.md +++ b/docs/stackit.md @@ -33,6 +33,7 @@ stackit [flags] * [stackit config](./stackit_config.md) - Provides functionality for CLI configuration options * [stackit curl](./stackit_curl.md) - Executes an authenticated HTTP request to an endpoint * [stackit dns](./stackit_dns.md) - Provides functionality for DNS +* [stackit git](./stackit_git.md) - Provides functionality for STACKIT Git * [stackit image](./stackit_image.md) - Manage server images * [stackit key-pair](./stackit_key-pair.md) - Provides functionality for SSH key pairs * [stackit load-balancer](./stackit_load-balancer.md) - Provides functionality for Load Balancer diff --git a/docs/stackit_git.md b/docs/stackit_git.md new file mode 100644 index 000000000..8a959c7d2 --- /dev/null +++ b/docs/stackit_git.md @@ -0,0 +1,37 @@ +## stackit git + +Provides functionality for STACKIT Git + +### Synopsis + +Provides functionality for STACKIT Git. + +``` +stackit git [flags] +``` + +### Options + +``` + -h, --help Help for "stackit git" +``` + +### 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](./stackit.md) - Manage STACKIT resources using the command line +* [stackit git create](./stackit_git_create.md) - Creates STACKIT Git instance +* [stackit git delete](./stackit_git_delete.md) - Deletes STACKIT Git instance +* [stackit git describe](./stackit_git_describe.md) - Describes STACKIT Git instance +* [stackit git list](./stackit_git_list.md) - Lists all instances of STACKIT Git. + diff --git a/docs/stackit_git_create.md b/docs/stackit_git_create.md new file mode 100644 index 000000000..fa7a2a97d --- /dev/null +++ b/docs/stackit_git_create.md @@ -0,0 +1,41 @@ +## stackit git create + +Creates STACKIT Git instance + +### Synopsis + +Create a STACKIT Git instance by name. + +``` +stackit git create [flags] +``` + +### Examples + +``` + Create a instance with name 'my-new-instance' + $ stackit git create --name my-new-instance +``` + +### Options + +``` + -h, --help Help for "stackit git create" + --name string The name of the instance. +``` + +### 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 git](./stackit_git.md) - Provides functionality for STACKIT Git + diff --git a/docs/stackit_git_delete.md b/docs/stackit_git_delete.md new file mode 100644 index 000000000..6f863ee60 --- /dev/null +++ b/docs/stackit_git_delete.md @@ -0,0 +1,40 @@ +## stackit git delete + +Deletes STACKIT Git instance + +### Synopsis + +Deletes a STACKIT Git instance by its internal ID. + +``` +stackit git delete INSTANCE_ID [flags] +``` + +### Examples + +``` + Delete a instance with ID "xxx" + $ stackit git delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit git delete" +``` + +### 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 git](./stackit_git.md) - Provides functionality for STACKIT Git + diff --git a/docs/stackit_git_describe.md b/docs/stackit_git_describe.md new file mode 100644 index 000000000..e2aedcc40 --- /dev/null +++ b/docs/stackit_git_describe.md @@ -0,0 +1,40 @@ +## stackit git describe + +Describes STACKIT Git instance + +### Synopsis + +Describes a STACKIT Git instance by its internal ID. + +``` +stackit git describe INSTANCE_ID [flags] +``` + +### Examples + +``` + Describe instance "xxx" + $ stackit git describe xxx +``` + +### Options + +``` + -h, --help Help for "stackit git 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 git](./stackit_git.md) - Provides functionality for STACKIT Git + diff --git a/docs/stackit_git_list.md b/docs/stackit_git_list.md new file mode 100644 index 000000000..c0f65927b --- /dev/null +++ b/docs/stackit_git_list.md @@ -0,0 +1,44 @@ +## stackit git list + +Lists all instances of STACKIT Git. + +### Synopsis + +Lists all instances of STACKIT Git for the current project. + +``` +stackit git list [flags] +``` + +### Examples + +``` + List all STACKIT Git instances + $ stackit git instance list + + Lists up to 10 STACKIT Git instances + $ stackit git instance list --limit=10 +``` + +### Options + +``` + -h, --help Help for "stackit git list" + --limit int Limit the output to the first n elements +``` + +### 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 git](./stackit_git.md) - Provides functionality for STACKIT Git + diff --git a/go.mod b/go.mod index d4fa80e97..5e4de09de 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.3 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3 + github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.1 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2 diff --git a/go.sum b/go.sum index 8735251de..d16afaad1 100644 --- a/go.sum +++ b/go.sum @@ -570,6 +570,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 h1:aXVMNdiH github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3 h1:WJnA6YTOlBxMJf9PRuxkXduxj+fyWi+wOks69PvN1qI= github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= +github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 h1:/NXxiJf/NFpj+DFXc07vsx+0he/xufdhIskXUlSeyyw= +github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 h1:zh6e2eHgqex++fr6N0RK7wMMBGesC3QhBd42FdTq2Z8= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3 h1:StQg5p4h1aLFwIHQWWe5l44aFue+ZvQMGDbypP1DMYw= diff --git a/internal/cmd/git/create/create.go b/internal/cmd/git/create/create.go new file mode 100644 index 000000000..6df750b37 --- /dev/null +++ b/internal/cmd/git/create/create.go @@ -0,0 +1,167 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/git/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" + "github.com/stackitcloud/stackit-sdk-go/services/git/wait" +) + +const ( + nameFlag = "name" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Id *string + Name string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates STACKIT Git instance", + Long: "Create a STACKIT Git instance by name.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a instance with name 'my-new-instance'`, + `$ stackit git create --name my-new-instance`, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) (err error) { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create the instance %q?", model.Name) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + result, err := request.Execute() + if err != nil { + return fmt.Errorf("create stackit git instance: %w", err) + } + model.Id = result.Id + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Creating stackit git instance") + _, err = wait.CreateGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, *model.Id).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for stackit git Instance creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model, result) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "The name of the instance.") + if err := flags.MarkFlagsRequired(cmd, nameFlag); err != nil { + cobra.CheckErr(err) + } +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + name := flags.FlagToStringValue(p, cmd, nameFlag) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: name, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClient) git.ApiCreateInstanceRequest { + return apiClient.CreateInstance(ctx, model.ProjectId).CreateInstancePayload(createPayload(model)) +} + +func createPayload(model *inputModel) git.CreateInstancePayload { + return git.CreateInstancePayload{ + Name: &model.Name, + } +} + +func outputResult(p *print.Printer, model *inputModel, resp *git.Instance) error { + if model == nil { + return fmt.Errorf("input model is nil") + } + var outputFormat string + if model.GlobalFlagModel != nil { + outputFormat = model.OutputFormat + } + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal instance: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal iminstanceage: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + p.Outputf("Created instance %q with id %s\n", model.Name, utils.PtrString(model.Id)) + return nil + } +} diff --git a/internal/cmd/git/create/create_test.go b/internal/cmd/git/create/create_test.go new file mode 100644 index 000000000..33ed0cc7e --- /dev/null +++ b/internal/cmd/git/create/create_test.go @@ -0,0 +1,257 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &git.APIClient{} + testProjectId = uuid.NewString() + + testName = "test-instance" +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + + nameFlag: testName, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + Name: testName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureCreatePayload(mods ...func(payload *git.CreateInstancePayload)) (payload git.CreateInstancePayload) { + payload = git.CreateInstancePayload{ + Name: &testName, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *git.ApiCreateInstanceRequest)) git.ApiCreateInstanceRequest { + request := testClient.CreateInstance(testCtx, testProjectId) + + request = request.CreateInstancePayload(fixtureCreatePayload()) + + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "name missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateFlagGroups(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flag groups: %v", err) + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest git.ApiCreateInstanceRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "name flag", + model: fixtureInputModel(func(model *inputModel) { + model.Name = "new-name" + }), + expectedRequest: fixtureRequest(func(request *git.ApiCreateInstanceRequest) { + *request = request.CreateInstancePayload(fixtureCreatePayload(func(payload *git.CreateInstancePayload) { + payload.Name = utils.Ptr("new-name") + })) + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(git.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + resp *git.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "nil", + args: args{ + model: nil, + resp: nil, + }, + wantErr: true, + }, + { + name: "empty input", + args: args{ + model: &inputModel{}, + resp: &git.Instance{}, + }, + wantErr: false, + }, + { + name: "output json", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + OutputFormat: print.JSONOutputFormat, + }, + }, + resp: nil, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/git/delete/delete.go b/internal/cmd/git/delete/delete.go new file mode 100644 index 000000000..67ae11438 --- /dev/null +++ b/internal/cmd/git/delete/delete.go @@ -0,0 +1,132 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/git/client" + gitUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/git/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" + "github.com/stackitcloud/stackit-sdk-go/services/git/wait" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + InstanceId string +} + +const instanceIdArg = "INSTANCE_ID" + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", instanceIdArg), + Short: "Deletes STACKIT Git instance", + Long: "Deletes a STACKIT Git instance by its internal ID.", + Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample(`Delete a instance with ID "xxx"`, `$ stackit git delete xxx`), + ), + 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) + if err != nil { + return err + } + + projectName, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) + projectName = model.ProjectId + } + + instanceName, err := gitUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get stackit git intance name: %v", err) + instanceName = model.InstanceId + } else if instanceName == "" { + instanceName = model.InstanceId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete the stackit git instance %q for %q?", instanceName, projectName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + err = request.Execute() + if err != nil { + return fmt.Errorf("delete instance: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for stackit git instance deletion: %w", err) + } + s.Stop() + } + + operationState := "Deleted" + if model.Async { + operationState = "Triggered deletion of" + } + params.Printer.Info("%s stackit git instance %s \n", operationState, model.InstanceId) + + return nil + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + InstanceId: cliArgs[0], + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClient) git.ApiDeleteInstanceRequest { + return apiClient.DeleteInstance(ctx, model.ProjectId, model.InstanceId) +} diff --git a/internal/cmd/git/delete/delete_test.go b/internal/cmd/git/delete/delete_test.go new file mode 100644 index 000000000..8c90a4f1d --- /dev/null +++ b/internal/cmd/git/delete/delete_test.go @@ -0,0 +1,182 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &git.APIClient{} + testProjectId = uuid.NewString() + testInstanceId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + InstanceId: testInstanceId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *git.ApiDeleteInstanceRequest)) git.ApiDeleteInstanceRequest { + request := testClient.DeleteInstance(testCtx, testProjectId, testInstanceId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + args []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + args: []string{testInstanceId}, + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + 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, + }, + { + description: "no arguments", + flagValues: fixtureFlagValues(), + args: nil, + isValid: false, + }, + { + description: "multiple arguments", + flagValues: fixtureFlagValues(), + args: []string{"foo", "bar"}, + isValid: false, + }, + { + description: "invalid instance id", + flagValues: fixtureFlagValues(), + args: []string{"foo"}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + cmd.SetArgs(tt.args) + + 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) + } + } + + if err := cmd.ValidateArgs(tt.args); err != nil { + if !tt.isValid { + return + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd, tt.args) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest git.ApiDeleteInstanceRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/git/describe/describe.go b/internal/cmd/git/describe/describe.go new file mode 100644 index 000000000..8e2f266e1 --- /dev/null +++ b/internal/cmd/git/describe/describe.go @@ -0,0 +1,152 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/git/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + InstanceId string +} + +const instanceIdArg = "INSTANCE_ID" + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", instanceIdArg), + Short: "Describes STACKIT Git instance", + Long: "Describes a STACKIT Git instance by its internal ID.", + Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample(`Describe instance "xxx"`, `$ stackit git describe xxx`), + ), + 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) + if err != nil { + return err + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + instance, err := request.Execute() + if err != nil { + return fmt.Errorf("get instance: %w", err) + } + + if err := outputResult(params.Printer, model.OutputFormat, instance); err != nil { + return err + } + + return nil + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + InstanceId: cliArgs[0], + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClient) git.ApiGetInstanceRequest { + return apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId) +} + +func outputResult(p *print.Printer, outputFormat string, resp *git.Instance) error { + if resp == nil { + return fmt.Errorf("instance not found") + } + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal instance: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal instance: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + if id := resp.Id; id != nil { + table.AddRow("ID", *id) + table.AddSeparator() + } + if name := resp.Name; name != nil { + table.AddRow("NAME", *name) + table.AddSeparator() + } + if url := resp.Url; url != nil { + table.AddRow("URL", *url) + table.AddSeparator() + } + if version := resp.Version; version != nil { + table.AddRow("VERSION", *version) + table.AddSeparator() + } + if state := resp.State; state != nil { + table.AddRow("STATE", *state) + table.AddSeparator() + } + if created := resp.Created; created != nil { + table.AddRow("CREATED", *created) + table.AddSeparator() + } + + if err := table.Display(p); err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/git/describe/describe_test.go b/internal/cmd/git/describe/describe_test.go new file mode 100644 index 000000000..17cd8dae8 --- /dev/null +++ b/internal/cmd/git/describe/describe_test.go @@ -0,0 +1,226 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &git.APIClient{} + testProjectId = uuid.NewString() + testInstanceId = []string{uuid.NewString()} +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + InstanceId: testInstanceId[0], + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *git.ApiGetInstanceRequest)) git.ApiGetInstanceRequest { + request := testClient.GetInstance(testCtx, testProjectId, testInstanceId[0]) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + flagValues map[string]string + isValid bool + args []string + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + args: testInstanceId, + isValid: true, + }, + { + description: "no values", + flagValues: map[string]string{}, + args: testInstanceId, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + args: testInstanceId, + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + args: testInstanceId, + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + args: testInstanceId, + isValid: false, + }, + { + description: "no instance id passed", + flagValues: fixtureFlagValues(), + args: nil, + isValid: false, + }, + { + description: "multiple instance ids passed", + flagValues: fixtureFlagValues(), + args: []string{uuid.NewString(), uuid.NewString()}, + isValid: false, + }, + { + description: "invalid instance id passed", + flagValues: fixtureFlagValues(), + args: []string{"foobar"}, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Errorf("cannot 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) + } + } + + if err := cmd.ValidateRequiredFlags(); err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + if err := cmd.ValidateArgs(tt.args); err != nil { + if !tt.isValid { + return + } + } + + model, err := parseInput(p, cmd, tt.args) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest git.ApiGetInstanceRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp *git.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{ + resp: &git.Instance{}, + }, + wantErr: false, + }, + { + name: "nil", + args: args{}, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/git/git.go b/internal/cmd/git/git.go new file mode 100644 index 000000000..fcacb4fcd --- /dev/null +++ b/internal/cmd/git/git.go @@ -0,0 +1,34 @@ +package git + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/git/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/git/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/git/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/git/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "git", + Short: "Provides functionality for STACKIT Git", + Long: "Provides functionality for STACKIT Git.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand( + list.NewCmd(params), + describe.NewCmd(params), + create.NewCmd(params), + delete.NewCmd(params), + ) +} diff --git a/internal/cmd/git/list/list.go b/internal/cmd/git/list/list.go new file mode 100644 index 000000000..0057342ff --- /dev/null +++ b/internal/cmd/git/list/list.go @@ -0,0 +1,163 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + + "github.com/goccy/go-yaml" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/git/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +const limitFlag = "limit" + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all instances of STACKIT Git.", + Long: "Lists all instances of STACKIT Git for the current project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all STACKIT Git instances`, + "$ stackit git instance list"), + examples.NewExample( + "Lists up to 10 STACKIT Git instances", + "$ stackit git instance list --limit=10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get STACKIT Git instances: %w", err) + } + instances := *resp.Instances + if len(instances) == 0 { + 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 + } + params.Printer.Info("No instances found for project %q\n", projectLabel) + return nil + } else if model.Limit != nil && len(instances) > int(*model.Limit) { + instances = (instances)[:*model.Limit] + } + return outputResult(params.Printer, model.OutputFormat, instances) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClient) git.ApiListInstancesRequest { + return apiClient.ListInstances(ctx, model.ProjectId) +} + +func outputResult(p *print.Printer, outputFormat string, instances []git.Instance) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(instances, "", " ") + if err != nil { + return fmt.Errorf("marshal Observability instance list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal Observability instance list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "URL", "VERSION", "STATE", "CREATED") + for i := range instances { + instance := (instances)[i] + table.AddRow( + utils.PtrString(instance.Id), + utils.PtrString(instance.Name), + utils.PtrString(instance.Url), + utils.PtrString(instance.Version), + utils.PtrString(instance.State), + utils.PtrString(instance.Created), + ) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/git/list/list_test.go b/internal/cmd/git/list/list_test.go new file mode 100644 index 000000000..f73297388 --- /dev/null +++ b/internal/cmd/git/list/list_test.go @@ -0,0 +1,237 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &git.APIClient{} +var testProjectId = uuid.NewString() + +const ( + testLimit = 10 +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *git.ApiListInstancesRequest)) git.ApiListInstancesRequest { + request := testClient.ListInstances(testCtx, testProjectId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "with limit flag", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(testLimit) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(testLimit)) + }), + }, + { + description: "with limit flag == 0", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(0) + }), + isValid: false, + }, + { + description: "with limit flag < 0", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(-1) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest git.ApiListInstancesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instances []git.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty instances slice", + args: args{ + instances: []git.Instance{}, + }, + wantErr: false, + }, + { + name: "set empty instances in instances slice", + args: args{ + instances: []git.Instance{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 6da6491d6..750bdfa9a 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -14,6 +14,7 @@ import ( configCmd "github.com/stackitcloud/stackit-cli/internal/cmd/config" "github.com/stackitcloud/stackit-cli/internal/cmd/curl" "github.com/stackitcloud/stackit-cli/internal/cmd/dns" + "github.com/stackitcloud/stackit-cli/internal/cmd/git" "github.com/stackitcloud/stackit-cli/internal/cmd/image" keypair "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair" loadbalancer "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer" @@ -191,6 +192,7 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(image.NewCmd(params)) cmd.AddCommand(quota.NewCmd(params)) cmd.AddCommand(affinityGroups.NewCmd(params)) + cmd.AddCommand(git.NewCmd(params)) } // traverseCommands calls f for c and all of its children. diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index da282c335..957d7c475 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -45,6 +45,7 @@ const ( SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" IaaSCustomEndpointKey = "iaas_custom_endpoint" TokenCustomEndpointKey = "token_custom_endpoint" + GitCustomEndpointKey = "git_custom_endpoint" ProjectNameKey = "project_name" DefaultProfileName = "default" @@ -103,6 +104,7 @@ var ConfigKeys = []string{ SQLServerFlexCustomEndpointKey, IaaSCustomEndpointKey, TokenCustomEndpointKey, + GitCustomEndpointKey, } var defaultConfigFolderPath string @@ -187,6 +189,7 @@ func setConfigDefaults() { viper.SetDefault(SQLServerFlexCustomEndpointKey, "") viper.SetDefault(IaaSCustomEndpointKey, "") viper.SetDefault(TokenCustomEndpointKey, "") + viper.SetDefault(GitCustomEndpointKey, "") } func getConfigFilePath(configFolder string) string { diff --git a/internal/pkg/services/git/client/client.go b/internal/pkg/services/git/client/client.go new file mode 100644 index 000000000..dde3b7be6 --- /dev/null +++ b/internal/pkg/services/git/client/client.go @@ -0,0 +1,45 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/spf13/viper" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +func ConfigureClient(p *print.Printer) (*git.APIClient, error) { + var err error + var apiClient *git.APIClient + var cfgOptions []sdkConfig.ConfigurationOption + + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return nil, &errors.AuthError{} + } + cfgOptions = append(cfgOptions, authCfgOption) + + customEndpoint := viper.GetString(config.GitCustomEndpointKey) + + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err = git.NewAPIClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return nil, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/internal/pkg/services/git/utils/utils.go b/internal/pkg/services/git/utils/utils.go new file mode 100644 index 000000000..3a875c920 --- /dev/null +++ b/internal/pkg/services/git/utils/utils.go @@ -0,0 +1,23 @@ +package utils + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type GitClient interface { + GetInstanceExecute(ctx context.Context, projectId string, instanceId string) (*git.Instance, error) +} + +func GetInstanceName(ctx context.Context, apiClient GitClient, projectId, instanceId string) (string, error) { + resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId) + if err != nil { + return "", fmt.Errorf("get instance: %w", err) + } + if resp.Name == nil { + return "", nil + } + return *resp.Name, nil +} diff --git a/internal/pkg/services/git/utils/utils_test.go b/internal/pkg/services/git/utils/utils_test.go new file mode 100644 index 000000000..7ec5dc494 --- /dev/null +++ b/internal/pkg/services/git/utils/utils_test.go @@ -0,0 +1,66 @@ +package utils + +import ( + "context" + "fmt" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type GitClientMocked struct { + GetInstanceFails bool + GetInstanceResp *git.Instance +} + +func (m *GitClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*git.Instance, error) { + if m.GetInstanceFails { + return nil, fmt.Errorf("could not get instance") + } + return m.GetInstanceResp, nil +} + +func TestGetinstanceName(t *testing.T) { + tests := []struct { + name string + instanceResp *git.Instance + instanceErr bool + want string + wantErr bool + }{ + { + name: "successful retrieval", + instanceResp: &git.Instance{Name: utils.Ptr("test-instance")}, + want: "test-instance", + wantErr: false, + }, + { + name: "error on retrieval", + instanceErr: true, + wantErr: true, + }, + { + name: "nil name", + instanceErr: false, + instanceResp: &git.Instance{}, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := &GitClientMocked{ + GetInstanceFails: tt.instanceErr, + GetInstanceResp: tt.instanceResp, + } + got, err := GetInstanceName(context.Background(), client, "", "") + if (err != nil) != tt.wantErr { + t.Errorf("GetInstanceName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetInstanceName() = %v, want %v", got, tt.want) + } + }) + } +} From aacb3cba5b097ba48c948f1d90eedef03949c532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 13 May 2025 13:50:59 +0200 Subject: [PATCH 300/619] fix panic in auth.TokenExpired (#736) --- internal/pkg/auth/user_token_flow.go | 2 ++ internal/pkg/auth/user_token_flow_test.go | 37 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/internal/pkg/auth/user_token_flow.go b/internal/pkg/auth/user_token_flow.go index 8a49c6b45..215db2fa3 100644 --- a/internal/pkg/auth/user_token_flow.go +++ b/internal/pkg/auth/user_token_flow.go @@ -118,6 +118,8 @@ func TokenExpired(token string) (bool, error) { expirationTimestampNumeric, err := tokenParsed.Claims.GetExpirationTime() if err != nil { return false, fmt.Errorf("get expiration timestamp from access token: %w", err) + } else if expirationTimestampNumeric == nil { + return false, nil } expirationTimestamp := expirationTimestampNumeric.Time now := time.Now() diff --git a/internal/pkg/auth/user_token_flow_test.go b/internal/pkg/auth/user_token_flow_test.go index 6aeac368f..cd31350ad 100644 --- a/internal/pkg/auth/user_token_flow_test.go +++ b/internal/pkg/auth/user_token_flow_test.go @@ -381,3 +381,40 @@ func createTokens(accessTokenExpiresAt, refreshTokenExpiresAt time.Time) (access return accessToken, refreshToken, nil } + +func TestTokenExpired(t *testing.T) { + tests := []struct { + desc string + token string + expected bool + }{ + { + desc: "token without exp", + token: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`, + expected: false, + }, + { + desc: "exp 0", + token: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjB9.rIhVGrtR0B0gUYPZDnB6LZ_w7zckH_9qFZBWG4rCkRY`, + expected: true, + }, + { + desc: "exp 9007199254740991", + token: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNTc2MDkwNzExMTExMTExfQ.aStshPjoSKTIcBeESbLJWvbMVuw-XWInXcf1P7tiWaE`, + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + actual, err := TokenExpired(tt.token) + if err != nil { + t.Fatalf("TokenExpired() error = %v", err) + } + + if actual != tt.expected { + t.Errorf("TokenExpired() = %v, want %v", actual, tt.expected) + } + }) + } +} From e42e4eae189df0bf6c809d5a075f28fa00822c3b Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Tue, 13 May 2025 17:30:34 +0200 Subject: [PATCH 301/619] fix(postgresql): Display correct error message when project id is not set (#745) Signed-off-by: Alexander Dahmen --- internal/cmd/postgresflex/options/options.go | 4 +++ .../cmd/postgresflex/options/options_test.go | 35 ++++++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index 66535e387..8a3bd6287 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -10,6 +10,7 @@ import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -99,6 +100,9 @@ func configureFlags(cmd *cobra.Command) { func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } flavors := flags.FlagToBoolValue(p, cmd, flavorsFlag) versions := flags.FlagToBoolValue(p, cmd, versionsFlag) storages := flags.FlagToBoolValue(p, cmd, storagesFlag) diff --git a/internal/cmd/postgresflex/options/options_test.go b/internal/cmd/postgresflex/options/options_test.go index 7643dad69..54df1ccf9 100644 --- a/internal/cmd/postgresflex/options/options_test.go +++ b/internal/cmd/postgresflex/options/options_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -16,6 +17,7 @@ import ( type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testProjectId = uuid.NewString() type postgresFlexClientMocked struct { listFlavorsFails bool @@ -63,10 +65,11 @@ func (c *postgresFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - flavorsFlag: "true", - versionsFlag: "true", - storagesFlag: "true", - flavorIdFlag: "2.4", + globalflags.ProjectIdFlag: testProjectId, + flavorsFlag: "true", + versionsFlag: "true", + storagesFlag: "true", + flavorIdFlag: "2.4", } for _, mod := range mods { mod(flagValues) @@ -76,10 +79,13 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModelAllFalse(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{Verbosity: globalflags.VerbosityDefault}, - Flavors: false, - Versions: false, - Storages: false, + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Flavors: false, + Versions: false, + Storages: false, } for _, mod := range mods { mod(model) @@ -89,11 +95,14 @@ func fixtureInputModelAllFalse(mods ...func(model *inputModel)) *inputModel { func fixtureInputModelAllTrue(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{Verbosity: globalflags.VerbosityDefault}, - Flavors: true, - Versions: true, - Storages: true, - FlavorId: utils.Ptr("2.4"), + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Flavors: true, + Versions: true, + Storages: true, + FlavorId: utils.Ptr("2.4"), } for _, mod := range mods { mod(model) From 050383e0943908a520409ce05c56956dc09cb735 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 14 May 2025 09:02:42 +0200 Subject: [PATCH 302/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/ske to v0.22.4 (#746) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5e4de09de..01ff6a218 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.3 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.4 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 diff --git a/go.sum b/go.sum index d16afaad1..265567e0c 100644 --- a/go.sum +++ b/go.sum @@ -608,8 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3 h1:qCn6ZS/ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3 h1:rDsIPzaNJ4bnKJp9XFNzna+pXylGYVHUBPl5hqBWhX8= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.3 h1:dN6MOgb9CXaZ9hsdCIrrNGyw7EggPvE5kaTvNKvrEzI= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.3/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.4 h1:whyCGfzlLcyb23uKGJLrftjT57vqa1jS3Xz5voUHK+M= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.4/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3 h1:MF46ffu+A8eu17N7LGFG2T50PhjDw2L0f68Uu316r8U= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= From 056988638e883ac56ff98da7022b22be63cce941 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 17:34:47 +0200 Subject: [PATCH 303/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex (#755) Bumps [github.com/stackitcloud/stackit-sdk-go/services/mongodbflex](https://github.com/stackitcloud/stackit-sdk-go) from 1.0.1 to 1.2.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/cdn/v1.0.1...services/cdn/v1.2.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/mongodbflex dependency-version: 1.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 01ff6a218..f647f857e 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3 github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.1 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.3 diff --git a/go.sum b/go.sum index 265567e0c..20844f876 100644 --- a/go.sum +++ b/go.sum @@ -580,8 +580,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2 h1:wM/Gop6sG/fkpzs github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2 h1:JoPz34UT1Gx7TV6GpOzWdNBq78co7MV12jynADI4AMc= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.1 h1:CBGVT+5ilIFVtz5gDnQ58zNapFCLpjOftuVeATdg1qo= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.0.1/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 h1:U/IhjLOz0vG6zuxTqGhBd8f609s6JB+X9PaL6x/VM58= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 h1:RFe45uLzTSmd69yaQe5zLDY3+1hYi6/lSZUVcjbb6+c= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2 h1:anITBRTlQoneEawVg4hHjs4IceFJLFq9KdDU+d5y5DU= From 646f07f0cc0387a4fe5ed80ddf3ef209f9a84518 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 17:38:06 +0200 Subject: [PATCH 304/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/rabbitmq (#754) Bumps [github.com/stackitcloud/stackit-sdk-go/services/rabbitmq](https://github.com/stackitcloud/stackit-sdk-go) from 0.22.2 to 0.24.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.22.2...services/ske/v0.24.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/rabbitmq dependency-version: 0.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f647f857e..d7936bede 100644 --- a/go.mod +++ b/go.mod @@ -241,7 +241,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum index 20844f876..644ac8ffe 100644 --- a/go.sum +++ b/go.sum @@ -590,8 +590,8 @@ github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2 h1:p1bub8QayR github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 h1:AIQueG1oSdKbxK8ASZZYkmqzJ7NhKzKcR5AQsndoF18= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.2 h1:++lyru25B7J8cKaEBCw9ZKgXDIJGmQvmFXR+BpAcR4g= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.22.2/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 h1:YEfhKt3T25uY7vs8QcAPfdTs1GLil0BcrLCJ5RhMyR0= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2 h1:KKANO+wsLVkuH8N+xuYrEx+rDcliv48zYk3I7QzdX3A= github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.3 h1:4DNnEZj4uSyE+gDS+j9MCUuax9nfnttfro+JJE8QRSE= From 9a7bfd11badf548a2b5c43891bde1222792df298 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 15:46:25 +0000 Subject: [PATCH 305/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mariadb (#753) Bumps [github.com/stackitcloud/stackit-sdk-go/services/mariadb](https://github.com/stackitcloud/stackit-sdk-go) from 0.22.2 to 0.24.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.22.2...services/ske/v0.24.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/mariadb dependency-version: 0.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d7936bede..eceb1d08e 100644 --- a/go.mod +++ b/go.mod @@ -238,7 +238,7 @@ require ( github.com/spf13/cast v1.7.1 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3 github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 diff --git a/go.sum b/go.sum index 644ac8ffe..e6cf43226 100644 --- a/go.sum +++ b/go.sum @@ -578,8 +578,8 @@ github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3 h1:StQg5p4h1 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2 h1:wM/Gop6sG/fkpzsZGhrPN2AzkKxHup175WaFBGaeQ7s= github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2 h1:JoPz34UT1Gx7TV6GpOzWdNBq78co7MV12jynADI4AMc= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.22.2/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 h1:t/Ten9AuoWFmrDq5gAI3kVZShF3i8zEAaeBsYYqiaao= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 h1:U/IhjLOz0vG6zuxTqGhBd8f609s6JB+X9PaL6x/VM58= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 h1:RFe45uLzTSmd69yaQe5zLDY3+1hYi6/lSZUVcjbb6+c= From f94c636b2e17710a6d3ba3eb39d4b4e6e951434f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 20 May 2025 09:05:31 +0200 Subject: [PATCH 306/619] fix(deps): update module github.com/lmittmann/tint to v1.1.0 (#758) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eceb1d08e..476f8d185 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jedib0t/go-pretty/v6 v6.6.7 - github.com/lmittmann/tint v1.0.7 + github.com/lmittmann/tint v1.1.0 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 diff --git a/go.sum b/go.sum index e6cf43226..d9adcad8c 100644 --- a/go.sum +++ b/go.sum @@ -400,8 +400,8 @@ github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y= -github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.1.0 h1:0hDmvuGv3U+Cep/jHpPxwjrCFjT6syam7iY7nTmA7ug= +github.com/lmittmann/tint v1.1.0/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= From 2c3c0a3f17b694512dfd59b8196faf5f7aa58777 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 20 May 2025 09:07:55 +0200 Subject: [PATCH 307/619] chore(deps): update renovatebot/github-action action to v42.0.3 (#757) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 92e3fbd8c..9c914fc30 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v42.0.2 + uses: renovatebot/github-action@v42.0.3 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From e655dcaf32a3478a0c635c1e1e87c0ca3f27f085 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 20 May 2025 15:37:31 +0200 Subject: [PATCH 308/619] fix(deps): update stackit sdk modules (#750) * fix(deps): update stackit sdk modules * fix: compile errors --------- Co-authored-by: Renovate Bot Co-authored-by: Marcel Jacek --- docs/stackit_dns_record-set_create.md | 2 +- docs/stackit_dns_zone_create.md | 2 +- go.mod | 28 +++++----- go.sum | 56 +++++++++---------- internal/cmd/dns/record-set/create/create.go | 17 ++++-- .../cmd/dns/record-set/create/create_test.go | 4 +- internal/cmd/dns/zone/create/create.go | 16 +++++- internal/cmd/dns/zone/create/create_test.go | 11 ++-- .../cmd/load-balancer/create/create_test.go | 4 +- .../generate-payload/generate_payload.go | 4 +- .../generate-payload/generate_payload_test.go | 8 +-- .../cmd/load-balancer/update/update_test.go | 4 +- .../scrape-config/create/create_test.go | 11 ++-- .../scrape-config/update/update_test.go | 2 +- .../cmd/ske/cluster/create/create_test.go | 9 +-- .../cmd/ske/cluster/update/update_test.go | 9 +-- internal/cmd/ske/options/options.go | 2 +- internal/pkg/services/dns/utils/utils.go | 2 +- .../pkg/services/observability/utils/utils.go | 6 +- .../observability/utils/utils_test.go | 12 ++-- .../services/serverbackup/utils/utils_test.go | 2 +- .../service-enablement/utils/utils.go | 3 +- .../service-enablement/utils/utils_test.go | 11 ++-- internal/pkg/services/ske/utils/utils.go | 2 +- internal/pkg/services/ske/utils/utils_test.go | 16 +++--- 25 files changed, 128 insertions(+), 115 deletions(-) diff --git a/docs/stackit_dns_record-set_create.md b/docs/stackit_dns_record-set_create.md index f692b80ad..dfb740ad9 100644 --- a/docs/stackit_dns_record-set_create.md +++ b/docs/stackit_dns_record-set_create.md @@ -25,7 +25,7 @@ stackit dns record-set create [flags] --name string Name of the record, should be compliant with RFC1035, Section 2.3.4 --record strings Records belonging to the record set --ttl int Time to live, if not provided defaults to the zone's default TTL - --type string Record type, one of ["A" "AAAA" "SOA" "CNAME" "NS" "MX" "TXT" "SRV" "PTR" "ALIAS" "DNAME" "CAA"] (default "A") + --type string Record type, one of ["A" "AAAA" "SOA" "CNAME" "NS" "MX" "TXT" "SRV" "PTR" "ALIAS" "DNAME" "CAA" "DNSKEY" "DS" "LOC" "NAPTR" "SSHFP" "TLSA" "URI" "CERT" "SVCB"] (default "A") --zone-id string Zone ID ``` diff --git a/docs/stackit_dns_zone_create.md b/docs/stackit_dns_zone_create.md index 081628e19..0a0efde1c 100644 --- a/docs/stackit_dns_zone_create.md +++ b/docs/stackit_dns_zone_create.md @@ -36,7 +36,7 @@ stackit dns zone create [flags] --primary strings Primary name server for secondary zone --refresh-time int Refresh time --retry-time int Retry time - --type string Zone type + --type string Zone type, one of: ["primary" "secondary"] ``` ### Options inherited from parent commands diff --git a/go.mod b/go.mod index 476f8d185..681e23976 100644 --- a/go.mod +++ b/go.mod @@ -16,23 +16,23 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.1 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.3 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.22.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.3 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.2 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.3 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.4 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.7.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.23.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.1.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.30.0 @@ -236,13 +236,13 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.23.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.23.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.33.0 // indirect diff --git a/go.sum b/go.sum index d9adcad8c..990d6b2de 100644 --- a/go.sum +++ b/go.sum @@ -564,54 +564,54 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJSjtaGnUI7UE7ITb5IT0= github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.3 h1:JVRsMN5uKPxy9ynsxmhGfAecz87LjqN5G5Vg8MRwyRc= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.3/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1 h1:7JbFIXiq3IlFST7N7kS0gxX5EKX/rYs87kUVtR00sHw= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 h1:aXVMNdiHCtT07bro52KjnxEBMDNK9DweJBlk+G4ElCM= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3 h1:WJnA6YTOlBxMJf9PRuxkXduxj+fyWi+wOks69PvN1qI= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.3/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.14.0 h1:aji1vxn1LVfM+SCfOSXUz0Pwv+ZQjyt9PmV0ejHLy5U= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.14.0/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 h1:/NXxiJf/NFpj+DFXc07vsx+0he/xufdhIskXUlSeyyw= github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 h1:zh6e2eHgqex++fr6N0RK7wMMBGesC3QhBd42FdTq2Z8= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3 h1:StQg5p4h1aLFwIHQWWe5l44aFue+ZvQMGDbypP1DMYw= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.3/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2 h1:wM/Gop6sG/fkpzsZGhrPN2AzkKxHup175WaFBGaeQ7s= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.2/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0 h1:9gUobm//GzVGYTbfa39tNRceEjQskNuNVZyUS9rOZ4Y= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.23.0 h1:ksxHeILZutooun0Hy/cY8qikC9owya1UDJR+FSQSlRw= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.23.0/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 h1:t/Ten9AuoWFmrDq5gAI3kVZShF3i8zEAaeBsYYqiaao= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 h1:U/IhjLOz0vG6zuxTqGhBd8f609s6JB+X9PaL6x/VM58= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 h1:RFe45uLzTSmd69yaQe5zLDY3+1hYi6/lSZUVcjbb6+c= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2 h1:anITBRTlQoneEawVg4hHjs4IceFJLFq9KdDU+d5y5DU= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.5.2/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2 h1:p1bub8QayR+NkYtGd8DNSjxlRmoyR7Dr97LiwWVW1Ow= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.21.2/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.6.0 h1:QqlFcMv/TbIG95u/xHB/9aLvElplj1lKnTIyUSwEtT4= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.6.0/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.22.0 h1:XDt4NCiWdpjbbw9UevsxLJ3SGkO1bSoJnV96RSHNNoI= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.22.0/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 h1:AIQueG1oSdKbxK8ASZZYkmqzJ7NhKzKcR5AQsndoF18= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 h1:YEfhKt3T25uY7vs8QcAPfdTs1GLil0BcrLCJ5RhMyR0= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2 h1:KKANO+wsLVkuH8N+xuYrEx+rDcliv48zYk3I7QzdX3A= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.22.2/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.3 h1:4DNnEZj4uSyE+gDS+j9MCUuax9nfnttfro+JJE8QRSE= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.13.3/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.2 h1:+YwMWWvZlUtw6TEfTqXPdUyN9hbkECU4DULwgIMu6A0= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.0.2/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.23.0 h1:arcom/1Chl3+SkDZYRNx5IemkLlqU2mnXrQmg9dsxQI= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.23.0/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0 h1:Rpbt83RyXS0AMw97g5L9oQdCAmVBGAyHpeCcDXesuEk= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0 h1:nvwaviIDf5ffAydfQBrl48K1nPowyDq05ompo9ZzFzY= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4 h1:UCX1qy44q22bDGv7BhLtOrWCzriS9m4MQsIOX6n+lgM= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.3 h1:OR5CZnxZMbGXsYPOZL00En3RhXeUuEJcZVN9iSxxTs8= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.0.3/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0 h1:cKQAuKSihSX1Jpacub2rZ1StItiO7SIO0y+Fi2yukd4= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 h1:iLyXsBF+lP7iE4rnoK3hO8l4wHcgySRXD65oeUgt6Jc= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3 h1:qCn6ZS/oJEqA4PBMLMDvvctQ4eQEoCQSSWES394+AcQ= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.6.3/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3 h1:rDsIPzaNJ4bnKJp9XFNzna+pXylGYVHUBPl5hqBWhX8= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.0.3/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.4 h1:whyCGfzlLcyb23uKGJLrftjT57vqa1jS3Xz5voUHK+M= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.22.4/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3 h1:MF46ffu+A8eu17N7LGFG2T50PhjDw2L0f68Uu316r8U= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.0.3/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.7.0 h1:QiHkjmforciAfBnf/oMjGmoZWYYD38ZrgLNWK149xQQ= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.7.0/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0 h1:Wb/eEqbnwLw+lsTlAC8qTFoLMtXOTWcZDUDSiUB7GnM= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.23.0 h1:kPAYBLDJC8W3GvDt+KtqDl2EZJgbU9l1tUj0JbCWA+4= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.23.0/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.1.0 h1:awy7JzBwAVJEKcJVt1DBZtZ0qtdT2aEuWCkgQvKky9w= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.1.0/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 49db52860..045f6ce29 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -30,8 +30,8 @@ const ( ttlFlag = "ttl" typeFlag = "type" - defaultType = "A" - txtType = "TXT" + defaultType = dns.CREATERECORDSETPAYLOADTYPE_A + txtType = dns.CREATERECORDSETPAYLOADTYPE_TXT ) type inputModel struct { @@ -41,7 +41,7 @@ type inputModel struct { Name *string Records []string TTL *int64 - Type string + Type dns.CreateRecordSetPayloadTypes } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -109,14 +109,17 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func configureFlags(cmd *cobra.Command) { - typeFlagOptions := []string{"A", "AAAA", "SOA", "CNAME", "NS", "MX", "TXT", "SRV", "PTR", "ALIAS", "DNAME", "CAA"} + var typeFlagOptions []string + for _, val := range dns.AllowedCreateRecordSetPayloadTypesEnumValues { + typeFlagOptions = append(typeFlagOptions, string(val)) + } cmd.Flags().Var(flags.UUIDFlag(), zoneIdFlag, "Zone ID") cmd.Flags().String(commentFlag, "", "User comment") cmd.Flags().String(nameFlag, "", "Name of the record, should be compliant with RFC1035, Section 2.3.4") cmd.Flags().Int64(ttlFlag, 0, "Time to live, if not provided defaults to the zone's default TTL") cmd.Flags().StringSlice(recordFlag, []string{}, "Records belonging to the record set") - cmd.Flags().Var(flags.EnumFlag(false, defaultType, typeFlagOptions...), typeFlag, fmt.Sprintf("Record type, one of %q", typeFlagOptions)) + cmd.Flags().Var(flags.EnumFlag(false, string(defaultType), typeFlagOptions...), typeFlag, fmt.Sprintf("Record type, one of %q", typeFlagOptions)) err := flags.MarkFlagsRequired(cmd, zoneIdFlag, nameFlag, recordFlag) cobra.CheckErr(err) @@ -128,6 +131,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return nil, &errors.ProjectIdError{} } + recordType := flags.FlagWithDefaultToStringValue(p, cmd, typeFlag) + model := inputModel{ GlobalFlagModel: globalFlags, ZoneId: flags.FlagToStringValue(p, cmd, zoneIdFlag), @@ -135,7 +140,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Name: flags.FlagToStringPointer(p, cmd, nameFlag), Records: flags.FlagToStringSliceValue(p, cmd, recordFlag), TTL: flags.FlagToInt64Pointer(p, cmd, ttlFlag), - Type: flags.FlagWithDefaultToStringValue(p, cmd, typeFlag), + Type: dns.CreateRecordSetPayloadTypes(recordType), } if model.Type == txtType { diff --git a/internal/cmd/dns/record-set/create/create_test.go b/internal/cmd/dns/record-set/create/create_test.go index 99a216aeb..789e46626 100644 --- a/internal/cmd/dns/record-set/create/create_test.go +++ b/internal/cmd/dns/record-set/create/create_test.go @@ -75,7 +75,7 @@ func fixtureRequest(mods ...func(request *dns.ApiCreateRecordSetRequest)) dns.Ap {Content: utils.Ptr("1.1.1.1")}, }, Ttl: utils.Ptr(int64(3600)), - Type: utils.Ptr("SOA"), + Type: dns.CREATERECORDSETPAYLOADTYPE_SOA.Ptr(), }) for _, mod := range mods { mod(&request) @@ -247,7 +247,7 @@ func TestParseInput(t *testing.T) { { description: "TXT record with > 255 characters", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[typeFlag] = txtType + flagValues[typeFlag] = string(txtType) flagValues[recordFlag] = strings.Join(recordTxtOver255Char, "") }), isValid: true, diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 4855e4337..081602f18 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -46,7 +46,7 @@ type inputModel struct { DefaultTTL *int64 Primaries *[]string Acl *string - Type *string + Type *dns.CreateZonePayloadTypes RetryTime *int64 RefreshTime *int64 NegativeCache *int64 @@ -124,12 +124,17 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func configureFlags(cmd *cobra.Command) { + var typeFlagOptions []string + for _, val := range dns.AllowedCreateZonePayloadTypesEnumValues { + typeFlagOptions = append(typeFlagOptions, string(val)) + } + cmd.Flags().String(nameFlag, "", "User given name of the zone") cmd.Flags().String(dnsNameFlag, "", "Fully qualified domain name of the DNS zone") cmd.Flags().Int64(defaultTTLFlag, 1000, "Default time to live") cmd.Flags().StringSlice(primaryFlag, []string{}, "Primary name server for secondary zone") cmd.Flags().String(aclFlag, "", "Access control list") - cmd.Flags().String(typeFlag, "", "Zone type") + cmd.Flags().Var(flags.EnumFlag(false, "", append(typeFlagOptions, "")...), typeFlag, fmt.Sprintf("Zone type, one of: %q", typeFlagOptions)) cmd.Flags().Int64(retryTimeFlag, 0, "Retry time") cmd.Flags().Int64(refreshTimeFlag, 0, "Refresh time") cmd.Flags().Int64(negativeCacheFlag, 0, "Negative cache") @@ -148,6 +153,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return nil, &errors.ProjectIdError{} } + var zoneType *dns.CreateZonePayloadTypes + if zoneTypeString := flags.FlagToStringPointer(p, cmd, typeFlag); zoneTypeString != nil && *zoneTypeString != "" { + zoneType = dns.CreateZonePayloadTypes(*zoneTypeString).Ptr() + } + model := inputModel{ GlobalFlagModel: globalFlags, Name: flags.FlagToStringPointer(p, cmd, nameFlag), @@ -155,7 +165,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { DefaultTTL: flags.FlagToInt64Pointer(p, cmd, defaultTTLFlag), Primaries: flags.FlagToStringSlicePointer(p, cmd, primaryFlag), Acl: flags.FlagToStringPointer(p, cmd, aclFlag), - Type: flags.FlagToStringPointer(p, cmd, typeFlag), + Type: zoneType, RetryTime: flags.FlagToInt64Pointer(p, cmd, retryTimeFlag), RefreshTime: flags.FlagToInt64Pointer(p, cmd, refreshTimeFlag), NegativeCache: flags.FlagToInt64Pointer(p, cmd, negativeCacheFlag), diff --git a/internal/cmd/dns/zone/create/create_test.go b/internal/cmd/dns/zone/create/create_test.go index 39412b8ac..536711d80 100644 --- a/internal/cmd/dns/zone/create/create_test.go +++ b/internal/cmd/dns/zone/create/create_test.go @@ -29,7 +29,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st dnsNameFlag: "example.com", defaultTTLFlag: "3600", aclFlag: "0.0.0.0/0", - typeFlag: "master", + typeFlag: string(dns.CREATEZONEPAYLOADTYPE_PRIMARY), primaryFlag: "1.1.1.1", retryTimeFlag: "600", refreshTimeFlag: "3600", @@ -56,7 +56,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { DefaultTTL: utils.Ptr(int64(3600)), Primaries: utils.Ptr([]string{"1.1.1.1"}), Acl: utils.Ptr("0.0.0.0/0"), - Type: utils.Ptr("master"), + Type: dns.CREATEZONEPAYLOADTYPE_PRIMARY.Ptr(), RetryTime: utils.Ptr(int64(600)), RefreshTime: utils.Ptr(int64(3600)), NegativeCache: utils.Ptr(int64(60)), @@ -79,7 +79,7 @@ func fixtureRequest(mods ...func(request *dns.ApiCreateZoneRequest)) dns.ApiCrea DefaultTTL: utils.Ptr(int64(3600)), Primaries: utils.Ptr([]string{"1.1.1.1"}), Acl: utils.Ptr("0.0.0.0/0"), - Type: utils.Ptr("master"), + Type: dns.CREATEZONEPAYLOADTYPE_PRIMARY.Ptr(), RetryTime: utils.Ptr(int64(600)), RefreshTime: utils.Ptr(int64(3600)), NegativeCache: utils.Ptr(int64(60)), @@ -139,7 +139,6 @@ func TestParseInput(t *testing.T) { defaultTTLFlag: "0", aclFlag: "", typeFlag: "", - primaryFlag: "", retryTimeFlag: "0", refreshTimeFlag: "0", negativeCacheFlag: "0", @@ -157,9 +156,9 @@ func TestParseInput(t *testing.T) { Name: utils.Ptr(""), DnsName: utils.Ptr(""), DefaultTTL: utils.Ptr(int64(0)), - Primaries: utils.Ptr([]string{}), + Primaries: nil, Acl: utils.Ptr(""), - Type: utils.Ptr(""), + Type: nil, RetryTime: utils.Ptr(int64(0)), RefreshTime: utils.Ptr(int64(0)), NegativeCache: utils.Ptr(int64(0)), diff --git a/internal/cmd/load-balancer/create/create_test.go b/internal/cmd/load-balancer/create/create_test.go index eca1281a8..66cdb2754 100644 --- a/internal/cmd/load-balancer/create/create_test.go +++ b/internal/cmd/load-balancer/create/create_test.go @@ -36,7 +36,7 @@ var testPayload = &loadbalancer.CreateLoadBalancerPayload{ { DisplayName: utils.Ptr(""), Port: utils.Ptr(int64(0)), - Protocol: utils.Ptr(""), + Protocol: loadbalancer.ListenerProtocol("").Ptr(), ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{ { Name: utils.Ptr(""), @@ -55,7 +55,7 @@ var testPayload = &loadbalancer.CreateLoadBalancerPayload{ Networks: &[]loadbalancer.Network{ { NetworkId: utils.Ptr(""), - Role: utils.Ptr(""), + Role: loadbalancer.NetworkRole("").Ptr(), }, }, Options: &loadbalancer.LoadBalancerOptions{ diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index 1197cf7a9..42cbb4a59 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -35,7 +35,7 @@ var ( defaultPayloadListener = &loadbalancer.Listener{ DisplayName: utils.Ptr(""), Port: utils.Ptr(int64(0)), - Protocol: utils.Ptr(""), + Protocol: loadbalancer.ListenerProtocol("").Ptr(), ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{ { Name: utils.Ptr(""), @@ -52,7 +52,7 @@ var ( defaultPayloadNetwork = &loadbalancer.Network{ NetworkId: utils.Ptr(""), - Role: utils.Ptr(""), + Role: loadbalancer.NetworkRole("").Ptr(), } defaultPayloadTargetPool = &loadbalancer.TargetPool{ diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go index 5943215b8..66a0891ec 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go @@ -226,7 +226,7 @@ func TestModifyListeners(t *testing.T) { { DisplayName: utils.Ptr(""), Port: utils.Ptr(int64(0)), - Protocol: utils.Ptr(""), + Protocol: loadbalancer.ListenerProtocol("").Ptr(), Name: utils.Ptr(""), ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{ { @@ -244,7 +244,7 @@ func TestModifyListeners(t *testing.T) { { DisplayName: utils.Ptr(""), Port: utils.Ptr(int64(0)), - Protocol: utils.Ptr(""), + Protocol: loadbalancer.ListenerProtocol("").Ptr(), Name: utils.Ptr(""), ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{ { @@ -265,7 +265,7 @@ func TestModifyListeners(t *testing.T) { { DisplayName: utils.Ptr(""), Port: utils.Ptr(int64(0)), - Protocol: utils.Ptr(""), + Protocol: loadbalancer.ListenerProtocol("").Ptr(), Name: nil, ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{ { @@ -283,7 +283,7 @@ func TestModifyListeners(t *testing.T) { { DisplayName: utils.Ptr(""), Port: utils.Ptr(int64(0)), - Protocol: utils.Ptr(""), + Protocol: loadbalancer.ListenerProtocol("").Ptr(), Name: nil, ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{ { diff --git a/internal/cmd/load-balancer/update/update_test.go b/internal/cmd/load-balancer/update/update_test.go index 9d97f07fc..b57d57336 100644 --- a/internal/cmd/load-balancer/update/update_test.go +++ b/internal/cmd/load-balancer/update/update_test.go @@ -33,7 +33,7 @@ var testPayload = loadbalancer.UpdateLoadBalancerPayload{ { DisplayName: utils.Ptr(""), Port: utils.Ptr(int64(0)), - Protocol: utils.Ptr(""), + Protocol: loadbalancer.ListenerProtocol("").Ptr(), ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{ { Name: utils.Ptr(""), @@ -52,7 +52,7 @@ var testPayload = loadbalancer.UpdateLoadBalancerPayload{ Networks: &[]loadbalancer.Network{ { NetworkId: utils.Ptr(""), - Role: utils.Ptr(""), + Role: loadbalancer.NetworkRole("").Ptr(), }, }, Options: &loadbalancer.LoadBalancerOptions{ diff --git a/internal/cmd/observability/scrape-config/create/create_test.go b/internal/cmd/observability/scrape-config/create/create_test.go index 54c0573e3..533bf457b 100644 --- a/internal/cmd/observability/scrape-config/create/create_test.go +++ b/internal/cmd/observability/scrape-config/create/create_test.go @@ -2,6 +2,7 @@ package create import ( "context" + "fmt" "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -34,7 +35,7 @@ var testPayload = &observability.CreateScrapeConfigPayload{ JobName: utils.Ptr("default-name"), MetricsRelabelConfigs: &[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ { - Action: utils.Ptr("replace"), + Action: observability.CREATESCRAPECONFIGPAYLOADMETRICSRELABELCONFIGSINNERACTION_REPLACE.Ptr(), Modulus: utils.Ptr(1.0), Regex: utils.Ptr("regex"), Replacement: utils.Ptr("replacement"), @@ -48,7 +49,7 @@ var testPayload = &observability.CreateScrapeConfigPayload{ "key2": []interface{}{}, }, SampleLimit: utils.Ptr(1.0), - Scheme: utils.Ptr("scheme"), + Scheme: observability.CREATESCRAPECONFIGPAYLOADSCHEME_HTTPS.Ptr(), ScrapeInterval: utils.Ptr("interval"), ScrapeTimeout: utils.Ptr("timeout"), StaticConfigs: &[]observability.CreateScrapeConfigPayloadStaticConfigsInner{ @@ -69,7 +70,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st flagValues := map[string]string{ projectIdFlag: testProjectId, instanceIdFlag: testInstanceId, - payloadFlag: `{ + payloadFlag: fmt.Sprintf(`{ "jobName": "default-name", "basicAuth": { "username": "username", @@ -95,7 +96,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st "key2": [] }, "sampleLimit": 1.0, - "scheme": "scheme", + "scheme": "%s", "scrapeInterval": "interval", "scrapeTimeout": "timeout", "staticConfigs": [ @@ -110,7 +111,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st "tlsConfig": { "insecureSkipVerify": true } - }`, + }`, observability.CREATESCRAPECONFIGPAYLOADSCHEME_HTTPS), } for _, mod := range mods { mod(flagValues) diff --git a/internal/cmd/observability/scrape-config/update/update_test.go b/internal/cmd/observability/scrape-config/update/update_test.go index ad5870231..595b4f09e 100644 --- a/internal/cmd/observability/scrape-config/update/update_test.go +++ b/internal/cmd/observability/scrape-config/update/update_test.go @@ -34,7 +34,7 @@ var testPayload = observability.UpdateScrapeConfigPayload{ MetricsPath: utils.Ptr("/metrics"), MetricsRelabelConfigs: &[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ { - Action: utils.Ptr("replace"), + Action: observability.CREATESCRAPECONFIGPAYLOADMETRICSRELABELCONFIGSINNERACTION_REPLACE.Ptr(), Modulus: utils.Ptr(1.0), Regex: utils.Ptr("regex"), Replacement: utils.Ptr("replacement"), diff --git a/internal/cmd/ske/cluster/create/create_test.go b/internal/cmd/ske/cluster/create/create_test.go index 3cc543398..f64a03eb1 100644 --- a/internal/cmd/ske/cluster/create/create_test.go +++ b/internal/cmd/ske/cluster/create/create_test.go @@ -2,6 +2,7 @@ package create import ( "context" + "fmt" "testing" "time" @@ -47,7 +48,7 @@ var testPayload = &ske.CreateOrUpdateClusterPayload{ Size: utils.Ptr(int64(40)), }, AvailabilityZones: &[]string{"eu01-3"}, - Cri: &ske.CRI{Name: utils.Ptr("cri")}, + Cri: &ske.CRI{Name: ske.CRINAME_DOCKER.Ptr()}, }, }, Extensions: &ske.Extension{ @@ -81,7 +82,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, - payloadFlag: `{ + payloadFlag: fmt.Sprintf(`{ "name": "cli-jp", "kubernetes": { "version": "1.25.15" @@ -100,7 +101,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st "maximum": 2, "maxSurge": 1, "volume": { "type": "storage_premium_perf0", "size": 40 }, - "cri": { "name": "cri" }, + "cri": { "name": "%s" }, "availabilityZones": ["eu01-3"] } ], @@ -115,7 +116,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st "start": "0000-01-01T03:00:00+02:00" } } - }`, + }`, ske.CRINAME_DOCKER), } for _, mod := range mods { mod(flagValues) diff --git a/internal/cmd/ske/cluster/update/update_test.go b/internal/cmd/ske/cluster/update/update_test.go index e4ec07b3f..8eab71453 100644 --- a/internal/cmd/ske/cluster/update/update_test.go +++ b/internal/cmd/ske/cluster/update/update_test.go @@ -2,6 +2,7 @@ package update import ( "context" + "fmt" "testing" "time" @@ -47,7 +48,7 @@ var testPayload = ske.CreateOrUpdateClusterPayload{ Size: utils.Ptr(int64(40)), }, AvailabilityZones: &[]string{"eu01-3"}, - Cri: &ske.CRI{Name: utils.Ptr("cri")}, + Cri: &ske.CRI{Name: ske.CRINAME_DOCKER.Ptr()}, }, }, Extensions: &ske.Extension{ @@ -81,7 +82,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ projectIdFlag: testProjectId, - payloadFlag: `{ + payloadFlag: fmt.Sprintf(`{ "name": "cli-jp", "kubernetes": { "version": "1.25.15" @@ -100,7 +101,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st "maximum": 2, "maxSurge": 1, "volume": { "type": "storage_premium_perf0", "size": 40 }, - "cri": { "name": "cri" }, + "cri": { "name": "%s" }, "availabilityZones": ["eu01-3"] } ], @@ -115,7 +116,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st "start": "0000-01-01T03:00:00+02:00" } } - }`, + }`, ske.CRINAME_DOCKER), } for _, mod := range mods { mod(flagValues) diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index 0608e5a7d..dbcfa7613 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -275,7 +275,7 @@ func buildMachineImagesTable(resp *ske.ProviderOptions) tables.Table { criNames := make([]string, 0) for i := range *version.Cri { cri := (*version.Cri)[i] - criNames = append(criNames, *cri.Name) + criNames = append(criNames, string(*cri.Name)) } criNamesString := strings.Join(criNames, ", ") diff --git a/internal/pkg/services/dns/utils/utils.go b/internal/pkg/services/dns/utils/utils.go index 351cf2e47..141fb50e0 100644 --- a/internal/pkg/services/dns/utils/utils.go +++ b/internal/pkg/services/dns/utils/utils.go @@ -35,7 +35,7 @@ func GetRecordSetType(ctx context.Context, apiClient DNSClient, projectId, zoneI if err != nil { return utils.Ptr(""), fmt.Errorf("get DNS recordset: %w", err) } - return resp.Rrset.Type, nil + return (*string)(resp.Rrset.Type), nil } func FormatTxtRecord(input string) (string, error) { diff --git a/internal/pkg/services/observability/utils/utils.go b/internal/pkg/services/observability/utils/utils.go index fef48457e..234da09be 100644 --- a/internal/pkg/services/observability/utils/utils.go +++ b/internal/pkg/services/observability/utils/utils.go @@ -31,7 +31,7 @@ var ( DefaultCreateScrapeConfigPayload = observability.CreateScrapeConfigPayload{ JobName: utils.Ptr("default-name"), MetricsPath: utils.Ptr("/metrics"), - Scheme: utils.Ptr("https"), + Scheme: observability.CREATESCRAPECONFIGPAYLOADSCHEME_HTTPS.Ptr(), ScrapeInterval: utils.Ptr("5m"), ScrapeTimeout: utils.Ptr("2m"), StaticConfigs: utils.Ptr(defaultStaticConfigs), @@ -106,7 +106,7 @@ func MapToUpdateScrapeConfigPayload(resp *observability.GetScrapeConfigResponse) MetricsRelabelConfigs: metricsRelabelConfigs, Params: params, SampleLimit: utils.ConvertInt64PToFloat64P(data.SampleLimit), - Scheme: data.Scheme, + Scheme: observability.UpdateScrapeConfigPayloadGetSchemeAttributeType(data.Scheme), ScrapeInterval: data.ScrapeInterval, ScrapeTimeout: data.ScrapeTimeout, StaticConfigs: staticConfigs, @@ -127,7 +127,7 @@ func mapMetricsRelabelConfig(metricsRelabelConfigs *[]observability.MetricsRelab var mappedConfigs []observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner for _, config := range *metricsRelabelConfigs { mappedConfig := observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ - Action: config.Action, + Action: observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInnerGetActionAttributeType(config.Action), Modulus: utils.ConvertInt64PToFloat64P(config.Modulus), Regex: config.Regex, Replacement: config.Replacement, diff --git a/internal/pkg/services/observability/utils/utils_test.go b/internal/pkg/services/observability/utils/utils_test.go index 36484e547..0b5083aad 100644 --- a/internal/pkg/services/observability/utils/utils_test.go +++ b/internal/pkg/services/observability/utils/utils_test.go @@ -48,7 +48,7 @@ func fixtureGetScrapeConfigResponse(mods ...func(*observability.GetScrapeConfigR MetricsPath: utils.Ptr("/metrics"), MetricsRelabelConfigs: &[]observability.MetricsRelabelConfig{ { - Action: utils.Ptr("replace"), + Action: observability.METRICSRELABELCONFIGACTION_REPLACE.Ptr(), Modulus: &number, Regex: utils.Ptr("regex"), Replacement: utils.Ptr("replacement"), @@ -62,7 +62,7 @@ func fixtureGetScrapeConfigResponse(mods ...func(*observability.GetScrapeConfigR "key2": {}, }, SampleLimit: &number, - Scheme: utils.Ptr("scheme"), + Scheme: observability.JOBSCHEME_HTTP.Ptr(), ScrapeInterval: utils.Ptr("interval"), ScrapeTimeout: utils.Ptr("timeout"), StaticConfigs: &[]observability.StaticConfigs{ @@ -99,7 +99,7 @@ func fixtureUpdateScrapeConfigPayload(mods ...func(*observability.UpdateScrapeCo MetricsPath: utils.Ptr("/metrics"), MetricsRelabelConfigs: &[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ { - Action: utils.Ptr("replace"), + Action: utils.Ptr(observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInnerAction("replace")), Modulus: utils.Ptr(1.0), Regex: utils.Ptr("regex"), Replacement: utils.Ptr("replacement"), @@ -113,7 +113,7 @@ func fixtureUpdateScrapeConfigPayload(mods ...func(*observability.UpdateScrapeCo "key2": []string{}, }, SampleLimit: utils.Ptr(1.0), - Scheme: utils.Ptr("scheme"), + Scheme: observability.UPDATESCRAPECONFIGPAYLOADSCHEME_HTTP.Ptr(), ScrapeInterval: utils.Ptr("interval"), ScrapeTimeout: utils.Ptr("timeout"), StaticConfigs: &[]observability.UpdateScrapeConfigPayloadStaticConfigsInner{ @@ -432,7 +432,7 @@ func TestMapMetricsRelabelConfig(t *testing.T) { description: "base case", config: &[]observability.MetricsRelabelConfig{ { - Action: utils.Ptr("replace"), + Action: observability.METRICSRELABELCONFIGACTION_REPLACE.Ptr(), Modulus: utils.Int64Ptr(1), Regex: utils.Ptr("regex"), Replacement: utils.Ptr("replacement"), @@ -443,7 +443,7 @@ func TestMapMetricsRelabelConfig(t *testing.T) { }, expected: &[]observability.CreateScrapeConfigPayloadMetricsRelabelConfigsInner{ { - Action: utils.Ptr("replace"), + Action: observability.CREATESCRAPECONFIGPAYLOADMETRICSRELABELCONFIGSINNERACTION_REPLACE.Ptr(), Modulus: utils.Float64Ptr(1.0), Regex: utils.Ptr("regex"), Replacement: utils.Ptr("replacement"), diff --git a/internal/pkg/services/serverbackup/utils/utils_test.go b/internal/pkg/services/serverbackup/utils/utils_test.go index b9ca14087..73b915b3a 100644 --- a/internal/pkg/services/serverbackup/utils/utils_test.go +++ b/internal/pkg/services/serverbackup/utils/utils_test.go @@ -88,7 +88,7 @@ func TestCanDisableBackupService(t *testing.T) { LastRestoredAt: utils.Ptr("test timestamp"), Name: utils.Ptr("test name"), Size: utils.Ptr(int64(5)), - Status: utils.Ptr("test status"), + Status: serverbackup.BACKUPSTATUS_BACKING_UP.Ptr(), VolumeBackups: nil, }, }, diff --git a/internal/pkg/services/service-enablement/utils/utils.go b/internal/pkg/services/service-enablement/utils/utils.go index a6e29254c..5f1976164 100644 --- a/internal/pkg/services/service-enablement/utils/utils.go +++ b/internal/pkg/services/service-enablement/utils/utils.go @@ -6,7 +6,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" - "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/wait" ) const ( @@ -29,5 +28,5 @@ func ProjectEnabled(ctx context.Context, apiClient ServiceEnablementClient, proj } return false, err } - return *project.State == wait.ServiceStateEnabled, nil + return *project.State == serviceenablement.SERVICESTATUSSTATE_ENABLED, nil } diff --git a/internal/pkg/services/service-enablement/utils/utils_test.go b/internal/pkg/services/service-enablement/utils/utils_test.go index 3c364847a..b898adb69 100644 --- a/internal/pkg/services/service-enablement/utils/utils_test.go +++ b/internal/pkg/services/service-enablement/utils/utils_test.go @@ -5,12 +5,9 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/uuid" "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" - "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/wait" ) var ( @@ -45,7 +42,7 @@ func TestProjectEnabled(t *testing.T) { }{ { description: "project enabled", - getProjectResp: &serviceenablement.ServiceStatus{State: utils.Ptr(wait.ServiceStateEnabled)}, + getProjectResp: &serviceenablement.ServiceStatus{State: serviceenablement.SERVICESTATUSSTATE_ENABLED.Ptr()}, isValid: true, expectedOutput: true, }, @@ -57,19 +54,19 @@ func TestProjectEnabled(t *testing.T) { }, { description: "project disabled 1", - getProjectResp: &serviceenablement.ServiceStatus{State: utils.Ptr(wait.ServiceStateEnabling)}, + getProjectResp: &serviceenablement.ServiceStatus{State: serviceenablement.SERVICESTATUSSTATE_ENABLING.Ptr()}, isValid: true, expectedOutput: false, }, { description: "project disabled 2", - getProjectResp: &serviceenablement.ServiceStatus{State: utils.Ptr(wait.ServiceStateDisabled)}, + getProjectResp: &serviceenablement.ServiceStatus{State: serviceenablement.SERVICESTATUSSTATE_DISABLING.Ptr()}, isValid: true, expectedOutput: false, }, { description: "project disabled 3", - getProjectResp: &serviceenablement.ServiceStatus{State: utils.Ptr(wait.ServiceStateDisabling)}, + getProjectResp: &serviceenablement.ServiceStatus{State: serviceenablement.SERVICESTATUSSTATE_DISABLING.Ptr()}, isValid: true, expectedOutput: false, }, diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 452d4b584..283760f63 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -17,7 +17,7 @@ import ( const ( defaultNodepoolAvailabilityZone = "eu01-3" - defaultNodepoolCRI = "containerd" + defaultNodepoolCRI = ske.CRINAME_CONTAINERD defaultNodepoolMachineType = "b1.2" defaultNodepoolMachineImageName = "flatcar" defaultNodepoolMaxSurge = 1 diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index e19c16116..9c6c37ace 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -167,10 +167,10 @@ func fixtureProviderOptions(mods ...func(*ske.ProviderOptions)) *ske.ProviderOpt Version: utils.Ptr("1.2.3"), Cri: &[]ske.CRI{ { - Name: utils.Ptr("not-containerd"), + Name: ske.CRINAME_DOCKER.Ptr(), }, { - Name: utils.Ptr("containerd"), + Name: ske.CRINAME_CONTAINERD.Ptr(), }, }, }, @@ -179,10 +179,10 @@ func fixtureProviderOptions(mods ...func(*ske.ProviderOptions)) *ske.ProviderOpt Version: utils.Ptr("3.2.1"), Cri: &[]ske.CRI{ { - Name: utils.Ptr("not-containerd"), + Name: ske.CRINAME_DOCKER.Ptr(), }, { - Name: utils.Ptr("containerd"), + Name: ske.CRINAME_CONTAINERD.Ptr(), }, }, }, @@ -196,7 +196,7 @@ func fixtureProviderOptions(mods ...func(*ske.ProviderOptions)) *ske.ProviderOpt Version: utils.Ptr("4.4.4"), Cri: &[]ske.CRI{ { - Name: utils.Ptr("containerd"), + Name: ske.CRINAME_CONTAINERD.Ptr(), }, }, }, @@ -219,7 +219,7 @@ func fixtureProviderOptions(mods ...func(*ske.ProviderOptions)) *ske.ProviderOpt Version: utils.Ptr("4.4.4"), Cri: &[]ske.CRI{ { - Name: utils.Ptr("containerd"), + Name: ske.CRINAME_CONTAINERD.Ptr(), }, }, }, @@ -233,7 +233,7 @@ func fixtureProviderOptions(mods ...func(*ske.ProviderOptions)) *ske.ProviderOpt Version: utils.Ptr("4.4.4"), Cri: &[]ske.CRI{ { - Name: utils.Ptr("not-containerd"), + Name: ske.CRINAME_DOCKER.Ptr(), }, }, }, @@ -264,7 +264,7 @@ func fixtureGetDefaultPayload(mods ...func(*ske.CreateOrUpdateClusterPayload)) * "eu01-3", }, Cri: &ske.CRI{ - Name: utils.Ptr("containerd"), + Name: ske.CRINAME_CONTAINERD.Ptr(), }, Machine: &ske.Machine{ Type: utils.Ptr("b1.2"), From 02c137056ba4aee724fcce3b6c6d5a9ce162251d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 13:46:48 +0000 Subject: [PATCH 309/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/redis (#759) Bumps [github.com/stackitcloud/stackit-sdk-go/services/redis](https://github.com/stackitcloud/stackit-sdk-go) from 0.22.2 to 0.24.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.22.2...services/ske/v0.24.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/redis dependency-version: 0.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 681e23976..f4bd3108a 100644 --- a/go.mod +++ b/go.mod @@ -242,7 +242,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 github.com/stackitcloud/stackit-sdk-go/services/observability v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.23.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.33.0 // indirect diff --git a/go.sum b/go.sum index 990d6b2de..ce2106369 100644 --- a/go.sum +++ b/go.sum @@ -592,8 +592,8 @@ github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 h1:AIQueG1oS github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 h1:YEfhKt3T25uY7vs8QcAPfdTs1GLil0BcrLCJ5RhMyR0= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.23.0 h1:arcom/1Chl3+SkDZYRNx5IemkLlqU2mnXrQmg9dsxQI= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.23.0/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0 h1:FZdQwBKyW86l1EwiEUSDsAfhF9si337kNAnagz9ND6A= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0 h1:Rpbt83RyXS0AMw97g5L9oQdCAmVBGAyHpeCcDXesuEk= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0 h1:nvwaviIDf5ffAydfQBrl48K1nPowyDq05ompo9ZzFzY= From c05dbcfa26f00c9a5ee1bcac36384486cfdcc834 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 15:47:14 +0200 Subject: [PATCH 310/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/dns (#760) Bumps [github.com/stackitcloud/stackit-sdk-go/services/dns](https://github.com/stackitcloud/stackit-sdk-go) from 0.13.3 to 0.15.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/dns/v0.13.3...core/v0.15.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/dns dependency-version: 0.15.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f4bd3108a..bbe503aa8 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.14.0 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 diff --git a/go.sum b/go.sum index ce2106369..b71e12411 100644 --- a/go.sum +++ b/go.sum @@ -568,8 +568,8 @@ github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1 h1:7JbFIXiq3IlFST7N7k github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 h1:aXVMNdiHCtT07bro52KjnxEBMDNK9DweJBlk+G4ElCM= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.14.0 h1:aji1vxn1LVfM+SCfOSXUz0Pwv+ZQjyt9PmV0ejHLy5U= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.14.0/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 h1:GQAA9gqhKN0ZRc1vRYURHeVjSghh+iF+5DK0HdeuakI= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 h1:/NXxiJf/NFpj+DFXc07vsx+0he/xufdhIskXUlSeyyw= github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 h1:zh6e2eHgqex++fr6N0RK7wMMBGesC3QhBd42FdTq2Z8= From 398a00513665666daf939e041de6e76daa995084 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 16:26:01 +0200 Subject: [PATCH 311/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/secretsmanager (#764) Bumps [github.com/stackitcloud/stackit-sdk-go/services/secretsmanager](https://github.com/stackitcloud/stackit-sdk-go) from 0.11.4 to 0.12.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/secretsmanager/v0.11.4...core/v0.12.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/secretsmanager dependency-version: 0.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bbe503aa8..2343ac1c1 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.7.0 diff --git a/go.sum b/go.sum index b71e12411..4c033e056 100644 --- a/go.sum +++ b/go.sum @@ -598,8 +598,8 @@ github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0 h1:Rpbt8 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0 h1:nvwaviIDf5ffAydfQBrl48K1nPowyDq05ompo9ZzFzY= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4 h1:UCX1qy44q22bDGv7BhLtOrWCzriS9m4MQsIOX6n+lgM= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.11.4/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 h1:oGR3wRC0xfX2Itpwbh/SrT/k2fnmMSzvy2U9U2lDQPs= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0 h1:cKQAuKSihSX1Jpacub2rZ1StItiO7SIO0y+Fi2yukd4= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 h1:iLyXsBF+lP7iE4rnoK3hO8l4wHcgySRXD65oeUgt6Jc= From d806060671e6c4937be20d13a30f7008b805d5f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 16:26:18 +0200 Subject: [PATCH 312/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serviceaccount (#763) Bumps [github.com/stackitcloud/stackit-sdk-go/services/serviceaccount](https://github.com/stackitcloud/stackit-sdk-go) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.7.0...core/v0.8.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/serviceaccount dependency-version: 0.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2343ac1c1..1753cbf79 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.7.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/ske v0.23.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.1.0 diff --git a/go.sum b/go.sum index 4c033e056..7331de7a1 100644 --- a/go.sum +++ b/go.sum @@ -604,8 +604,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0 h1:cKQAuKSih github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 h1:iLyXsBF+lP7iE4rnoK3hO8l4wHcgySRXD65oeUgt6Jc= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.7.0 h1:QiHkjmforciAfBnf/oMjGmoZWYYD38ZrgLNWK149xQQ= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.7.0/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0 h1:rgSKhgnybB3vrAKAafnuOLjyhn4LtxUxvmgmi810N3U= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0 h1:Wb/eEqbnwLw+lsTlAC8qTFoLMtXOTWcZDUDSiUB7GnM= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= github.com/stackitcloud/stackit-sdk-go/services/ske v0.23.0 h1:kPAYBLDJC8W3GvDt+KtqDl2EZJgbU9l1tUj0JbCWA+4= From 6cf705d8333079cb3f86ce82c2ddc2e9fe7edf86 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 16:26:38 +0200 Subject: [PATCH 313/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/logme (#762) Bumps [github.com/stackitcloud/stackit-sdk-go/services/logme](https://github.com/stackitcloud/stackit-sdk-go) from 0.23.0 to 0.24.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.23.0...services/ske/v0.24.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/logme dependency-version: 0.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1753cbf79..5a28c6ac0 100644 --- a/go.mod +++ b/go.mod @@ -237,7 +237,7 @@ require ( github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.23.0 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 github.com/stackitcloud/stackit-sdk-go/services/observability v0.6.0 diff --git a/go.sum b/go.sum index 7331de7a1..1d1a6d7fc 100644 --- a/go.sum +++ b/go.sum @@ -576,8 +576,8 @@ github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 h1:zh6e2eHgqex++fr6 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0 h1:9gUobm//GzVGYTbfa39tNRceEjQskNuNVZyUS9rOZ4Y= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.23.0 h1:ksxHeILZutooun0Hy/cY8qikC9owya1UDJR+FSQSlRw= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.23.0/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0 h1:5J2TH9ig5cp+5pCHugrsDJuFsRnIOQHQUqsxlweRXL0= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 h1:t/Ten9AuoWFmrDq5gAI3kVZShF3i8zEAaeBsYYqiaao= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 h1:U/IhjLOz0vG6zuxTqGhBd8f609s6JB+X9PaL6x/VM58= From 84c119946fd414e4e7c2199d7dda5ac825eb0007 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 22 May 2025 11:33:27 +0200 Subject: [PATCH 314/619] fix(deps): update stackit sdk modules (#761) * adjust tests for new interfaces --------- Co-authored-by: Renovate Bot Co-authored-by: Marcel Jacek --- go.mod | 32 +++++----- go.sum | 64 +++++++++---------- internal/cmd/beta/alb/list/list_test.go | 5 +- internal/cmd/beta/alb/plans/plans_test.go | 1 - internal/cmd/beta/alb/quotas/quotas_test.go | 1 - internal/cmd/git/create/create_test.go | 2 +- internal/cmd/image/create/create_test.go | 6 +- internal/cmd/image/list/list_test.go | 4 +- internal/cmd/image/update/update_test.go | 6 +- .../observability-credentials/add/add_test.go | 2 +- .../target-pool/add-target/add_target_test.go | 6 +- .../remove-target/remove_target_test.go | 2 +- .../network-area/route/create/create_test.go | 2 +- .../disable/disable_test.go | 2 +- .../public-read-access/enable/enable_test.go | 2 +- .../single-sign-on/disable/disable_test.go | 2 +- .../single-sign-on/enable/enable_test.go | 2 +- internal/cmd/project/list/list_test.go | 2 +- .../cmd/security-group/create/create_test.go | 4 +- internal/cmd/security-group/list/list_test.go | 4 +- .../cmd/security-group/update/update_test.go | 2 +- internal/cmd/server/reboot/reboot_test.go | 2 +- .../load-balancer/utils/utils_test.go | 2 +- 23 files changed, 77 insertions(+), 80 deletions(-) diff --git a/go.mod b/go.mod index 5a28c6ac0..da11cae93 100644 --- a/go.mod +++ b/go.mod @@ -16,23 +16,23 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.1 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 - github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 + github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.22.0 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.23.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 golang.org/x/oauth2 v0.30.0 @@ -236,11 +236,11 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 1d1a6d7fc..60169ba09 100644 --- a/go.sum +++ b/go.sum @@ -564,54 +564,54 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJSjtaGnUI7UE7ITb5IT0= github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1 h1:7JbFIXiq3IlFST7N7kS0gxX5EKX/rYs87kUVtR00sHw= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.3.1/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3 h1:aXVMNdiHCtT07bro52KjnxEBMDNK9DweJBlk+G4ElCM= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.3/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0 h1:l53lihnLUbAORdQPoUL2NlczWfeXfW5gHhoAIPsqGfI= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 h1:VpONplkdlEh7Pf22+cNnnHH4bx+S9QI+z55XYRE74JY= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 h1:GQAA9gqhKN0ZRc1vRYURHeVjSghh+iF+5DK0HdeuakI= github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= -github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3 h1:/NXxiJf/NFpj+DFXc07vsx+0he/xufdhIskXUlSeyyw= -github.com/stackitcloud/stackit-sdk-go/services/git v0.3.3/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2 h1:zh6e2eHgqex++fr6N0RK7wMMBGesC3QhBd42FdTq2Z8= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.2/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0 h1:9gUobm//GzVGYTbfa39tNRceEjQskNuNVZyUS9rOZ4Y= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.1.0/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= +github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0 h1:s0A2EPBrnBxfKStKA/B1izbyYHw/0m2RdqN3Inkv9hI= +github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0 h1:3D34kZSosO25ydqUz72y8sg6yigthKf35DO8SFUyzFU= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.0 h1:gaTgjmEIvq7Nmji5YHh1haFvA/8dWyOgCg3lw6drjL4= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.0/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0 h1:5J2TH9ig5cp+5pCHugrsDJuFsRnIOQHQUqsxlweRXL0= github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 h1:t/Ten9AuoWFmrDq5gAI3kVZShF3i8zEAaeBsYYqiaao= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 h1:U/IhjLOz0vG6zuxTqGhBd8f609s6JB+X9PaL6x/VM58= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3 h1:RFe45uLzTSmd69yaQe5zLDY3+1hYi6/lSZUVcjbb6+c= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.1.3/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.6.0 h1:QqlFcMv/TbIG95u/xHB/9aLvElplj1lKnTIyUSwEtT4= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.6.0/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.22.0 h1:XDt4NCiWdpjbbw9UevsxLJ3SGkO1bSoJnV96RSHNNoI= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.22.0/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4 h1:AIQueG1oSdKbxK8ASZZYkmqzJ7NhKzKcR5AQsndoF18= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.0.4/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 h1:+dKIPVz9ydKbX3x6+1NvYk++OA378w74p+N6SjDmzBQ= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.0 h1:TMHTJvVZj2Ne0tBgKxeSB5kUVP0dx3WQ2YZhbSIMp0E= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.0/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 h1:/OaZCyrD8LFa4W6a2Vu2QSVMJwLLBr8ZdBKzX00MV1Q= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 h1:r29a9GoBLVw2VZSzdPftlIsE5t7shdxobwoT6NVUIjU= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 h1:YEfhKt3T25uY7vs8QcAPfdTs1GLil0BcrLCJ5RhMyR0= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0 h1:FZdQwBKyW86l1EwiEUSDsAfhF9si337kNAnagz9ND6A= github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0 h1:Rpbt83RyXS0AMw97g5L9oQdCAmVBGAyHpeCcDXesuEk= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.14.0/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0 h1:nvwaviIDf5ffAydfQBrl48K1nPowyDq05ompo9ZzFzY= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.1.0/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.15.0 h1:lFxbZmcD+YyMVN35k2UxCpGoqhR+FyfgaOEcdWSOrwQ= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.15.0/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.0 h1:fMtKiC1VwABJXckRTyxLWWMDCNrbVdpCwQ63aBKgR5k= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.0/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 h1:oGR3wRC0xfX2Itpwbh/SrT/k2fnmMSzvy2U9U2lDQPs= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0 h1:cKQAuKSihSX1Jpacub2rZ1StItiO7SIO0y+Fi2yukd4= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.1.0/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3 h1:iLyXsBF+lP7iE4rnoK3hO8l4wHcgySRXD65oeUgt6Jc= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.0.3/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.0 h1:h3tF+yBqrFeRpvyeeGTM33ExA/YYbjwfKYvuZj7gQyM= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.0/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0 h1:WJA2v8XCISdrcbnJXstsjVE+QAFVsDpfJHNp0ORe1Bc= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0 h1:rgSKhgnybB3vrAKAafnuOLjyhn4LtxUxvmgmi810N3U= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0 h1:Wb/eEqbnwLw+lsTlAC8qTFoLMtXOTWcZDUDSiUB7GnM= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.1.0/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.23.0 h1:kPAYBLDJC8W3GvDt+KtqDl2EZJgbU9l1tUj0JbCWA+4= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.23.0/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.1.0 h1:awy7JzBwAVJEKcJVt1DBZtZ0qtdT2aEuWCkgQvKky9w= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.1.0/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.0 h1:7CETDuCaEkA+YDbje6jaWhWO8w05lVxELTs93he9YG8= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.0/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.0 h1:VuX2xLDdPeeXH2+E4FPnTRxGXu68cI62titv4W1V5ic= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.0/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 h1:WvPLO1c7oT/MWmCRTt7jRyxus2g3DIluIW5iAsUpSFM= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/internal/cmd/beta/alb/list/list_test.go b/internal/cmd/beta/alb/list/list_test.go index 547787166..f0fb05146 100644 --- a/internal/cmd/beta/alb/list/list_test.go +++ b/internal/cmd/beta/alb/list/list_test.go @@ -5,12 +5,12 @@ import ( "strconv" "testing" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -49,7 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *alb.ApiListLoadBalancersRequest)) alb.ApiListLoadBalancersRequest { - request := testClient.ListLoadBalancers(context.Background(), testProjectId, testRegion) + request := testClient.ListLoadBalancers(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -160,7 +160,6 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), - cmpopts.IgnoreFields(alb.ApiListLoadBalancersRequest{}, "ctx"), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/beta/alb/plans/plans_test.go b/internal/cmd/beta/alb/plans/plans_test.go index bfbda8586..84b5c9002 100644 --- a/internal/cmd/beta/alb/plans/plans_test.go +++ b/internal/cmd/beta/alb/plans/plans_test.go @@ -156,7 +156,6 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), - cmpopts.IgnoreFields(alb.ApiListLoadBalancersRequest{}, "ctx"), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/beta/alb/quotas/quotas_test.go b/internal/cmd/beta/alb/quotas/quotas_test.go index 1ff2aaacd..6240e20d3 100644 --- a/internal/cmd/beta/alb/quotas/quotas_test.go +++ b/internal/cmd/beta/alb/quotas/quotas_test.go @@ -156,7 +156,6 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), - cmpopts.IgnoreFields(alb.ApiListLoadBalancersRequest{}, "ctx"), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/git/create/create_test.go b/internal/cmd/git/create/create_test.go index 33ed0cc7e..26499bf8b 100644 --- a/internal/cmd/git/create/create_test.go +++ b/internal/cmd/git/create/create_test.go @@ -184,7 +184,7 @@ func TestBuildRequest(t *testing.T) { model.Name = "new-name" }), expectedRequest: fixtureRequest(func(request *git.ApiCreateInstanceRequest) { - *request = request.CreateInstancePayload(fixtureCreatePayload(func(payload *git.CreateInstancePayload) { + *request = (*request).CreateInstancePayload(fixtureCreatePayload(func(payload *git.CreateInstancePayload) { payload.Name = utils.Ptr("new-name") })) }), diff --git a/internal/cmd/image/create/create_test.go b/internal/cmd/image/create/create_test.go index cdf15ce81..e0ed042c9 100644 --- a/internal/cmd/image/create/create_test.go +++ b/internal/cmd/image/create/create_test.go @@ -339,7 +339,7 @@ func TestBuildRequest(t *testing.T) { model.Labels = nil }), expectedRequest: fixtureRequest(func(request *iaas.ApiCreateImageRequest) { - *request = request.CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { + *request = (*request).CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { payload.Labels = nil })) }), @@ -350,7 +350,7 @@ func TestBuildRequest(t *testing.T) { model.Config.CdromBus = utils.Ptr("foobar") }), expectedRequest: fixtureRequest(func(request *iaas.ApiCreateImageRequest) { - *request = request.CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { + *request = (*request).CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { payload.Config.CdromBus = iaas.NewNullableString(utils.Ptr("foobar")) })) }), @@ -361,7 +361,7 @@ func TestBuildRequest(t *testing.T) { model.Config.Uefi = false }), expectedRequest: fixtureRequest(func(request *iaas.ApiCreateImageRequest) { - *request = request.CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { + *request = (*request).CreateImagePayload(fixtureCreatePayload(func(payload *iaas.CreateImagePayload) { payload.Config.Uefi = utils.Ptr(false) })) }), diff --git a/internal/cmd/image/list/list_test.go b/internal/cmd/image/list/list_test.go index c357d3bc1..6437127df 100644 --- a/internal/cmd/image/list/list_test.go +++ b/internal/cmd/image/list/list_test.go @@ -184,7 +184,7 @@ func TestBuildRequest(t *testing.T) { model.LabelSelector = utils.Ptr("") }), expectedRequest: fixtureRequest(func(request *iaas.ApiListImagesRequest) { - *request = request.LabelSelector("") + *request = (*request).LabelSelector("") }), }, { @@ -193,7 +193,7 @@ func TestBuildRequest(t *testing.T) { model.LabelSelector = utils.Ptr("foo=bar") }), expectedRequest: fixtureRequest(func(request *iaas.ApiListImagesRequest) { - *request = request.LabelSelector("foo=bar") + *request = (*request).LabelSelector("foo=bar") }), }, } diff --git a/internal/cmd/image/update/update_test.go b/internal/cmd/image/update/update_test.go index bb313b3c2..17216cbb9 100644 --- a/internal/cmd/image/update/update_test.go +++ b/internal/cmd/image/update/update_test.go @@ -373,7 +373,7 @@ func TestBuildRequest(t *testing.T) { model.Labels = nil }), expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateImageRequest) { - *request = request.UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { + *request = (*request).UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { payload.Labels = nil })) }), @@ -384,7 +384,7 @@ func TestBuildRequest(t *testing.T) { model.Name = utils.Ptr("something else") }), expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateImageRequest) { - *request = request.UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { + *request = (*request).UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { payload.Name = utils.Ptr("something else") })) }), @@ -395,7 +395,7 @@ func TestBuildRequest(t *testing.T) { model.Config.CdromBus = utils.Ptr("something else") }), expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateImageRequest) { - *request = request.UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { + *request = (*request).UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { payload.Config.CdromBus.Set(utils.Ptr("something else")) })) }), diff --git a/internal/cmd/load-balancer/observability-credentials/add/add_test.go b/internal/cmd/load-balancer/observability-credentials/add/add_test.go index 5ee5523f8..bedebaf95 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add_test.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add_test.go @@ -189,7 +189,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), - cmpopts.IgnoreFields(loadbalancer.ApiCreateCredentialsRequest{}, "xRequestID"), + cmpopts.IgnoreFields(loadbalancer.CreateCredentialsRequest{}, "xRequestID"), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go b/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go index 61d2fe4a6..7d7b1799f 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go @@ -338,7 +338,7 @@ func TestBuildRequest(t *testing.T) { }, } }) - *request = request.UpdateTargetPoolPayload(*payload) + *request = (*request).UpdateTargetPoolPayload(*payload) }), }, { @@ -357,7 +357,7 @@ func TestBuildRequest(t *testing.T) { }, } }) - *request = request.UpdateTargetPoolPayload(*payload) + *request = (*request).UpdateTargetPoolPayload(*payload) }), }, { @@ -376,7 +376,7 @@ func TestBuildRequest(t *testing.T) { }, } }) - *request = request.UpdateTargetPoolPayload(*payload) + *request = (*request).UpdateTargetPoolPayload(*payload) }), }, { diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go index d945f3c8e..14bb4fadc 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go @@ -320,7 +320,7 @@ func TestBuildRequest(t *testing.T) { payload := fixturePayload(func(payload *loadbalancer.UpdateTargetPoolPayload) { payload.Targets = utils.Ptr((*payload.Targets)[1:]) }) - *request = request.UpdateTargetPoolPayload(*payload) + *request = (*request).UpdateTargetPoolPayload(*payload) }), }, { diff --git a/internal/cmd/network-area/route/create/create_test.go b/internal/cmd/network-area/route/create/create_test.go index 182555c0c..a1ab93772 100644 --- a/internal/cmd/network-area/route/create/create_test.go +++ b/internal/cmd/network-area/route/create/create_test.go @@ -241,7 +241,7 @@ func TestBuildRequest(t *testing.T) { model.Labels = utils.Ptr(map[string]string{"key": "value"}) }), expectedRequest: fixtureRequest(func(request *iaas.ApiCreateNetworkAreaRouteRequest) { - *request = request.CreateNetworkAreaRoutePayload(fixturePayload(func(payload *iaas.CreateNetworkAreaRoutePayload) { + *request = (*request).CreateNetworkAreaRoutePayload(fixturePayload(func(payload *iaas.CreateNetworkAreaRoutePayload) { (*payload.Ipv4)[0].Labels = utils.Ptr(map[string]interface{}{"key": "value"}) })) }), diff --git a/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go b/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go index a8db1bd9d..9dc5019d2 100644 --- a/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go @@ -262,7 +262,7 @@ func TestBuildRequest(t *testing.T) { }), isValid: true, expectedRequest: fixtureRequest(func(request *observability.ApiUpdateGrafanaConfigsRequest) { - *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { + *request = (*request).UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { payload.GenericOauth = nil })) }), diff --git a/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go b/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go index d425e7078..6d1fbea0a 100644 --- a/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go @@ -262,7 +262,7 @@ func TestBuildRequest(t *testing.T) { }), isValid: true, expectedRequest: fixtureRequest(func(request *observability.ApiUpdateGrafanaConfigsRequest) { - *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { + *request = (*request).UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { payload.GenericOauth = nil })) }), diff --git a/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go index 53c087352..e536ab098 100644 --- a/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go @@ -262,7 +262,7 @@ func TestBuildRequest(t *testing.T) { }), isValid: true, expectedRequest: fixtureRequest(func(request *observability.ApiUpdateGrafanaConfigsRequest) { - *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { + *request = (*request).UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { payload.GenericOauth = nil })) }), diff --git a/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go index cdc464409..033227257 100644 --- a/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go @@ -262,7 +262,7 @@ func TestBuildRequest(t *testing.T) { }), isValid: true, expectedRequest: fixtureRequest(func(request *observability.ApiUpdateGrafanaConfigsRequest) { - *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { + *request = (*request).UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *observability.UpdateGrafanaConfigsPayload) { payload.GenericOauth = nil })) }), diff --git a/internal/cmd/project/list/list_test.go b/internal/cmd/project/list/list_test.go index 79397409f..6d187a9bc 100644 --- a/internal/cmd/project/list/list_test.go +++ b/internal/cmd/project/list/list_test.go @@ -67,7 +67,7 @@ func fixtureRequest(mods ...func(request *resourcemanager.ApiListProjectsRequest testCreationTimeAfter, err := time.Parse(creationTimeAfterFormat, testCreationTimeAfter) if err != nil { - return resourcemanager.ApiListProjectsRequest{} + return resourcemanager.ListProjectsRequest{} } request = request.CreationTimeStart(testCreationTimeAfter) request = request.Member("member") diff --git a/internal/cmd/security-group/create/create_test.go b/internal/cmd/security-group/create/create_test.go index 9b2561489..7b9cbd21e 100644 --- a/internal/cmd/security-group/create/create_test.go +++ b/internal/cmd/security-group/create/create_test.go @@ -227,7 +227,7 @@ func TestBuildRequest(t *testing.T) { model.Labels = nil }), expectedRequest: fixtureRequest(func(request *iaas.ApiCreateSecurityGroupRequest) { - *request = request.CreateSecurityGroupPayload(iaas.CreateSecurityGroupPayload{ + *request = (*request).CreateSecurityGroupPayload(iaas.CreateSecurityGroupPayload{ Description: &testDescription, Labels: nil, Name: &testName, @@ -241,7 +241,7 @@ func TestBuildRequest(t *testing.T) { model.Stateful = utils.Ptr(false) }), expectedRequest: fixtureRequest(func(request *iaas.ApiCreateSecurityGroupRequest) { - *request = request.CreateSecurityGroupPayload(iaas.CreateSecurityGroupPayload{ + *request = (*request).CreateSecurityGroupPayload(iaas.CreateSecurityGroupPayload{ Description: &testDescription, Labels: utils.Ptr(toStringAnyMapPtr(testLabels)), Name: &testName, diff --git a/internal/cmd/security-group/list/list_test.go b/internal/cmd/security-group/list/list_test.go index a78e3501a..bade91812 100644 --- a/internal/cmd/security-group/list/list_test.go +++ b/internal/cmd/security-group/list/list_test.go @@ -178,7 +178,7 @@ func TestBuildRequest(t *testing.T) { model.LabelSelector = utils.Ptr("") }), expectedRequest: fixtureRequest(func(request *iaas.ApiListSecurityGroupsRequest) { - *request = request.LabelSelector("") + *request = (*request).LabelSelector("") }), }, { @@ -187,7 +187,7 @@ func TestBuildRequest(t *testing.T) { model.LabelSelector = utils.Ptr("foo=bar") }), expectedRequest: fixtureRequest(func(request *iaas.ApiListSecurityGroupsRequest) { - *request = request.LabelSelector("foo=bar") + *request = (*request).LabelSelector("foo=bar") }), }, } diff --git a/internal/cmd/security-group/update/update_test.go b/internal/cmd/security-group/update/update_test.go index 3bc10055a..1d89a9e48 100644 --- a/internal/cmd/security-group/update/update_test.go +++ b/internal/cmd/security-group/update/update_test.go @@ -268,7 +268,7 @@ func TestBuildRequest(t *testing.T) { model.Labels = nil }), expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateSecurityGroupRequest) { - *request = request.UpdateSecurityGroupPayload(iaas.UpdateSecurityGroupPayload{ + *request = (*request).UpdateSecurityGroupPayload(iaas.UpdateSecurityGroupPayload{ Description: &testDescription, Labels: nil, Name: &testName, diff --git a/internal/cmd/server/reboot/reboot_test.go b/internal/cmd/server/reboot/reboot_test.go index 77e99f506..cfcda6783 100644 --- a/internal/cmd/server/reboot/reboot_test.go +++ b/internal/cmd/server/reboot/reboot_test.go @@ -199,7 +199,7 @@ func TestBuildRequest(t *testing.T) { model.HardReboot = true }), expectedRequest: fixtureRequest(func(request *iaas.ApiRebootServerRequest) { - *request = request.Action("hard") + *request = (*request).Action("hard") }), }, } diff --git a/internal/pkg/services/load-balancer/utils/utils_test.go b/internal/pkg/services/load-balancer/utils/utils_test.go index e33fd75b8..5941b2c93 100644 --- a/internal/pkg/services/load-balancer/utils/utils_test.go +++ b/internal/pkg/services/load-balancer/utils/utils_test.go @@ -56,7 +56,7 @@ func (m *loadBalancerClientMocked) ListLoadBalancersExecute(_ context.Context, _ } func (m *loadBalancerClientMocked) UpdateTargetPool(_ context.Context, _, _, _, _ string) loadbalancer.ApiUpdateTargetPoolRequest { - return loadbalancer.ApiUpdateTargetPoolRequest{} + return loadbalancer.UpdateTargetPoolRequest{} } func fixtureLoadBalancer(mods ...func(*loadbalancer.LoadBalancer)) *loadbalancer.LoadBalancer { From c944b623a708bef4a1492912c8cd7b47f3672981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 19:04:05 +0200 Subject: [PATCH 315/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/core (#765) Bumps [github.com/stackitcloud/stackit-sdk-go/core](https://github.com/stackitcloud/stackit-sdk-go) from 0.17.1 to 0.17.2. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.17.1...core/v0.17.2) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/core dependency-version: 0.17.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index da11cae93..083a9ff21 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 - github.com/stackitcloud/stackit-sdk-go/core v0.17.1 + github.com/stackitcloud/stackit-sdk-go/core v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 diff --git a/go.sum b/go.sum index 60169ba09..b6ec7f43d 100644 --- a/go.sum +++ b/go.sum @@ -562,8 +562,8 @@ github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJSjtaGnUI7UE7ITb5IT0= -github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= +github.com/stackitcloud/stackit-sdk-go/core v0.17.2 h1:jPyn+i8rkp2hM80+hOg0B/1EVRbMt778Tr5RWyK1m2E= +github.com/stackitcloud/stackit-sdk-go/core v0.17.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0 h1:l53lihnLUbAORdQPoUL2NlczWfeXfW5gHhoAIPsqGfI= github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 h1:VpONplkdlEh7Pf22+cNnnHH4bx+S9QI+z55XYRE74JY= From c97358d37e0ad47a1196685942b7584bee6730d8 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 27 May 2025 09:43:56 +0200 Subject: [PATCH 316/619] chore(deps): update renovatebot/github-action action to v42.0.4 (#768) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 9c914fc30..fad54ed06 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v42.0.3 + uses: renovatebot/github-action@v42.0.4 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 763c365dc46c54b24b93e03f851c74504e793182 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 09:44:27 +0200 Subject: [PATCH 317/619] chore(deps): bump renovatebot/github-action from 42.0.3 to 42.0.4 (#767) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 42.0.3 to 42.0.4. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v42.0.3...v42.0.4) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 42.0.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 9af83eb2358fc4f6bbf19f6fc88a10cba620e07d Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 30 May 2025 10:40:37 +0200 Subject: [PATCH 318/619] fix(deps): update module github.com/goccy/go-yaml to v1.18.0 (#772) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 083a9ff21..6443731c8 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.17.1 + github.com/goccy/go-yaml v1.18.0 github.com/golang-jwt/jwt/v5 v5.2.2 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index b6ec7f43d..bee34c2e2 100644 --- a/go.sum +++ b/go.sum @@ -213,8 +213,8 @@ github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUW github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY= -github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= From 178938c8ff48db33c2a02e6aa4be536afe12e27b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 10:41:00 +0200 Subject: [PATCH 319/619] chore(deps): bump github.com/goccy/go-yaml from 1.17.1 to 1.18.0 (#771) Bumps [github.com/goccy/go-yaml](https://github.com/goccy/go-yaml) from 1.17.1 to 1.18.0. - [Release notes](https://github.com/goccy/go-yaml/releases) - [Changelog](https://github.com/goccy/go-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/goccy/go-yaml/compare/v1.17.1...v1.18.0) --- updated-dependencies: - dependency-name: github.com/goccy/go-yaml dependency-version: 1.18.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From d9564a888641fa34a4677f0d7b88eb9c381cd32e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 08:51:52 +0000 Subject: [PATCH 320/619] chore(deps): bump github.com/lmittmann/tint from 1.1.0 to 1.1.1 (#769) Bumps [github.com/lmittmann/tint](https://github.com/lmittmann/tint) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/lmittmann/tint/releases) - [Commits](https://github.com/lmittmann/tint/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: github.com/lmittmann/tint dependency-version: 1.1.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6443731c8..3b1bfcf65 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jedib0t/go-pretty/v6 v6.6.7 - github.com/lmittmann/tint v1.1.0 + github.com/lmittmann/tint v1.1.1 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 diff --git a/go.sum b/go.sum index bee34c2e2..4fedc90e9 100644 --- a/go.sum +++ b/go.sum @@ -400,8 +400,8 @@ github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/lmittmann/tint v1.1.0 h1:0hDmvuGv3U+Cep/jHpPxwjrCFjT6syam7iY7nTmA7ug= -github.com/lmittmann/tint v1.1.0/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.1.1 h1:xmmGuinUsCSxWdwH1OqMUQ4tzQsq3BdjJLAAmVKJ9Dw= +github.com/lmittmann/tint v1.1.1/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= From b31f6328a831a70e83a93575a9d33670f77fa79d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 3 Jun 2025 14:28:51 +0200 Subject: [PATCH 321/619] feat(ci): add check for goreleaser configuration (#766) --- .github/workflows/ci.yaml | 12 ++++++++++++ .goreleaser.yaml | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 66c094cd5..239a463dc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,3 +25,15 @@ jobs: - name: Test run: make test + + config: + name: Check GoReleaser config + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check GoReleaser + uses: goreleaser/goreleaser-action@v6 + with: + args: check \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 6e766acc7..01e963403 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -45,10 +45,10 @@ builds: ' archives: - - format: tar.gz + - formats: [ 'tar.gz' ] format_overrides: - goos: windows - format: zip + formats: [ 'zip' ] release: # If set to auto, the GitHub release will be marked as "Pre-release" @@ -66,7 +66,7 @@ changelog: nfpms: - id: linux-packages # IDs of the builds for which to create packages for - builds: + ids: - linux-builds package_name: stackit vendor: STACKIT @@ -114,7 +114,7 @@ brews: snapcrafts: # IDs of the builds for which to create packages for - - builds: + - ids: - linux-builds # The name of the snap name: stackit From f26bc5de893f5a2f9175ce48224f60fe3e9e7ed7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 5 Jun 2025 08:27:13 +0200 Subject: [PATCH 322/619] fix(deps): update stackit sdk modules (#779) Co-authored-by: Renovate Bot --- go.mod | 34 ++++++++++++++--------------- go.sum | 68 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/go.mod b/go.mod index 3b1bfcf65..73689825e 100644 --- a/go.mod +++ b/go.mod @@ -16,22 +16,22 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.2 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 - github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1 + github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.15.0 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.24.0 @@ -236,13 +236,13 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.33.0 // indirect diff --git a/go.sum b/go.sum index 4fedc90e9..66574ce96 100644 --- a/go.sum +++ b/go.sum @@ -564,52 +564,52 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.2 h1:jPyn+i8rkp2hM80+hOg0B/1EVRbMt778Tr5RWyK1m2E= github.com/stackitcloud/stackit-sdk-go/core v0.17.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0 h1:l53lihnLUbAORdQPoUL2NlczWfeXfW5gHhoAIPsqGfI= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.0/go.mod h1:IYXv5QX/LEYfF02eN1/1KKo979yPewWhrbhpRnG2yOg= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.1 h1:9IS0yj2ooxzwz9Lb2UtdLrz+Cnn4ckPsebMGuCDKbag= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.1/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 h1:VpONplkdlEh7Pf22+cNnnHH4bx+S9QI+z55XYRE74JY= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 h1:GQAA9gqhKN0ZRc1vRYURHeVjSghh+iF+5DK0HdeuakI= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= -github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0 h1:s0A2EPBrnBxfKStKA/B1izbyYHw/0m2RdqN3Inkv9hI= -github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1 h1:+7iIR5r2epGNkAcuERX4kEg1H8hz2yR9+/zLYqZR7Xk= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= +github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 h1:xs8CMY7t8nULQvZr5+XZRs8yWw8YMVw+HfjcuMhieR4= +github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0 h1:3D34kZSosO25ydqUz72y8sg6yigthKf35DO8SFUyzFU= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.0 h1:gaTgjmEIvq7Nmji5YHh1haFvA/8dWyOgCg3lw6drjL4= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.0/go.mod h1:h3oM6cS23Yfynp8Df1hNr0FxtY5Alii/2g8Wqi5SIVE= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0 h1:5J2TH9ig5cp+5pCHugrsDJuFsRnIOQHQUqsxlweRXL0= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.0/go.mod h1:+3jizYma6Dq3XVn6EMMdSBF9eIm0w6hCJvrStB3AIL0= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0 h1:t/Ten9AuoWFmrDq5gAI3kVZShF3i8zEAaeBsYYqiaao= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.0/go.mod h1:qgvi3qiAzB1wKpMJ5CPnEaUToeiwgnQxGvlkjdisaLU= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 h1:U/IhjLOz0vG6zuxTqGhBd8f609s6JB+X9PaL6x/VM58= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.1 h1:AN8rN13biq3vcJzi2GqGLx84AsuMdnBlPgQj1i83Lmo= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.1/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 h1:hfnILDJGBwwqUIs4xt/7Jj4LBe+JsSdHy+Md2ynUg4Y= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 h1:7nN7ZCuWSbJMy5KqoOqSbp5JKIOvyuDqVRtxVvT1iyE= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 h1:TWz7qJ4Mg5pquDXODSZ1dzhS95ZYn3w1aKjuRU2VqCg= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 h1:+dKIPVz9ydKbX3x6+1NvYk++OA378w74p+N6SjDmzBQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.0 h1:TMHTJvVZj2Ne0tBgKxeSB5kUVP0dx3WQ2YZhbSIMp0E= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.0/go.mod h1:1gMNjPCqT868oIqdWGkiReS1G/qpM4bYKYBmDRi8sqg= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 h1:/OaZCyrD8LFa4W6a2Vu2QSVMJwLLBr8ZdBKzX00MV1Q= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1 h1:6OObzh2zk7wg75zYstcj0kjOjaxWc4joqA6qdeo8DP4= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 h1:E6vCqPn1NiPHnbnvqLNQNz6a/cmeyRb5iA9cDUPtP58= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 h1:r29a9GoBLVw2VZSzdPftlIsE5t7shdxobwoT6NVUIjU= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0 h1:YEfhKt3T25uY7vs8QcAPfdTs1GLil0BcrLCJ5RhMyR0= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.0/go.mod h1:9JoCgKe2IKmawcuAYIuxrAMMb6pk5XiY80Z3sU7IWy0= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0 h1:FZdQwBKyW86l1EwiEUSDsAfhF9si337kNAnagz9ND6A= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.0/go.mod h1:mID7cr40WzI4wdvveYhLzvkk+zPfolfo5+VcDGo5slU= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.15.0 h1:lFxbZmcD+YyMVN35k2UxCpGoqhR+FyfgaOEcdWSOrwQ= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.15.0/go.mod h1:Picm0mP7TUBTAu+MzWtedz61LczMnWH4ghPjwB/g5DE= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.0 h1:fMtKiC1VwABJXckRTyxLWWMDCNrbVdpCwQ63aBKgR5k= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.0/go.mod h1:qId86UiowpDDs0L+mstdzz3xXtnW+R56wh7q8CQltb4= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1 h1:2rDFwJtZOFYFUiJqJ9uIwM+mu+BbtuVaUHARRJtrZPU= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1/go.mod h1:YL0l9l9xzJy2BmV+U9XkcXlQaHbE2KyA37GpGvBXIJ4= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1 h1:4H+GL4eLEO116Vlh0pe+udGGYnMohA8YhLW9KYGdEOc= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1/go.mod h1:PAQH8+1DDGc6uibvC3nDtfRLu8uxutIr25mPJvrCOy8= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0 h1:y8QUHaEdprQJ3VJgOpTVT1nOyTByKsw6k6ccQBoe1wo= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0/go.mod h1:TBvZpbCju0Zmq8GoS4CEtUg2MqtdqWrGeEAOXwkJNQo= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.1 h1:CjlTuoLg1qlAQt+/5a2ElnyEx/Zf1j7j61OJykKfdIM= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.1/go.mod h1:m9f9XZDeKpmqE/G0Sj5Rpdsiw+qcUo0Rcm3idAbyp1c= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 h1:oGR3wRC0xfX2Itpwbh/SrT/k2fnmMSzvy2U9U2lDQPs= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.0 h1:h3tF+yBqrFeRpvyeeGTM33ExA/YYbjwfKYvuZj7gQyM= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.0/go.mod h1:j2GV/ePXEccwq0WV7DtmKpsZcJ2X45Be3D4oAlJdddo= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.1 h1:0Kro/2d0GnqhOFTYq/4r9HwjZB/aT2erC1nyNmI0lnk= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.1/go.mod h1:S/zLsdZvtPXDSYyl7h2GLHhsnVf6AzB96PdslPWevJI= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0 h1:WJA2v8XCISdrcbnJXstsjVE+QAFVsDpfJHNp0ORe1Bc= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0 h1:rgSKhgnybB3vrAKAafnuOLjyhn4LtxUxvmgmi810N3U= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.0/go.mod h1:e3WMlYcUZZ5bpndWuCrxEQqIOPsYPuus9O/EG2eIfG4= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.0 h1:7CETDuCaEkA+YDbje6jaWhWO8w05lVxELTs93he9YG8= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.0/go.mod h1:TYWEik7b2aJrCJrRWU3mn1p1hmShCwizRthT3xl6z0o= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.0 h1:VuX2xLDdPeeXH2+E4FPnTRxGXu68cI62titv4W1V5ic= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.0/go.mod h1:nJTJ3qT2xHmOs2aqQgBPfOLp322gE9pvpRaluTlRmN8= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1 h1:01AIQQtHdJ96La6BPVTRp6SLiGe5LXF+JmDKXbt4ZX0= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1/go.mod h1:t77MA8uyEU9KZd1On5JpnxI3xhVPKIS8WutStqvU8Cw= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 h1:h1TsWatlsexLeKdkb3L8chcxaXJOy/cLXctsRxhb4xg= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1/go.mod h1:M4xZ2BnmROvLV2MrAP6A8o9BnyT0CkvpEcP8lBOfRs8= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.1 h1:X1Q/uHa7voS8mrZZYeJm8TWJ7bW78OMIsHXDd+IB79M= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.1/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 h1:WvPLO1c7oT/MWmCRTt7jRyxus2g3DIluIW5iAsUpSFM= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= From d23703f3f9b6dcafa096bd717200e625273132f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:20:22 +0200 Subject: [PATCH 323/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/iaas (#781) Bumps [github.com/stackitcloud/stackit-sdk-go/services/iaas](https://github.com/stackitcloud/stackit-sdk-go) from 0.23.0 to 0.24.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.23.0...services/ske/v0.24.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/iaas dependency-version: 0.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 73689825e..37aae7089 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 diff --git a/go.sum b/go.sum index 66574ce96..fb577f0c0 100644 --- a/go.sum +++ b/go.sum @@ -572,8 +572,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1 h1:+7iIR5r2epGNkAcuE github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 h1:xs8CMY7t8nULQvZr5+XZRs8yWw8YMVw+HfjcuMhieR4= github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0 h1:3D34kZSosO25ydqUz72y8sg6yigthKf35DO8SFUyzFU= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.23.0/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 h1:aLlZmcsDHqqc7KPsevvs+W6EPZFT51u/dx5TcVQsE6g= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0/go.mod h1:TaMx7kukGpRm0BkNCmS7u2x12q1pgfbD55DAnLIjOIQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.1 h1:AN8rN13biq3vcJzi2GqGLx84AsuMdnBlPgQj1i83Lmo= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.1/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 h1:hfnILDJGBwwqUIs4xt/7Jj4LBe+JsSdHy+Md2ynUg4Y= From 6c8da29b73fbd3ec7a5770f00219ee0551c19b29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Jun 2025 15:28:01 +0000 Subject: [PATCH 324/619] chore(deps): bump golang.org/x/mod from 0.24.0 to 0.25.0 (#780) Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.24.0 to 0.25.0. - [Commits](https://github.com/golang/mod/compare/v0.24.0...v0.25.0) --- updated-dependencies: - dependency-name: golang.org/x/mod dependency-version: 0.25.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 37aae7089..83d1c3a8f 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.24.0 + golang.org/x/mod v0.25.0 golang.org/x/oauth2 v0.30.0 golang.org/x/term v0.32.0 golang.org/x/text v0.25.0 diff --git a/go.sum b/go.sum index fb577f0c0..5c27f0587 100644 --- a/go.sum +++ b/go.sum @@ -752,8 +752,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 6dde93a18c77e777234d90bb2a5083728f01474b Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 6 Jun 2025 13:18:27 +0200 Subject: [PATCH 325/619] fix(deps): update module golang.org/x/text to v0.26.0 (#784) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 83d1c3a8f..76f2bebba 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( golang.org/x/mod v0.25.0 golang.org/x/oauth2 v0.30.0 golang.org/x/term v0.32.0 - golang.org/x/text v0.25.0 + golang.org/x/text v0.26.0 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 ) @@ -206,7 +206,7 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/sync v0.14.0 // indirect + golang.org/x/sync v0.15.0 // indirect golang.org/x/tools v0.33.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 5c27f0587..337a68c44 100644 --- a/go.sum +++ b/go.sum @@ -819,8 +819,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -896,8 +896,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 507e45a8156432acc19944f671e1ccb0f89576f6 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 6 Jun 2025 13:34:51 +0200 Subject: [PATCH 326/619] chore(deps): update module golang.org/x/tools to v0.34.0 (#783) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 76f2bebba..5d7f96d18 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( ) require ( - golang.org/x/net v0.40.0 // indirect + golang.org/x/net v0.41.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -207,7 +207,7 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.15.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/tools v0.34.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect honnef.co/go/tools v0.6.1 // indirect diff --git a/go.sum b/go.sum index 337a68c44..28c2201a4 100644 --- a/go.sum +++ b/go.sum @@ -794,8 +794,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -961,8 +961,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 833ff47953e6f3a4564b99174ba50ccc16d6878e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 10 Jun 2025 09:11:50 +0200 Subject: [PATCH 327/619] fix(deps): update module github.com/lmittmann/tint to v1.1.2 (#785) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5d7f96d18..f5f9b909b 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jedib0t/go-pretty/v6 v6.6.7 - github.com/lmittmann/tint v1.1.1 + github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 diff --git a/go.sum b/go.sum index 28c2201a4..2ea97887b 100644 --- a/go.sum +++ b/go.sum @@ -400,8 +400,8 @@ github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/lmittmann/tint v1.1.1 h1:xmmGuinUsCSxWdwH1OqMUQ4tzQsq3BdjJLAAmVKJ9Dw= -github.com/lmittmann/tint v1.1.1/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= +github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= From 9e00bf9f253db61b0f72dc4a2df15f8f425293c2 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 11 Jun 2025 10:27:39 +0200 Subject: [PATCH 328/619] chore(deps): update renovatebot/github-action action to v42.0.5 (#788) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index fad54ed06..a51dda518 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v42.0.4 + uses: renovatebot/github-action@v42.0.5 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 81fefcd1ffe6e41ab1859e71005b38dc9ccf8492 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:24:36 +0200 Subject: [PATCH 329/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/loadbalancer (#792) Bumps [github.com/stackitcloud/stackit-sdk-go/services/loadbalancer](https://github.com/stackitcloud/stackit-sdk-go) from 1.2.1 to 1.3.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/cdn/v1.2.1...services/loadbalancer/v1.3.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/loadbalancer dependency-version: 1.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f5f9b909b..608303720 100644 --- a/go.mod +++ b/go.mod @@ -236,7 +236,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 diff --git a/go.sum b/go.sum index 2ea97887b..79b6f3d73 100644 --- a/go.sum +++ b/go.sum @@ -574,8 +574,8 @@ github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 h1:xs8CMY7t8nULQvZr5+ github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 h1:aLlZmcsDHqqc7KPsevvs+W6EPZFT51u/dx5TcVQsE6g= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0/go.mod h1:TaMx7kukGpRm0BkNCmS7u2x12q1pgfbD55DAnLIjOIQ= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.1 h1:AN8rN13biq3vcJzi2GqGLx84AsuMdnBlPgQj1i83Lmo= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.2.1/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.3.0 h1:ELclQQLM8pd/60WNC506XeECwu5GupIldvvJOqwZvGw= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.3.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 h1:hfnILDJGBwwqUIs4xt/7Jj4LBe+JsSdHy+Md2ynUg4Y= github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 h1:7nN7ZCuWSbJMy5KqoOqSbp5JKIOvyuDqVRtxVvT1iyE= From 462b064d6a2dc5f1c3826f0a2211054fa991f5b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:32:45 +0200 Subject: [PATCH 330/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/ske (#793) Bumps [github.com/stackitcloud/stackit-sdk-go/services/ske](https://github.com/stackitcloud/stackit-sdk-go) from 0.24.1 to 0.25.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.24.1...services/ske/v0.25.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/ske dependency-version: 0.25.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 608303720..abc9ade22 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.1 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.25.0 diff --git a/go.sum b/go.sum index 79b6f3d73..2487a8862 100644 --- a/go.sum +++ b/go.sum @@ -608,8 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1 h1:01AIQQt github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1/go.mod h1:t77MA8uyEU9KZd1On5JpnxI3xhVPKIS8WutStqvU8Cw= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 h1:h1TsWatlsexLeKdkb3L8chcxaXJOy/cLXctsRxhb4xg= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1/go.mod h1:M4xZ2BnmROvLV2MrAP6A8o9BnyT0CkvpEcP8lBOfRs8= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.1 h1:X1Q/uHa7voS8mrZZYeJm8TWJ7bW78OMIsHXDd+IB79M= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.24.1/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.25.0 h1:9ufUW3J/d29TizLd32Kt4b+4RUN1FRod9Q3X1HbTg58= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.25.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 h1:WvPLO1c7oT/MWmCRTt7jRyxus2g3DIluIW5iAsUpSFM= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= From 2c00ad0eea0e3e1d09c2fbb60be05c1ee4d4254b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:52:21 +0200 Subject: [PATCH 331/619] fix(cli): List mongodb storages returns empty result (#778) --- internal/cmd/mongodbflex/options/options.go | 2 +- internal/cmd/postgresflex/options/options.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 10e9f6f5c..55ad63408 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -225,7 +225,7 @@ func outputResultAsTable(p *print.Printer, model *inputModel, options *options) if model.Versions && len(*options.Versions) != 0 { content = append(content, buildVersionsTable(*options.Versions)) } - if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) == 0 { + if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) > 0 { content = append(content, buildStoragesTable(*options.Storages.Storages)) } diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index 8a3bd6287..c327e030b 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -222,7 +222,7 @@ func outputResultAsTable(p *print.Printer, model inputModel, options *options) e if model.Versions && len(*options.Versions) != 0 { content = append(content, buildVersionsTable(*options.Versions)) } - if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) == 0 { + if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) > 0 { content = append(content, buildStoragesTable(*options.Storages.Storages)) } From 472ff267cdef810d84817df5b4db020334c375fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Fri, 13 Jun 2025 12:48:00 +0200 Subject: [PATCH 332/619] refactor(cli): add ConvertStringMapToInterfaceMap util function (#790) --- internal/cmd/image/create/create.go | 10 +- internal/cmd/image/update/update.go | 11 +-- internal/cmd/key-pair/create/create.go | 11 +-- internal/cmd/key-pair/update/update.go | 10 +- internal/cmd/network-area/create/create.go | 11 +-- .../cmd/network-area/route/create/create.go | 11 +-- .../cmd/network-area/route/update/update.go | 8 +- internal/cmd/network-area/update/update.go | 11 +-- .../cmd/network-interface/create/create.go | 12 +-- .../cmd/network-interface/update/update.go | 12 +-- internal/cmd/network/create/create.go | 11 +-- internal/cmd/network/update/update.go | 11 +-- internal/cmd/public-ip/create/create.go | 11 +-- internal/cmd/public-ip/update/update.go | 11 +-- internal/cmd/security-group/create/create.go | 10 +- internal/cmd/security-group/update/update.go | 10 +- internal/cmd/server/create/create.go | 10 +- internal/cmd/server/update/update.go | 11 +-- internal/pkg/utils/utils.go | 15 +++ internal/pkg/utils/utils_test.go | 99 +++++++++++++++++++ 20 files changed, 133 insertions(+), 173 deletions(-) diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 930811f51..d25c6adc4 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -340,18 +340,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func createPayload(_ context.Context, model *inputModel) iaas.CreateImagePayload { - var labelsMap *map[string]any - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } payload := iaas.CreateImagePayload{ DiskFormat: &model.DiskFormat, Name: &model.Name, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), MinDiskSize: model.MinDiskSize, MinRam: model.MinRam, Protected: model.Protected, diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index e46e90790..02cd034fb 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -243,17 +243,10 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateImageRequest { request := apiClient.UpdateImage(ctx, model.ProjectId, model.Id) payload := iaas.NewUpdateImagePayload() - var labelsMap *map[string]any - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } + // Config *ImageConfig `json:"config,omitempty"` payload.DiskFormat = model.DiskFormat - payload.Labels = labelsMap + payload.Labels = utils.ConvertStringMapToInterfaceMap(model.Labels) payload.MinDiskSize = model.MinDiskSize payload.MinRam = model.MinRam payload.Name = model.Name diff --git a/internal/cmd/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go index 5c4fb9196..a95ee34ec 100644 --- a/internal/cmd/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -124,18 +124,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateKeyPairRequest { req := apiClient.CreateKeyPair(ctx) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.CreateKeyPairPayload{ Name: model.Name, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), PublicKey: model.PublicKey, } diff --git a/internal/cmd/key-pair/update/update.go b/internal/cmd/key-pair/update/update.go index c34c1362b..b8b7ffbbd 100644 --- a/internal/cmd/key-pair/update/update.go +++ b/internal/cmd/key-pair/update/update.go @@ -87,16 +87,8 @@ func configureFlags(cmd *cobra.Command) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateKeyPairRequest { req := apiClient.UpdateKeyPair(ctx, *model.KeyPairName) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } payload := iaas.UpdateKeyPairPayload{ - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } return req.UpdateKeyPairPayload(payload) } diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index 0bc3ae47a..870e6a439 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -172,18 +172,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } } - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.CreateNetworkAreaPayload{ Name: model.Name, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), AddressFamily: &iaas.CreateAreaAddressFamily{ Ipv4: &iaas.CreateAreaIPv4{ DefaultNameservers: model.DnsNameServers, diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index 4cd29e663..781a4c3d0 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -147,21 +147,12 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRouteRequest { req := apiClient.CreateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.CreateNetworkAreaRoutePayload{ Ipv4: &[]iaas.Route{ { Prefix: model.Prefix, Nexthop: model.Nexthop, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), }, }, } diff --git a/internal/cmd/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go index 1fb9f13f6..2866508b2 100644 --- a/internal/cmd/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -130,14 +130,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNetworkAreaRouteRequest { req := apiClient.UpdateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.RouteId) - // convert map[string]string to map[string]interface{} - labelsMap := make(map[string]interface{}) - for k, v := range *model.Labels { - labelsMap[k] = v - } - payload := iaas.UpdateNetworkAreaRoutePayload{ - Labels: &labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } req = req.UpdateNetworkAreaRoutePayload(payload) diff --git a/internal/cmd/network-area/update/update.go b/internal/cmd/network-area/update/update.go index 122e94f33..0cc0e2e1e 100644 --- a/internal/cmd/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -153,18 +153,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiPartialUpdateNetworkAreaRequest { req := apiClient.PartialUpdateNetworkArea(ctx, *model.OrganizationId, model.AreaId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.PartialUpdateNetworkAreaPayload{ Name: model.Name, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), AddressFamily: &iaas.UpdateAreaAddressFamily{ Ipv4: &iaas.UpdateAreaIPv4{ DefaultNameservers: model.DnsNameServers, diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index f1024f844..f96687591 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -207,21 +207,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNicRequest { req := apiClient.CreateNic(ctx, model.ProjectId, *model.NetworkId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - convertedMap := make(map[string]interface{}, len(*model.Labels)) - for k, v := range *model.Labels { - convertedMap[k] = v - } - labelsMap = &convertedMap - } - payload := iaas.CreateNicPayload{ AllowedAddresses: model.AllowedAddresses, Ipv4: model.Ipv4, Ipv6: model.Ipv6, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), Name: model.Name, NicSecurity: model.NicSecurity, SecurityGroups: model.SecurityGroups, diff --git a/internal/cmd/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go index e92c5b8be..92b3e02ab 100644 --- a/internal/cmd/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -199,19 +199,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNicRequest { req := apiClient.UpdateNic(ctx, model.ProjectId, *model.NetworkId, model.NicId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - convertedMap := make(map[string]interface{}, len(*model.Labels)) - for k, v := range *model.Labels { - convertedMap[k] = v - } - labelsMap = &convertedMap - } - payload := iaas.UpdateNicPayload{ AllowedAddresses: model.AllowedAddresses, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), Name: model.Name, NicSecurity: model.NicSecurity, SecurityGroups: model.SecurityGroups, diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index 08e4e20b2..ce5871590 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -229,15 +229,6 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } } - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - routed := true if model.NonRouted { routed = false @@ -245,7 +236,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli payload := iaas.CreateNetworkPayload{ Name: model.Name, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), Routed: &routed, } diff --git a/internal/cmd/network/update/update.go b/internal/cmd/network/update/update.go index 22a8cf87a..712342cfc 100644 --- a/internal/cmd/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -179,15 +179,6 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli req := apiClient.PartialUpdateNetwork(ctx, model.ProjectId, model.NetworkId) addressFamily := &iaas.UpdateNetworkAddressFamily{} - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - if model.IPv6DnsNameServers != nil || model.NoIPv6Gateway || model.IPv6Gateway != nil { addressFamily.Ipv6 = &iaas.UpdateNetworkIPv6Body{ Nameservers: model.IPv6DnsNameServers, @@ -214,7 +205,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli payload := iaas.PartialUpdateNetworkPayload{ Name: model.Name, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } if addressFamily.Ipv4 != nil || addressFamily.Ipv6 != nil { diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index 68252751f..9d29b78d2 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -126,18 +126,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreatePublicIPRequest { req := apiClient.CreatePublicIP(ctx, model.ProjectId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.CreatePublicIPPayload{ NetworkInterface: iaas.NewNullableString(model.AssociatedResourceId), - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } return req.CreatePublicIPPayload(payload) diff --git a/internal/cmd/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go index 939b91ccf..78ae5d13e 100644 --- a/internal/cmd/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -130,17 +130,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdatePublicIPRequest { req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.PublicIpId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.UpdatePublicIPPayload{ - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } return req.UpdatePublicIPPayload(payload) diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index 54f521d26..5bce0c52b 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -127,17 +127,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateSecurityGroupRequest { request := apiClient.CreateSecurityGroup(ctx, model.ProjectId) - var labelsMap *map[string]any - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } payload := iaas.CreateSecurityGroupPayload{ Description: model.Description, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), Name: model.Name, Stateful: model.Stateful, } diff --git a/internal/cmd/security-group/update/update.go b/internal/cmd/security-group/update/update.go index 083470467..487dca9e0 100644 --- a/internal/cmd/security-group/update/update.go +++ b/internal/cmd/security-group/update/update.go @@ -135,15 +135,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli request := apiClient.UpdateSecurityGroup(ctx, model.ProjectId, model.SecurityGroupId) payload := iaas.NewUpdateSecurityGroupPayload() payload.Description = model.Description - var labelsMap *map[string]any - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload.Labels = labelsMap + payload.Labels = utils.ConvertStringMapToInterfaceMap(model.Labels) payload.Name = model.Name request = request.UpdateSecurityGroupPayload(*payload) diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 33b20c247..882c971cb 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -281,14 +281,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateServerRequest { req := apiClient.CreateServer(ctx, model.ProjectId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } var userData *[]byte if model.UserData != nil { @@ -307,7 +299,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli ServiceAccountMails: model.ServiceAccountMails, UserData: userData, Volumes: model.Volumes, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } if model.BootVolumePerformanceClass != nil || model.BootVolumeSize != nil || model.BootVolumeDeleteOnTermination != nil || model.BootVolumeSourceId != nil || model.BootVolumeSourceType != nil { diff --git a/internal/cmd/server/update/update.go b/internal/cmd/server/update/update.go index 7d4c56241..bc6f821a1 100644 --- a/internal/cmd/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -129,18 +129,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateServerRequest { req := apiClient.UpdateServer(ctx, model.ProjectId, model.ServerId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.UpdateServerPayload{ Name: model.Name, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } return req.UpdateServerPayload(payload) diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index 7aff6e713..a26d7b4b2 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -129,3 +129,18 @@ func Base64Encode(message []byte) string { func UserAgentConfigOption(cliVersion string) sdkConfig.ConfigurationOption { return sdkConfig.WithUserAgent(fmt.Sprintf("stackit-cli/%s", cliVersion)) } + +// ConvertStringMapToInterfaceMap converts a map[string]string to a pointer to map[string]interface{}. +// Returns nil if the input map is empty. +// +//nolint:gocritic // Linter wants to have a non-pointer type for the map, but this would mean a nil check has to be done before every usage of this func. +func ConvertStringMapToInterfaceMap(m *map[string]string) *map[string]interface{} { + if m == nil || len(*m) == 0 { + return nil + } + result := make(map[string]interface{}, len(*m)) + for k, v := range *m { + result[k] = v + } + return &result +} diff --git a/internal/pkg/utils/utils_test.go b/internal/pkg/utils/utils_test.go index 894f4f2e2..86588bad8 100644 --- a/internal/pkg/utils/utils_test.go +++ b/internal/pkg/utils/utils_test.go @@ -149,3 +149,102 @@ func TestUserAgentConfigOption(t *testing.T) { }) } } + +func TestConvertStringMapToInterfaceMap(t *testing.T) { + tests := []struct { + name string + input *map[string]string + expected *map[string]interface{} + }{ + { + name: "nil input", + input: nil, + expected: nil, + }, + { + name: "empty map", + input: &map[string]string{}, + expected: nil, + }, + { + name: "single key-value pair", + input: &map[string]string{ + "key1": "value1", + }, + expected: &map[string]interface{}{ + "key1": "value1", + }, + }, + { + name: "multiple key-value pairs", + input: &map[string]string{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + expected: &map[string]interface{}{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + }, + { + name: "special characters in values", + input: &map[string]string{ + "key1": "value with spaces", + "key2": "value,with,commas", + "key3": "value\nwith\nnewlines", + }, + expected: &map[string]interface{}{ + "key1": "value with spaces", + "key2": "value,with,commas", + "key3": "value\nwith\nnewlines", + }, + }, + { + name: "empty values", + input: &map[string]string{ + "key1": "", + "key2": "value2", + }, + expected: &map[string]interface{}{ + "key1": "", + "key2": "value2", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ConvertStringMapToInterfaceMap(tt.input) + + // Check if both are nil + if result == nil && tt.expected == nil { + return + } + + // Check if one is nil and other isn't + if (result == nil && tt.expected != nil) || (result != nil && tt.expected == nil) { + t.Errorf("ConvertStringMapToInterfaceMap() = %v, want %v", result, tt.expected) + return + } + + // Compare maps + if len(*result) != len(*tt.expected) { + t.Errorf("ConvertStringMapToInterfaceMap() map length = %d, want %d", len(*result), len(*tt.expected)) + return + } + + for k, v := range *result { + expectedVal, ok := (*tt.expected)[k] + if !ok { + t.Errorf("ConvertStringMapToInterfaceMap() unexpected key %s in result", k) + continue + } + if v != expectedVal { + t.Errorf("ConvertStringMapToInterfaceMap() value for key %s = %v, want %v", k, v, expectedVal) + } + } + }) + } +} From 056ae2e7275d21d67ee85ff5ab4ef75295895e2e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 13 Jun 2025 12:54:35 +0200 Subject: [PATCH 333/619] fix(deps): update stackit sdk modules (#796) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index abc9ade22..29ef475e5 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.2 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.1 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 @@ -236,7 +236,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 diff --git a/go.sum b/go.sum index 2487a8862..3560b9d7b 100644 --- a/go.sum +++ b/go.sum @@ -564,8 +564,8 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.2 h1:jPyn+i8rkp2hM80+hOg0B/1EVRbMt778Tr5RWyK1m2E= github.com/stackitcloud/stackit-sdk-go/core v0.17.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.1 h1:9IS0yj2ooxzwz9Lb2UtdLrz+Cnn4ckPsebMGuCDKbag= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.4.1/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 h1:7UKUi7Od7KpuVjV4I/jUAV5NEatUomwWFd/IRODbioY= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 h1:VpONplkdlEh7Pf22+cNnnHH4bx+S9QI+z55XYRE74JY= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1 h1:+7iIR5r2epGNkAcuERX4kEg1H8hz2yR9+/zLYqZR7Xk= @@ -574,8 +574,8 @@ github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 h1:xs8CMY7t8nULQvZr5+ github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 h1:aLlZmcsDHqqc7KPsevvs+W6EPZFT51u/dx5TcVQsE6g= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0/go.mod h1:TaMx7kukGpRm0BkNCmS7u2x12q1pgfbD55DAnLIjOIQ= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.3.0 h1:ELclQQLM8pd/60WNC506XeECwu5GupIldvvJOqwZvGw= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.3.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 h1:Ef4SyTBjIkfwaws4mssa6AoK+OokHFtr7ZIflUpoXVE= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 h1:hfnILDJGBwwqUIs4xt/7Jj4LBe+JsSdHy+Md2ynUg4Y= github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 h1:7nN7ZCuWSbJMy5KqoOqSbp5JKIOvyuDqVRtxVvT1iyE= From d3f7641e51902b1e0602ae840c289f5a79f99983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 16 Jun 2025 17:03:42 +0200 Subject: [PATCH 334/619] fix(iaas): prevent nil pointer dereference on empty volume name (#799) relates to STACKITCLI-208 --- internal/cmd/affinity-groups/delete/delete.go | 4 +- internal/cmd/image/delete/delete.go | 6 +- internal/cmd/image/update/update.go | 6 +- internal/cmd/network-area/delete/delete.go | 2 - .../cmd/network-area/describe/describe.go | 5 +- .../network-range/delete/delete.go | 2 - .../network-area/network-range/list/list.go | 6 +- .../cmd/network-area/route/create/create.go | 2 - .../cmd/network-area/route/delete/delete.go | 2 - internal/cmd/network-area/route/list/list.go | 6 +- .../cmd/network-area/route/update/update.go | 6 +- internal/cmd/server/volume/attach/attach.go | 6 +- .../cmd/server/volume/describe/describe.go | 6 +- internal/cmd/server/volume/detach/detach.go | 6 +- internal/cmd/server/volume/list/list.go | 5 +- internal/cmd/server/volume/update/update.go | 6 +- internal/cmd/volume/delete/delete.go | 10 +- internal/pkg/services/iaas/utils/utils.go | 41 ++++++- .../pkg/services/iaas/utils/utils_test.go | 113 +++++++++++++++++- 19 files changed, 173 insertions(+), 67 deletions(-) diff --git a/internal/cmd/affinity-groups/delete/delete.go b/internal/cmd/affinity-groups/delete/delete.go index eab65fd66..a05c2e7bc 100644 --- a/internal/cmd/affinity-groups/delete/delete.go +++ b/internal/cmd/affinity-groups/delete/delete.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "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" @@ -93,7 +93,7 @@ func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClie func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/cmd/image/delete/delete.go b/internal/cmd/image/delete/delete.go index bfce6ae4c..10a49e46d 100644 --- a/internal/cmd/image/delete/delete.go +++ b/internal/cmd/image/delete/delete.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "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" @@ -57,8 +57,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get image name: %v", err) imageName = model.ImageId - } else if imageName == "" { - imageName = model.ImageId } if !model.AssumeYes { @@ -87,7 +85,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index 02cd034fb..f461a388d 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -135,8 +135,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.WarningLevel, "cannot retrieve image name: %v", err) imageLabel = model.Id - } else if imageLabel == "" { - imageLabel = model.Id } if !model.AssumeYes { @@ -194,7 +192,7 @@ func configureFlags(cmd *cobra.Command) { func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/cmd/network-area/delete/delete.go b/internal/cmd/network-area/delete/delete.go index 9664f8305..b545fca4b 100644 --- a/internal/cmd/network-area/delete/delete.go +++ b/internal/cmd/network-area/delete/delete.go @@ -63,8 +63,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = model.AreaId - } else if networkAreaLabel == "" { - networkAreaLabel = model.AreaId } if !model.AssumeYes { diff --git a/internal/cmd/network-area/describe/describe.go b/internal/cmd/network-area/describe/describe.go index 45c2cc4dc..e086f3dd9 100644 --- a/internal/cmd/network-area/describe/describe.go +++ b/internal/cmd/network-area/describe/describe.go @@ -3,6 +3,7 @@ package describe import ( "context" "encoding/json" + "errors" "fmt" "strings" @@ -79,7 +80,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if model.ShowAttachedProjects { projects, err = iaasUtils.ListAttachedProjects(ctx, apiClient, *model.OrganizationId, model.AreaId) - if err != nil { + if err != nil && errors.Is(err, iaasUtils.ErrItemsNil) { + projects = []string{} + } else if err != nil { return fmt.Errorf("get attached projects: %w", err) } } diff --git a/internal/cmd/network-area/network-range/delete/delete.go b/internal/cmd/network-area/network-range/delete/delete.go index fb4f53de0..feec26e6b 100644 --- a/internal/cmd/network-area/network-range/delete/delete.go +++ b/internal/cmd/network-area/network-range/delete/delete.go @@ -61,8 +61,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId - } else if networkAreaLabel == "" { - networkAreaLabel = *model.NetworkAreaId } networkRangeLabel, err := iaasUtils.GetNetworkRangePrefix(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) if err != nil { diff --git a/internal/cmd/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go index e7acd42e8..e4531121f 100644 --- a/internal/cmd/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -8,7 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -81,8 +81,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get organization name: %v", err) networkAreaLabel = *model.NetworkAreaId - } else if networkAreaLabel == "" { - networkAreaLabel = *model.NetworkAreaId } params.Printer.Info("No network ranges found for SNA %q\n", networkAreaLabel) return nil @@ -114,7 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) if limit != nil && *limit < 1 { - return nil, &errors.FlagValidationError{ + return nil, &cliErr.FlagValidationError{ Flag: limitFlag, Details: "must be greater than 0", } diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index 781a4c3d0..bc0eaf5c3 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -74,8 +74,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId - } else if networkAreaLabel == "" { - networkAreaLabel = *model.NetworkAreaId } if !model.AssumeYes { diff --git a/internal/cmd/network-area/route/delete/delete.go b/internal/cmd/network-area/route/delete/delete.go index 11e36eff8..114a5d11d 100644 --- a/internal/cmd/network-area/route/delete/delete.go +++ b/internal/cmd/network-area/route/delete/delete.go @@ -61,8 +61,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId - } else if networkAreaLabel == "" { - networkAreaLabel = *model.NetworkAreaId } if !model.AssumeYes { diff --git a/internal/cmd/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go index 2c099c3f8..2ea248551 100644 --- a/internal/cmd/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -80,8 +80,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId - } else if networkAreaLabel == "" { - networkAreaLabel = *model.NetworkAreaId } params.Printer.Info("No static routes found for STACKIT Network Area %q\n", networkAreaLabel) return nil @@ -113,7 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) if limit != nil && *limit < 1 { - return nil, &errors.FlagValidationError{ + return nil, &cliErr.FlagValidationError{ Flag: limitFlag, Details: "must be greater than 0", } diff --git a/internal/cmd/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go index 2866508b2..f644da320 100644 --- a/internal/cmd/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -70,8 +70,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId - } else if networkAreaLabel == "" { - networkAreaLabel = *model.NetworkAreaId } // Call API @@ -104,7 +102,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu labels := flags.FlagToStringToStringPointer(p, cmd, labelFlag) if labels == nil { - return nil, &errors.EmptyUpdateError{} + return nil, &cliErr.EmptyUpdateError{} } model := inputModel{ diff --git a/internal/cmd/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go index e4c714531..00217c513 100644 --- a/internal/cmd/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -69,8 +69,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId - } else if volumeLabel == "" { - volumeLabel = model.VolumeId } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) @@ -115,7 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu volumeId := inputArgs[0] globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/cmd/server/volume/describe/describe.go b/internal/cmd/server/volume/describe/describe.go index 5b46ced73..be160a2ca 100644 --- a/internal/cmd/server/volume/describe/describe.go +++ b/internal/cmd/server/volume/describe/describe.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -69,8 +69,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId - } else if volumeLabel == "" { - volumeLabel = model.VolumeId } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) @@ -106,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu volumeId := inputArgs[0] globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/cmd/server/volume/detach/detach.go b/internal/cmd/server/volume/detach/detach.go index d794ddcf8..ebd4fb70d 100644 --- a/internal/cmd/server/volume/detach/detach.go +++ b/internal/cmd/server/volume/detach/detach.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -59,8 +59,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId - } else if volumeLabel == "" { - volumeLabel = model.VolumeId } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) @@ -105,7 +103,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu volumeId := inputArgs[0] globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/cmd/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go index 93263daf2..1fab049e4 100644 --- a/internal/cmd/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -83,6 +83,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, *volumes[i].VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = "" } volumeNames = append(volumeNames, volumeLabel) } @@ -104,7 +105,7 @@ func configureFlags(cmd *cobra.Command) { func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/cmd/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go index 768643d36..3e2e4ae6b 100644 --- a/internal/cmd/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -65,8 +65,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId - } else if volumeLabel == "" { - volumeLabel = model.VolumeId } serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) @@ -111,7 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu volumeId := inputArgs[0] globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/cmd/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go index 910e849b4..117c17032 100644 --- a/internal/cmd/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -6,7 +6,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliErr "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" @@ -57,12 +57,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - volumeLabel := model.VolumeId - volumeName, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) - } else if volumeName != "" { - volumeLabel = volumeName + volumeLabel = model.VolumeId } if !model.AssumeYes { @@ -107,7 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } model := inputModel{ diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index b3456d254..f2616a01a 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -2,11 +2,18 @@ package utils import ( "context" + "errors" "fmt" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +var ( + ErrResponseNil = errors.New("response is nil") + ErrNameNil = errors.New("name is nil") + ErrItemsNil = errors.New("items is nil") +) + type IaaSClient interface { GetSecurityGroupRuleExecute(ctx context.Context, projectId, securityGroupRuleId, securityGroupId string) (*iaas.SecurityGroupRule, error) GetSecurityGroupExecute(ctx context.Context, projectId, securityGroupId string) (*iaas.SecurityGroup, error) @@ -34,6 +41,10 @@ func GetSecurityGroupName(ctx context.Context, apiClient IaaSClient, projectId, resp, err := apiClient.GetSecurityGroupExecute(ctx, projectId, securityGroupId) if err != nil { return "", fmt.Errorf("get security group: %w", err) + } else if resp == nil { + return "", ErrResponseNil + } else if resp.Name == nil { + return "", ErrNameNil } return *resp.Name, nil } @@ -62,6 +73,10 @@ func GetVolumeName(ctx context.Context, apiClient IaaSClient, projectId, volumeI resp, err := apiClient.GetVolumeExecute(ctx, projectId, volumeId) if err != nil { return "", fmt.Errorf("get volume: %w", err) + } else if resp == nil { + return "", ErrResponseNil + } else if resp.Name == nil { + return "", ErrNameNil } return *resp.Name, nil } @@ -70,6 +85,10 @@ func GetNetworkName(ctx context.Context, apiClient IaaSClient, projectId, networ resp, err := apiClient.GetNetworkExecute(ctx, projectId, networkId) if err != nil { return "", fmt.Errorf("get network: %w", err) + } else if resp == nil { + return "", ErrResponseNil + } else if resp.Name == nil { + return "", ErrNameNil } return *resp.Name, nil } @@ -78,6 +97,10 @@ func GetNetworkAreaName(ctx context.Context, apiClient IaaSClient, organizationI resp, err := apiClient.GetNetworkAreaExecute(ctx, organizationId, areaId) if err != nil { return "", fmt.Errorf("get network area: %w", err) + } else if resp == nil { + return "", ErrResponseNil + } else if resp.Name == nil { + return "", ErrNameNil } return *resp.Name, nil } @@ -86,6 +109,10 @@ func ListAttachedProjects(ctx context.Context, apiClient IaaSClient, organizatio resp, err := apiClient.ListNetworkAreaProjectsExecute(ctx, organizationId, areaId) if err != nil { return nil, fmt.Errorf("list network area attached projects: %w", err) + } else if resp == nil { + return nil, ErrResponseNil + } else if resp.Items == nil { + return nil, ErrItemsNil } return *resp.Items, nil } @@ -124,9 +151,10 @@ func GetImageName(ctx context.Context, apiClient IaaSClient, projectId, imageId resp, err := apiClient.GetImageExecute(ctx, projectId, imageId) if err != nil { return "", fmt.Errorf("get image: %w", err) - } - if resp.Name == nil { - return "", nil + } else if resp == nil { + return "", ErrResponseNil + } else if resp.Name == nil { + return "", ErrNameNil } return *resp.Name, nil } @@ -135,9 +163,10 @@ func GetAffinityGroupName(ctx context.Context, apiClient IaaSClient, projectId, resp, err := apiClient.GetAffinityGroupExecute(ctx, projectId, affinityGroupId) if err != nil { return "", fmt.Errorf("get affinity group: %w", err) - } - if resp.Name == nil { - return "", nil + } else if resp == nil { + return "", ErrResponseNil + } else if resp.Name == nil { + return "", ErrNameNil } return *resp.Name, nil } diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index d62dac35c..f4375251d 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -186,6 +186,26 @@ func TestGetSecurityGroupName(t *testing.T) { }, wantErr: true, }, + { + name: "response is nil", + args: args{ + getInstanceResp: nil, + getInstanceFails: false, + }, + wantErr: true, + want: "", + }, + { + name: "name in response is nil", + args: args{ + getInstanceResp: &iaas.SecurityGroup{ + Name: nil, + }, + getInstanceFails: false, + }, + wantErr: true, + want: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -330,6 +350,26 @@ func TestGetVolumeName(t *testing.T) { }, wantErr: true, }, + { + name: "response is nil", + args: args{ + getInstanceResp: nil, + getInstanceFails: false, + }, + wantErr: true, + want: "", + }, + { + name: "name in response is nil", + args: args{ + getInstanceResp: &iaas.Volume{ + Name: nil, + }, + getInstanceFails: false, + }, + wantErr: true, + want: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -376,6 +416,26 @@ func TestGetNetworkName(t *testing.T) { }, wantErr: true, }, + { + name: "response is nil", + args: args{ + getInstanceResp: nil, + getInstanceFails: false, + }, + wantErr: true, + want: "", + }, + { + name: "name in response is nil", + args: args{ + getInstanceResp: &iaas.Network{ + Name: nil, + }, + getInstanceFails: false, + }, + wantErr: true, + want: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -421,6 +481,27 @@ func TestGetNetworkAreaName(t *testing.T) { getInstanceFails: true, }, wantErr: true, + want: "", + }, + { + name: "response is nil", + args: args{ + getInstanceResp: nil, + getInstanceFails: false, + }, + wantErr: true, + want: "", + }, + { + name: "name in response is nil", + args: args{ + getInstanceResp: &iaas.NetworkArea{ + Name: nil, + }, + getInstanceFails: false, + }, + wantErr: true, + want: "", }, } for _, tt := range tests { @@ -701,10 +782,18 @@ func TestGetImageName(t *testing.T) { wantErr: true, }, { - name: "nil name", + name: "response is nil", + imageErr: false, + imageResp: nil, + want: "", + wantErr: true, + }, + { + name: "name in response is nil", imageErr: false, - imageResp: &iaas.Image{}, + imageResp: &iaas.Image{Name: nil}, want: "", + wantErr: true, }, } for _, tt := range tests { @@ -745,10 +834,22 @@ func TestGetAffinityGroupName(t *testing.T) { wantErr: true, }, { - name: "nil affinity group name", - affinityErr: false, - affinityResp: &iaas.AffinityGroup{}, - want: "", + name: "response is nil", + affinityErr: false, + affinityResp: &iaas.AffinityGroup{ + Name: nil, + }, + want: "", + wantErr: true, + }, + { + name: "affinity group name in response is nil", + affinityErr: false, + affinityResp: &iaas.AffinityGroup{ + Name: nil, + }, + want: "", + wantErr: true, }, } for _, tt := range tests { From ee4633e72c8f9260b85716f055ea78944d348099 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 18:22:26 +0200 Subject: [PATCH 335/619] chore(deps): bump renovatebot/github-action from 42.0.5 to 42.0.6 (#800) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 42.0.5 to 42.0.6. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v42.0.5...v42.0.6) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 42.0.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index a51dda518..27f85d5ee 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v42.0.5 + uses: renovatebot/github-action@v42.0.6 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From cf9ff846e38068c8be8abec7bc69fd8f9f42dcef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 17 Jun 2025 13:00:44 +0200 Subject: [PATCH 336/619] fix(ci): split goreleaser post hook into multiple steps (#803) --- .goreleaser.yaml | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 01e963403..99b8757e1 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -32,17 +32,22 @@ builds: - amd64 hooks: post: - - | - sh -c ' - codesign -s "{{.Env.APPLE_APPLICATION_IDENTITY}}" -f -v --options=runtime "dist/macos-builds_{{.Target}}/{{.Name}}" - codesign -vvv --deep --strict "dist/macos-builds_{{.Target}}/{{.Name}}" - ls -l "dist/macos_{{.Target}}" - hdiutil create -volname "STACKIT-CLI" -srcfolder "dist/macos-builds_{{.Target}}/{{.Name}}" -ov -format UDZO "dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg" - codesign -s "{{.Env.APPLE_APPLICATION_IDENTITY}}" -f -v --options=runtime "dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg" - xcrun notarytool submit --keychain-profile "stackit-cli" --wait --progress dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg - xcrun stapler staple "dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg" - spctl -a -t open --context context:primary-signature -v dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg - ' + - cmd: codesign -s "{{.Env.APPLE_APPLICATION_IDENTITY}}" -f -v --options=runtime "dist/macos-builds_{{.Target}}/{{.Name}}" + output: true + - cmd: codesign -vvv --deep --strict "dist/macos-builds_{{.Target}}/{{.Name}}" + output: true + - cmd: ls -l "dist/macos_{{.Target}}" + output: true + - cmd: hdiutil create -volname "STACKIT-CLI" -srcfolder "dist/macos-builds_{{.Target}}/{{.Name}}" -ov -format UDZO "dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg" + output: true + - cmd: codesign -s "{{.Env.APPLE_APPLICATION_IDENTITY}}" -f -v --options=runtime "dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg" + output: true + - cmd: xcrun notarytool submit --keychain-profile "stackit-cli" --wait --progress dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg + output: true + - cmd: xcrun stapler staple "dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg" + output: true + - cmd: spctl -a -t open --context context:primary-signature -v dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg + output: true archives: - formats: [ 'tar.gz' ] @@ -151,4 +156,4 @@ winget: base: owner: microsoft name: winget-pkgs - branch: master \ No newline at end of file + branch: master From 793ae0f6408910b522d0a7613f712c609d1c2221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Tue, 17 Jun 2025 13:11:09 +0200 Subject: [PATCH 337/619] feat(cli): onboard iaas volume backup api (#773) relates to STACKITCLI-192 --- docs/stackit_volume.md | 1 + docs/stackit_volume_backup.md | 39 +++ docs/stackit_volume_backup_create.md | 50 +++ docs/stackit_volume_backup_delete.md | 40 +++ docs/stackit_volume_backup_describe.md | 43 +++ docs/stackit_volume_backup_list.md | 51 +++ docs/stackit_volume_backup_restore.md | 40 +++ docs/stackit_volume_backup_update.md | 45 +++ go.mod | 8 +- go.sum | 16 +- internal/cmd/volume/backup/backup.go | 36 ++ internal/cmd/volume/backup/create/create.go | 226 +++++++++++++ .../cmd/volume/backup/create/create_test.go | 309 ++++++++++++++++++ internal/cmd/volume/backup/delete/delete.go | 125 +++++++ .../cmd/volume/backup/delete/delete_test.go | 183 +++++++++++ .../cmd/volume/backup/describe/describe.go | 162 +++++++++ .../volume/backup/describe/describe_test.go | 217 ++++++++++++ internal/cmd/volume/backup/list/list.go | 202 ++++++++++++ internal/cmd/volume/backup/list/list_test.go | 233 +++++++++++++ internal/cmd/volume/backup/restore/restore.go | 138 ++++++++ .../cmd/volume/backup/restore/restore_test.go | 183 +++++++++++ internal/cmd/volume/backup/update/update.go | 168 ++++++++++ .../cmd/volume/backup/update/update_test.go | 192 +++++++++++ internal/cmd/volume/create/create.go | 11 +- internal/cmd/volume/update/update.go | 11 +- internal/cmd/volume/volume.go | 2 + internal/pkg/services/iaas/utils/utils.go | 21 ++ .../pkg/services/iaas/utils/utils_test.go | 17 + 28 files changed, 2737 insertions(+), 32 deletions(-) create mode 100644 docs/stackit_volume_backup.md create mode 100644 docs/stackit_volume_backup_create.md create mode 100644 docs/stackit_volume_backup_delete.md create mode 100644 docs/stackit_volume_backup_describe.md create mode 100644 docs/stackit_volume_backup_list.md create mode 100644 docs/stackit_volume_backup_restore.md create mode 100644 docs/stackit_volume_backup_update.md create mode 100644 internal/cmd/volume/backup/backup.go create mode 100644 internal/cmd/volume/backup/create/create.go create mode 100644 internal/cmd/volume/backup/create/create_test.go create mode 100644 internal/cmd/volume/backup/delete/delete.go create mode 100644 internal/cmd/volume/backup/delete/delete_test.go create mode 100644 internal/cmd/volume/backup/describe/describe.go create mode 100644 internal/cmd/volume/backup/describe/describe_test.go create mode 100644 internal/cmd/volume/backup/list/list.go create mode 100644 internal/cmd/volume/backup/list/list_test.go create mode 100644 internal/cmd/volume/backup/restore/restore.go create mode 100644 internal/cmd/volume/backup/restore/restore_test.go create mode 100644 internal/cmd/volume/backup/update/update.go create mode 100644 internal/cmd/volume/backup/update/update_test.go diff --git a/docs/stackit_volume.md b/docs/stackit_volume.md index c83878554..4955b6299 100644 --- a/docs/stackit_volume.md +++ b/docs/stackit_volume.md @@ -30,6 +30,7 @@ stackit volume [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit volume backup](./stackit_volume_backup.md) - Provides functionality for volume backups * [stackit volume create](./stackit_volume_create.md) - Creates a volume * [stackit volume delete](./stackit_volume_delete.md) - Deletes a volume * [stackit volume describe](./stackit_volume_describe.md) - Shows details of a volume diff --git a/docs/stackit_volume_backup.md b/docs/stackit_volume_backup.md new file mode 100644 index 000000000..f6390f385 --- /dev/null +++ b/docs/stackit_volume_backup.md @@ -0,0 +1,39 @@ +## stackit volume backup + +Provides functionality for volume backups + +### Synopsis + +Provides functionality for volume backups. + +``` +stackit volume backup [flags] +``` + +### Options + +``` + -h, --help Help for "stackit volume backup" +``` + +### 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 volume](./stackit_volume.md) - Provides functionality for volumes +* [stackit volume backup create](./stackit_volume_backup_create.md) - Creates a backup from a specific source +* [stackit volume backup delete](./stackit_volume_backup_delete.md) - Deletes a backup +* [stackit volume backup describe](./stackit_volume_backup_describe.md) - Describes a backup +* [stackit volume backup list](./stackit_volume_backup_list.md) - Lists all backups +* [stackit volume backup restore](./stackit_volume_backup_restore.md) - Restores a backup +* [stackit volume backup update](./stackit_volume_backup_update.md) - Updates a backup + diff --git a/docs/stackit_volume_backup_create.md b/docs/stackit_volume_backup_create.md new file mode 100644 index 000000000..5a322f34a --- /dev/null +++ b/docs/stackit_volume_backup_create.md @@ -0,0 +1,50 @@ +## stackit volume backup create + +Creates a backup from a specific source + +### Synopsis + +Creates a backup from a specific source (volume or snapshot). + +``` +stackit volume backup create [flags] +``` + +### Examples + +``` + Create a backup from a volume + $ stackit volume backup create --source-id xxx --source-type volume + + Create a backup from a snapshot with a name + $ stackit volume backup create --source-id xxx --source-type snapshot --name my-backup + + Create a backup with labels + $ stackit volume backup create --source-id xxx --source-type volume --labels key1=value1,key2=value2 +``` + +### Options + +``` + -h, --help Help for "stackit volume backup create" + --labels stringToString Key-value string pairs as labels (default []) + --name string Name of the backup + --source-id string ID of the source from which a backup should be created + --source-type string Source type of the backup, one of ["volume" "snapshot"] +``` + +### 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 volume backup](./stackit_volume_backup.md) - Provides functionality for volume backups + diff --git a/docs/stackit_volume_backup_delete.md b/docs/stackit_volume_backup_delete.md new file mode 100644 index 000000000..5300f7854 --- /dev/null +++ b/docs/stackit_volume_backup_delete.md @@ -0,0 +1,40 @@ +## stackit volume backup delete + +Deletes a backup + +### Synopsis + +Deletes a backup by its ID. + +``` +stackit volume backup delete BACKUP_ID [flags] +``` + +### Examples + +``` + Delete a backup with ID "xxx" + $ stackit volume backup delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit volume backup delete" +``` + +### 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 volume backup](./stackit_volume_backup.md) - Provides functionality for volume backups + diff --git a/docs/stackit_volume_backup_describe.md b/docs/stackit_volume_backup_describe.md new file mode 100644 index 000000000..dbff5e4dc --- /dev/null +++ b/docs/stackit_volume_backup_describe.md @@ -0,0 +1,43 @@ +## stackit volume backup describe + +Describes a backup + +### Synopsis + +Describes a backup by its ID. + +``` +stackit volume backup describe BACKUP_ID [flags] +``` + +### Examples + +``` + Get details of a backup with ID "xxx" + $ stackit volume backup describe xxx + + Get details of a backup with ID "xxx" in JSON format + $ stackit volume backup describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit volume backup 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 volume backup](./stackit_volume_backup.md) - Provides functionality for volume backups + diff --git a/docs/stackit_volume_backup_list.md b/docs/stackit_volume_backup_list.md new file mode 100644 index 000000000..91f3ca99a --- /dev/null +++ b/docs/stackit_volume_backup_list.md @@ -0,0 +1,51 @@ +## stackit volume backup list + +Lists all backups + +### Synopsis + +Lists all backups in a project. + +``` +stackit volume backup list [flags] +``` + +### Examples + +``` + List all backups + $ stackit volume backup list + + List all backups in JSON format + $ stackit volume backup list --output-format json + + List up to 10 backups + $ stackit volume backup list --limit 10 + + List backups with specific labels + $ stackit volume backup list --label-selector key1=value1,key2=value2 +``` + +### Options + +``` + -h, --help Help for "stackit volume backup list" + --label-selector string Filter backups by labels + --limit int Maximum number of entries to list +``` + +### 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 volume backup](./stackit_volume_backup.md) - Provides functionality for volume backups + diff --git a/docs/stackit_volume_backup_restore.md b/docs/stackit_volume_backup_restore.md new file mode 100644 index 000000000..80dc563db --- /dev/null +++ b/docs/stackit_volume_backup_restore.md @@ -0,0 +1,40 @@ +## stackit volume backup restore + +Restores a backup + +### Synopsis + +Restores a backup by its ID. + +``` +stackit volume backup restore BACKUP_ID [flags] +``` + +### Examples + +``` + Restore a backup with ID "xxx" + $ stackit volume backup restore xxx +``` + +### Options + +``` + -h, --help Help for "stackit volume backup restore" +``` + +### 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 volume backup](./stackit_volume_backup.md) - Provides functionality for volume backups + diff --git a/docs/stackit_volume_backup_update.md b/docs/stackit_volume_backup_update.md new file mode 100644 index 000000000..02f86f4e8 --- /dev/null +++ b/docs/stackit_volume_backup_update.md @@ -0,0 +1,45 @@ +## stackit volume backup update + +Updates a backup + +### Synopsis + +Updates a backup by its ID. + +``` +stackit volume backup update BACKUP_ID [flags] +``` + +### Examples + +``` + Update the name of a backup with ID "xxx" + $ stackit volume backup update xxx --name new-name + + Update the labels of a backup with ID "xxx" + $ stackit volume backup update xxx --labels key1=value1,key2=value2 +``` + +### Options + +``` + -h, --help Help for "stackit volume backup update" + --labels stringToString Key-value string pairs as labels (default []) + --name string Name of the backup +``` + +### 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 volume backup](./stackit_volume_backup.md) - Provides functionality for volume backups + diff --git a/go.mod b/go.mod index 29ef475e5..c3bb00c1f 100644 --- a/go.mod +++ b/go.mod @@ -18,11 +18,11 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1 - github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.1 diff --git a/go.sum b/go.sum index 3560b9d7b..6bd663516 100644 --- a/go.sum +++ b/go.sum @@ -568,10 +568,10 @@ github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 h1:7UKUi7Od7KpuVjV4I/ github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 h1:VpONplkdlEh7Pf22+cNnnHH4bx+S9QI+z55XYRE74JY= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1 h1:+7iIR5r2epGNkAcuERX4kEg1H8hz2yR9+/zLYqZR7Xk= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.1/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= -github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 h1:xs8CMY7t8nULQvZr5+XZRs8yWw8YMVw+HfjcuMhieR4= -github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 h1:GQAA9gqhKN0ZRc1vRYURHeVjSghh+iF+5DK0HdeuakI= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= +github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0 h1:s0A2EPBrnBxfKStKA/B1izbyYHw/0m2RdqN3Inkv9hI= +github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 h1:aLlZmcsDHqqc7KPsevvs+W6EPZFT51u/dx5TcVQsE6g= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0/go.mod h1:TaMx7kukGpRm0BkNCmS7u2x12q1pgfbD55DAnLIjOIQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 h1:Ef4SyTBjIkfwaws4mssa6AoK+OokHFtr7ZIflUpoXVE= @@ -580,14 +580,14 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 h1:hfnILDJGBwwqUIs github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 h1:7nN7ZCuWSbJMy5KqoOqSbp5JKIOvyuDqVRtxVvT1iyE= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 h1:TWz7qJ4Mg5pquDXODSZ1dzhS95ZYn3w1aKjuRU2VqCg= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 h1:U/IhjLOz0vG6zuxTqGhBd8f609s6JB+X9PaL6x/VM58= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 h1:+dKIPVz9ydKbX3x6+1NvYk++OA378w74p+N6SjDmzBQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1 h1:6OObzh2zk7wg75zYstcj0kjOjaxWc4joqA6qdeo8DP4= github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 h1:E6vCqPn1NiPHnbnvqLNQNz6a/cmeyRb5iA9cDUPtP58= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 h1:/OaZCyrD8LFa4W6a2Vu2QSVMJwLLBr8ZdBKzX00MV1Q= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 h1:r29a9GoBLVw2VZSzdPftlIsE5t7shdxobwoT6NVUIjU= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1 h1:2rDFwJtZOFYFUiJqJ9uIwM+mu+BbtuVaUHARRJtrZPU= diff --git a/internal/cmd/volume/backup/backup.go b/internal/cmd/volume/backup/backup.go new file mode 100644 index 000000000..b7cf8b37b --- /dev/null +++ b/internal/cmd/volume/backup/backup.go @@ -0,0 +1,36 @@ +package backup + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/restore" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "backup", + Short: "Provides functionality for volume backups", + Long: "Provides functionality for volume backups.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(restore.NewCmd(params)) +} diff --git a/internal/cmd/volume/backup/create/create.go b/internal/cmd/volume/backup/create/create.go new file mode 100644 index 000000000..447a3ea16 --- /dev/null +++ b/internal/cmd/volume/backup/create/create.go @@ -0,0 +1,226 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasutils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" +) + +const ( + sourceIdFlag = "source-id" + sourceTypeFlag = "source-type" + nameFlag = "name" + labelsFlag = "labels" +) + +var sourceTypeFlagOptions = []string{"volume", "snapshot"} + +type inputModel struct { + *globalflags.GlobalFlagModel + SourceID string + SourceType string + Name *string + Labels map[string]string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a backup from a specific source", + Long: "Creates a backup from a specific source (volume or snapshot).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a backup from a volume`, + "$ stackit volume backup create --source-id xxx --source-type volume"), + examples.NewExample( + `Create a backup from a snapshot with a name`, + "$ stackit volume backup create --source-id xxx --source-type snapshot --name my-backup"), + examples.NewExample( + `Create a backup with labels`, + "$ stackit volume backup create --source-id xxx --source-type volume --labels key1=value1,key2=value2"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + 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 + } + + // Get source name for label (use ID if name not available) + sourceLabel := model.SourceID + if model.SourceType == "volume" { + name, err := iaasutils.GetVolumeName(ctx, apiClient, model.ProjectId, model.SourceID) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) + } else if name != "" { + sourceLabel = name + } + } else if model.SourceType == "snapshot" { + name, err := iaasutils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.SourceID) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get snapshot name: %v", err) + } else if name != "" { + sourceLabel = name + } + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create backup from %s? (This cannot be undone)", sourceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create volume backup: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Creating backup") + resp, err = wait.CreateBackupWaitHandler(ctx, apiClient, model.ProjectId, *resp.Id).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for backup creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model.OutputFormat, model.Async, sourceLabel, projectLabel, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(sourceIdFlag, "", "ID of the source from which a backup should be created") + cmd.Flags().Var(flags.EnumFlag(false, "", sourceTypeFlagOptions...), sourceTypeFlag, fmt.Sprintf("Source type of the backup, one of %q", sourceTypeFlagOptions)) + cmd.Flags().String(nameFlag, "", "Name of the backup") + cmd.Flags().StringToString(labelsFlag, nil, "Key-value string pairs as labels") + + err := flags.MarkFlagsRequired(cmd, sourceIdFlag, sourceTypeFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + sourceID := flags.FlagToStringValue(p, cmd, sourceIdFlag) + if sourceID == "" { + return nil, fmt.Errorf("source-id is required") + } + + sourceType := flags.FlagToStringValue(p, cmd, sourceTypeFlag) + + name := flags.FlagToStringPointer(p, cmd, nameFlag) + labels := flags.FlagToStringToStringPointer(p, cmd, labelsFlag) + if labels == nil { + labels = &map[string]string{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SourceID: sourceID, + SourceType: sourceType, + Name: name, + Labels: *labels, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateBackupRequest { + req := apiClient.CreateBackup(ctx, model.ProjectId) + + payload := iaas.CreateBackupPayload{ + Name: model.Name, + Labels: utils.ConvertStringMapToInterfaceMap(utils.Ptr(model.Labels)), + Source: &iaas.BackupSource{ + Id: &model.SourceID, + Type: &model.SourceType, + }, + } + + return req.CreateBackupPayload(payload) +} + +func outputResult(p *print.Printer, outputFormat string, async bool, sourceLabel, projectLabel string, resp *iaas.Backup) error { + if resp == nil { + return fmt.Errorf("create backup response is empty") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal backup: %w", err) + } + p.Outputln(string(details)) + return nil + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal backup: %w", err) + } + p.Outputln(string(details)) + return nil + + default: + if async { + p.Outputf("Triggered backup of %s in %s. Backup ID: %s\n", sourceLabel, projectLabel, utils.PtrString(resp.Id)) + } else { + p.Outputf("Created backup of %s in %s. Backup ID: %s\n", sourceLabel, projectLabel, utils.PtrString(resp.Id)) + } + return nil + } +} diff --git a/internal/cmd/volume/backup/create/create_test.go b/internal/cmd/volume/backup/create/create_test.go new file mode 100644 index 000000000..3c4980cc6 --- /dev/null +++ b/internal/cmd/volume/backup/create/create_test.go @@ -0,0 +1,309 @@ +package create + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +const ( + testName = "my-backup" + testSourceType = "volume" +) + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testSourceId = uuid.NewString() + testLabels = map[string]string{"key1": "value1"} +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + sourceIdFlag: testSourceId, + sourceTypeFlag: testSourceType, + nameFlag: testName, + labelsFlag: "key1=value1", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + SourceID: testSourceId, + SourceType: testSourceType, + Name: utils.Ptr(testName), + Labels: testLabels, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateBackupRequest)) iaas.ApiCreateBackupRequest { + request := testClient.CreateBackup(testCtx, testProjectId) + + createPayload := iaas.NewCreateBackupPayloadWithDefaults() + createPayload.Name = utils.Ptr(testName) + createPayload.Labels = &map[string]interface{}{ + "key1": "value1", + } + createPayload.Source = &iaas.BackupSource{ + Id: &testSourceId, + Type: utils.Ptr(testSourceType), + } + + request = request.CreateBackupPayload(*createPayload) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no source id", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, sourceIdFlag) + }), + isValid: false, + }, + { + description: "no source type", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, sourceTypeFlag) + }), + isValid: false, + }, + { + description: "invalid source type", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sourceTypeFlag] = "invalid" + }), + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "only required flags", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + delete(flagValues, labelsFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = nil + model.Labels = make(map[string]string) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + backupId := "test-backup-id" + + type args struct { + outputFormat string + async bool + sourceLabel string + projectLabel string + backup *iaas.Backup + } + + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty backup", + args: args{}, + wantErr: true, + }, + { + name: "backup is nil", + args: args{ + backup: nil, + }, + wantErr: true, + }, + { + name: "minimal backup", + args: args{ + backup: &iaas.Backup{ + Id: &backupId, + }, + sourceLabel: "test-source", + projectLabel: "test-project", + }, + wantErr: false, + }, + { + name: "async mode", + args: args{ + backup: &iaas.Backup{ + Id: &backupId, + }, + sourceLabel: "test-source", + projectLabel: "test-project", + async: true, + }, + wantErr: false, + }, + { + name: "json output", + args: args{ + backup: &iaas.Backup{ + Id: &backupId, + }, + outputFormat: print.JSONOutputFormat, + }, + wantErr: false, + }, + { + name: "yaml output", + args: args{ + backup: &iaas.Backup{ + Id: &backupId, + }, + outputFormat: print.YAMLOutputFormat, + }, + wantErr: false, + }, + } + + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = cmd + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.sourceLabel, tt.args.projectLabel, tt.args.backup); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/volume/backup/delete/delete.go b/internal/cmd/volume/backup/delete/delete.go new file mode 100644 index 000000000..b40d93ea7 --- /dev/null +++ b/internal/cmd/volume/backup/delete/delete.go @@ -0,0 +1,125 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + iaasutils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" +) + +const ( + backupIdArg = "BACKUP_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + BackupId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", backupIdArg), + Short: "Deletes a backup", + Long: "Deletes a backup by its ID.", + Args: args.SingleArg(backupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a backup with ID "xxx"`, "$ stackit volume backup delete xxx"), + ), + 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 + } + + backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.BackupId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get backup name: %v", err) + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete backup %q? (This cannot be undone)", backupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete backup: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Deleting backup") + _, err = wait.DeleteBackupWaitHandler(ctx, apiClient, model.ProjectId, model.BackupId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for backup deletion: %w", err) + } + s.Stop() + } + + if model.Async { + params.Printer.Outputf("Triggered deletion of backup %q\n", backupLabel) + } else { + params.Printer.Outputf("Deleted backup %q\n", backupLabel) + } + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + backupId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + BackupId: backupId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteBackupRequest { + req := apiClient.DeleteBackup(ctx, model.ProjectId, model.BackupId) + return req +} diff --git a/internal/cmd/volume/backup/delete/delete_test.go b/internal/cmd/volume/backup/delete/delete_test.go new file mode 100644 index 000000000..8425e9c98 --- /dev/null +++ b/internal/cmd/volume/backup/delete/delete_test.go @@ -0,0 +1,183 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testBackupId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + BackupId: testBackupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteBackupRequest)) iaas.ApiDeleteBackupRequest { + request := testClient.DeleteBackup(testCtx, testProjectId, testBackupId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %v", err) + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/volume/backup/describe/describe.go b/internal/cmd/volume/backup/describe/describe.go new file mode 100644 index 000000000..f181195d9 --- /dev/null +++ b/internal/cmd/volume/backup/describe/describe.go @@ -0,0 +1,162 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + backupIdArg = "BACKUP_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + BackupId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", backupIdArg), + Short: "Describes a backup", + Long: "Describes a backup by its ID.", + Args: args.SingleArg(backupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get details of a backup with ID "xxx"`, + "$ stackit volume backup describe xxx"), + examples.NewExample( + `Get details of a backup with ID "xxx" in JSON format`, + "$ stackit volume backup describe xxx --output-format json"), + ), + 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 + } + + // Call API + req := buildRequest(ctx, model, apiClient) + backup, err := req.Execute() + if err != nil { + return fmt.Errorf("get backup details: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, backup) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + backupId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + BackupId: backupId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetBackupRequest { + req := apiClient.GetBackup(ctx, model.ProjectId, model.BackupId) + return req +} + +func outputResult(p *print.Printer, outputFormat string, backup *iaas.Backup) error { + if backup == nil { + return fmt.Errorf("backup response is empty") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(backup, "", " ") + if err != nil { + return fmt.Errorf("marshal backup: %w", err) + } + p.Outputln(string(details)) + return nil + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal backup: %w", err) + } + p.Outputln(string(details)) + return nil + + default: + table := tables.NewTable() + table.AddRow("ID", utils.PtrString(backup.Id)) + table.AddSeparator() + table.AddRow("NAME", utils.PtrString(backup.Name)) + table.AddSeparator() + table.AddRow("SIZE", utils.PtrByteSizeDefault(backup.Size, "")) + table.AddSeparator() + table.AddRow("STATUS", utils.PtrString(backup.Status)) + table.AddSeparator() + table.AddRow("SNAPSHOT ID", utils.PtrString(backup.SnapshotId)) + table.AddSeparator() + table.AddRow("VOLUME ID", utils.PtrString(backup.VolumeId)) + table.AddSeparator() + table.AddRow("AVAILABILITY ZONE", utils.PtrString(backup.AvailabilityZone)) + table.AddSeparator() + + if backup.Labels != nil && len(*backup.Labels) > 0 { + var labels []string + for key, value := range *backup.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } + + table.AddRow("CREATED AT", utils.ConvertTimePToDateTimeString(backup.CreatedAt)) + table.AddSeparator() + table.AddRow("UPDATED AT", utils.ConvertTimePToDateTimeString(backup.UpdatedAt)) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/volume/backup/describe/describe_test.go b/internal/cmd/volume/backup/describe/describe_test.go new file mode 100644 index 000000000..3dcac1e56 --- /dev/null +++ b/internal/cmd/volume/backup/describe/describe_test.go @@ -0,0 +1,217 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testBackupId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + BackupId: testBackupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetBackupRequest)) iaas.ApiGetBackupRequest { + request := testClient.GetBackup(testCtx, testProjectId, testBackupId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %v", err) + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + backup *iaas.Backup + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "backup as argument", + args: args{ + backup: &iaas.Backup{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.backup); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/volume/backup/list/list.go b/internal/cmd/volume/backup/list/list.go new file mode 100644 index 000000000..540c00480 --- /dev/null +++ b/internal/cmd/volume/backup/list/list.go @@ -0,0 +1,202 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + limitFlag = "limit" + labelSelectorFlag = "label-selector" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + LabelSelector *string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all backups", + Long: "Lists all backups in a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all backups`, + "$ stackit volume backup list"), + examples.NewExample( + `List all backups in JSON format`, + "$ stackit volume backup list --output-format json"), + examples.NewExample( + `List up to 10 backups`, + "$ stackit volume backup list --limit 10"), + examples.NewExample( + `List backups with specific labels`, + "$ stackit volume backup list --label-selector key1=value1,key2=value2"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get backups: %w", err) + } + if resp.Items == nil || len(*resp.Items) == 0 { + 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 + } + params.Printer.Info("No backups found for project %s\n", projectLabel) + return nil + } + backups := *resp.Items + + // Truncate output + if model.Limit != nil && len(backups) > int(*model.Limit) { + backups = backups[:*model.Limit] + } + + return outputResult(params.Printer, model.OutputFormat, backups) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter backups by labels") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + labelSelector := flags.FlagToStringPointer(p, cmd, labelSelectorFlag) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + LabelSelector: labelSelector, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListBackupsRequest { + req := apiClient.ListBackups(ctx, model.ProjectId) + + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + + return req +} + +func outputResult(p *print.Printer, outputFormat string, backups []iaas.Backup) error { + if backups == nil { + return fmt.Errorf("backups is empty") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(backups, "", " ") + if err != nil { + return fmt.Errorf("marshal backup list: %w", err) + } + p.Outputln(string(details)) + return nil + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal backup list: %w", err) + } + p.Outputln(string(details)) + return nil + + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "SIZE", "STATUS", "SNAPSHOT ID", "VOLUME ID", "AVAILABILITY ZONE", "LABELS", "CREATED AT", "UPDATED AT") + + for _, backup := range backups { + var labelsString string + if backup.Labels != nil { + var labels []string + for key, value := range *backup.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + labelsString = strings.Join(labels, ", ") + } + + table.AddRow( + utils.PtrString(backup.Id), + utils.PtrString(backup.Name), + utils.PtrByteSizeDefault(backup.Size, ""), + utils.PtrString(backup.Status), + utils.PtrString(backup.SnapshotId), + utils.PtrString(backup.VolumeId), + utils.PtrString(backup.AvailabilityZone), + labelsString, + utils.ConvertTimePToDateTimeString(backup.CreatedAt), + utils.ConvertTimePToDateTimeString(backup.UpdatedAt), + ) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/volume/backup/list/list_test.go b/internal/cmd/volume/backup/list/list_test.go new file mode 100644 index 000000000..7a24783c2 --- /dev/null +++ b/internal/cmd/volume/backup/list/list_test.go @@ -0,0 +1,233 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", + labelSelectorFlag: "key1=value1", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr("key1=value1"), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListBackupsRequest)) iaas.ApiListBackupsRequest { + request := testClient.ListBackups(testCtx, testProjectId) + request = request.LabelSelector("key1=value1") + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + configureFlags(cmd) + + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListBackupsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + backups []iaas.Backup + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty backup in slice", + args: args{ + backups: []iaas.Backup{{}}, + }, + wantErr: false, + }, + { + name: "empty slice", + args: args{ + backups: []iaas.Backup{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.backups); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/volume/backup/restore/restore.go b/internal/cmd/volume/backup/restore/restore.go new file mode 100644 index 000000000..3249f0560 --- /dev/null +++ b/internal/cmd/volume/backup/restore/restore.go @@ -0,0 +1,138 @@ +package restore + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + iaasutils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" +) + +const ( + backupIdArg = "BACKUP_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + BackupId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("restore %s", backupIdArg), + Short: "Restores a backup", + Long: "Restores a backup by its ID.", + Args: args.SingleArg(backupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Restore a backup with ID "xxx"`, "$ stackit volume backup restore xxx"), + ), + 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 + } + + backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.BackupId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get backup details: %v", err) + } + + // Get source details for labels + var sourceLabel string + backup, err := apiClient.GetBackup(ctx, model.ProjectId, model.BackupId).Execute() + if err == nil && backup != nil && backup.VolumeId != nil { + sourceLabel = *backup.VolumeId + name, err := iaasutils.GetVolumeName(ctx, apiClient, model.ProjectId, *backup.VolumeId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get volume details: %v", err) + } else if name != "" { + sourceLabel = name + } + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to restore %q with backup %q? (This cannot be undone)", sourceLabel, backupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("restore backup: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Restoring backup") + _, err = wait.RestoreBackupWaitHandler(ctx, apiClient, model.ProjectId, model.BackupId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for backup restore: %w", err) + } + s.Stop() + } + + if model.Async { + params.Printer.Outputf("Triggered restore of %q with %q in %q\n", sourceLabel, backupLabel, model.ProjectId) + } else { + params.Printer.Outputf("Restored %q with %q in %q\n", sourceLabel, backupLabel, model.ProjectId) + } + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + backupId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + BackupId: backupId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRestoreBackupRequest { + req := apiClient.RestoreBackup(ctx, model.ProjectId, model.BackupId) + return req +} diff --git a/internal/cmd/volume/backup/restore/restore_test.go b/internal/cmd/volume/backup/restore/restore_test.go new file mode 100644 index 000000000..217300720 --- /dev/null +++ b/internal/cmd/volume/backup/restore/restore_test.go @@ -0,0 +1,183 @@ +package restore + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testBackupId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + BackupId: testBackupId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiRestoreBackupRequest)) iaas.ApiRestoreBackupRequest { + request := testClient.RestoreBackup(testCtx, testProjectId, testBackupId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %v", err) + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiRestoreBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/volume/backup/update/update.go b/internal/cmd/volume/backup/update/update.go new file mode 100644 index 000000000..f23bb5108 --- /dev/null +++ b/internal/cmd/volume/backup/update/update.go @@ -0,0 +1,168 @@ +package update + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasutils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + backupIdArg = "BACKUP_ID" + nameFlag = "name" + labelsFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + BackupId string + Name *string + Labels map[string]string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", backupIdArg), + Short: "Updates a backup", + Long: "Updates a backup by its ID.", + Args: args.SingleArg(backupIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update the name of a backup with ID "xxx"`, + "$ stackit volume backup update xxx --name new-name"), + examples.NewExample( + `Update the labels of a backup with ID "xxx"`, + "$ stackit volume backup update xxx --labels key1=value1,key2=value2"), + ), + 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 + } + + backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.BackupId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get backup name: %v", err) + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update backup %q? (This cannot be undone)", model.BackupId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update backup: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, backupLabel, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "Name of the backup") + cmd.Flags().StringToString(labelsFlag, nil, "Key-value string pairs as labels") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + backupId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + name := flags.FlagToStringPointer(p, cmd, nameFlag) + labels := flags.FlagToStringToStringPointer(p, cmd, labelsFlag) + if labels == nil { + labels = &map[string]string{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + BackupId: backupId, + Name: name, + Labels: *labels, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateBackupRequest { + req := apiClient.UpdateBackup(ctx, model.ProjectId, model.BackupId) + + payload := iaas.UpdateBackupPayload{ + Name: model.Name, + Labels: utils.ConvertStringMapToInterfaceMap(utils.Ptr(model.Labels)), + } + + req = req.UpdateBackupPayload(payload) + return req +} + +func outputResult(p *print.Printer, outputFormat, backupLabel string, backup *iaas.Backup) error { + if backup == nil { + return fmt.Errorf("backup response is empty") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(backup, "", " ") + if err != nil { + return fmt.Errorf("marshal backup: %w", err) + } + p.Outputln(string(details)) + return nil + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal backup: %w", err) + } + p.Outputln(string(details)) + return nil + + default: + p.Outputf("Updated backup %q\n", backupLabel) + return nil + } +} diff --git a/internal/cmd/volume/backup/update/update_test.go b/internal/cmd/volume/backup/update/update_test.go new file mode 100644 index 000000000..b0826ae65 --- /dev/null +++ b/internal/cmd/volume/backup/update/update_test.go @@ -0,0 +1,192 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testBackupId = uuid.NewString() + testName = "test-backup" + testLabels = map[string]string{"key1": "value1"} +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testBackupId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + nameFlag: testName, + labelsFlag: "key1=value1", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + BackupId: testBackupId, + Name: &testName, + Labels: testLabels, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateBackupRequest)) iaas.ApiUpdateBackupRequest { + request := testClient.UpdateBackup(testCtx, testProjectId, testBackupId) + payload := iaas.NewUpdateBackupPayloadWithDefaults() + payload.Name = &testName + + // Convert test labels to map[string]interface{} + labelsMap := map[string]interface{}{} + for k, v := range testLabels { + labelsMap[k] = v + } + payload.Labels = &labelsMap + + request = request.UpdateBackupPayload(*payload) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %v", err) + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateBackupRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index 258e0752a..5519bd5d8 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -174,20 +174,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli Type: model.SourceType, } - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.CreateVolumePayload{ AvailabilityZone: model.AvailabilityZone, Name: model.Name, Description: model.Description, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), PerformanceClass: model.PerformanceClass, Size: model.Size, } diff --git a/internal/cmd/volume/update/update.go b/internal/cmd/volume/update/update.go index 80e137987..263f333af 100644 --- a/internal/cmd/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -135,19 +135,10 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateVolumeRequest { req := apiClient.UpdateVolume(ctx, model.ProjectId, model.VolumeId) - var labelsMap *map[string]interface{} - if model.Labels != nil && len(*model.Labels) > 0 { - // convert map[string]string to map[string]interface{} - labelsMap = utils.Ptr(map[string]interface{}{}) - for k, v := range *model.Labels { - (*labelsMap)[k] = v - } - } - payload := iaas.UpdateVolumePayload{ Name: model.Name, Description: model.Description, - Labels: labelsMap, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } return req.UpdateVolumePayload(payload) diff --git a/internal/cmd/volume/volume.go b/internal/cmd/volume/volume.go index 1e876e85b..d5cad1614 100644 --- a/internal/cmd/volume/volume.go +++ b/internal/cmd/volume/volume.go @@ -2,6 +2,7 @@ package volume import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/create" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/describe" @@ -35,4 +36,5 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(update.NewCmd(params)) cmd.AddCommand(resize.NewCmd(params)) cmd.AddCommand(performanceclass.NewCmd(params)) + cmd.AddCommand(backup.NewCmd(params)) } diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index f2616a01a..f3d3571d7 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -26,6 +26,8 @@ type IaaSClient interface { GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) GetImageExecute(ctx context.Context, projectId string, imageId string) (*iaas.Image, error) GetAffinityGroupExecute(ctx context.Context, projectId string, affinityGroupId string) (*iaas.AffinityGroup, error) + GetSnapshotExecute(ctx context.Context, projectId, snapshotId string) (*iaas.Snapshot, error) + GetBackupExecute(ctx context.Context, projectId, backupId string) (*iaas.Backup, error) } func GetSecurityGroupRuleName(ctx context.Context, apiClient IaaSClient, projectId, securityGroupRuleId, securityGroupId string) (string, error) { @@ -170,3 +172,22 @@ func GetAffinityGroupName(ctx context.Context, apiClient IaaSClient, projectId, } return *resp.Name, nil } + +func GetSnapshotName(ctx context.Context, apiClient IaaSClient, projectId, snapshotId string) (string, error) { + resp, err := apiClient.GetSnapshotExecute(ctx, projectId, snapshotId) + if err != nil { + return "", fmt.Errorf("get snapshot: %w", err) + } + return *resp.Name, nil +} + +func GetBackupName(ctx context.Context, apiClient IaaSClient, projectId, backupId string) (string, error) { + resp, err := apiClient.GetBackupExecute(ctx, projectId, backupId) + if err != nil { + return backupId, fmt.Errorf("get backup: %w", err) + } + if resp != nil && resp.Name != nil { + return *resp.Name, nil + } + return backupId, nil +} diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index f4375251d..e2ccdc469 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -33,6 +33,10 @@ type IaaSClientMocked struct { GetImageResp *iaas.Image GetAffinityGroupsFails bool GetAffinityGroupResp *iaas.AffinityGroup + GetBackupFails bool + GetBackupResp *iaas.Backup + GetSnapshotFails bool + GetSnapshotResp *iaas.Snapshot } func (m *IaaSClientMocked) GetAffinityGroupExecute(_ context.Context, _, _ string) (*iaas.AffinityGroup, error) { @@ -112,6 +116,19 @@ func (m *IaaSClientMocked) GetImageExecute(_ context.Context, _, _ string) (*iaa return m.GetImageResp, nil } +func (m *IaaSClientMocked) GetBackupExecute(_ context.Context, _, _ string) (*iaas.Backup, error) { + if m.GetBackupFails { + return nil, fmt.Errorf("could not get backup") + } + return m.GetBackupResp, nil +} + +func (m *IaaSClientMocked) GetSnapshotExecute(_ context.Context, _, _ string) (*iaas.Snapshot, error) { + if m.GetSnapshotFails { + return nil, fmt.Errorf("could not get snapshot") + } + return m.GetSnapshotResp, nil +} func TestGetSecurityGroupRuleName(t *testing.T) { type args struct { getInstanceFails bool From 7a990bfd278dbf887f5c482237b4732d16ec946e Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Tue, 17 Jun 2025 13:34:09 +0200 Subject: [PATCH 338/619] feat: add test coverage comment (#802) * generate test coverage in CI * add test coverage as comment in PR --- .github/workflows/ci.yaml | 35 +++++++++++++++++++++++++++++++++-- Makefile | 2 +- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 239a463dc..3f41f7681 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,6 +1,15 @@ name: CI -on: [pull_request, workflow_dispatch] +on: + pull_request: + workflow_dispatch: + push: + branches: + - main + +env: + CODE_COVERAGE_FILE_NAME: "coverage.out" # must be the same as in Makefile + CODE_COVERAGE_ARTIFACT_NAME: "code-coverage" jobs: main: @@ -26,8 +35,15 @@ jobs: - name: Test run: make test + - name: Archive code coverage results + uses: actions/upload-artifact@v4 + with: + name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} + path: ${{ env.CODE_COVERAGE_FILE_NAME }} + config: name: Check GoReleaser config + if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - name: Checkout @@ -36,4 +52,19 @@ jobs: - name: Check GoReleaser uses: goreleaser/goreleaser-action@v6 with: - args: check \ No newline at end of file + args: check + + code_coverage: + name: "Code coverage report" + if: github.event_name == 'pull_request' # Do not run when workflow is triggered by push to main branch + runs-on: ubuntu-latest + needs: main + permissions: + contents: read + actions: read # to download code coverage results from "main" job + pull-requests: write # write permission needed to comment on PR + steps: + - uses: fgrosse/go-coverage-report@v1.1.1 + with: + coverage-artifact-name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} + coverage-file-name: ${{ env.CODE_COVERAGE_FILE_NAME }} \ No newline at end of file diff --git a/Makefile b/Makefile index 171d9864d..a3b64bb3d 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ lint: lint-golangci-lint lint-yamllint # Test test: @echo ">> Running tests for the CLI application" - @go test ./... -count=1 + @go test ./... -count=1 -coverprofile=coverage.out # Test coverage coverage: From bd9167ed62515b4ec6e4ec6f0521c10fa9f6a23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 17 Jun 2025 15:31:08 +0200 Subject: [PATCH 339/619] fix(ci): increase keychain timeout for release workflow (#804) --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0bddeed42..09d8ce121 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -48,6 +48,8 @@ jobs: security create-keychain -p "${{ secrets.TEMP_KEYCHAIN }}" $KEYCHAIN_PATH security default-keychain -s $KEYCHAIN_PATH security unlock-keychain -p "${{ secrets.TEMP_KEYCHAIN }}" $KEYCHAIN_PATH + # the keychain gets locked automatically after 300s, so we have to extend this interval to e.g. 900 seconds + security set-keychain-settings -lut 900 security import ./ApplicationID.p12 -P "${{ secrets.APPLICATION_ID }}" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH echo -n $AUTHKEY_BASE64 | base64 -d -o ./AuthKey.p8 From 8fdadf8259420219c1c1c0c51349c6fdddf0791f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 17 Jun 2025 16:07:07 +0200 Subject: [PATCH 340/619] fix(ci): fix goreleaser post-hooks (#808) --- .goreleaser.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 99b8757e1..b0195645c 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -36,8 +36,6 @@ builds: output: true - cmd: codesign -vvv --deep --strict "dist/macos-builds_{{.Target}}/{{.Name}}" output: true - - cmd: ls -l "dist/macos_{{.Target}}" - output: true - cmd: hdiutil create -volname "STACKIT-CLI" -srcfolder "dist/macos-builds_{{.Target}}/{{.Name}}" -ov -format UDZO "dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg" output: true - cmd: codesign -s "{{.Env.APPLE_APPLICATION_IDENTITY}}" -f -v --options=runtime "dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg" From 179ce5fb07e4e92d530bea674f9530ab52c53d19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 14:12:51 +0000 Subject: [PATCH 341/619] chore(deps): bump fgrosse/go-coverage-report from 1.1.1 to 1.2.0 (#809) Bumps [fgrosse/go-coverage-report](https://github.com/fgrosse/go-coverage-report) from 1.1.1 to 1.2.0. - [Release notes](https://github.com/fgrosse/go-coverage-report/releases) - [Changelog](https://github.com/fgrosse/go-coverage-report/blob/main/CHANGELOG.md) - [Commits](https://github.com/fgrosse/go-coverage-report/compare/v1.1.1...v1.2.0) --- updated-dependencies: - dependency-name: fgrosse/go-coverage-report dependency-version: 1.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3f41f7681..18a3a9e6f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -64,7 +64,7 @@ jobs: actions: read # to download code coverage results from "main" job pull-requests: write # write permission needed to comment on PR steps: - - uses: fgrosse/go-coverage-report@v1.1.1 + - uses: fgrosse/go-coverage-report@v1.2.0 with: coverage-artifact-name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} coverage-file-name: ${{ env.CODE_COVERAGE_FILE_NAME }} \ No newline at end of file From add42ab27b2687e5e9744556322a713bd149c421 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:12:15 +0000 Subject: [PATCH 342/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/git (#807) Bumps [github.com/stackitcloud/stackit-sdk-go/services/git](https://github.com/stackitcloud/stackit-sdk-go) from 0.5.0 to 0.5.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.5.0...services/git/v0.5.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/git dependency-version: 0.5.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c3bb00c1f..f2e22bd07 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 - github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 diff --git a/go.sum b/go.sum index 6bd663516..e8e97bea4 100644 --- a/go.sum +++ b/go.sum @@ -570,8 +570,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 h1:VpONplkd github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 h1:GQAA9gqhKN0ZRc1vRYURHeVjSghh+iF+5DK0HdeuakI= github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= -github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0 h1:s0A2EPBrnBxfKStKA/B1izbyYHw/0m2RdqN3Inkv9hI= -github.com/stackitcloud/stackit-sdk-go/services/git v0.5.0/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM= +github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 h1:xs8CMY7t8nULQvZr5+XZRs8yWw8YMVw+HfjcuMhieR4= +github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 h1:aLlZmcsDHqqc7KPsevvs+W6EPZFT51u/dx5TcVQsE6g= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0/go.mod h1:TaMx7kukGpRm0BkNCmS7u2x12q1pgfbD55DAnLIjOIQ= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 h1:Ef4SyTBjIkfwaws4mssa6AoK+OokHFtr7ZIflUpoXVE= From a8c66c10966209d8e286b2e58878e80459638e30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:28:13 +0200 Subject: [PATCH 343/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/opensearch (#806) Bumps [github.com/stackitcloud/stackit-sdk-go/services/opensearch](https://github.com/stackitcloud/stackit-sdk-go) from 0.23.0 to 0.23.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.23.0...services/opensearch/v0.23.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/opensearch dependency-version: 0.23.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f2e22bd07..09f8d7f57 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.1 diff --git a/go.sum b/go.sum index e8e97bea4..694741eef 100644 --- a/go.sum +++ b/go.sum @@ -586,8 +586,8 @@ github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 h1:+dKIPVz9 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1 h1:6OObzh2zk7wg75zYstcj0kjOjaxWc4joqA6qdeo8DP4= github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0 h1:/OaZCyrD8LFa4W6a2Vu2QSVMJwLLBr8ZdBKzX00MV1Q= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.0/go.mod h1:c30J6f/fXtbzcHkH3ZcabZUek3wfy5CRnEkcW5e5yXg= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 h1:E6vCqPn1NiPHnbnvqLNQNz6a/cmeyRb5iA9cDUPtP58= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 h1:r29a9GoBLVw2VZSzdPftlIsE5t7shdxobwoT6NVUIjU= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1 h1:2rDFwJtZOFYFUiJqJ9uIwM+mu+BbtuVaUHARRJtrZPU= From f2b13ce1886d6d4c5c6602146d6f61a7097a1dc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:38:04 +0200 Subject: [PATCH 344/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex (#805) Bumps [github.com/stackitcloud/stackit-sdk-go/services/mongodbflex](https://github.com/stackitcloud/stackit-sdk-go) from 1.2.0 to 1.2.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/cdn/v1.2.0...services/cdn/v1.2.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/mongodbflex dependency-version: 1.2.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 09f8d7f57..bfcfe57cf 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0 diff --git a/go.sum b/go.sum index 694741eef..faea33252 100644 --- a/go.sum +++ b/go.sum @@ -580,8 +580,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 h1:hfnILDJGBwwqUIs github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 h1:7nN7ZCuWSbJMy5KqoOqSbp5JKIOvyuDqVRtxVvT1iyE= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0 h1:U/IhjLOz0vG6zuxTqGhBd8f609s6JB+X9PaL6x/VM58= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.0/go.mod h1:+JSnz5/AvGN5ek/iH008frRc/NgjSr1EVOTIbyLwAuQ= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 h1:TWz7qJ4Mg5pquDXODSZ1dzhS95ZYn3w1aKjuRU2VqCg= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 h1:+dKIPVz9ydKbX3x6+1NvYk++OA378w74p+N6SjDmzBQ= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1 h1:6OObzh2zk7wg75zYstcj0kjOjaxWc4joqA6qdeo8DP4= From b33804093334362ab4a7bb836d441e140f3c8998 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 23 Jun 2025 10:01:27 +0200 Subject: [PATCH 345/619] chore(deps): update renovatebot/github-action action to v43 (#819) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 27f85d5ee..90be71550 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v42.0.6 + uses: renovatebot/github-action@v43.0.0 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From efc9ef6e14c6372394efc3cfcf253bb02bab0ae7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jun 2025 08:17:53 +0000 Subject: [PATCH 346/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/dns (#815) Bumps [github.com/stackitcloud/stackit-sdk-go/services/dns](https://github.com/stackitcloud/stackit-sdk-go) from 0.15.0 to 0.16.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.15.0...core/v0.16.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/dns dependency-version: 0.16.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bfcfe57cf..a36133890 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 diff --git a/go.sum b/go.sum index faea33252..179a09c5a 100644 --- a/go.sum +++ b/go.sum @@ -568,8 +568,8 @@ github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 h1:7UKUi7Od7KpuVjV4I/ github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 h1:VpONplkdlEh7Pf22+cNnnHH4bx+S9QI+z55XYRE74JY= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0 h1:GQAA9gqhKN0ZRc1vRYURHeVjSghh+iF+5DK0HdeuakI= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.15.0/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0 h1:86F0qHx2YOzxoGkcFX1tT20+Yz1mwaPPS2aFODxuMpY= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 h1:xs8CMY7t8nULQvZr5+XZRs8yWw8YMVw+HfjcuMhieR4= github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 h1:aLlZmcsDHqqc7KPsevvs+W6EPZFT51u/dx5TcVQsE6g= From 4025abe26e9be56e42b0a37a4be7dc3937e7d3b8 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 25 Jun 2025 09:47:02 +0200 Subject: [PATCH 347/619] fix(deps): update stackit sdk modules (#810) Co-authored-by: Renovate Bot --- go.mod | 28 ++++++++++++++-------------- go.sum | 56 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/go.mod b/go.mod index a36133890..505be5323 100644 --- a/go.mod +++ b/go.mod @@ -17,21 +17,21 @@ require ( github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0 - github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 + github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.25.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.25.0 @@ -237,10 +237,10 @@ require ( github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 179a09c5a..5c6291045 100644 --- a/go.sum +++ b/go.sum @@ -566,26 +566,26 @@ github.com/stackitcloud/stackit-sdk-go/core v0.17.2 h1:jPyn+i8rkp2hM80+hOg0B/1EV github.com/stackitcloud/stackit-sdk-go/core v0.17.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 h1:7UKUi7Od7KpuVjV4I/jUAV5NEatUomwWFd/IRODbioY= github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0 h1:VpONplkdlEh7Pf22+cNnnHH4bx+S9QI+z55XYRE74JY= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.7.0/go.mod h1:dJ19ZwFjp2bfC5ZobXV3vUdSpE3quUw3GuoFSKLpHIo= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 h1:KXMiTBV4KcOEQRFddtOUFspL+KRvjDQNDIs73bdiey0= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0/go.mod h1:+2mx2MclJFMQ4Y6b20jspYAnIeFJP3/yvO6Gfvcvf6Q= github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0 h1:86F0qHx2YOzxoGkcFX1tT20+Yz1mwaPPS2aFODxuMpY= github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= -github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1 h1:xs8CMY7t8nULQvZr5+XZRs8yWw8YMVw+HfjcuMhieR4= -github.com/stackitcloud/stackit-sdk-go/services/git v0.5.1/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0 h1:aLlZmcsDHqqc7KPsevvs+W6EPZFT51u/dx5TcVQsE6g= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.24.0/go.mod h1:TaMx7kukGpRm0BkNCmS7u2x12q1pgfbD55DAnLIjOIQ= +github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0 h1:C+8z3MdvnTngcH9L72VHLXRKNWHHYp+7FO/F6imKmB4= +github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.25.0 h1:K9RjMPlEK1XQegZBMIrI/KHAorzRdOt5YpftsT7pMEk= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.25.0/go.mod h1:lUGkcbyMkd4nRBDFmKohIwlgtOZqQo4Ek5S5ajw90Xg= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 h1:Ef4SyTBjIkfwaws4mssa6AoK+OokHFtr7ZIflUpoXVE= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1 h1:hfnILDJGBwwqUIs4xt/7Jj4LBe+JsSdHy+Md2ynUg4Y= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.24.1/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1 h1:7nN7ZCuWSbJMy5KqoOqSbp5JKIOvyuDqVRtxVvT1iyE= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.24.1/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCxpFXN2K7g2ih0gQM6cyZ1VhTmtQfI= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 h1:vxk6ztgzUIPMkfv27NRpniFqCyGGGFsWJQUvFs43bQA= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 h1:TWz7qJ4Mg5pquDXODSZ1dzhS95ZYn3w1aKjuRU2VqCg= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0 h1:+dKIPVz9ydKbX3x6+1NvYk++OA378w74p+N6SjDmzBQ= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.2.0/go.mod h1:iCOYS9yICXQPyMAIdUGMqJDLY8HXKiVAdiMzO/mPvtA= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1 h1:6OObzh2zk7wg75zYstcj0kjOjaxWc4joqA6qdeo8DP4= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.7.1/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 h1:bK5FDpSGfUKDXNkqOoiqOU9hua2YfcdYsGS4zQQ9wg0= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0/go.mod h1:Q2SJXlZTksvNAb1QnpGNfDSw/OMPN9uopaKuptUGhO8= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0 h1:8v9Iupkc3meXcVPMpteXDz07YzY2M5jud50vEtAvbs8= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 h1:E6vCqPn1NiPHnbnvqLNQNz6a/cmeyRb5iA9cDUPtP58= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 h1:r29a9GoBLVw2VZSzdPftlIsE5t7shdxobwoT6NVUIjU= @@ -594,22 +594,22 @@ github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1 h1:2rDFwJtZOFYF github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1/go.mod h1:YL0l9l9xzJy2BmV+U9XkcXlQaHbE2KyA37GpGvBXIJ4= github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1 h1:4H+GL4eLEO116Vlh0pe+udGGYnMohA8YhLW9KYGdEOc= github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1/go.mod h1:PAQH8+1DDGc6uibvC3nDtfRLu8uxutIr25mPJvrCOy8= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0 h1:y8QUHaEdprQJ3VJgOpTVT1nOyTByKsw6k6ccQBoe1wo= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.16.0/go.mod h1:TBvZpbCju0Zmq8GoS4CEtUg2MqtdqWrGeEAOXwkJNQo= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.1 h1:CjlTuoLg1qlAQt+/5a2ElnyEx/Zf1j7j61OJykKfdIM= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.2.1/go.mod h1:m9f9XZDeKpmqE/G0Sj5Rpdsiw+qcUo0Rcm3idAbyp1c= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0 h1:oGR3wRC0xfX2Itpwbh/SrT/k2fnmMSzvy2U9U2lDQPs= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.12.0/go.mod h1:iD7R3CNdLUDUyKP+lATsQy+V4QGMMOb15zPnNq4wnbs= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.1 h1:0Kro/2d0GnqhOFTYq/4r9HwjZB/aT2erC1nyNmI0lnk= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.2.1/go.mod h1:S/zLsdZvtPXDSYyl7h2GLHhsnVf6AzB96PdslPWevJI= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0 h1:WJA2v8XCISdrcbnJXstsjVE+QAFVsDpfJHNp0ORe1Bc= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.1.0/go.mod h1:5F7/2BiKhrbvHD56mj5xR9qf8P0V2yMgeitmdIpQv4s= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1 h1:01AIQQtHdJ96La6BPVTRp6SLiGe5LXF+JmDKXbt4ZX0= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.8.1/go.mod h1:t77MA8uyEU9KZd1On5JpnxI3xhVPKIS8WutStqvU8Cw= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 h1:lxI0LnHcTpnF8g0tHTCQ1UIVLlNHk1W1WAclp3Ut0fw= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0/go.mod h1:TBvZpbCju0Zmq8GoS4CEtUg2MqtdqWrGeEAOXwkJNQo= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 h1:ewFXnESJWsUen0T9sSt0lwL28fhqCVB1HSLdY0szrdA= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0/go.mod h1:m9f9XZDeKpmqE/G0Sj5Rpdsiw+qcUo0Rcm3idAbyp1c= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0 h1:CtCaG8nycfviq/QgNM7OoBWs/Ap9IQvOmvI0tZhYdPI= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0/go.mod h1:/MiR18oug1V0sxPT4KO6a+LhgPARNBGvgVx3qv3zJ0A= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.0 h1:LGiq+2o2D3snaL1vqBQkvPTAEVPT2PKPrJzQL07hZgY= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.0/go.mod h1:S/zLsdZvtPXDSYyl7h2GLHhsnVf6AzB96PdslPWevJI= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 h1:poL/Hz3a6OHZ/eKtwMGm5nLqC3fEJjzPQlN/7/+mk8Y= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0/go.mod h1:ssbyAHtxyuBvheMEItydM78/JxjDl3naUtllrC7ghDs= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 h1:2d28WFQB9QB3af4uoPFglQDhH1LepEe6F2YoFCBecVI= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0/go.mod h1:t77MA8uyEU9KZd1On5JpnxI3xhVPKIS8WutStqvU8Cw= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 h1:h1TsWatlsexLeKdkb3L8chcxaXJOy/cLXctsRxhb4xg= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1/go.mod h1:M4xZ2BnmROvLV2MrAP6A8o9BnyT0CkvpEcP8lBOfRs8= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.25.0 h1:9ufUW3J/d29TizLd32Kt4b+4RUN1FRod9Q3X1HbTg58= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.25.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0 h1:bwLmLXvtCl1XkPRP+YrXwfz+lBMaGWH/crlNbYtxeqE= +github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 h1:WvPLO1c7oT/MWmCRTt7jRyxus2g3DIluIW5iAsUpSFM= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= From b27b82c8867014f1c624869996e25a5e5d0e2245 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 25 Jun 2025 09:58:00 +0200 Subject: [PATCH 348/619] chore(deps): update renovatebot/github-action action to v43.0.1 (#822) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 90be71550..ffb733574 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.0 + uses: renovatebot/github-action@v43.0.1 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 8a59085cff725ffd99c98d0ade6981463b9ff6ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Wed, 25 Jun 2025 15:42:09 +0200 Subject: [PATCH 349/619] feat(cli): onboard iaas snapshot api (#774) --- docs/stackit_volume.md | 1 + docs/stackit_volume_snapshot.md | 38 +++ docs/stackit_volume_snapshot_create.md | 49 ++++ docs/stackit_volume_snapshot_delete.md | 40 +++ docs/stackit_volume_snapshot_describe.md | 43 +++ docs/stackit_volume_snapshot_list.md | 48 ++++ docs/stackit_volume_snapshot_update.md | 45 ++++ .../cmd/volume/backup/describe/describe.go | 2 +- internal/cmd/volume/backup/list/list.go | 2 +- .../cmd/volume/backup/update/update_test.go | 8 +- internal/cmd/volume/snapshot/create/create.go | 171 ++++++++++++ .../cmd/volume/snapshot/create/create_test.go | 207 +++++++++++++++ internal/cmd/volume/snapshot/delete/delete.go | 127 +++++++++ .../cmd/volume/snapshot/delete/delete_test.go | 197 ++++++++++++++ .../cmd/volume/snapshot/describe/describe.go | 157 +++++++++++ .../volume/snapshot/describe/describe_test.go | 242 +++++++++++++++++ internal/cmd/volume/snapshot/list/list.go | 198 ++++++++++++++ .../cmd/volume/snapshot/list/list_test.go | 250 ++++++++++++++++++ internal/cmd/volume/snapshot/snapshot.go | 33 +++ internal/cmd/volume/snapshot/update/update.go | 143 ++++++++++ .../cmd/volume/snapshot/update/update_test.go | 240 +++++++++++++++++ internal/cmd/volume/volume.go | 2 + internal/pkg/services/iaas/utils/utils.go | 4 + internal/pkg/utils/utils.go | 9 + 24 files changed, 2248 insertions(+), 8 deletions(-) create mode 100644 docs/stackit_volume_snapshot.md create mode 100644 docs/stackit_volume_snapshot_create.md create mode 100644 docs/stackit_volume_snapshot_delete.md create mode 100644 docs/stackit_volume_snapshot_describe.md create mode 100644 docs/stackit_volume_snapshot_list.md create mode 100644 docs/stackit_volume_snapshot_update.md create mode 100644 internal/cmd/volume/snapshot/create/create.go create mode 100644 internal/cmd/volume/snapshot/create/create_test.go create mode 100644 internal/cmd/volume/snapshot/delete/delete.go create mode 100644 internal/cmd/volume/snapshot/delete/delete_test.go create mode 100644 internal/cmd/volume/snapshot/describe/describe.go create mode 100644 internal/cmd/volume/snapshot/describe/describe_test.go create mode 100644 internal/cmd/volume/snapshot/list/list.go create mode 100644 internal/cmd/volume/snapshot/list/list_test.go create mode 100644 internal/cmd/volume/snapshot/snapshot.go create mode 100644 internal/cmd/volume/snapshot/update/update.go create mode 100644 internal/cmd/volume/snapshot/update/update_test.go diff --git a/docs/stackit_volume.md b/docs/stackit_volume.md index 4955b6299..3412504c2 100644 --- a/docs/stackit_volume.md +++ b/docs/stackit_volume.md @@ -37,5 +37,6 @@ stackit volume [flags] * [stackit volume list](./stackit_volume_list.md) - Lists all volumes of a project * [stackit volume performance-class](./stackit_volume_performance-class.md) - Provides functionality for volume performance classes available inside a project * [stackit volume resize](./stackit_volume_resize.md) - Resizes a volume +* [stackit volume snapshot](./stackit_volume_snapshot.md) - Provides functionality for snapshots * [stackit volume update](./stackit_volume_update.md) - Updates a volume diff --git a/docs/stackit_volume_snapshot.md b/docs/stackit_volume_snapshot.md new file mode 100644 index 000000000..61f6f428e --- /dev/null +++ b/docs/stackit_volume_snapshot.md @@ -0,0 +1,38 @@ +## stackit volume snapshot + +Provides functionality for snapshots + +### Synopsis + +Provides functionality for snapshots. + +``` +stackit volume snapshot [flags] +``` + +### Options + +``` + -h, --help Help for "stackit volume snapshot" +``` + +### 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 volume](./stackit_volume.md) - Provides functionality for volumes +* [stackit volume snapshot create](./stackit_volume_snapshot_create.md) - Creates a snapshot from a volume +* [stackit volume snapshot delete](./stackit_volume_snapshot_delete.md) - Deletes a snapshot +* [stackit volume snapshot describe](./stackit_volume_snapshot_describe.md) - Describes a snapshot +* [stackit volume snapshot list](./stackit_volume_snapshot_list.md) - Lists all snapshots +* [stackit volume snapshot update](./stackit_volume_snapshot_update.md) - Updates a snapshot + diff --git a/docs/stackit_volume_snapshot_create.md b/docs/stackit_volume_snapshot_create.md new file mode 100644 index 000000000..4ed86ad39 --- /dev/null +++ b/docs/stackit_volume_snapshot_create.md @@ -0,0 +1,49 @@ +## stackit volume snapshot create + +Creates a snapshot from a volume + +### Synopsis + +Creates a snapshot from a volume. + +``` +stackit volume snapshot create [flags] +``` + +### Examples + +``` + Create a snapshot from a volume with ID "xxx" + $ stackit volume snapshot create --volume-id xxx + + Create a snapshot from a volume with ID "xxx" and name "my-snapshot" + $ stackit volume snapshot create --volume-id xxx --name my-snapshot + + Create a snapshot from a volume with ID "xxx" and labels + $ stackit volume snapshot create --volume-id xxx --labels key1=value1,key2=value2 +``` + +### Options + +``` + -h, --help Help for "stackit volume snapshot create" + --labels stringToString Key-value string pairs as labels (default []) + --name string Name of the snapshot + --volume-id string ID of the volume from which a snapshot should be created +``` + +### 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 volume snapshot](./stackit_volume_snapshot.md) - Provides functionality for snapshots + diff --git a/docs/stackit_volume_snapshot_delete.md b/docs/stackit_volume_snapshot_delete.md new file mode 100644 index 000000000..df9a37828 --- /dev/null +++ b/docs/stackit_volume_snapshot_delete.md @@ -0,0 +1,40 @@ +## stackit volume snapshot delete + +Deletes a snapshot + +### Synopsis + +Deletes a snapshot by its ID. + +``` +stackit volume snapshot delete SNAPSHOT_ID [flags] +``` + +### Examples + +``` + Delete a snapshot with ID "xxx" + $ stackit volume snapshot delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit volume snapshot delete" +``` + +### 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 volume snapshot](./stackit_volume_snapshot.md) - Provides functionality for snapshots + diff --git a/docs/stackit_volume_snapshot_describe.md b/docs/stackit_volume_snapshot_describe.md new file mode 100644 index 000000000..5f7f256b7 --- /dev/null +++ b/docs/stackit_volume_snapshot_describe.md @@ -0,0 +1,43 @@ +## stackit volume snapshot describe + +Describes a snapshot + +### Synopsis + +Describes a snapshot by its ID. + +``` +stackit volume snapshot describe SNAPSHOT_ID [flags] +``` + +### Examples + +``` + Get details of a snapshot with ID "xxx" + $ stackit volume snapshot describe xxx + + Get details of a snapshot with ID "xxx" in JSON format + $ stackit volume snapshot describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit volume snapshot 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 volume snapshot](./stackit_volume_snapshot.md) - Provides functionality for snapshots + diff --git a/docs/stackit_volume_snapshot_list.md b/docs/stackit_volume_snapshot_list.md new file mode 100644 index 000000000..f4fe9dd3a --- /dev/null +++ b/docs/stackit_volume_snapshot_list.md @@ -0,0 +1,48 @@ +## stackit volume snapshot list + +Lists all snapshots + +### Synopsis + +Lists all snapshots in a project. + +``` +stackit volume snapshot list [flags] +``` + +### Examples + +``` + List all snapshots + $ stackit volume snapshot list + + List snapshots with a limit of 10 + $ stackit volume snapshot list --limit 10 + + List snapshots filtered by label + $ stackit volume snapshot list --label-selector key1=value1 +``` + +### Options + +``` + -h, --help Help for "stackit volume snapshot list" + --label-selector string Filter snapshots by labels + --limit int Maximum number of entries to list +``` + +### 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 volume snapshot](./stackit_volume_snapshot.md) - Provides functionality for snapshots + diff --git a/docs/stackit_volume_snapshot_update.md b/docs/stackit_volume_snapshot_update.md new file mode 100644 index 000000000..2b74b5ae8 --- /dev/null +++ b/docs/stackit_volume_snapshot_update.md @@ -0,0 +1,45 @@ +## stackit volume snapshot update + +Updates a snapshot + +### Synopsis + +Updates a snapshot by its ID. + +``` +stackit volume snapshot update SNAPSHOT_ID [flags] +``` + +### Examples + +``` + Update a snapshot name with ID "xxx" + $ stackit volume snapshot update xxx --name my-new-name + + Update a snapshot labels with ID "xxx" + $ stackit volume snapshot update xxx --labels key1=value1,key2=value2 +``` + +### Options + +``` + -h, --help Help for "stackit volume snapshot update" + --labels stringToString Key-value string pairs as labels (default []) + --name string Name of the snapshot +``` + +### 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 volume snapshot](./stackit_volume_snapshot.md) - Provides functionality for snapshots + diff --git a/internal/cmd/volume/backup/describe/describe.go b/internal/cmd/volume/backup/describe/describe.go index f181195d9..d3322f6d0 100644 --- a/internal/cmd/volume/backup/describe/describe.go +++ b/internal/cmd/volume/backup/describe/describe.go @@ -128,7 +128,7 @@ func outputResult(p *print.Printer, outputFormat string, backup *iaas.Backup) er table.AddSeparator() table.AddRow("NAME", utils.PtrString(backup.Name)) table.AddSeparator() - table.AddRow("SIZE", utils.PtrByteSizeDefault(backup.Size, "")) + table.AddRow("SIZE", utils.PtrGigaByteSizeDefault(backup.Size, "n/a")) table.AddSeparator() table.AddRow("STATUS", utils.PtrString(backup.Status)) table.AddSeparator() diff --git a/internal/cmd/volume/backup/list/list.go b/internal/cmd/volume/backup/list/list.go index 540c00480..f3d7062c7 100644 --- a/internal/cmd/volume/backup/list/list.go +++ b/internal/cmd/volume/backup/list/list.go @@ -184,7 +184,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []iaas.Backup) table.AddRow( utils.PtrString(backup.Id), utils.PtrString(backup.Name), - utils.PtrByteSizeDefault(backup.Size, ""), + utils.PtrGigaByteSizeDefault(backup.Size, "n/a"), utils.PtrString(backup.Status), utils.PtrString(backup.SnapshotId), utils.PtrString(backup.VolumeId), diff --git a/internal/cmd/volume/backup/update/update_test.go b/internal/cmd/volume/backup/update/update_test.go index b0826ae65..21aa21c1e 100644 --- a/internal/cmd/volume/backup/update/update_test.go +++ b/internal/cmd/volume/backup/update/update_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -68,12 +69,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiUpdateBackupRequest)) iaas.Api payload := iaas.NewUpdateBackupPayloadWithDefaults() payload.Name = &testName - // Convert test labels to map[string]interface{} - labelsMap := map[string]interface{}{} - for k, v := range testLabels { - labelsMap[k] = v - } - payload.Labels = &labelsMap + payload.Labels = utils.ConvertStringMapToInterfaceMap(utils.Ptr(testLabels)) request = request.UpdateBackupPayload(*payload) for _, mod := range mods { diff --git a/internal/cmd/volume/snapshot/create/create.go b/internal/cmd/volume/snapshot/create/create.go new file mode 100644 index 000000000..856b0a929 --- /dev/null +++ b/internal/cmd/volume/snapshot/create/create.go @@ -0,0 +1,171 @@ +package create + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" +) + +const ( + volumeIdFlag = "volume-id" + nameFlag = "name" + labelsFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + VolumeID string + Name *string + Labels map[string]string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a snapshot from a volume", + Long: "Creates a snapshot from a volume.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a snapshot from a volume with ID "xxx"`, + "$ stackit volume snapshot create --volume-id xxx"), + examples.NewExample( + `Create a snapshot from a volume with ID "xxx" and name "my-snapshot"`, + "$ stackit volume snapshot create --volume-id xxx --name my-snapshot"), + examples.NewExample( + `Create a snapshot from a volume with ID "xxx" and labels`, + "$ stackit volume snapshot create --volume-id xxx --labels key1=value1,key2=value2"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + 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 + } + + // Get volume name for label + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeID) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) + volumeLabel = model.VolumeID + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create snapshot from volume %q? (This cannot be undone)", volumeLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create snapshot: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Creating snapshot") + resp, err = wait.CreateSnapshotWaitHandler(ctx, apiClient, model.ProjectId, *resp.Id).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for snapshot creation: %w", err) + } + s.Stop() + } + + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + params.Printer.Outputf("%s snapshot of %q in %q. Snapshot ID: %s\n", operationState, volumeLabel, projectLabel, utils.PtrString(resp.Id)) + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), volumeIdFlag, "ID of the volume from which a snapshot should be created") + cmd.Flags().String(nameFlag, "", "Name of the snapshot") + cmd.Flags().StringToString(labelsFlag, nil, "Key-value string pairs as labels") + + err := flags.MarkFlagsRequired(cmd, volumeIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + volumeID := flags.FlagToStringValue(p, cmd, volumeIdFlag) + + name := flags.FlagToStringPointer(p, cmd, nameFlag) + labels := flags.FlagToStringToStringPointer(p, cmd, labelsFlag) + if labels == nil { + labels = &map[string]string{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + VolumeID: volumeID, + Name: name, + Labels: *labels, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateSnapshotRequest { + req := apiClient.CreateSnapshot(ctx, model.ProjectId) + payload := iaas.NewCreateSnapshotPayloadWithDefaults() + payload.VolumeId = &model.VolumeID + payload.Name = model.Name + payload.Labels = utils.ConvertStringMapToInterfaceMap(utils.Ptr(model.Labels)) + + req = req.CreateSnapshotPayload(*payload) + return req +} diff --git a/internal/cmd/volume/snapshot/create/create_test.go b/internal/cmd/volume/snapshot/create/create_test.go new file mode 100644 index 000000000..08c5c0baa --- /dev/null +++ b/internal/cmd/volume/snapshot/create/create_test.go @@ -0,0 +1,207 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +const ( + testName = "test-snapshot" +) + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testVolumeId = uuid.NewString() + testLabels = map[string]string{"key1": "value1"} +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + volumeIdFlag: testVolumeId, + nameFlag: testName, + labelsFlag: "key1=value1", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + VolumeID: testVolumeId, + Name: utils.Ptr(testName), + Labels: testLabels, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateSnapshotRequest)) iaas.ApiCreateSnapshotRequest { + request := testClient.CreateSnapshot(testCtx, testProjectId) + payload := iaas.NewCreateSnapshotPayloadWithDefaults() + payload.VolumeId = &testVolumeId + payload.Name = utils.Ptr(testName) + + payload.Labels = utils.ConvertStringMapToInterfaceMap(utils.Ptr(testLabels)) + + request = request.CreateSnapshotPayload(*payload) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no volume id", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, volumeIdFlag) + }), + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "volume id invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[volumeIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "only required flags", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + delete(flagValues, labelsFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = nil + model.Labels = make(map[string]string) + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateSnapshotRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/volume/snapshot/delete/delete.go b/internal/cmd/volume/snapshot/delete/delete.go new file mode 100644 index 000000000..0a4c17faa --- /dev/null +++ b/internal/cmd/volume/snapshot/delete/delete.go @@ -0,0 +1,127 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" +) + +const ( + snapshotIdArg = "SNAPSHOT_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SnapshotId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", snapshotIdArg), + Short: "Deletes a snapshot", + Long: "Deletes a snapshot by its ID.", + Args: args.SingleArg(snapshotIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a snapshot with ID "xxx"`, + "$ stackit volume snapshot delete xxx"), + ), + 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 + } + + // Get snapshot name for label + snapshotLabel, err := iaasUtils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.SnapshotId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get snapshot name: %v", err) + snapshotLabel = model.SnapshotId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete snapshot %q? (This cannot be undone)", snapshotLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete snapshot: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Deleting snapshot") + _, err = wait.DeleteSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.SnapshotId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for snapshot deletion: %w", err) + } + s.Stop() + } + + operationState := "Deleted" + if model.Async { + operationState = "Triggered deletion of" + } + params.Printer.Outputf("%s snapshot %q\n", operationState, snapshotLabel) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + snapshotId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SnapshotId: snapshotId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteSnapshotRequest { + return apiClient.DeleteSnapshot(ctx, model.ProjectId, model.SnapshotId) +} diff --git a/internal/cmd/volume/snapshot/delete/delete_test.go b/internal/cmd/volume/snapshot/delete/delete_test.go new file mode 100644 index 000000000..bf1f87d15 --- /dev/null +++ b/internal/cmd/volume/snapshot/delete/delete_test.go @@ -0,0 +1,197 @@ +package delete + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testSnapshotId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testSnapshotId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + SnapshotId: testSnapshotId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteSnapshotRequest)) iaas.ApiDeleteSnapshotRequest { + request := testClient.DeleteSnapshot(testCtx, testProjectId, testSnapshotId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "snapshot id invalid", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %v", err) + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteSnapshotRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/volume/snapshot/describe/describe.go b/internal/cmd/volume/snapshot/describe/describe.go new file mode 100644 index 000000000..7ae36212e --- /dev/null +++ b/internal/cmd/volume/snapshot/describe/describe.go @@ -0,0 +1,157 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + snapshotIdArg = "SNAPSHOT_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SnapshotId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", snapshotIdArg), + Short: "Describes a snapshot", + Long: "Describes a snapshot by its ID.", + Args: args.SingleArg(snapshotIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get details of a snapshot with ID "xxx"`, + "$ stackit volume snapshot describe xxx"), + examples.NewExample( + `Get details of a snapshot with ID "xxx" in JSON format`, + "$ stackit volume snapshot describe xxx --output-format json"), + ), + 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 + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get snapshot details: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + snapshotId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SnapshotId: snapshotId, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetSnapshotRequest { + return apiClient.GetSnapshot(ctx, model.ProjectId, model.SnapshotId) +} + +func outputResult(p *print.Printer, outputFormat string, snapshot *iaas.Snapshot) error { + if snapshot == nil { + return fmt.Errorf("get snapshot response is empty") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(snapshot, "", " ") + if err != nil { + return fmt.Errorf("marshal snapshot: %w", err) + } + p.Outputln(string(details)) + return nil + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(snapshot, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal snapshot: %w", err) + } + p.Outputln(string(details)) + return nil + + default: + table := tables.NewTable() + table.AddRow("ID", utils.PtrString(snapshot.Id)) + table.AddSeparator() + table.AddRow("NAME", utils.PtrString(snapshot.Name)) + table.AddSeparator() + table.AddRow("SIZE", utils.PtrGigaByteSizeDefault(snapshot.Size, "n/a")) + table.AddSeparator() + table.AddRow("STATUS", utils.PtrString(snapshot.Status)) + table.AddSeparator() + table.AddRow("VOLUME ID", utils.PtrString(snapshot.VolumeId)) + table.AddSeparator() + + if snapshot.Labels != nil && len(*snapshot.Labels) > 0 { + labels := []string{} + for key, value := range *snapshot.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + table.AddRow("LABELS", strings.Join(labels, "\n")) + table.AddSeparator() + } + + table.AddRow("CREATED AT", utils.ConvertTimePToDateTimeString(snapshot.CreatedAt)) + table.AddSeparator() + table.AddRow("UPDATED AT", utils.ConvertTimePToDateTimeString(snapshot.UpdatedAt)) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/volume/snapshot/describe/describe_test.go b/internal/cmd/volume/snapshot/describe/describe_test.go new file mode 100644 index 000000000..5d501758f --- /dev/null +++ b/internal/cmd/volume/snapshot/describe/describe_test.go @@ -0,0 +1,242 @@ +package describe + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testSnapshotId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testSnapshotId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + SnapshotId: testSnapshotId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetSnapshotRequest)) iaas.ApiGetSnapshotRequest { + request := testClient.GetSnapshot(testCtx, testProjectId, testSnapshotId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "snapshot id invalid", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %v", err) + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetSnapshotRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + snapshot *iaas.Snapshot + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty snapshot", + args: args{ + snapshot: &iaas.Snapshot{}, + }, + wantErr: false, + }, + { + name: "snapshot with values", + args: args{ + snapshot: &iaas.Snapshot{ + Id: utils.Ptr("snapshot-1"), + Name: utils.Ptr("test-snapshot"), + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.snapshot); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/volume/snapshot/list/list.go b/internal/cmd/volume/snapshot/list/list.go new file mode 100644 index 000000000..83b59987c --- /dev/null +++ b/internal/cmd/volume/snapshot/list/list.go @@ -0,0 +1,198 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + limitFlag = "limit" + labelSelectorFlag = "label-selector" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 + LabelSelector *string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all snapshots", + Long: "Lists all snapshots in a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all snapshots`, + "$ stackit volume snapshot list"), + examples.NewExample( + `List snapshots with a limit of 10`, + "$ stackit volume snapshot list --limit 10"), + examples.NewExample( + `List snapshots filtered by label`, + "$ stackit volume snapshot list --label-selector key1=value1"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list snapshots: %w", err) + } + + // Check if response is empty + if resp.Items == nil || len(*resp.Items) == 0 { + 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 + } + params.Printer.Info("No snapshots found for project %q\n", projectLabel) + return nil + } + + snapshots := *resp.Items + + // Apply limit if specified + if model.Limit != nil && int(*model.Limit) < len(snapshots) { + snapshots = snapshots[:*model.Limit] + } + + return outputResult(params.Printer, model.OutputFormat, snapshots) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + cmd.Flags().String(labelSelectorFlag, "", "Filter snapshots by labels") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + labelSelector := flags.FlagToStringPointer(p, cmd, labelSelectorFlag) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + LabelSelector: labelSelector, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListSnapshotsRequest { + req := apiClient.ListSnapshots(ctx, model.ProjectId) + if model.LabelSelector != nil { + req = req.LabelSelector(*model.LabelSelector) + } + return req +} + +func outputResult(p *print.Printer, outputFormat string, snapshots []iaas.Snapshot) error { + if snapshots == nil { + return fmt.Errorf("list snapshots response is empty") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(snapshots, "", " ") + if err != nil { + return fmt.Errorf("marshal snapshots: %w", err) + } + p.Outputln(string(details)) + return nil + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(snapshots, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal snapshots: %w", err) + } + p.Outputln(string(details)) + return nil + + default: + table := tables.NewTable() + table.SetHeader("ID", "NAME", "SIZE", "STATUS", "VOLUME ID", "LABELS", "CREATED AT", "UPDATED AT") + + for _, snapshot := range snapshots { + var labelsString string + if snapshot.Labels != nil { + var labels []string + for key, value := range *snapshot.Labels { + labels = append(labels, fmt.Sprintf("%s: %s", key, value)) + } + labelsString = strings.Join(labels, "\n") + } + table.AddRow( + utils.PtrString(snapshot.Id), + utils.PtrString(snapshot.Name), + utils.PtrGigaByteSizeDefault(snapshot.Size, "n/a"), + utils.PtrString(snapshot.Status), + utils.PtrString(snapshot.VolumeId), + labelsString, + utils.ConvertTimePToDateTimeString(snapshot.CreatedAt), + utils.ConvertTimePToDateTimeString(snapshot.UpdatedAt), + ) + table.AddSeparator() + } + + p.Outputln(table.Render()) + return nil + } +} diff --git a/internal/cmd/volume/snapshot/list/list_test.go b/internal/cmd/volume/snapshot/list/list_test.go new file mode 100644 index 000000000..e1f68f1b1 --- /dev/null +++ b/internal/cmd/volume/snapshot/list/list_test.go @@ -0,0 +1,250 @@ +package list + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", + labelSelectorFlag: "key1=value1", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Limit: utils.Ptr(int64(10)), + LabelSelector: utils.Ptr("key1=value1"), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListSnapshotsRequest)) iaas.ApiListSnapshotsRequest { + request := testClient.ListSnapshots(testCtx, testProjectId) + request = request.LabelSelector("key1=value1") + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "only required flags", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, limitFlag) + delete(flagValues, labelSelectorFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Limit = nil + model.LabelSelector = nil + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + model, err := parseInput(p, cmd) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListSnapshotsRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "without label selector", + model: fixtureInputModel(func(model *inputModel) { + model.LabelSelector = nil + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiListSnapshotsRequest) { + *request = testClient.ListSnapshots(testCtx, testProjectId) + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + snapshots []iaas.Snapshot + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "empty snapshot in slice", + args: args{ + snapshots: []iaas.Snapshot{{}}, + }, + wantErr: false, + }, + { + name: "snapshots as argument", + args: args{ + snapshots: []iaas.Snapshot{ + { + Id: utils.Ptr("snapshot-1"), + }, + { + Id: utils.Ptr("snapshot-2"), + }, + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.snapshots); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/volume/snapshot/snapshot.go b/internal/cmd/volume/snapshot/snapshot.go new file mode 100644 index 000000000..9656b1465 --- /dev/null +++ b/internal/cmd/volume/snapshot/snapshot.go @@ -0,0 +1,33 @@ +package snapshot + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "snapshot", + Short: "Provides functionality for snapshots", + Long: "Provides functionality for snapshots.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) +} diff --git a/internal/cmd/volume/snapshot/update/update.go b/internal/cmd/volume/snapshot/update/update.go new file mode 100644 index 000000000..543c484d1 --- /dev/null +++ b/internal/cmd/volume/snapshot/update/update.go @@ -0,0 +1,143 @@ +package update + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + snapshotIdArg = "SNAPSHOT_ID" + nameFlag = "name" + labelsFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SnapshotId string + Name *string + Labels map[string]string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", snapshotIdArg), + Short: "Updates a snapshot", + Long: "Updates a snapshot by its ID.", + Args: args.SingleArg(snapshotIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update a snapshot name with ID "xxx"`, + "$ stackit volume snapshot update xxx --name my-new-name"), + examples.NewExample( + `Update a snapshot labels with ID "xxx"`, + "$ stackit volume snapshot update xxx --labels key1=value1,key2=value2"), + ), + 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 + } + + // Get snapshot name for label + snapshotLabel, err := iaasUtils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.SnapshotId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get snapshot name: %v", err) + snapshotLabel = model.SnapshotId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update snapshot %q?", snapshotLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("update snapshot: %w", err) + } + + params.Printer.Outputf("Updated snapshot %q\n", snapshotLabel) + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "Name of the snapshot") + cmd.Flags().StringToString(labelsFlag, nil, "Key-value string pairs as labels") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + snapshotId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + name := flags.FlagToStringPointer(p, cmd, nameFlag) + labels := flags.FlagToStringToStringPointer(p, cmd, labelsFlag) + if labels == nil { + labels = &map[string]string{} + } + + if name == nil && len(*labels) == 0 { + return nil, fmt.Errorf("either name or labels must be provided") + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SnapshotId: snapshotId, + Name: name, + Labels: *labels, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateSnapshotRequest { + req := apiClient.UpdateSnapshot(ctx, model.ProjectId, model.SnapshotId) + payload := iaas.NewUpdateSnapshotPayloadWithDefaults() + payload.Name = model.Name + payload.Labels = utils.ConvertStringMapToInterfaceMap(utils.Ptr(model.Labels)) + + req = req.UpdateSnapshotPayload(*payload) + return req +} diff --git a/internal/cmd/volume/snapshot/update/update_test.go b/internal/cmd/volume/snapshot/update/update_test.go new file mode 100644 index 000000000..cb4af61fc --- /dev/null +++ b/internal/cmd/volume/snapshot/update/update_test.go @@ -0,0 +1,240 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() + testSnapshotId = uuid.NewString() + testName = "test-snapshot" + testLabels = map[string]string{"key1": "value1"} +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testSnapshotId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + nameFlag: testName, + labelsFlag: "key1=value1", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + SnapshotId: testSnapshotId, + Name: &testName, + Labels: testLabels, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateSnapshotRequest)) iaas.ApiUpdateSnapshotRequest { + request := testClient.UpdateSnapshot(testCtx, testProjectId, testSnapshotId) + payload := iaas.NewUpdateSnapshotPayloadWithDefaults() + payload.Name = &testName + payload.Labels = utils.ConvertStringMapToInterfaceMap(utils.Ptr(testLabels)) + + request = request.UpdateSnapshotPayload(*payload) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "snapshot id invalid", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no update flags", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + delete(flagValues, labelsFlag) + }), + isValid: false, + }, + { + description: "only name flag", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, labelsFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Labels = make(map[string]string) + }), + }, + { + description: "only labels flag", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Name = nil + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %v", err) + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateSnapshotRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/volume/volume.go b/internal/cmd/volume/volume.go index d5cad1614..8da9cbd13 100644 --- a/internal/cmd/volume/volume.go +++ b/internal/cmd/volume/volume.go @@ -9,6 +9,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/volume/list" performanceclass "github.com/stackitcloud/stackit-cli/internal/cmd/volume/performance-class" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/resize" + "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -36,5 +37,6 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(update.NewCmd(params)) cmd.AddCommand(resize.NewCmd(params)) cmd.AddCommand(performanceclass.NewCmd(params)) + cmd.AddCommand(snapshot.NewCmd(params)) cmd.AddCommand(backup.NewCmd(params)) } diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index f3d3571d7..2cf460334 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -177,6 +177,10 @@ func GetSnapshotName(ctx context.Context, apiClient IaaSClient, projectId, snaps resp, err := apiClient.GetSnapshotExecute(ctx, projectId, snapshotId) if err != nil { return "", fmt.Errorf("get snapshot: %w", err) + } else if resp == nil { + return "", ErrResponseNil + } else if resp.Name == nil { + return "", ErrNameNil } return *resp.Name, nil } diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index a26d7b4b2..2db0936b8 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -119,6 +119,15 @@ func PtrByteSizeDefault(size *int64, defaultValue string) string { return bytesize.New(float64(*size)).String() } +// PtrGigaByteSizeDefault return the value of an int64 pointer to a string representation of gigabytes. If the pointer is nil, +// it returns the [defaultValue]. +func PtrGigaByteSizeDefault(size *int64, defaultValue string) string { + if size == nil { + return defaultValue + } + return (bytesize.New(float64(*size)) * bytesize.GB).String() +} + // Base64Encode encodes a []byte to a base64 representation as string func Base64Encode(message []byte) string { b := make([]byte, base64.StdEncoding.EncodedLen(len(message))) From eb4cd720f7159ab158b62f3bbe6c02bbde04ec79 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Mon, 30 Jun 2025 11:07:41 +0200 Subject: [PATCH 350/619] fix: replaced deprecated brews config in goreleaser (#811) Co-authored-by: Alexander Dahmen --- .goreleaser.yaml | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index b0195645c..f8c772377 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -32,6 +32,7 @@ builds: - amd64 hooks: post: + # Signing - cmd: codesign -s "{{.Env.APPLE_APPLICATION_IDENTITY}}" -f -v --options=runtime "dist/macos-builds_{{.Target}}/{{.Name}}" output: true - cmd: codesign -vvv --deep --strict "dist/macos-builds_{{.Target}}/{{.Name}}" @@ -46,12 +47,29 @@ builds: output: true - cmd: spctl -a -t open --context context:primary-signature -v dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg output: true + # Completion files + - cmd: mkdir -p dist/macos-builds_{{.Target}}/completions + - cmd: sh -c './dist/macos-builds_{{.Target}}/{{.Name}} completion zsh > ./dist/macos-builds_{{.Target}}/completions/stackit.zsh' + - cmd: sh -c './dist/macos-builds_{{.Target}}/{{.Name}} completion bash > ./dist/macos-builds_{{.Target}}/completions/stackit.bash' + - cmd: sh -c './dist/macos-builds_{{.Target}}/{{.Name}} completion fish > ./dist/macos-builds_{{.Target}}/completions/stackit.fish' archives: - - formats: [ 'tar.gz' ] + - ids: + - linux-builds + - windows-builds + formats: [ 'tar.gz' ] format_overrides: - goos: windows formats: [ 'zip' ] + - id: macos-archives + ids: + - macos-builds + formats: [ 'tar.gz' ] + files: + - src: ./dist/macos-builds_{{.Target}}/completions/* + dst: completions + - LICENSE.md + - README.md release: # If set to auto, the GitHub release will be marked as "Pre-release" @@ -96,8 +114,11 @@ signs: "${artifact}", ] -brews: +homebrew_casks: - name: stackit + directory: Casks + conflicts: + - formula: stackit repository: owner: stackitcloud name: homebrew-tap @@ -106,14 +127,14 @@ brews: email: noreply@stackit.de homepage: "https://github.com/stackitcloud/stackit-cli" description: "A command-line interface to manage STACKIT resources.\nThis CLI is in a beta state. More services and functionality will be supported soon." - directory: Formula license: "Apache-2.0" # If set to auto, the release will not be uploaded to the homebrew tap repo # if the tag has a prerelease indicator (e.g. v0.0.1-alpha1) skip_upload: auto - install: | - bin.install "stackit" - generate_completions_from_executable(bin/"stackit", "completion") + completions: + zsh: ./completions/stackit.zsh + bash: ./completions/stackit.bash + fish: ./completions/stackit.fish snapcrafts: # IDs of the builds for which to create packages for From b6ed745e5a1eb20b981bf51df3b35ce376f54fb0 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Mon, 30 Jun 2025 11:43:39 +0200 Subject: [PATCH 351/619] Add installation instructions for rpm packages (#827) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add installation instructions for rpm packages Signed-off-by: Alexander Dahmen * Update INSTALLATION.md Co-authored-by: Ruben Hönle --------- Signed-off-by: Alexander Dahmen Co-authored-by: Ruben Hönle --- INSTALLATION.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/INSTALLATION.md b/INSTALLATION.md index 72d06b8ec..35bdd5149 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -90,6 +90,18 @@ asset_filters=["stackit-cli_", "_linux_amd64.tar.gz"] eget stackitcloud/stackit-cli ``` +#### RPM package via dnf, yum and zypper + +The STACKIT CLI is available as [RPM Package](https://github.com/stackitcloud/stackit-cli/releases) and can be installed via dnf, yum and zypper package manager. + +Just download the rpm package from the [release page](https://github.com/stackitcloud/stackit-cli/releases) and run the install command like the following: + +```shell +dnf install stackitcli.rpm +yum install stackitcli.rpm +zypper install stackitcli.rpm +``` + #### Any distribution Alternatively, you can install via [Homebrew](https://brew.sh/) or refer to one of the installation methods below. From ae7bb742190c65d2e062cf2fc5aa779bb19839bf Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 30 Jun 2025 13:18:00 +0200 Subject: [PATCH 352/619] fix(deps): update stackit sdk modules (#826) * fix(deps): update stackit sdk modules * Update docs Signed-off-by: Alexander Dahmen --------- Signed-off-by: Alexander Dahmen Co-authored-by: Renovate Bot Co-authored-by: Alexander Dahmen --- docs/stackit_dns_record-set_create.md | 2 +- go.mod | 14 +++++++------- go.sum | 28 +++++++++++++-------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/stackit_dns_record-set_create.md b/docs/stackit_dns_record-set_create.md index dfb740ad9..4f51534ad 100644 --- a/docs/stackit_dns_record-set_create.md +++ b/docs/stackit_dns_record-set_create.md @@ -25,7 +25,7 @@ stackit dns record-set create [flags] --name string Name of the record, should be compliant with RFC1035, Section 2.3.4 --record strings Records belonging to the record set --ttl int Time to live, if not provided defaults to the zone's default TTL - --type string Record type, one of ["A" "AAAA" "SOA" "CNAME" "NS" "MX" "TXT" "SRV" "PTR" "ALIAS" "DNAME" "CAA" "DNSKEY" "DS" "LOC" "NAPTR" "SSHFP" "TLSA" "URI" "CERT" "SVCB"] (default "A") + --type string Record type, one of ["A" "AAAA" "SOA" "CNAME" "NS" "MX" "TXT" "SRV" "PTR" "ALIAS" "DNAME" "CAA" "DNSKEY" "DS" "LOC" "NAPTR" "SSHFP" "TLSA" "URI" "CERT" "SVCB" "TYPE" "CSYNC" "HINFO" "HTTPS"] (default "A") --zone-id string Zone ID ``` diff --git a/go.mod b/go.mod index 505be5323..df13fa311 100644 --- a/go.mod +++ b/go.mod @@ -18,12 +18,12 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.25.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0 @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.25.0 golang.org/x/oauth2 v0.30.0 @@ -241,8 +241,8 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.33.0 // indirect diff --git a/go.sum b/go.sum index 5c6291045..d44916ac4 100644 --- a/go.sum +++ b/go.sum @@ -568,12 +568,12 @@ github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 h1:7UKUi7Od7KpuVjV4I/ github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 h1:KXMiTBV4KcOEQRFddtOUFspL+KRvjDQNDIs73bdiey0= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0/go.mod h1:+2mx2MclJFMQ4Y6b20jspYAnIeFJP3/yvO6Gfvcvf6Q= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0 h1:86F0qHx2YOzxoGkcFX1tT20+Yz1mwaPPS2aFODxuMpY= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.16.0/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 h1:x5mx/C2bdtpOH974RofXD0Y8YOyJtYXwIyaCyWOXMwU= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0 h1:C+8z3MdvnTngcH9L72VHLXRKNWHHYp+7FO/F6imKmB4= github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.25.0 h1:K9RjMPlEK1XQegZBMIrI/KHAorzRdOt5YpftsT7pMEk= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.25.0/go.mod h1:lUGkcbyMkd4nRBDFmKohIwlgtOZqQo4Ek5S5ajw90Xg= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0 h1:7qm/Tft79wFlHomPdgjUJ9uJU8kEk+k9ficMGRoHtf0= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0/go.mod h1:lUGkcbyMkd4nRBDFmKohIwlgtOZqQo4Ek5S5ajw90Xg= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 h1:Ef4SyTBjIkfwaws4mssa6AoK+OokHFtr7ZIflUpoXVE= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCxpFXN2K7g2ih0gQM6cyZ1VhTmtQfI= @@ -586,14 +586,14 @@ github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 h1:bK5FDpSG github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0/go.mod h1:Q2SJXlZTksvNAb1QnpGNfDSw/OMPN9uopaKuptUGhO8= github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0 h1:8v9Iupkc3meXcVPMpteXDz07YzY2M5jud50vEtAvbs8= github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1 h1:E6vCqPn1NiPHnbnvqLNQNz6a/cmeyRb5iA9cDUPtP58= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.23.1/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0 h1:r29a9GoBLVw2VZSzdPftlIsE5t7shdxobwoT6NVUIjU= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.1.0/go.mod h1:4g/L5PHfz1xk3udEhvPy2nXiH4UgRO5Cj6iwUa7k5VQ= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1 h1:2rDFwJtZOFYFUiJqJ9uIwM+mu+BbtuVaUHARRJtrZPU= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.24.1/go.mod h1:YL0l9l9xzJy2BmV+U9XkcXlQaHbE2KyA37GpGvBXIJ4= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1 h1:4H+GL4eLEO116Vlh0pe+udGGYnMohA8YhLW9KYGdEOc= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.24.1/go.mod h1:PAQH8+1DDGc6uibvC3nDtfRLu8uxutIr25mPJvrCOy8= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 h1:+qFjzDDv/0ZHGdVuW2HzAphRBmlc1+abw7k1RaAqmQo= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 h1:DGgKKCh3AmUBqDG0DrsWVcclxSaG82TVEf18A29w+J0= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0/go.mod h1:I67K+QjPAIMrW/r/0GOdX2WSmA8J72LNzpe8rElfxFI= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.0 h1:Xhgo0Di6NDjkg0Bf3f6LHlQ09u0Dj/3WdDb0xd47vEU= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.0/go.mod h1:YL0l9l9xzJy2BmV+U9XkcXlQaHbE2KyA37GpGvBXIJ4= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 h1:wdQoQ9RUkpX80twtG9xUghW9Xn1ka9zOjIxJDLbtwSo= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0/go.mod h1:PAQH8+1DDGc6uibvC3nDtfRLu8uxutIr25mPJvrCOy8= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 h1:lxI0LnHcTpnF8g0tHTCQ1UIVLlNHk1W1WAclp3Ut0fw= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0/go.mod h1:TBvZpbCju0Zmq8GoS4CEtUg2MqtdqWrGeEAOXwkJNQo= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 h1:ewFXnESJWsUen0T9sSt0lwL28fhqCVB1HSLdY0szrdA= @@ -610,8 +610,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 h1:h1Ts github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1/go.mod h1:M4xZ2BnmROvLV2MrAP6A8o9BnyT0CkvpEcP8lBOfRs8= github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0 h1:bwLmLXvtCl1XkPRP+YrXwfz+lBMaGWH/crlNbYtxeqE= github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0 h1:WvPLO1c7oT/MWmCRTt7jRyxus2g3DIluIW5iAsUpSFM= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.2.0/go.mod h1:CyYJqR0tZWs2r5bGz69j4bmvhxdsd4QLCm1Uf+LouB0= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 h1:pUl/981oAXPnZd7++69NfEWv6JwW9UpxER16XxQUdOk= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0/go.mod h1:S04/QsQrB2EgYGjl62BO+9QUswrlRBoBosigrhdmccM= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From b16d44833828f12a74cec6f5bb18e262a7176daa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:51:56 +0200 Subject: [PATCH 353/619] chore(deps): bump renovatebot/github-action from 43.0.1 to 43.0.2 (#828) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 43.0.1 to 43.0.2. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v43.0.1...v43.0.2) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 43.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index ffb733574..2e1f2a8e3 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.1 + uses: renovatebot/github-action@v43.0.2 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From e40da0d8d52a033b4d6932fc9da8770b43663dca Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:52:05 +0200 Subject: [PATCH 354/619] chore(deps): update renovatebot/github-action action to v43.0.2 (#829) Co-authored-by: Renovate Bot From 4586494efc29e3e9f4da3d8e1327a75b780222c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 16:18:43 +0200 Subject: [PATCH 355/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex (#832) Bumps [github.com/stackitcloud/stackit-sdk-go/services/mongodbflex](https://github.com/stackitcloud/stackit-sdk-go) from 1.2.1 to 1.3.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/cdn/v1.2.1...services/cdn/v1.3.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/mongodbflex dependency-version: 1.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index df13fa311..0e45e99f3 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 diff --git a/go.sum b/go.sum index d44916ac4..d8ebc3717 100644 --- a/go.sum +++ b/go.sum @@ -580,8 +580,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCx github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 h1:vxk6ztgzUIPMkfv27NRpniFqCyGGGFsWJQUvFs43bQA= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1 h1:TWz7qJ4Mg5pquDXODSZ1dzhS95ZYn3w1aKjuRU2VqCg= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.2.1/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.3.0 h1:3R3S2R3m4Auh3cANM3t+AVDhWTKylXQHNBk42TKSbR4= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.3.0/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 h1:bK5FDpSGfUKDXNkqOoiqOU9hua2YfcdYsGS4zQQ9wg0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0/go.mod h1:Q2SJXlZTksvNAb1QnpGNfDSw/OMPN9uopaKuptUGhO8= github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0 h1:8v9Iupkc3meXcVPMpteXDz07YzY2M5jud50vEtAvbs8= From a57fd5803951ad746e9f37437ef4de957296afe5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 7 Jul 2025 09:31:17 +0200 Subject: [PATCH 356/619] fix(deps): update stackit sdk modules (#838) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 0e45e99f3..ed253d620 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0 + github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 @@ -27,7 +27,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 diff --git a/go.sum b/go.sum index d8ebc3717..fc887f795 100644 --- a/go.sum +++ b/go.sum @@ -570,8 +570,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 h1:KXMiTBV4 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0/go.mod h1:+2mx2MclJFMQ4Y6b20jspYAnIeFJP3/yvO6Gfvcvf6Q= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 h1:x5mx/C2bdtpOH974RofXD0Y8YOyJtYXwIyaCyWOXMwU= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= -github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0 h1:C+8z3MdvnTngcH9L72VHLXRKNWHHYp+7FO/F6imKmB4= -github.com/stackitcloud/stackit-sdk-go/services/git v0.6.0/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= +github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 h1:UJDtK96cjQqp5yWb8TxXLG42SOGcnBSgfYO7P3pk/j0= +github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0 h1:7qm/Tft79wFlHomPdgjUJ9uJU8kEk+k9ficMGRoHtf0= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0/go.mod h1:lUGkcbyMkd4nRBDFmKohIwlgtOZqQo4Ek5S5ajw90Xg= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 h1:Ef4SyTBjIkfwaws4mssa6AoK+OokHFtr7ZIflUpoXVE= @@ -600,8 +600,8 @@ github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 h1:ewFXnESJWsU github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0/go.mod h1:m9f9XZDeKpmqE/G0Sj5Rpdsiw+qcUo0Rcm3idAbyp1c= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0 h1:CtCaG8nycfviq/QgNM7OoBWs/Ap9IQvOmvI0tZhYdPI= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0/go.mod h1:/MiR18oug1V0sxPT4KO6a+LhgPARNBGvgVx3qv3zJ0A= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.0 h1:LGiq+2o2D3snaL1vqBQkvPTAEVPT2PKPrJzQL07hZgY= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.0/go.mod h1:S/zLsdZvtPXDSYyl7h2GLHhsnVf6AzB96PdslPWevJI= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1 h1:pvAYt53jUSUf1yHQJ+mcjQ+sgrpUBBqfw1EznGnP5A4= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1/go.mod h1:S/zLsdZvtPXDSYyl7h2GLHhsnVf6AzB96PdslPWevJI= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 h1:poL/Hz3a6OHZ/eKtwMGm5nLqC3fEJjzPQlN/7/+mk8Y= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0/go.mod h1:ssbyAHtxyuBvheMEItydM78/JxjDl3naUtllrC7ghDs= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 h1:2d28WFQB9QB3af4uoPFglQDhH1LepEe6F2YoFCBecVI= From fcd206796252cf6e67b24fe41ffd462ec8d43b29 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Mon, 7 Jul 2025 16:04:43 +0200 Subject: [PATCH 357/619] chore: update code owners (#840) --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index eab47aae8..7ec96a1b5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @marceljk @bahkauv70 @Fyusel @rubenhoenle \ No newline at end of file +* @stackitcloud/developer-tools \ No newline at end of file From 3bf6282d3f2fe4afe0e5b0a94bdb474c38c02aca Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Mon, 7 Jul 2025 16:57:38 +0200 Subject: [PATCH 358/619] fix(image): update overwrites nullable values (#834) * feat: add architecture flag #833 * fix: update overwrites nullable values #830 --- docs/stackit_image_create.md | 1 + docs/stackit_image_update.md | 1 + internal/cmd/image/create/create.go | 60 ++++++++++++++++------ internal/cmd/image/create/create_test.go | 4 ++ internal/cmd/image/describe/describe.go | 4 ++ internal/cmd/image/list/list.go | 13 +++-- internal/cmd/image/update/update.go | 65 ++++++++++++++++++------ internal/cmd/image/update/update_test.go | 25 +++++++++ 8 files changed, 138 insertions(+), 35 deletions(-) diff --git a/docs/stackit_image_create.md b/docs/stackit_image_create.md index 3c608126c..1dbfc5278 100644 --- a/docs/stackit_image_create.md +++ b/docs/stackit_image_create.md @@ -23,6 +23,7 @@ stackit image create [flags] ### Options ``` + --architecture string Sets the CPU architecture. By default x86 is used. --boot-menu Enables the BIOS bootmenu. --cdrom-bus string Sets CDROM bus controller type. --disk-bus string Sets Disk bus controller type. diff --git a/docs/stackit_image_update.md b/docs/stackit_image_update.md index 3c6acbe62..d088d9962 100644 --- a/docs/stackit_image_update.md +++ b/docs/stackit_image_update.md @@ -23,6 +23,7 @@ stackit image update IMAGE_ID [flags] ### Options ``` + --architecture string Sets the CPU architecture. --boot-menu Enables the BIOS bootmenu. --cdrom-bus string Sets CDROM bus controller type. --disk-bus string Sets Disk bus controller type. diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index d25c6adc4..0e0a84cbb 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -31,6 +31,7 @@ const ( localFilePathFlag = "local-file-path" noProgressIndicatorFlag = "no-progress" + architectureFlag = "architecture" bootMenuFlag = "boot-menu" cdromBusFlag = "cdrom-bus" diskBusFlag = "disk-bus" @@ -53,6 +54,7 @@ const ( ) type imageConfig struct { + Architecture *string BootMenu *bool CdromBus *string DiskBus *string @@ -261,6 +263,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(localFilePathFlag, "", "The path to the local disk image file.") cmd.Flags().Bool(noProgressIndicatorFlag, false, "Show no progress indicator for upload.") + cmd.Flags().String(architectureFlag, "", "Sets the CPU architecture. By default x86 is used.") cmd.Flags().Bool(bootMenuFlag, false, "Enables the BIOS bootmenu.") cmd.Flags().String(cdromBusFlag, "", "Sets CDROM bus controller type.") cmd.Flags().String(diskBusFlag, "", "Sets Disk bus controller type.") @@ -302,6 +305,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), NoProgressIndicator: flags.FlagToBoolPointer(p, cmd, noProgressIndicatorFlag), Config: &imageConfig{ + Architecture: flags.FlagToStringPointer(p, cmd, architectureFlag), BootMenu: flags.FlagToBoolPointer(p, cmd, bootMenuFlag), CdromBus: flags.FlagToStringPointer(p, cmd, cdromBusFlag), DiskBus: flags.FlagToStringPointer(p, cmd, diskBusFlag), @@ -348,21 +352,47 @@ func createPayload(_ context.Context, model *inputModel) iaas.CreateImagePayload MinRam: model.MinRam, Protected: model.Protected, } - if model.Config != nil { - payload.Config = &iaas.ImageConfig{ - BootMenu: model.Config.BootMenu, - CdromBus: iaas.NewNullableString(model.Config.CdromBus), - DiskBus: iaas.NewNullableString(model.Config.DiskBus), - NicModel: iaas.NewNullableString(model.Config.NicModel), - OperatingSystem: model.Config.OperatingSystem, - OperatingSystemDistro: iaas.NewNullableString(model.Config.OperatingSystemDistro), - OperatingSystemVersion: iaas.NewNullableString(model.Config.OperatingSystemVersion), - RescueBus: iaas.NewNullableString(model.Config.RescueBus), - RescueDevice: iaas.NewNullableString(model.Config.RescueDevice), - SecureBoot: model.Config.SecureBoot, - Uefi: utils.Ptr(model.Config.Uefi), - VideoModel: iaas.NewNullableString(model.Config.VideoModel), - VirtioScsi: model.Config.VirtioScsi, + if config := model.Config; config != nil { + payload.Config = &iaas.ImageConfig{} + payload.Config.Uefi = utils.Ptr(config.Uefi) + if config.Architecture != nil { + payload.Config.Architecture = model.Config.Architecture + } + if config.BootMenu != nil { + payload.Config.BootMenu = model.Config.BootMenu + } + if config.CdromBus != nil { + payload.Config.CdromBus = iaas.NewNullableString(model.Config.CdromBus) + } + if config.DiskBus != nil { + payload.Config.DiskBus = iaas.NewNullableString(config.DiskBus) + } + if config.NicModel != nil { + payload.Config.NicModel = iaas.NewNullableString(config.NicModel) + } + if config.OperatingSystem != nil { + payload.Config.OperatingSystem = config.OperatingSystem + } + if config.OperatingSystemDistro != nil { + payload.Config.OperatingSystemDistro = iaas.NewNullableString(config.OperatingSystemDistro) + } + if config.OperatingSystemVersion != nil { + payload.Config.OperatingSystemVersion = iaas.NewNullableString(config.OperatingSystemVersion) + } + if config.RescueBus != nil { + payload.Config.RescueBus = iaas.NewNullableString(config.RescueBus) + } + if config.RescueDevice != nil { + payload.Config.RescueDevice = iaas.NewNullableString(config.RescueDevice) + } + if config.SecureBoot != nil { + payload.Config.SecureBoot = config.SecureBoot + } + if config.VideoModel != nil { + payload.Config.VideoModel = iaas.NewNullableString(config.VideoModel) + } + if config.VirtioScsi != nil { + payload.Config.VirtioScsi = config.VirtioScsi } } diff --git a/internal/cmd/image/create/create_test.go b/internal/cmd/image/create/create_test.go index e0ed042c9..45a926fbf 100644 --- a/internal/cmd/image/create/create_test.go +++ b/internal/cmd/image/create/create_test.go @@ -39,6 +39,7 @@ var ( testOperatingSystemVersion = "test-distro-version" testRescueBus = "test-rescue-bus" testRescueDevice = "test-rescue-device" + testArchitecture = "arm64" testBootmenu = true testSecureBoot = true testUefi = true @@ -54,6 +55,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st nameFlag: testName, diskFormatFlag: testDiskFormat, localFilePathFlag: testLocalImagePath, + architectureFlag: testArchitecture, bootMenuFlag: strconv.FormatBool(testBootmenu), cdromBusFlag: testCdRomBus, diskBusFlag: testDiskBus, @@ -96,6 +98,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { LocalFilePath: testLocalImagePath, Labels: utils.Ptr(parseLabels(testLabels)), Config: &imageConfig{ + Architecture: &testArchitecture, BootMenu: &testBootmenu, CdromBus: &testCdRomBus, DiskBus: &testDiskBus, @@ -123,6 +126,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func fixtureCreatePayload(mods ...func(payload *iaas.CreateImagePayload)) (payload iaas.CreateImagePayload) { payload = iaas.CreateImagePayload{ Config: &iaas.ImageConfig{ + Architecture: &testArchitecture, BootMenu: &testBootmenu, CdromBus: iaas.NewNullableString(&testCdRomBus), DiskBus: iaas.NewNullableString(&testDiskBus), diff --git a/internal/cmd/image/describe/describe.go b/internal/cmd/image/describe/describe.go index d1c945b81..9a5e5e918 100644 --- a/internal/cmd/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -141,6 +141,10 @@ func outputResult(p *print.Printer, outputFormat string, resp *iaas.Image) error table.AddSeparator() } if config := resp.Config; config != nil { + if architecture := config.Architecture; architecture != nil { + table.AddRow("ARCHITECTURE", *architecture) + table.AddSeparator() + } if os := config.OperatingSystem; os != nil { table.AddRow("OPERATING SYSTEM", *os) table.AddSeparator() diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index 00f28b066..67e0c951c 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -165,14 +165,18 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) err return nil default: table := tables.NewTable() - table.SetHeader("ID", "NAME", "OS", "DISTRIBUTION", "VERSION", "LABELS") + table.SetHeader("ID", "NAME", "OS", "ARCHITECTURE", "DISTRIBUTION", "VERSION", "LABELS") for _, item := range items { var ( - os string = "n/a" - distro string = "n/a" - version string = "n/a" + architecture string = "n/a" + os string = "n/a" + distro string = "n/a" + version string = "n/a" ) if cfg := item.Config; cfg != nil { + if v := cfg.Architecture; v != nil { + architecture = *v + } if v := cfg.OperatingSystem; v != nil { os = *v } @@ -186,6 +190,7 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) err table.AddRow(utils.PtrString(item.Id), utils.PtrString(item.Name), os, + architecture, distro, version, utils.JoinStringKeysPtr(*item.Labels, ",")) diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index f461a388d..e434f1238 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -20,6 +20,7 @@ import ( ) type imageConfig struct { + Architecture *string BootMenu *bool CdromBus *string DiskBus *string @@ -80,6 +81,7 @@ const ( nameFlag = "name" diskFormatFlag = "disk-format" + architectureFlag = "architecture" bootMenuFlag = "boot-menu" cdromBusFlag = "cdrom-bus" diskBusFlag = "disk-bus" @@ -98,7 +100,6 @@ const ( minDiskSizeFlag = "min-disk-size" minRamFlag = "min-ram" - ownerFlag = "owner" protectedFlag = "protected" ) @@ -166,6 +167,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(nameFlag, "", "The name of the image.") cmd.Flags().String(diskFormatFlag, "", "The disk format of the image. ") + cmd.Flags().String(architectureFlag, "", "Sets the CPU architecture.") cmd.Flags().Bool(bootMenuFlag, false, "Enables the BIOS bootmenu.") cmd.Flags().String(cdromBusFlag, "", "Sets CDROM bus controller type.") cmd.Flags().String(diskBusFlag, "", "Sets Disk bus controller type.") @@ -203,6 +205,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM DiskFormat: flags.FlagToStringPointer(p, cmd, diskFormatFlag), Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), Config: &imageConfig{ + Architecture: flags.FlagToStringPointer(p, cmd, architectureFlag), BootMenu: flags.FlagToBoolPointer(p, cmd, bootMenuFlag), CdromBus: flags.FlagToStringPointer(p, cmd, cdromBusFlag), DiskBus: flags.FlagToStringPointer(p, cmd, diskBusFlag), @@ -226,6 +229,10 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM return nil, fmt.Errorf("no flags have been passed") } + if model.Config.isEmpty() { + model.Config = nil + } + if p.IsVerbosityDebug() { modelStr, err := print.BuildDebugStrFromInputModel(model) if err != nil { @@ -249,22 +256,48 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli payload.MinRam = model.MinRam payload.Name = model.Name payload.Protected = model.Protected + payload.Config = nil - if model.Config != nil { - payload.Config = &iaas.ImageConfig{ - BootMenu: model.Config.BootMenu, - CdromBus: iaas.NewNullableString(model.Config.CdromBus), - DiskBus: iaas.NewNullableString(model.Config.DiskBus), - NicModel: iaas.NewNullableString(model.Config.NicModel), - OperatingSystem: model.Config.OperatingSystem, - OperatingSystemDistro: iaas.NewNullableString(model.Config.OperatingSystemDistro), - OperatingSystemVersion: iaas.NewNullableString(model.Config.OperatingSystemVersion), - RescueBus: iaas.NewNullableString(model.Config.RescueBus), - RescueDevice: iaas.NewNullableString(model.Config.RescueDevice), - SecureBoot: model.Config.SecureBoot, - Uefi: model.Config.Uefi, - VideoModel: iaas.NewNullableString(model.Config.VideoModel), - VirtioScsi: model.Config.VirtioScsi, + if config := model.Config; config != nil { + payload.Config = &iaas.ImageConfig{} + if model.Config.BootMenu != nil { + payload.Config.BootMenu = model.Config.BootMenu + } + if model.Config.CdromBus != nil { + payload.Config.CdromBus = iaas.NewNullableString(model.Config.CdromBus) + } + if model.Config.DiskBus != nil { + payload.Config.DiskBus = iaas.NewNullableString(model.Config.DiskBus) + } + if model.Config.NicModel != nil { + payload.Config.NicModel = iaas.NewNullableString(model.Config.NicModel) + } + if model.Config.OperatingSystem != nil { + payload.Config.OperatingSystem = model.Config.OperatingSystem + } + if model.Config.OperatingSystemDistro != nil { + payload.Config.OperatingSystemDistro = iaas.NewNullableString(model.Config.OperatingSystemDistro) + } + if model.Config.OperatingSystemVersion != nil { + payload.Config.OperatingSystemVersion = iaas.NewNullableString(model.Config.OperatingSystemVersion) + } + if model.Config.RescueBus != nil { + payload.Config.RescueBus = iaas.NewNullableString(model.Config.RescueBus) + } + if model.Config.RescueDevice != nil { + payload.Config.RescueDevice = iaas.NewNullableString(model.Config.RescueDevice) + } + if model.Config.SecureBoot != nil { + payload.Config.SecureBoot = model.Config.SecureBoot + } + if model.Config.Uefi != nil { + payload.Config.Uefi = model.Config.Uefi + } + if model.Config.VideoModel != nil { + payload.Config.VideoModel = iaas.NewNullableString(model.Config.VideoModel) + } + if model.Config.VirtioScsi != nil { + payload.Config.VirtioScsi = model.Config.VirtioScsi } } diff --git a/internal/cmd/image/update/update_test.go b/internal/cmd/image/update/update_test.go index 17216cbb9..5e4d620ca 100644 --- a/internal/cmd/image/update/update_test.go +++ b/internal/cmd/image/update/update_test.go @@ -298,6 +298,20 @@ func TestParseInput(t *testing.T) { model.Config.RescueDevice = nil }), }, + { + description: "update only name", + flagValues: map[string]string{ + projectIdFlag: testProjectId, + nameFlag: "foo", + }, + args: testImageId, + isValid: true, + expectedModel: &inputModel{ + Name: utils.Ptr("foo"), + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + Id: testImageId[0], + }, + }, } for _, tt := range tests { @@ -400,6 +414,17 @@ func TestBuildRequest(t *testing.T) { })) }), }, + { + description: "no config set", + model: fixtureInputModel(func(model *inputModel) { + model.Config = nil + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateImageRequest) { + *request = (*request).UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { + payload.Config = nil + })) + }), + }, } for _, tt := range tests { From 99638edf6a1e594f4411a63001a72ca0c704f27d Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Mon, 7 Jul 2025 18:01:40 +0200 Subject: [PATCH 359/619] feat(ske): Region adjustment (#842) Signed-off-by: Alexander Dahmen --- go.mod | 2 +- go.sum | 4 +-- internal/cmd/ske/cluster/create/create.go | 8 ++--- .../cmd/ske/cluster/create/create_test.go | 8 +++-- internal/cmd/ske/cluster/delete/delete.go | 4 +-- .../cmd/ske/cluster/delete/delete_test.go | 8 +++-- internal/cmd/ske/cluster/describe/describe.go | 2 +- .../cmd/ske/cluster/describe/describe_test.go | 8 +++-- .../generate-payload/generate_payload.go | 4 +-- .../generate-payload/generate_payload_test.go | 12 +++++--- internal/cmd/ske/cluster/list/list.go | 4 +-- internal/cmd/ske/cluster/list/list_test.go | 10 +++++-- internal/cmd/ske/cluster/update/update.go | 6 ++-- .../cmd/ske/cluster/update/update_test.go | 8 +++-- .../complete-rotation/complete_rotation.go | 4 +-- .../complete_rotation_test.go | 8 +++-- .../start-rotation/start_rotation.go | 4 +-- .../start-rotation/start_rotation_test.go | 8 +++-- internal/cmd/ske/kubeconfig/create/create.go | 4 +-- .../cmd/ske/kubeconfig/create/create_test.go | 8 +++-- internal/cmd/ske/kubeconfig/login/login.go | 13 ++++++--- .../cmd/ske/kubeconfig/login/login_test.go | 5 +++- internal/cmd/ske/options/options.go | 6 ++-- internal/cmd/ske/options/options_test.go | 29 ++++++++++++------- internal/pkg/services/ske/client/client.go | 3 +- internal/pkg/services/ske/utils/utils.go | 12 ++++---- internal/pkg/services/ske/utils/utils_test.go | 10 ++++--- 27 files changed, 128 insertions(+), 74 deletions(-) diff --git a/go.mod b/go.mod index ed253d620..5f9d4f9db 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.25.0 diff --git a/go.sum b/go.sum index fc887f795..888db04e5 100644 --- a/go.sum +++ b/go.sum @@ -608,8 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 h1:2d28WFQ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0/go.mod h1:t77MA8uyEU9KZd1On5JpnxI3xhVPKIS8WutStqvU8Cw= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 h1:h1TsWatlsexLeKdkb3L8chcxaXJOy/cLXctsRxhb4xg= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1/go.mod h1:M4xZ2BnmROvLV2MrAP6A8o9BnyT0CkvpEcP8lBOfRs8= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0 h1:bwLmLXvtCl1XkPRP+YrXwfz+lBMaGWH/crlNbYtxeqE= -github.com/stackitcloud/stackit-sdk-go/services/ske v0.27.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.0.0 h1:PX8VTo2UhPd6BeEaCHFlpIkDbk9OFQEO6eJJ8JkxesA= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.0.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 h1:pUl/981oAXPnZd7++69NfEWv6JwW9UpxER16XxQUdOk= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0/go.mod h1:S04/QsQrB2EgYGjl62BO+9QUswrlRBoBosigrhdmccM= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 3f7f9a802..557fb9a3a 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -108,7 +108,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Check if cluster exists - exists, err := skeUtils.ClusterExists(ctx, apiClient, model.ProjectId, model.ClusterName) + exists, err := skeUtils.ClusterExists(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName) if err != nil { return err } @@ -118,7 +118,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { // Fill in default payload, if needed if model.Payload == nil { - defaultPayload, err := skeUtils.GetDefaultPayload(ctx, apiClient) + defaultPayload, err := skeUtils.GetDefaultPayload(ctx, apiClient, model.Region) if err != nil { return fmt.Errorf("get default payload: %w", err) } @@ -137,7 +137,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Creating cluster") - _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient, model.ProjectId, name).WaitWithContext(ctx) + _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient, model.ProjectId, model.Region, name).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SKE cluster creation: %w", err) } @@ -192,7 +192,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiCreateOrUpdateClusterRequest { - req := apiClient.CreateOrUpdateCluster(ctx, model.ProjectId, model.ClusterName) + req := apiClient.CreateOrUpdateCluster(ctx, model.ProjectId, model.Region, model.ClusterName) req = req.CreateOrUpdateClusterPayload(*model.Payload) return req diff --git a/internal/cmd/ske/cluster/create/create_test.go b/internal/cmd/ske/cluster/create/create_test.go index f64a03eb1..8fba70614 100644 --- a/internal/cmd/ske/cluster/create/create_test.go +++ b/internal/cmd/ske/cluster/create/create_test.go @@ -26,6 +26,8 @@ var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() var testClusterName = "cluster" +const testRegion = "eu01" + var testPayload = &ske.CreateOrUpdateClusterPayload{ Kubernetes: &ske.Kubernetes{ Version: utils.Ptr("1.25.15"), @@ -81,7 +83,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, payloadFlag: fmt.Sprintf(`{ "name": "cli-jp", "kubernetes": { @@ -128,6 +131,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ClusterName: testClusterName, @@ -140,7 +144,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiCreateOrUpdateClusterRequest)) ske.ApiCreateOrUpdateClusterRequest { - request := testClient.CreateOrUpdateCluster(testCtx, testProjectId, fixtureInputModel().ClusterName) + request := testClient.CreateOrUpdateCluster(testCtx, testProjectId, testRegion, fixtureInputModel().ClusterName) request = request.CreateOrUpdateClusterPayload(*testPayload) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/ske/cluster/delete/delete.go b/internal/cmd/ske/cluster/delete/delete.go index 8a6e5c9cc..b10871bfe 100644 --- a/internal/cmd/ske/cluster/delete/delete.go +++ b/internal/cmd/ske/cluster/delete/delete.go @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Deleting cluster") - _, err = wait.DeleteClusterWaitHandler(ctx, apiClient, model.ProjectId, model.ClusterName).WaitWithContext(ctx) + _, err = wait.DeleteClusterWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SKE cluster deletion: %w", err) } @@ -114,6 +114,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiDeleteClusterRequest { - req := apiClient.DeleteCluster(ctx, model.ProjectId, model.ClusterName) + req := apiClient.DeleteCluster(ctx, model.ProjectId, model.Region, model.ClusterName) return req } diff --git a/internal/cmd/ske/cluster/delete/delete_test.go b/internal/cmd/ske/cluster/delete/delete_test.go index b51e559ad..2835c477b 100644 --- a/internal/cmd/ske/cluster/delete/delete_test.go +++ b/internal/cmd/ske/cluster/delete/delete_test.go @@ -23,6 +23,8 @@ var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() var testClusterName = "cluster" +const testRegion = "eu01" + func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testClusterName, @@ -35,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ClusterName: testClusterName, @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiDeleteClusterRequest)) ske.ApiDeleteClusterRequest { - request := testClient.DeleteCluster(testCtx, testProjectId, testClusterName) + request := testClient.DeleteCluster(testCtx, testProjectId, testRegion, testClusterName) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 703ce9b0f..40bf4897f 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -93,7 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiGetClusterRequest { - req := apiClient.GetCluster(ctx, model.ProjectId, model.ClusterName) + req := apiClient.GetCluster(ctx, model.ProjectId, model.Region, model.ClusterName) return req } diff --git a/internal/cmd/ske/cluster/describe/describe_test.go b/internal/cmd/ske/cluster/describe/describe_test.go index 13a1b9468..df33417ff 100644 --- a/internal/cmd/ske/cluster/describe/describe_test.go +++ b/internal/cmd/ske/cluster/describe/describe_test.go @@ -23,6 +23,8 @@ var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() var testClusterName = "cluster" +const testRegion = "eu01" + func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testClusterName, @@ -35,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ClusterName: testClusterName, @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiGetClusterRequest)) ske.ApiGetClusterRequest { - request := testClient.GetCluster(testCtx, testProjectId, testClusterName) + request := testClient.GetCluster(testCtx, testProjectId, testRegion, testClusterName) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload.go b/internal/cmd/ske/cluster/generate-payload/generate_payload.go index 14400f175..566e51f33 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload.go @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { var payload *ske.CreateOrUpdateClusterPayload if model.ClusterName == nil { - payload, err = skeUtils.GetDefaultPayload(ctx, apiClient) + payload, err = skeUtils.GetDefaultPayload(ctx, apiClient, model.Region) if err != nil { return err } @@ -130,7 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiGetClusterRequest { - req := apiClient.GetCluster(ctx, model.ProjectId, *model.ClusterName) + req := apiClient.GetCluster(ctx, model.ProjectId, model.Region, *model.ClusterName) return req } diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go index ac758cd1d..856db970d 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go @@ -28,11 +28,14 @@ const ( testFilePath = "example-file" ) +const testRegion = "eu01" + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - clusterNameFlag: testClusterName, - filePathFlag: testFilePath, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + clusterNameFlag: testClusterName, + filePathFlag: testFilePath, } for _, mod := range mods { mod(flagValues) @@ -44,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ClusterName: utils.Ptr(testClusterName), @@ -56,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiGetClusterRequest)) ske.ApiGetClusterRequest { - request := testClient.GetCluster(testCtx, testProjectId, testClusterName) + request := testClient.GetCluster(testCtx, testProjectId, testRegion, testClusterName) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 6674be931..31b8f2b7b 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -144,7 +144,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiListClustersRequest { - req := apiClient.ListClusters(ctx, model.ProjectId) + req := apiClient.ListClusters(ctx, model.ProjectId, model.Region) return req } @@ -172,7 +172,7 @@ func outputResult(p *print.Printer, outputFormat string, clusters []ske.Cluster) for i := range clusters { c := clusters[i] monitoring := "Disabled" - if c.Extensions != nil && c.Extensions.Argus != nil && *c.Extensions.Argus.Enabled { + if c.Extensions != nil && c.Extensions.Observability != nil && *c.Extensions.Observability.Enabled { monitoring = "Enabled" } statusAggregated, kubernetesVersion := "", "" diff --git a/internal/cmd/ske/cluster/list/list_test.go b/internal/cmd/ske/cluster/list/list_test.go index c7eb8a01a..e3c1a063c 100644 --- a/internal/cmd/ske/cluster/list/list_test.go +++ b/internal/cmd/ske/cluster/list/list_test.go @@ -24,10 +24,13 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() +const testRegion = "eu01" + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -39,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -50,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiListClustersRequest)) ske.ApiListClustersRequest { - request := testClient.ListClusters(testCtx, testProjectId) + request := testClient.ListClusters(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index 8ce6568e9..420c06349 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -79,7 +79,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Check if cluster exists - exists, err := skeUtils.ClusterExists(ctx, apiClient, model.ProjectId, model.ClusterName) + exists, err := skeUtils.ClusterExists(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName) if err != nil { return err } @@ -99,7 +99,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Updating cluster") - _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient, model.ProjectId, name).WaitWithContext(ctx) + _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient, model.ProjectId, model.Region, name).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for SKE cluster update: %w", err) } @@ -154,7 +154,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiCreateOrUpdateClusterRequest { - req := apiClient.CreateOrUpdateCluster(ctx, model.ProjectId, model.ClusterName) + req := apiClient.CreateOrUpdateCluster(ctx, model.ProjectId, model.Region, model.ClusterName) req = req.CreateOrUpdateClusterPayload(model.Payload) return req diff --git a/internal/cmd/ske/cluster/update/update_test.go b/internal/cmd/ske/cluster/update/update_test.go index 8eab71453..dcf82f207 100644 --- a/internal/cmd/ske/cluster/update/update_test.go +++ b/internal/cmd/ske/cluster/update/update_test.go @@ -26,6 +26,8 @@ var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() var testClusterName = "cluster" +const testRegion = "eu01" + var testPayload = ske.CreateOrUpdateClusterPayload{ Kubernetes: &ske.Kubernetes{ Version: utils.Ptr("1.25.15"), @@ -81,7 +83,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, payloadFlag: fmt.Sprintf(`{ "name": "cli-jp", "kubernetes": { @@ -128,6 +131,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ClusterName: testClusterName, @@ -140,7 +144,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiCreateOrUpdateClusterRequest)) ske.ApiCreateOrUpdateClusterRequest { - request := testClient.CreateOrUpdateCluster(testCtx, testProjectId, fixtureInputModel().ClusterName) + request := testClient.CreateOrUpdateCluster(testCtx, testProjectId, testRegion, fixtureInputModel().ClusterName) request = request.CreateOrUpdateClusterPayload(testPayload) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go index 4b9dfa1d6..982e9267d 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go @@ -87,7 +87,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Completing credentials rotation") - _, err = wait.CompleteCredentialsRotationWaitHandler(ctx, apiClient, model.ProjectId, model.ClusterName).WaitWithContext(ctx) + _, err = wait.CompleteCredentialsRotationWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for completing SKE credentials rotation %w", err) } @@ -132,6 +132,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiCompleteCredentialsRotationRequest { - req := apiClient.CompleteCredentialsRotation(ctx, model.ProjectId, model.ClusterName) + req := apiClient.CompleteCredentialsRotation(ctx, model.ProjectId, model.Region, model.ClusterName) return req } diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go index 35e773133..b8d40624c 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go @@ -23,6 +23,8 @@ var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() var testClusterName = "cluster" +const testRegion = "eu01" + func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testClusterName, @@ -35,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ClusterName: testClusterName, @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiCompleteCredentialsRotationRequest)) ske.ApiCompleteCredentialsRotationRequest { - request := testClient.CompleteCredentialsRotation(testCtx, testProjectId, testClusterName) + request := testClient.CompleteCredentialsRotation(testCtx, testProjectId, testRegion, testClusterName) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation.go b/internal/cmd/ske/credentials/start-rotation/start_rotation.go index 4e34c9ebe..a8314ad83 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation.go @@ -90,7 +90,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Starting credentials rotation") - _, err = wait.StartCredentialsRotationWaitHandler(ctx, apiClient, model.ProjectId, model.ClusterName).WaitWithContext(ctx) + _, err = wait.StartCredentialsRotationWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for start SKE credentials rotation %w", err) } @@ -135,6 +135,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiStartCredentialsRotationRequest { - req := apiClient.StartCredentialsRotation(ctx, model.ProjectId, model.ClusterName) + req := apiClient.StartCredentialsRotation(ctx, model.ProjectId, model.Region, model.ClusterName) return req } diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go b/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go index 29f2825ac..0e2f99fa3 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go @@ -23,6 +23,8 @@ var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() var testClusterName = "cluster" +const testRegion = "eu01" + func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testClusterName, @@ -35,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ClusterName: testClusterName, @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiStartCredentialsRotationRequest)) ske.ApiStartCredentialsRotationRequest { - request := testClient.StartCredentialsRotation(testCtx, testProjectId, testClusterName) + request := testClient.StartCredentialsRotation(testCtx, testProjectId, testRegion, testClusterName) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index c4565223c..fe2907958 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -228,7 +228,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequestCreate(ctx context.Context, model *inputModel, apiClient *ske.APIClient) (ske.ApiCreateKubeconfigRequest, error) { - req := apiClient.CreateKubeconfig(ctx, model.ProjectId, model.ClusterName) + req := apiClient.CreateKubeconfig(ctx, model.ProjectId, model.Region, model.ClusterName) payload := ske.CreateKubeconfigPayload{} @@ -240,7 +240,7 @@ func buildRequestCreate(ctx context.Context, model *inputModel, apiClient *ske.A } func buildRequestLogin(ctx context.Context, model *inputModel, apiClient *ske.APIClient) (ske.ApiGetLoginKubeconfigRequest, error) { - return apiClient.GetLoginKubeconfig(ctx, model.ProjectId, model.ClusterName), nil + return apiClient.GetLoginKubeconfig(ctx, model.ProjectId, model.Region, model.ClusterName), nil } func outputResult(p *print.Printer, outputFormat, clusterName, kubeconfigPath string, respKubeconfig *ske.Kubeconfig, respLogin *ske.LoginKubeconfig) error { diff --git a/internal/cmd/ske/kubeconfig/create/create_test.go b/internal/cmd/ske/kubeconfig/create/create_test.go index 558d273e5..513fae126 100644 --- a/internal/cmd/ske/kubeconfig/create/create_test.go +++ b/internal/cmd/ske/kubeconfig/create/create_test.go @@ -23,6 +23,8 @@ var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() var testClusterName = "cluster" +const testRegion = "eu01" + func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ testClusterName, @@ -35,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ClusterName: testClusterName, @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *ske.ApiCreateKubeconfigRequest)) ske.ApiCreateKubeconfigRequest { - request := testClient.CreateKubeconfig(testCtx, testProjectId, testClusterName) + request := testClient.CreateKubeconfig(testCtx, testProjectId, testRegion, testClusterName) request = request.CreateKubeconfigPayload(ske.CreateKubeconfigPayload{}) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/ske/kubeconfig/login/login.go b/internal/cmd/ske/kubeconfig/login/login.go index 058197418..3edc33b1f 100644 --- a/internal/cmd/ske/kubeconfig/login/login.go +++ b/internal/cmd/ske/kubeconfig/login/login.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/cache" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "k8s.io/client-go/rest" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -55,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ kubectl cluster-info", "$ kubectl get pods"), ), - RunE: func(_ *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() if err := cache.Init(); err != nil { @@ -69,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "See `stackit ske kubeconfig login --help` for detailed usage instructions.") } - clusterConfig, err := parseClusterConfig() + clusterConfig, err := parseClusterConfig(params.Printer, cmd) if err != nil { return fmt.Errorf("parseClusterConfig: %w", err) } @@ -123,9 +124,10 @@ type clusterConfig struct { ClusterName string `json:"clusterName"` cacheKey string + Region string } -func parseClusterConfig() (*clusterConfig, error) { +func parseClusterConfig(p *print.Printer, cmd *cobra.Command) (*clusterConfig, error) { obj, _, err := exec.LoadExecCredentialFromEnv() if err != nil { return nil, fmt.Errorf("LoadExecCredentialFromEnv: %w", err) @@ -155,6 +157,9 @@ func parseClusterConfig() (*clusterConfig, error) { config.cacheKey = fmt.Sprintf("ske-login-%x", sha256.Sum256([]byte(execCredential.Spec.Cluster.Server))) + globalFlags := globalflags.Parse(p, cmd) + config.Region = globalFlags.Region + return config, nil } @@ -200,7 +205,7 @@ func GetAndOutputKubeconfig(ctx context.Context, p *print.Printer, apiClient *sk } func buildRequest(ctx context.Context, apiClient *ske.APIClient, clusterConfig *clusterConfig) ske.ApiCreateKubeconfigRequest { - req := apiClient.CreateKubeconfig(ctx, clusterConfig.STACKITProjectID, clusterConfig.ClusterName) + req := apiClient.CreateKubeconfig(ctx, clusterConfig.STACKITProjectID, clusterConfig.Region, clusterConfig.ClusterName) expirationSeconds := strconv.Itoa(expirationSeconds) return req.CreateKubeconfigPayload(ske.CreateKubeconfigPayload{ExpirationSeconds: &expirationSeconds}) diff --git a/internal/cmd/ske/kubeconfig/login/login_test.go b/internal/cmd/ske/kubeconfig/login/login_test.go index c6b94c9a9..ce22fbc1f 100644 --- a/internal/cmd/ske/kubeconfig/login/login_test.go +++ b/internal/cmd/ske/kubeconfig/login/login_test.go @@ -22,11 +22,14 @@ var testClient = &ske.APIClient{} var testProjectId = uuid.NewString() var testClusterName = "cluster" +const testRegion = "eu01" + func fixtureClusterConfig(mods ...func(clusterConfig *clusterConfig)) *clusterConfig { clusterConfig := &clusterConfig{ STACKITProjectID: testProjectId, ClusterName: testClusterName, cacheKey: "", + Region: testRegion, } for _, mod := range mods { mod(clusterConfig) @@ -35,7 +38,7 @@ func fixtureClusterConfig(mods ...func(clusterConfig *clusterConfig)) *clusterCo } func fixtureRequest(mods ...func(request *ske.ApiCreateKubeconfigRequest)) ske.ApiCreateKubeconfigRequest { - request := testClient.CreateKubeconfig(testCtx, testProjectId, testClusterName) + request := testClient.CreateKubeconfig(testCtx, testProjectId, testRegion, testClusterName) request = request.CreateKubeconfigPayload(ske.CreateKubeconfigPayload{}) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index dbcfa7613..91564ceea 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Call API - req := buildRequest(ctx, apiClient) + req := buildRequest(ctx, apiClient, model) resp, err := req.Execute() if err != nil { return fmt.Errorf("get SKE provider options: %w", err) @@ -131,8 +131,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return &model, nil } -func buildRequest(ctx context.Context, apiClient *ske.APIClient) ske.ApiListProviderOptionsRequest { - req := apiClient.ListProviderOptions(ctx) +func buildRequest(ctx context.Context, apiClient *ske.APIClient, model *inputModel) ske.ApiListProviderOptionsRequest { + req := apiClient.ListProviderOptions(ctx, model.Region) return req } diff --git a/internal/cmd/ske/options/options_test.go b/internal/cmd/ske/options/options_test.go index b2181ef5b..d2317d1e5 100644 --- a/internal/cmd/ske/options/options_test.go +++ b/internal/cmd/ske/options/options_test.go @@ -18,6 +18,8 @@ type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &ske.APIClient{} +const testRegion = "eu01" + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ availabilityZonesFlag: "false", @@ -25,6 +27,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st machineImagesFlag: "false", machineTypesFlag: "false", volumeTypesFlag: "false", + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -34,7 +37,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModelAllFalse(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{Verbosity: globalflags.VerbosityDefault}, + GlobalFlagModel: &globalflags.GlobalFlagModel{Region: testRegion, Verbosity: globalflags.VerbosityDefault}, AvailabilityZones: false, KubernetesVersions: false, MachineImages: false, @@ -49,7 +52,7 @@ func fixtureInputModelAllFalse(mods ...func(model *inputModel)) *inputModel { func fixtureInputModelAllTrue(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{Verbosity: globalflags.VerbosityDefault}, + GlobalFlagModel: &globalflags.GlobalFlagModel{Region: testRegion, Verbosity: globalflags.VerbosityDefault}, AvailabilityZones: true, KubernetesVersions: true, MachineImages: true, @@ -76,10 +79,12 @@ func TestParseInput(t *testing.T) { expectedModel: fixtureInputModelAllTrue(), }, { - description: "no values", - flagValues: map[string]string{}, - isValid: true, - expectedModel: fixtureInputModelAllTrue(), + description: "no values", + flagValues: map[string]string{}, + isValid: true, + expectedModel: fixtureInputModelAllTrue(func(model *inputModel) { + model.Region = "" + }), }, { description: "some values 1", @@ -90,6 +95,7 @@ func TestParseInput(t *testing.T) { isValid: true, expectedModel: fixtureInputModelAllFalse(func(model *inputModel) { model.AvailabilityZones = true + model.Region = "" }), }, { @@ -103,6 +109,7 @@ func TestParseInput(t *testing.T) { expectedModel: fixtureInputModelAllFalse(func(model *inputModel) { model.KubernetesVersions = true model.MachineTypes = true + model.Region = "" }), }, { @@ -111,8 +118,10 @@ func TestParseInput(t *testing.T) { kubernetesVersionsFlag: "false", machineTypesFlag: "false", }, - isValid: true, - expectedModel: fixtureInputModelAllTrue(), + isValid: true, + expectedModel: fixtureInputModelAllTrue(func(model *inputModel) { + model.Region = "" + }), }, } @@ -169,13 +178,13 @@ func TestBuildRequest(t *testing.T) { }{ { description: "base", - expectedRequest: testClient.ListProviderOptions(testCtx), + expectedRequest: testClient.ListProviderOptions(testCtx, testRegion), }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - request := buildRequest(testCtx, testClient) + request := buildRequest(testCtx, testClient, fixtureInputModelAllTrue()) diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), diff --git a/internal/pkg/services/ske/client/client.go b/internal/pkg/services/ske/client/client.go index a361f73d2..1495ba7bf 100644 --- a/internal/pkg/services/ske/client/client.go +++ b/internal/pkg/services/ske/client/client.go @@ -27,8 +27,7 @@ func ConfigureClient(p *print.Printer, cliVersion string) (*ske.APIClient, error if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } else { - region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) + cfgOptions = append(cfgOptions, authCfgOption) } if p.IsVerbosityDebug() { diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 283760f63..4c5604fc4 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -32,12 +32,12 @@ const ( ) type SKEClient interface { - ListClustersExecute(ctx context.Context, projectId string) (*ske.ListClustersResponse, error) - ListProviderOptionsExecute(ctx context.Context) (*ske.ProviderOptions, error) + ListClustersExecute(ctx context.Context, projectId, region string) (*ske.ListClustersResponse, error) + ListProviderOptionsExecute(ctx context.Context, region string) (*ske.ProviderOptions, error) } -func ClusterExists(ctx context.Context, apiClient SKEClient, projectId, clusterName string) (bool, error) { - clusters, err := apiClient.ListClustersExecute(ctx, projectId) +func ClusterExists(ctx context.Context, apiClient SKEClient, projectId, region, clusterName string) (bool, error) { + clusters, err := apiClient.ListClustersExecute(ctx, projectId, region) if err != nil { return false, fmt.Errorf("list SKE clusters: %w", err) } @@ -49,8 +49,8 @@ func ClusterExists(ctx context.Context, apiClient SKEClient, projectId, clusterN return false, nil } -func GetDefaultPayload(ctx context.Context, apiClient SKEClient) (*ske.CreateOrUpdateClusterPayload, error) { - resp, err := apiClient.ListProviderOptionsExecute(ctx) +func GetDefaultPayload(ctx context.Context, apiClient SKEClient, region string) (*ske.CreateOrUpdateClusterPayload, error) { + resp, err := apiClient.ListProviderOptionsExecute(ctx, region) if err != nil { return nil, fmt.Errorf("get SKE provider options: %w", err) } diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index 9c6c37ace..27b9b8d6a 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -70,14 +70,16 @@ type skeClientMocked struct { listProviderOptionsResp *ske.ProviderOptions } -func (m *skeClientMocked) ListClustersExecute(_ context.Context, _ string) (*ske.ListClustersResponse, error) { +const testRegion = "eu01" + +func (m *skeClientMocked) ListClustersExecute(_ context.Context, _, _ string) (*ske.ListClustersResponse, error) { if m.listClustersFails { return nil, fmt.Errorf("could not list clusters") } return m.listClustersResp, nil } -func (m *skeClientMocked) ListProviderOptionsExecute(_ context.Context) (*ske.ProviderOptions, error) { +func (m *skeClientMocked) ListProviderOptionsExecute(_ context.Context, _ string) (*ske.ProviderOptions, error) { if m.listProviderOptionsFails { return nil, fmt.Errorf("could not list provider options") } @@ -124,7 +126,7 @@ func TestClusterExists(t *testing.T) { listClustersResp: tt.getClustersResp, } - exists, err := ClusterExists(context.Background(), client, testProjectId, testClusterName) + exists, err := ClusterExists(context.Background(), client, testProjectId, testRegion, testClusterName) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -400,7 +402,7 @@ func TestGetDefaultPayload(t *testing.T) { listProviderOptionsResp: tt.listProviderOptionsResp, } - output, err := GetDefaultPayload(context.Background(), client) + output, err := GetDefaultPayload(context.Background(), client, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") From 380330dc2ec1d9ff8a3b3d1709841b3d9bc7367e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 8 Jul 2025 10:36:30 +0200 Subject: [PATCH 360/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.27.0 (#844) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5f9d4f9db..604ff8faa 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 diff --git a/go.sum b/go.sum index 888db04e5..8b31d4ecc 100644 --- a/go.sum +++ b/go.sum @@ -572,8 +572,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 h1:x5mx/C2bdtpOH974R github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 h1:UJDtK96cjQqp5yWb8TxXLG42SOGcnBSgfYO7P3pk/j0= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0 h1:7qm/Tft79wFlHomPdgjUJ9uJU8kEk+k9ficMGRoHtf0= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.26.0/go.mod h1:lUGkcbyMkd4nRBDFmKohIwlgtOZqQo4Ek5S5ajw90Xg= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 h1:5vxOzwQ+rNm0g9ZLQW/31dqdDqGfw/FQbrjxUUAHtiA= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0/go.mod h1:lUGkcbyMkd4nRBDFmKohIwlgtOZqQo4Ek5S5ajw90Xg= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 h1:Ef4SyTBjIkfwaws4mssa6AoK+OokHFtr7ZIflUpoXVE= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCxpFXN2K7g2ih0gQM6cyZ1VhTmtQfI= From 64f3f143fe9ba7091c569631e4de9f107066bf66 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Wed, 9 Jul 2025 13:53:59 +0200 Subject: [PATCH 361/619] fix: add missing security group ID output to `security-group create` command (#846) --- internal/cmd/security-group/create/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index 5bce0c52b..1e17b9002 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -156,7 +156,7 @@ func outputResult(p *print.Printer, outputFormat, name string, resp iaas.Securit return nil default: - p.Outputf("Created security group %q\n", name) + p.Outputf("Created security group %q.\nSecurity Group ID %s\n", name, utils.PtrString(resp.Id)) return nil } } From 3d6a354815eddba620a95265d9929a9a8429d3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:40:27 +0200 Subject: [PATCH 362/619] feat: add refreshing access token functionality to get-access-token command (#847) --- .../auth/get-access-token/get_access_token.go | 11 +-- internal/pkg/auth/auth.go | 69 +++++++++++++++++++ 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index 0b13fd2fa..25576427a 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -29,19 +29,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return &cliErr.SessionExpiredError{} } - accessToken, err := auth.GetAccessToken() + // Try to get a valid access token, refreshing if necessary + accessToken, err := auth.RefreshAccessToken(params.Printer) if err != nil { return err } - accessTokenExpired, err := auth.TokenExpired(accessToken) - if err != nil { - return err - } - if accessTokenExpired { - return &cliErr.AccessTokenExpiredError{} - } - params.Printer.Outputf("%s\n", accessToken) return nil }, diff --git a/internal/pkg/auth/auth.go b/internal/pkg/auth/auth.go index 89a39ac29..634813f24 100644 --- a/internal/pkg/auth/auth.go +++ b/internal/pkg/auth/auth.go @@ -2,6 +2,7 @@ package auth import ( "fmt" + "net/http" "os" "strconv" "time" @@ -132,3 +133,71 @@ func getEmailFromToken(token string) (string, error) { return claims.Email, nil } + +// RefreshAccessToken refreshes the access token if it's expired for the user token flow. +// It returns the new access token or an error if the refresh fails. +func RefreshAccessToken(p *print.Printer) (string, error) { + flow, err := GetAuthFlow() + if err != nil { + return "", fmt.Errorf("get authentication flow: %w", err) + } + if flow != AUTH_FLOW_USER_TOKEN { + return "", fmt.Errorf("token refresh is only supported for user token flow, current flow: %s", flow) + } + + // Load tokens from storage + authFields := map[authFieldKey]string{ + ACCESS_TOKEN: "", + REFRESH_TOKEN: "", + IDP_TOKEN_ENDPOINT: "", + } + err = GetAuthFieldMap(authFields) + if err != nil { + return "", fmt.Errorf("get tokens from auth storage: %w", err) + } + + accessToken := authFields[ACCESS_TOKEN] + refreshToken := authFields[REFRESH_TOKEN] + tokenEndpoint := authFields[IDP_TOKEN_ENDPOINT] + + if accessToken == "" { + return "", fmt.Errorf("access token not set") + } + if refreshToken == "" { + return "", fmt.Errorf("refresh token not set") + } + if tokenEndpoint == "" { + return "", fmt.Errorf("token endpoint not set") + } + + // Check if access token is expired + accessTokenExpired, err := TokenExpired(accessToken) + if err != nil { + return "", fmt.Errorf("check if access token has expired: %w", err) + } + if !accessTokenExpired { + // Token is still valid, return it + return accessToken, nil + } + + p.Debug(print.DebugLevel, "access token expired, refreshing...") + + // Create a temporary userTokenFlow to reuse the refresh logic + utf := &userTokenFlow{ + printer: p, + client: &http.Client{}, + authFlow: flow, + accessToken: accessToken, + refreshToken: refreshToken, + tokenEndpoint: tokenEndpoint, + } + + // Refresh the tokens + err = refreshTokens(utf) + if err != nil { + return "", fmt.Errorf("refresh access token: %w", err) + } + + // Return the new access token + return utf.accessToken, nil +} From d03b5d41c2488aab4b58ce50687122c72ea392c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Wed, 9 Jul 2025 17:34:45 +0200 Subject: [PATCH 363/619] feat: add continue-on-error attribute to pipeline (#848) --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 18a3a9e6f..14432ab71 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -58,6 +58,7 @@ jobs: name: "Code coverage report" if: github.event_name == 'pull_request' # Do not run when workflow is triggered by push to main branch runs-on: ubuntu-latest + continue-on-error: true # Add this line to prevent pipeline failures in forks needs: main permissions: contents: read From c60995e3ce30a6972ac1e1a41b24372e52c04e2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:30:56 +0200 Subject: [PATCH 364/619] chore(deps): bump golang.org/x/text from 0.26.0 to 0.27.0 (#855) Bumps [golang.org/x/text](https://github.com/golang/text) from 0.26.0 to 0.27.0. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.26.0...v0.27.0) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-version: 0.27.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 604ff8faa..55b7b2acb 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( golang.org/x/mod v0.25.0 golang.org/x/oauth2 v0.30.0 golang.org/x/term v0.32.0 - golang.org/x/text v0.26.0 + golang.org/x/text v0.27.0 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 ) @@ -206,7 +206,7 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/sync v0.15.0 // indirect + golang.org/x/sync v0.16.0 // indirect golang.org/x/tools v0.34.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 8b31d4ecc..de3f72547 100644 --- a/go.sum +++ b/go.sum @@ -819,8 +819,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -896,8 +896,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From cb39a1f864f882320244c641a324a00548c4426b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:42:03 +0200 Subject: [PATCH 365/619] chore(deps): bump golang.org/x/mod from 0.25.0 to 0.26.0 (#854) Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.25.0 to 0.26.0. - [Commits](https://github.com/golang/mod/compare/v0.25.0...v0.26.0) --- updated-dependencies: - dependency-name: golang.org/x/mod dependency-version: 0.26.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 55b7b2acb..c608a296c 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.25.0 + golang.org/x/mod v0.26.0 golang.org/x/oauth2 v0.30.0 golang.org/x/term v0.32.0 golang.org/x/text v0.27.0 diff --git a/go.sum b/go.sum index de3f72547..69d5a8dc9 100644 --- a/go.sum +++ b/go.sum @@ -752,8 +752,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 7f974e1eff412db10c8489d9e0d7c9344a6fd50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 14 Jul 2025 09:54:54 +0200 Subject: [PATCH 366/619] feat(mongodbflex): region adjustment (#857) relates to STACKITCLI-215 --- go.mod | 2 +- go.sum | 4 +- .../mongodbflex/backup/describe/describe.go | 6 +- .../backup/describe/describe_test.go | 20 ++++--- internal/cmd/mongodbflex/backup/list/list.go | 6 +- .../cmd/mongodbflex/backup/list/list_test.go | 20 ++++--- .../backup/restore-jobs/restore_jobs.go | 4 +- .../backup/restore-jobs/restore_jobs_test.go | 20 ++++--- .../cmd/mongodbflex/backup/restore/restore.go | 10 ++-- .../backup/restore/restore_test.go | 23 +++---- .../mongodbflex/backup/schedule/schedule.go | 2 +- .../backup/schedule/schedule_test.go | 18 +++--- .../backup/update-schedule/update_schedule.go | 6 +- .../update-schedule/update_schedule_test.go | 31 ++++++---- .../cmd/mongodbflex/instance/create/create.go | 18 +++--- .../instance/create/create_test.go | 56 +++++++++-------- .../cmd/mongodbflex/instance/delete/delete.go | 6 +- .../instance/delete/delete_test.go | 16 +++-- .../mongodbflex/instance/describe/describe.go | 2 +- .../instance/describe/describe_test.go | 16 +++-- .../cmd/mongodbflex/instance/list/list.go | 2 +- .../mongodbflex/instance/list/list_test.go | 18 +++--- .../cmd/mongodbflex/instance/update/update.go | 22 +++---- .../instance/update/update_test.go | 60 ++++++++++--------- internal/cmd/mongodbflex/options/options.go | 20 +++---- .../cmd/mongodbflex/options/options_test.go | 8 +-- .../cmd/mongodbflex/user/create/create.go | 4 +- .../mongodbflex/user/create/create_test.go | 24 ++++---- .../cmd/mongodbflex/user/delete/delete.go | 6 +- .../mongodbflex/user/delete/delete_test.go | 18 +++--- .../cmd/mongodbflex/user/describe/describe.go | 2 +- .../user/describe/describe_test.go | 18 +++--- internal/cmd/mongodbflex/user/list/list.go | 4 +- .../cmd/mongodbflex/user/list/list_test.go | 20 ++++--- .../user/reset-password/reset_password.go | 6 +- .../reset-password/reset_password_test.go | 18 +++--- .../cmd/mongodbflex/user/update/update.go | 6 +- .../mongodbflex/user/update/update_test.go | 20 ++++--- .../pkg/services/mongodbflex/client/client.go | 3 - .../pkg/services/mongodbflex/utils/utils.go | 24 ++++---- .../services/mongodbflex/utils/utils_test.go | 37 ++++++------ 41 files changed, 347 insertions(+), 279 deletions(-) diff --git a/go.mod b/go.mod index c608a296c..97a3bf5ee 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.4.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 diff --git a/go.sum b/go.sum index 69d5a8dc9..f89590d9d 100644 --- a/go.sum +++ b/go.sum @@ -580,8 +580,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCx github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 h1:vxk6ztgzUIPMkfv27NRpniFqCyGGGFsWJQUvFs43bQA= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.3.0 h1:3R3S2R3m4Auh3cANM3t+AVDhWTKylXQHNBk42TKSbR4= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.3.0/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.4.0 h1:il4vBOejtX0//CWuY6CDpFfPpDIvin5V9QIaKvyXV/M= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.4.0/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 h1:bK5FDpSGfUKDXNkqOoiqOU9hua2YfcdYsGS4zQQ9wg0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0/go.mod h1:Q2SJXlZTksvNAb1QnpGNfDSw/OMPN9uopaKuptUGhO8= github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0 h1:8v9Iupkc3meXcVPMpteXDz07YzY2M5jud50vEtAvbs8= diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index f565aebd4..a1ca3aeaf 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -61,7 +61,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongoUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongoUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -75,7 +75,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("describe backup for MongoDB Flex instance: %w", err) } - restoreJobs, err := apiClient.ListRestoreJobs(ctx, model.ProjectId, model.InstanceId).Execute() + restoreJobs, err := apiClient.ListRestoreJobs(ctx, model.ProjectId, model.InstanceId, model.Region).Execute() if err != nil { return fmt.Errorf("get restore jobs for MongoDB Flex instance %q: %w", instanceLabel, err) } @@ -122,7 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiGetBackupRequest { - req := apiClient.GetBackup(ctx, model.ProjectId, model.InstanceId, model.BackupId) + req := apiClient.GetBackup(ctx, model.ProjectId, model.InstanceId, model.BackupId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/backup/describe/describe_test.go b/internal/cmd/mongodbflex/backup/describe/describe_test.go index 914f27259..f69454e9b 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe_test.go +++ b/internal/cmd/mongodbflex/backup/describe/describe_test.go @@ -14,7 +14,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testBackupId = "backupID" +) type testCtxKey struct{} @@ -22,7 +25,6 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &mongodbflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -var testBackupId = "backupID" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -36,8 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -50,6 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, InstanceId: testInstanceId, BackupId: testBackupId, @@ -61,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiGetBackupRequest)) mongodbflex.ApiGetBackupRequest { - request := testClient.GetBackup(testCtx, testProjectId, testInstanceId, testBackupId) + request := testClient.GetBackup(testCtx, testProjectId, testInstanceId, testBackupId, testRegion) for _, mod := range mods { mod(&request) } @@ -105,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +125,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index f2e40bd83..64187cf64 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -64,7 +64,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId @@ -82,7 +82,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } backups := *resp.Items - restoreJobs, err := apiClient.ListRestoreJobs(ctx, model.ProjectId, *model.InstanceId).Execute() + restoreJobs, err := apiClient.ListRestoreJobs(ctx, model.ProjectId, *model.InstanceId, model.Region).Execute() if err != nil { return fmt.Errorf("get restore jobs for MongoDB Flex instance %q: %w", instanceLabel, err) } @@ -141,7 +141,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiListBackupsRequest { - req := apiClient.ListBackups(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.ListBackups(ctx, model.ProjectId, *model.InstanceId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/backup/list/list_test.go b/internal/cmd/mongodbflex/backup/list/list_test.go index 3328c6030..8b6ce7a25 100644 --- a/internal/cmd/mongodbflex/backup/list/list_test.go +++ b/internal/cmd/mongodbflex/backup/list/list_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -26,9 +28,10 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -41,6 +44,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, InstanceId: utils.Ptr(testInstanceId), Limit: utils.Ptr(int64(10)), @@ -52,7 +56,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiListBackupsRequest)) mongodbflex.ApiListBackupsRequest { - request := testClient.ListBackups(testCtx, testProjectId, testInstanceId) + request := testClient.ListBackups(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -80,21 +84,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index 81c5853c8..7f529891e 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -63,7 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId @@ -135,7 +135,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiListRestoreJobsRequest { - req := apiClient.ListRestoreJobs(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.ListRestoreJobs(ctx, model.ProjectId, *model.InstanceId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go index 61f911ea7..fd00003a4 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -26,9 +28,10 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -40,6 +43,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: utils.Ptr(testInstanceId), @@ -52,7 +56,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiListRestoreJobsRequest)) mongodbflex.ApiListRestoreJobsRequest { - request := testClient.ListRestoreJobs(testCtx, testProjectId, testInstanceId) + request := testClient.ListRestoreJobs(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -80,21 +84,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index ed86d7c61..5c64f6aef 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongodbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.ProjectId @@ -102,7 +102,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Restoring instance") - _, err = wait.RestoreInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.BackupId).WaitWithContext(ctx) + _, err = wait.RestoreInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.BackupId, model.Region).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance restoration: %w", err) } @@ -123,7 +123,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Cloning instance") - _, err = wait.CloneInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + _, err = wait.CloneInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance cloning: %w", err) } @@ -184,7 +184,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRestoreRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiRestoreInstanceRequest { - req := apiClient.RestoreInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.RestoreInstance(ctx, model.ProjectId, model.InstanceId, model.Region) req = req.RestoreInstancePayload(mongodbflex.RestoreInstancePayload{ BackupId: &model.BackupId, InstanceId: &model.BackupInstanceId, @@ -193,7 +193,7 @@ func buildRestoreRequest(ctx context.Context, model *inputModel, apiClient *mong } func buildCloneRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiCloneInstanceRequest { - req := apiClient.CloneInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.CloneInstance(ctx, model.ProjectId, model.InstanceId, model.Region) req = req.CloneInstancePayload(mongodbflex.CloneInstancePayload{ Timestamp: &model.Timestamp, InstanceId: &model.BackupInstanceId, diff --git a/internal/cmd/mongodbflex/backup/restore/restore_test.go b/internal/cmd/mongodbflex/backup/restore/restore_test.go index bffa02934..27b1d3181 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore_test.go +++ b/internal/cmd/mongodbflex/backup/restore/restore_test.go @@ -15,11 +15,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} const ( + testRegion = "eu02" testBackupId = "backupID" testTimestamp = "2021-01-01T00:00:00Z" ) @@ -33,10 +32,11 @@ var testBackupInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - backupIdFlag: testBackupId, - backupInstanceIdFlag: testBackupInstanceId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + backupIdFlag: testBackupId, + backupInstanceIdFlag: testBackupInstanceId, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -61,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRestoreRequest(mods ...func(request mongodbflex.ApiRestoreInstanceRequest)) mongodbflex.ApiRestoreInstanceRequest { - request := testClient.RestoreInstance(testCtx, testProjectId, testInstanceId) + request := testClient.RestoreInstance(testCtx, testProjectId, testInstanceId, testRegion) request = request.RestoreInstancePayload(mongodbflex.RestoreInstancePayload{ BackupId: utils.Ptr(testBackupId), InstanceId: utils.Ptr(testBackupInstanceId), @@ -73,7 +74,7 @@ func fixtureRestoreRequest(mods ...func(request mongodbflex.ApiRestoreInstanceRe } func fixtureCloneRequest(mods ...func(request mongodbflex.ApiCloneInstanceRequest)) mongodbflex.ApiCloneInstanceRequest { - request := testClient.CloneInstance(testCtx, testProjectId, testInstanceId) + request := testClient.CloneInstance(testCtx, testProjectId, testInstanceId, testRegion) request = request.CloneInstancePayload(mongodbflex.CloneInstancePayload{ Timestamp: utils.Ptr(testTimestamp), InstanceId: utils.Ptr(testBackupInstanceId), @@ -106,21 +107,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index 16cd47d24..9117e83d9 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -100,7 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiGetInstanceRequest { - req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go index 705bd7432..1f67e3e64 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -26,8 +28,9 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -39,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -50,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiGetInstanceRequest)) mongodbflex.ApiGetInstanceRequest { - request := testClient.GetInstance(testCtx, testProjectId, testInstanceId) + request := testClient.GetInstance(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -78,21 +82,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go index e93f557ea..af23cdef6 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go @@ -81,7 +81,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongoDBflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) + instanceLabel, err := mongoDBflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId @@ -159,7 +159,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildUpdateBackupScheduleRequest(ctx context.Context, model *inputModel, instance *mongodbflex.Instance, apiClient *mongodbflex.APIClient) mongodbflex.ApiUpdateBackupScheduleRequest { - req := apiClient.UpdateBackupSchedule(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.UpdateBackupSchedule(ctx, model.ProjectId, *model.InstanceId, model.Region) payload := getUpdateBackupSchedulePayload(instance) @@ -229,6 +229,6 @@ func getUpdateBackupSchedulePayload(instance *mongodbflex.Instance) mongodbflex. } func buildGetInstanceRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiGetInstanceRequest { - req := apiClient.GetInstance(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.GetInstance(ctx, model.ProjectId, *model.InstanceId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule_test.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule_test.go index 1f6cc5aa0..77b6c5c2c 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule_test.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule_test.go @@ -13,7 +13,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" + testSchedule = "0 0/6 * * *" +) type testCtxKey struct{} @@ -21,13 +24,13 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &mongodbflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -var testSchedule = "0 0/6 * * *" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - scheduleFlag: testSchedule, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + scheduleFlag: testSchedule, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -39,10 +42,11 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: utils.Ptr(testInstanceId), - BackupSchedule: &testSchedule, + BackupSchedule: utils.Ptr(testSchedule), } for _, mod := range mods { mod(model) @@ -66,7 +70,7 @@ func fixturePayload(mods ...func(payload *mongodbflex.UpdateBackupSchedulePayloa } func fixtureUpdateBackupScheduleRequest(mods ...func(request *mongodbflex.ApiUpdateBackupScheduleRequest)) mongodbflex.ApiUpdateBackupScheduleRequest { - request := testClient.UpdateBackupSchedule(testCtx, testProjectId, testInstanceId) + request := testClient.UpdateBackupSchedule(testCtx, testProjectId, testInstanceId, testRegion) request = request.UpdateBackupSchedulePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -75,7 +79,7 @@ func fixtureUpdateBackupScheduleRequest(mods ...func(request *mongodbflex.ApiUpd } func fixtureGetInstanceRequest(mods ...func(request *mongodbflex.ApiGetInstanceRequest)) mongodbflex.ApiGetInstanceRequest { - request := testClient.GetInstance(testCtx, testProjectId, testInstanceId) + request := testClient.GetInstance(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -84,7 +88,7 @@ func fixtureGetInstanceRequest(mods ...func(request *mongodbflex.ApiGetInstanceR func fixtureInstance(mods ...func(instance *mongodbflex.Instance)) *mongodbflex.Instance { instance := mongodbflex.Instance{ - BackupSchedule: &testSchedule, + BackupSchedule: utils.Ptr(testSchedule), Options: &map[string]string{ "dailySnapshotRetentionDays": "0", "weeklySnapshotRetentionWeeks": "3", @@ -121,21 +125,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -260,6 +264,7 @@ func TestBuildUpdateBackupScheduleRequest(t *testing.T) { model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, }, InstanceId: utils.Ptr(testInstanceId), DailySnaphotRetentionDays: utils.Ptr(int64(2)), @@ -276,6 +281,7 @@ func TestBuildUpdateBackupScheduleRequest(t *testing.T) { model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, }, InstanceId: utils.Ptr(testInstanceId), BackupSchedule: utils.Ptr("0 0/6 5 2 1"), @@ -300,6 +306,7 @@ func TestBuildUpdateBackupScheduleRequest(t *testing.T) { model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, }, InstanceId: utils.Ptr(testInstanceId), }, diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 05df2b9e5..28a65e394 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -104,7 +104,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { // Fill in version, if needed if model.Version == nil { - version, err := mongodbflexUtils.GetLatestMongoDBVersion(ctx, apiClient, model.ProjectId) + version, err := mongodbflexUtils.GetLatestMongoDBVersion(ctx, apiClient, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("get latest MongoDB version: %w", err) } @@ -126,7 +126,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance creation: %w", err) } @@ -208,18 +208,18 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } type MongoDBFlexClient interface { - CreateInstance(ctx context.Context, projectId string) mongodbflex.ApiCreateInstanceRequest - ListFlavorsExecute(ctx context.Context, projectId string) (*mongodbflex.ListFlavorsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*mongodbflex.ListStoragesResponse, error) + CreateInstance(ctx context.Context, projectId, region string) mongodbflex.ApiCreateInstanceRequest + ListFlavorsExecute(ctx context.Context, projectId, region string) (*mongodbflex.ListFlavorsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, flavorId, region string) (*mongodbflex.ListStoragesResponse, error) } func buildRequest(ctx context.Context, model *inputModel, apiClient MongoDBFlexClient) (mongodbflex.ApiCreateInstanceRequest, error) { - req := apiClient.CreateInstance(ctx, model.ProjectId) + req := apiClient.CreateInstance(ctx, model.ProjectId, model.Region) var flavorId *string var err error - flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return req, fmt.Errorf("get MongoDB Flex flavors: %w", err) } @@ -241,7 +241,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient MongoDBFlexC flavorId = model.FlavorId } - storages, err := apiClient.ListStoragesExecute(ctx, model.ProjectId, *flavorId) + storages, err := apiClient.ListStoragesExecute(ctx, model.ProjectId, *flavorId, model.Region) if err != nil { return req, fmt.Errorf("get MongoDB Flex storages: %w", err) } @@ -257,7 +257,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient MongoDBFlexC req = req.CreateInstancePayload(mongodbflex.CreateInstancePayload{ Name: model.InstanceName, - Acl: &mongodbflex.ACL{Items: model.ACL}, + Acl: &mongodbflex.CreateInstancePayloadAcl{Items: model.ACL}, BackupSchedule: model.BackupSchedule, FlavorId: flavorId, Replicas: &replicas, diff --git a/internal/cmd/mongodbflex/instance/create/create_test.go b/internal/cmd/mongodbflex/instance/create/create_test.go index 72ab744b7..8d2bd7aba 100644 --- a/internal/cmd/mongodbflex/instance/create/create_test.go +++ b/internal/cmd/mongodbflex/instance/create/create_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -30,18 +32,18 @@ type mongoDBFlexClientMocked struct { listStoragesResp *mongodbflex.ListStoragesResponse } -func (c *mongoDBFlexClientMocked) CreateInstance(ctx context.Context, projectId string) mongodbflex.ApiCreateInstanceRequest { - return testClient.CreateInstance(ctx, projectId) +func (c *mongoDBFlexClientMocked) CreateInstance(ctx context.Context, projectId, region string) mongodbflex.ApiCreateInstanceRequest { + return testClient.CreateInstance(ctx, projectId, region) } -func (c *mongoDBFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*mongodbflex.ListStoragesResponse, error) { +func (c *mongoDBFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*mongodbflex.ListStoragesResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list storages failed") } return c.listStoragesResp, nil } -func (c *mongoDBFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*mongodbflex.ListFlavorsResponse, error) { +func (c *mongoDBFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*mongodbflex.ListFlavorsResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") } @@ -53,15 +55,16 @@ var testFlavorId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceNameFlag: "example-name", - aclFlag: "0.0.0.0/0", - backupScheduleFlag: "0 0/6 * * *", - flavorIdFlag: testFlavorId, - storageClassFlag: "premium-perf4-mongodb", // Non-default - storageSizeFlag: "10", - versionFlag: "6.0", - typeFlag: "Replica", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceNameFlag: "example-name", + aclFlag: "0.0.0.0/0", + backupScheduleFlag: "0 0/6 * * *", + flavorIdFlag: testFlavorId, + storageClassFlag: "premium-perf4-mongodb", // Non-default + storageSizeFlag: "10", + versionFlag: "6.0", + typeFlag: "Replica", } for _, mod := range mods { mod(flagValues) @@ -73,6 +76,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceName: utils.Ptr("example-name"), @@ -91,7 +95,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiCreateInstanceRequest)) mongodbflex.ApiCreateInstanceRequest { - request := testClient.CreateInstance(testCtx, testProjectId) + request := testClient.CreateInstance(testCtx, testProjectId, testRegion) request = request.CreateInstancePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -102,7 +106,7 @@ func fixtureRequest(mods ...func(request *mongodbflex.ApiCreateInstanceRequest)) func fixturePayload(mods ...func(payload *mongodbflex.CreateInstancePayload)) mongodbflex.CreateInstancePayload { payload := mongodbflex.CreateInstancePayload{ Name: utils.Ptr("example-name"), - Acl: &mongodbflex.ACL{Items: utils.Ptr([]string{"0.0.0.0/0"})}, + Acl: &mongodbflex.CreateInstancePayloadAcl{Items: utils.Ptr([]string{"0.0.0.0/0"})}, BackupSchedule: utils.Ptr("0 0/6 * * *"), FlavorId: utils.Ptr(testFlavorId), Replicas: utils.Ptr(int64(3)), @@ -166,21 +170,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -321,7 +325,7 @@ func TestBuildRequest(t *testing.T) { isValid: true, expectedRequest: fixtureRequest(), listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), @@ -349,7 +353,7 @@ func TestBuildRequest(t *testing.T) { isValid: true, expectedRequest: fixtureRequest(), listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), @@ -379,7 +383,7 @@ func TestBuildRequest(t *testing.T) { payload.Replicas = utils.Ptr(int64(1)) })), listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), @@ -404,7 +408,7 @@ func TestBuildRequest(t *testing.T) { payload.Replicas = utils.Ptr(int64(9)) })), listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), @@ -442,7 +446,7 @@ func TestBuildRequest(t *testing.T) { }, ), listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), @@ -477,7 +481,7 @@ func TestBuildRequest(t *testing.T) { }, ), listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), @@ -502,7 +506,7 @@ func TestBuildRequest(t *testing.T) { }, ), listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), diff --git a/internal/cmd/mongodbflex/instance/delete/delete.go b/internal/cmd/mongodbflex/instance/delete/delete.go index 609307fbd..b63d61d63 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete.go +++ b/internal/cmd/mongodbflex/instance/delete/delete.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance deletion: %w", err) } @@ -122,6 +122,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiDeleteInstanceRequest { - req := apiClient.DeleteInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.DeleteInstance(ctx, model.ProjectId, model.InstanceId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/instance/delete/delete_test.go b/internal/cmd/mongodbflex/instance/delete/delete_test.go index 1c02e7f87..8add607ed 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete_test.go +++ b/internal/cmd/mongodbflex/instance/delete/delete_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -35,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiDeleteInstanceRequest)) mongodbflex.ApiDeleteInstanceRequest { - request := testClient.DeleteInstance(testCtx, testProjectId, testInstanceId) + request := testClient.DeleteInstance(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -102,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -110,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -118,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index 65765a540..0a5c11e54 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -96,7 +96,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiGetInstanceRequest { - req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/instance/describe/describe_test.go b/internal/cmd/mongodbflex/instance/describe/describe_test.go index c933d86e4..aa0235465 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe_test.go +++ b/internal/cmd/mongodbflex/instance/describe/describe_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -35,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiGetInstanceRequest)) mongodbflex.ApiGetInstanceRequest { - request := testClient.GetInstance(testCtx, testProjectId, testInstanceId) + request := testClient.GetInstance(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -102,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -110,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -118,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index 633caee2c..fa30c47ca 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -127,7 +127,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiListInstancesRequest { - req := apiClient.ListInstances(ctx, model.ProjectId).Tag("") + req := apiClient.ListInstances(ctx, model.ProjectId, model.Region).Tag("") return req } diff --git a/internal/cmd/mongodbflex/instance/list/list_test.go b/internal/cmd/mongodbflex/instance/list/list_test.go index e8a95d34c..9c558f205 100644 --- a/internal/cmd/mongodbflex/instance/list/list_test.go +++ b/internal/cmd/mongodbflex/instance/list/list_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -26,8 +28,9 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -39,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -50,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiListInstancesRequest)) mongodbflex.ApiListInstancesRequest { - request := testClient.ListInstances(testCtx, testProjectId).Tag("") + request := testClient.ListInstances(testCtx, testProjectId, testRegion).Tag("") for _, mod := range mods { mod(&request) } @@ -78,21 +82,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index b861cc423..92dafbb94 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -83,7 +83,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -112,7 +112,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance update: %w", err) } @@ -200,19 +200,19 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } type MongoDBFlexClient interface { - PartialUpdateInstance(ctx context.Context, projectId, instanceId string) mongodbflex.ApiPartialUpdateInstanceRequest - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*mongodbflex.GetInstanceResponse, error) - ListFlavorsExecute(ctx context.Context, projectId string) (*mongodbflex.ListFlavorsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*mongodbflex.ListStoragesResponse, error) + PartialUpdateInstance(ctx context.Context, projectId, instanceId, region string) mongodbflex.ApiPartialUpdateInstanceRequest + GetInstanceExecute(ctx context.Context, projectId, instanceId, region string) (*mongodbflex.GetInstanceResponse, error) + ListFlavorsExecute(ctx context.Context, projectId, region string) (*mongodbflex.ListFlavorsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, flavorId, region string) (*mongodbflex.ListStoragesResponse, error) } func buildRequest(ctx context.Context, model *inputModel, apiClient MongoDBFlexClient) (mongodbflex.ApiPartialUpdateInstanceRequest, error) { - req := apiClient.PartialUpdateInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.PartialUpdateInstance(ctx, model.ProjectId, model.InstanceId, model.Region) var flavorId *string var err error - flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err := apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return req, fmt.Errorf("get MongoDB Flex flavors: %w", err) } @@ -221,7 +221,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient MongoDBFlexC ram := model.RAM cpu := model.CPU if model.RAM == nil || model.CPU == nil { - currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId) + currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId, model.Region) if err != nil { return req, fmt.Errorf("get MongoDB Flex instance: %w", err) } @@ -252,13 +252,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient MongoDBFlexC if model.StorageClass != nil || model.StorageSize != nil { validationFlavorId := flavorId if validationFlavorId == nil { - currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId) + currentInstance, err := apiClient.GetInstanceExecute(ctx, model.ProjectId, model.InstanceId, model.Region) if err != nil { return req, fmt.Errorf("get MongoDB Flex instance: %w", err) } validationFlavorId = currentInstance.Item.Flavor.Id } - storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *validationFlavorId) + storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *validationFlavorId, model.Region) if err != nil { return req, fmt.Errorf("get MongoDB Flex storages: %w", err) } diff --git a/internal/cmd/mongodbflex/instance/update/update_test.go b/internal/cmd/mongodbflex/instance/update/update_test.go index 0379f2c0f..1c0a92f2b 100644 --- a/internal/cmd/mongodbflex/instance/update/update_test.go +++ b/internal/cmd/mongodbflex/instance/update/update_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -32,25 +34,25 @@ type mongoDBFlexClientMocked struct { getInstanceResp *mongodbflex.GetInstanceResponse } -func (c *mongoDBFlexClientMocked) PartialUpdateInstance(ctx context.Context, projectId, instanceId string) mongodbflex.ApiPartialUpdateInstanceRequest { - return testClient.PartialUpdateInstance(ctx, projectId, instanceId) +func (c *mongoDBFlexClientMocked) PartialUpdateInstance(ctx context.Context, projectId, instanceId, region string) mongodbflex.ApiPartialUpdateInstanceRequest { + return testClient.PartialUpdateInstance(ctx, projectId, instanceId, region) } -func (c *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*mongodbflex.GetInstanceResponse, error) { +func (c *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*mongodbflex.GetInstanceResponse, error) { if c.getInstanceFails { return nil, fmt.Errorf("get instance failed") } return c.getInstanceResp, nil } -func (c *mongoDBFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*mongodbflex.ListStoragesResponse, error) { +func (c *mongoDBFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*mongodbflex.ListStoragesResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list storages failed") } return c.listStoragesResp, nil } -func (c *mongoDBFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*mongodbflex.ListFlavorsResponse, error) { +func (c *mongoDBFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*mongodbflex.ListFlavorsResponse, error) { if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") } @@ -73,7 +75,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureRequiredFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -83,15 +86,16 @@ func fixtureRequiredFlagValues(mods ...func(flagValues map[string]string)) map[s func fixtureStandardFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - flavorIdFlag: testFlavorId, - instanceNameFlag: "example-name", - aclFlag: "0.0.0.0/0", - backupScheduleFlag: "0 0 * * *", - storageClassFlag: "class", - storageSizeFlag: "10", - versionFlag: "5.0", - typeFlag: "Single", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + flavorIdFlag: testFlavorId, + instanceNameFlag: "example-name", + aclFlag: "0.0.0.0/0", + backupScheduleFlag: "0 0 * * *", + storageClassFlag: "class", + storageSizeFlag: "10", + versionFlag: "5.0", + typeFlag: "Single", } for _, mod := range mods { mod(flagValues) @@ -103,6 +107,7 @@ func fixtureRequiredInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -117,6 +122,7 @@ func fixtureStandardInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -136,7 +142,7 @@ func fixtureStandardInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiPartialUpdateInstanceRequest)) mongodbflex.ApiPartialUpdateInstanceRequest { - request := testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId) + request := testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId, testRegion) request = request.PartialUpdateInstancePayload(mongodbflex.PartialUpdateInstancePayload{}) for _, mod := range mods { mod(&request) @@ -204,7 +210,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -212,7 +218,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -220,7 +226,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureRequiredFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -368,7 +374,7 @@ func TestBuildRequest(t *testing.T) { }), isValid: true, listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), @@ -376,7 +382,7 @@ func TestBuildRequest(t *testing.T) { }, }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId, testRegion). PartialUpdateInstancePayload(mongodbflex.PartialUpdateInstancePayload{ FlavorId: utils.Ptr(testFlavorId), }), @@ -389,7 +395,7 @@ func TestBuildRequest(t *testing.T) { }), isValid: true, listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), @@ -397,7 +403,7 @@ func TestBuildRequest(t *testing.T) { }, }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId, testRegion). PartialUpdateInstancePayload(mongodbflex.PartialUpdateInstancePayload{ FlavorId: utils.Ptr(testFlavorId), }), @@ -422,7 +428,7 @@ func TestBuildRequest(t *testing.T) { Max: utils.Ptr(int64(100)), }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId, testRegion). PartialUpdateInstancePayload(mongodbflex.PartialUpdateInstancePayload{ Storage: &mongodbflex.Storage{ Class: utils.Ptr("class"), @@ -450,7 +456,7 @@ func TestBuildRequest(t *testing.T) { Max: utils.Ptr(int64(100)), }, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId, testRegion). PartialUpdateInstancePayload(mongodbflex.PartialUpdateInstancePayload{ Storage: &mongodbflex.Storage{ Class: utils.Ptr("class"), @@ -478,7 +484,7 @@ func TestBuildRequest(t *testing.T) { }, ), listFlavorsResp: &mongodbflex.ListFlavorsResponse{ - Flavors: &[]mongodbflex.HandlersInfraFlavor{ + Flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr(testFlavorId), Cpu: utils.Ptr(int64(2)), diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 55ad63408..53499547e 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -37,9 +37,9 @@ type inputModel struct { } type options struct { - Flavors *[]mongodbflex.HandlersInfraFlavor `json:"flavors,omitempty"` - Versions *[]string `json:"versions,omitempty"` - Storages *flavorStorages `json:"flavorStorages,omitempty"` + Flavors *[]mongodbflex.InstanceFlavor `json:"flavors,omitempty"` + Versions *[]string `json:"versions,omitempty"` + Storages *flavorStorages `json:"flavorStorages,omitempty"` } type flavorStorages struct { @@ -138,9 +138,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } type mongoDBFlexOptionsClient interface { - ListFlavorsExecute(ctx context.Context, projectId string) (*mongodbflex.ListFlavorsResponse, error) - ListVersionsExecute(ctx context.Context, projectId string) (*mongodbflex.ListVersionsResponse, error) - ListStoragesExecute(ctx context.Context, projectId, flavorId string) (*mongodbflex.ListStoragesResponse, error) + ListFlavorsExecute(ctx context.Context, projectId, region string) (*mongodbflex.ListFlavorsResponse, error) + ListVersionsExecute(ctx context.Context, projectId, region string) (*mongodbflex.ListVersionsResponse, error) + ListStoragesExecute(ctx context.Context, projectId, flavorId, region string) (*mongodbflex.ListStoragesResponse, error) } func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputModel, apiClient mongoDBFlexOptionsClient) error { @@ -150,19 +150,19 @@ func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputM var err error if model.Flavors { - flavors, err = apiClient.ListFlavorsExecute(ctx, model.ProjectId) + flavors, err = apiClient.ListFlavorsExecute(ctx, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("get MongoDB Flex flavors: %w", err) } } if model.Versions { - versions, err = apiClient.ListVersionsExecute(ctx, model.ProjectId) + versions, err = apiClient.ListVersionsExecute(ctx, model.ProjectId, model.Region) if err != nil { return fmt.Errorf("get MongoDB Flex versions: %w", err) } } if model.Storages { - storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *model.FlavorId) + storages, err = apiClient.ListStoragesExecute(ctx, model.ProjectId, *model.FlavorId, model.Region) if err != nil { return fmt.Errorf("get MongoDB Flex storages: %w", err) } @@ -237,7 +237,7 @@ func outputResultAsTable(p *print.Printer, model *inputModel, options *options) return nil } -func buildFlavorsTable(flavors []mongodbflex.HandlersInfraFlavor) tables.Table { +func buildFlavorsTable(flavors []mongodbflex.InstanceFlavor) tables.Table { table := tables.NewTable() table.SetTitle("Flavors") table.SetHeader("ID", "CPU", "MEMORY", "DESCRIPTION", "VALID INSTANCE TYPES") diff --git a/internal/cmd/mongodbflex/options/options_test.go b/internal/cmd/mongodbflex/options/options_test.go index dc1eb60c8..35ab363dc 100644 --- a/internal/cmd/mongodbflex/options/options_test.go +++ b/internal/cmd/mongodbflex/options/options_test.go @@ -28,17 +28,17 @@ type mongoDBFlexClientMocked struct { listStoragesCalled bool } -func (c *mongoDBFlexClientMocked) ListFlavorsExecute(_ context.Context, _ string) (*mongodbflex.ListFlavorsResponse, error) { +func (c *mongoDBFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*mongodbflex.ListFlavorsResponse, error) { c.listFlavorsCalled = true if c.listFlavorsFails { return nil, fmt.Errorf("list flavors failed") } return utils.Ptr(mongodbflex.ListFlavorsResponse{ - Flavors: utils.Ptr([]mongodbflex.HandlersInfraFlavor{}), + Flavors: utils.Ptr([]mongodbflex.InstanceFlavor{}), }), nil } -func (c *mongoDBFlexClientMocked) ListVersionsExecute(_ context.Context, _ string) (*mongodbflex.ListVersionsResponse, error) { +func (c *mongoDBFlexClientMocked) ListVersionsExecute(_ context.Context, _, _ string) (*mongodbflex.ListVersionsResponse, error) { c.listVersionsCalled = true if c.listVersionsFails { return nil, fmt.Errorf("list versions failed") @@ -48,7 +48,7 @@ func (c *mongoDBFlexClientMocked) ListVersionsExecute(_ context.Context, _ strin }), nil } -func (c *mongoDBFlexClientMocked) ListStoragesExecute(_ context.Context, _, _ string) (*mongodbflex.ListStoragesResponse, error) { +func (c *mongoDBFlexClientMocked) ListStoragesExecute(_ context.Context, _, _, _ string) (*mongodbflex.ListStoragesResponse, error) { c.listStoragesCalled = true if c.listStoragesFails { return nil, fmt.Errorf("list storages failed") diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index 095077242..924f91896 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -141,7 +141,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiCreateUserRequest { - req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId) + req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId, model.Region) req = req.CreateUserPayload(mongodbflex.CreateUserPayload{ Username: model.Username, Database: model.Database, diff --git a/internal/cmd/mongodbflex/user/create/create_test.go b/internal/cmd/mongodbflex/user/create/create_test.go index 75e02fef0..db666260b 100644 --- a/internal/cmd/mongodbflex/user/create/create_test.go +++ b/internal/cmd/mongodbflex/user/create/create_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -27,11 +29,12 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - usernameFlag: "johndoe", - databaseFlag: "default", - roleFlag: "read", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + usernameFlag: "johndoe", + databaseFlag: "default", + roleFlag: "read", } for _, mod := range mods { mod(flagValues) @@ -43,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiCreateUserRequest)) mongodbflex.ApiCreateUserRequest { - request := testClient.CreateUser(testCtx, testProjectId, testInstanceId) + request := testClient.CreateUser(testCtx, testProjectId, testInstanceId, testRegion) request = request.CreateUserPayload(mongodbflex.CreateUserPayload{ Username: utils.Ptr("johndoe"), Database: utils.Ptr("default"), @@ -102,21 +106,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/user/delete/delete.go b/internal/cmd/mongodbflex/user/delete/delete.go index 1d0818522..05e72686b 100644 --- a/internal/cmd/mongodbflex/user/delete/delete.go +++ b/internal/cmd/mongodbflex/user/delete/delete.go @@ -59,13 +59,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) + userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId @@ -128,6 +128,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiDeleteUserRequest { - req := apiClient.DeleteUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.DeleteUser(ctx, model.ProjectId, model.InstanceId, model.UserId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/user/delete/delete_test.go b/internal/cmd/mongodbflex/user/delete/delete_test.go index b373f7f56..1a20490f1 100644 --- a/internal/cmd/mongodbflex/user/delete/delete_test.go +++ b/internal/cmd/mongodbflex/user/delete/delete_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -36,8 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -61,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiDeleteUserRequest)) mongodbflex.ApiDeleteUserRequest { - request := testClient.DeleteUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.DeleteUser(testCtx, testProjectId, testInstanceId, testUserId, testRegion) for _, mod := range mods { mod(&request) } @@ -105,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +125,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/user/describe/describe.go b/internal/cmd/mongodbflex/user/describe/describe.go index 67eb3d84b..410896fc9 100644 --- a/internal/cmd/mongodbflex/user/describe/describe.go +++ b/internal/cmd/mongodbflex/user/describe/describe.go @@ -114,7 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiGetUserRequest { - req := apiClient.GetUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.GetUser(ctx, model.ProjectId, model.InstanceId, model.UserId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/user/describe/describe_test.go b/internal/cmd/mongodbflex/user/describe/describe_test.go index c151b4da0..5315f8b8a 100644 --- a/internal/cmd/mongodbflex/user/describe/describe_test.go +++ b/internal/cmd/mongodbflex/user/describe/describe_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -36,8 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -61,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiGetUserRequest)) mongodbflex.ApiGetUserRequest { - request := testClient.GetUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.GetUser(testCtx, testProjectId, testInstanceId, testUserId, testRegion) for _, mod := range mods { mod(&request) } @@ -105,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +125,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index ffdb6f10a..d9e947e9c 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -71,7 +71,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("get MongoDB Flex users: %w", err) } if resp.Items == nil || len(*resp.Items) == 0 { - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = *model.InstanceId @@ -135,7 +135,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiListUsersRequest { - req := apiClient.ListUsers(ctx, model.ProjectId, *model.InstanceId) + req := apiClient.ListUsers(ctx, model.ProjectId, *model.InstanceId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/user/list/list_test.go b/internal/cmd/mongodbflex/user/list/list_test.go index 18e9325f5..45d28d41d 100644 --- a/internal/cmd/mongodbflex/user/list/list_test.go +++ b/internal/cmd/mongodbflex/user/list/list_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -27,9 +29,10 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -41,6 +44,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: utils.Ptr(testInstanceId), @@ -53,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiListUsersRequest)) mongodbflex.ApiListUsersRequest { - request := testClient.ListUsers(testCtx, testProjectId, testInstanceId) + request := testClient.ListUsers(testCtx, testProjectId, testInstanceId, testRegion) for _, mod := range mods { mod(&request) } @@ -81,21 +85,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index 0144a20b5..c58dfd020 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -61,13 +61,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) + userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId @@ -130,7 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiResetUserRequest { - req := apiClient.ResetUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.ResetUser(ctx, model.ProjectId, model.InstanceId, model.UserId, model.Region) return req } diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go index d86e57206..349baec27 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -36,8 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -61,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiResetUserRequest)) mongodbflex.ApiResetUserRequest { - request := testClient.ResetUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.ResetUser(testCtx, testProjectId, testInstanceId, testUserId, testRegion) for _, mod := range mods { mod(&request) } @@ -105,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +125,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/mongodbflex/user/update/update.go b/internal/cmd/mongodbflex/user/update/update.go index 8dded41b0..4742a8e82 100644 --- a/internal/cmd/mongodbflex/user/update/update.go +++ b/internal/cmd/mongodbflex/user/update/update.go @@ -60,13 +60,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId) + userLabel, err := mongodbflexUtils.GetUserName(ctx, apiClient, model.ProjectId, model.InstanceId, model.UserId, model.Region) if err != nil { params.Printer.Debug(print.ErrorLevel, "get user name: %v", err) userLabel = model.UserId @@ -143,7 +143,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex.APIClient) mongodbflex.ApiPartialUpdateUserRequest { - req := apiClient.PartialUpdateUser(ctx, model.ProjectId, model.InstanceId, model.UserId) + req := apiClient.PartialUpdateUser(ctx, model.ProjectId, model.InstanceId, model.UserId, model.Region) req = req.PartialUpdateUserPayload(mongodbflex.PartialUpdateUserPayload{ Database: model.Database, Roles: model.Roles, diff --git a/internal/cmd/mongodbflex/user/update/update_test.go b/internal/cmd/mongodbflex/user/update/update_test.go index e4f74eb0f..3f12bda1a 100644 --- a/internal/cmd/mongodbflex/user/update/update_test.go +++ b/internal/cmd/mongodbflex/user/update/update_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu02" +) type testCtxKey struct{} @@ -37,9 +39,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - databaseFlag: "default", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + instanceIdFlag: testInstanceId, + databaseFlag: "default", } for _, mod := range mods { mod(flagValues) @@ -51,6 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -64,7 +68,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *mongodbflex.ApiPartialUpdateUserRequest)) mongodbflex.ApiPartialUpdateUserRequest { - request := testClient.PartialUpdateUser(testCtx, testProjectId, testInstanceId, testUserId) + request := testClient.PartialUpdateUser(testCtx, testProjectId, testInstanceId, testUserId, testRegion) request = request.PartialUpdateUserPayload(mongodbflex.PartialUpdateUserPayload{ Database: utils.Ptr("default"), }) @@ -128,7 +132,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -136,7 +140,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -144,7 +148,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/pkg/services/mongodbflex/client/client.go b/internal/pkg/services/mongodbflex/client/client.go index b69cc40bf..216fbd9d5 100644 --- a/internal/pkg/services/mongodbflex/client/client.go +++ b/internal/pkg/services/mongodbflex/client/client.go @@ -18,15 +18,12 @@ func ConfigureClient(p *print.Printer, cliVersion string) (*mongodbflex.APIClien p.Debug(print.ErrorLevel, "configure authentication: %v", err) return nil, &errors.AuthError{} } - region := viper.GetString(config.RegionKey) cfgOptions := []sdkConfig.ConfigurationOption{ utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), authCfgOption, } customEndpoint := viper.GetString(config.MongoDBFlexCustomEndpointKey) - if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) } diff --git a/internal/pkg/services/mongodbflex/utils/utils.go b/internal/pkg/services/mongodbflex/utils/utils.go index ad2e07f9e..52d9aa311 100644 --- a/internal/pkg/services/mongodbflex/utils/utils.go +++ b/internal/pkg/services/mongodbflex/utils/utils.go @@ -21,10 +21,10 @@ var instanceTypeToReplicas = map[string]int64{ } type MongoDBFlexClient interface { - ListVersionsExecute(ctx context.Context, projectId string) (*mongodbflex.ListVersionsResponse, error) - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*mongodbflex.GetInstanceResponse, error) - GetUserExecute(ctx context.Context, projectId, instanceId, userId string) (*mongodbflex.GetUserResponse, error) - ListRestoreJobsExecute(ctx context.Context, projectId string, instanceId string) (*mongodbflex.ListRestoreJobsResponse, error) + ListVersionsExecute(ctx context.Context, projectId, region string) (*mongodbflex.ListVersionsResponse, error) + GetInstanceExecute(ctx context.Context, projectId, instanceId, region string) (*mongodbflex.GetInstanceResponse, error) + GetUserExecute(ctx context.Context, projectId, instanceId, userId, region string) (*mongodbflex.GetUserResponse, error) + ListRestoreJobsExecute(ctx context.Context, projectId string, instanceId, region string) (*mongodbflex.ListRestoreJobsResponse, error) } func AvailableInstanceTypes() []string { @@ -57,7 +57,7 @@ func GetInstanceType(numReplicas int64) (string, error) { return "", fmt.Errorf("invalid number of replicas: %v", numReplicas) } -func ValidateFlavorId(flavorId string, flavors *[]mongodbflex.HandlersInfraFlavor) error { +func ValidateFlavorId(flavorId string, flavors *[]mongodbflex.InstanceFlavor) error { if flavors == nil { return fmt.Errorf("nil flavors") } @@ -101,7 +101,7 @@ func ValidateStorage(storageClass *string, storageSize *int64, storages *mongodb } } -func LoadFlavorId(cpu, ram int64, flavors *[]mongodbflex.HandlersInfraFlavor) (*string, error) { +func LoadFlavorId(cpu, ram int64, flavors *[]mongodbflex.InstanceFlavor) (*string, error) { if flavors == nil { return nil, fmt.Errorf("nil flavors") } @@ -122,8 +122,8 @@ func LoadFlavorId(cpu, ram int64, flavors *[]mongodbflex.HandlersInfraFlavor) (* } } -func GetLatestMongoDBVersion(ctx context.Context, apiClient MongoDBFlexClient, projectId string) (string, error) { - resp, err := apiClient.ListVersionsExecute(ctx, projectId) +func GetLatestMongoDBVersion(ctx context.Context, apiClient MongoDBFlexClient, projectId, region string) (string, error) { + resp, err := apiClient.ListVersionsExecute(ctx, projectId, region) if err != nil { return "", fmt.Errorf("get MongoDB versions: %w", err) } @@ -144,16 +144,16 @@ func GetLatestMongoDBVersion(ctx context.Context, apiClient MongoDBFlexClient, p return latestVersion, nil } -func GetInstanceName(ctx context.Context, apiClient MongoDBFlexClient, projectId, instanceId string) (string, error) { - resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId) +func GetInstanceName(ctx context.Context, apiClient MongoDBFlexClient, projectId, instanceId, region string) (string, error) { + resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId, region) if err != nil { return "", fmt.Errorf("get MongoDB Flex instance: %w", err) } return *resp.Item.Name, nil } -func GetUserName(ctx context.Context, apiClient MongoDBFlexClient, projectId, instanceId, userId string) (string, error) { - resp, err := apiClient.GetUserExecute(ctx, projectId, instanceId, userId) +func GetUserName(ctx context.Context, apiClient MongoDBFlexClient, projectId, instanceId, userId, region string) (string, error) { + resp, err := apiClient.GetUserExecute(ctx, projectId, instanceId, userId, region) if err != nil { return "", fmt.Errorf("get MongoDB Flex user: %w", err) } diff --git a/internal/pkg/services/mongodbflex/utils/utils_test.go b/internal/pkg/services/mongodbflex/utils/utils_test.go index 1024c5710..4867c5bb3 100644 --- a/internal/pkg/services/mongodbflex/utils/utils_test.go +++ b/internal/pkg/services/mongodbflex/utils/utils_test.go @@ -20,6 +20,7 @@ var ( ) const ( + testRegion = "eu02" testInstanceName = "instance" testUserName = "user" ) @@ -35,28 +36,28 @@ type mongoDBFlexClientMocked struct { listRestoreJobsResp *mongodbflex.ListRestoreJobsResponse } -func (m *mongoDBFlexClientMocked) ListVersionsExecute(_ context.Context, _ string) (*mongodbflex.ListVersionsResponse, error) { +func (m *mongoDBFlexClientMocked) ListVersionsExecute(_ context.Context, _, _ string) (*mongodbflex.ListVersionsResponse, error) { if m.listVersionsFails { return nil, fmt.Errorf("could not list versions") } return m.listVersionsResp, nil } -func (m *mongoDBFlexClientMocked) ListRestoreJobsExecute(_ context.Context, _, _ string) (*mongodbflex.ListRestoreJobsResponse, error) { +func (m *mongoDBFlexClientMocked) ListRestoreJobsExecute(_ context.Context, _, _, _ string) (*mongodbflex.ListRestoreJobsResponse, error) { if m.listRestoreJobsFails { return nil, fmt.Errorf("could not list versions") } return m.listRestoreJobsResp, nil } -func (m *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*mongodbflex.GetInstanceResponse, error) { +func (m *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*mongodbflex.GetInstanceResponse, error) { if m.getInstanceFails { return nil, fmt.Errorf("could not get instance") } return m.getInstanceResp, nil } -func (m *mongoDBFlexClientMocked) GetUserExecute(_ context.Context, _, _, _ string) (*mongodbflex.GetUserResponse, error) { +func (m *mongoDBFlexClientMocked) GetUserExecute(_ context.Context, _, _, _, _ string) (*mongodbflex.GetUserResponse, error) { if m.getUserFails { return nil, fmt.Errorf("could not get user") } @@ -175,13 +176,13 @@ func TestValidateFlavorId(t *testing.T) { tests := []struct { description string flavorId string - flavors *[]mongodbflex.HandlersInfraFlavor + flavors *[]mongodbflex.InstanceFlavor isValid bool }{ { description: "base", flavorId: "foo", - flavors: &[]mongodbflex.HandlersInfraFlavor{ + flavors: &[]mongodbflex.InstanceFlavor{ {Id: utils.Ptr("bar-1")}, {Id: utils.Ptr("bar-2")}, {Id: utils.Ptr("foo")}, @@ -197,13 +198,13 @@ func TestValidateFlavorId(t *testing.T) { { description: "no flavors", flavorId: "foo", - flavors: &[]mongodbflex.HandlersInfraFlavor{}, + flavors: &[]mongodbflex.InstanceFlavor{}, isValid: false, }, { description: "nil flavor id", flavorId: "foo", - flavors: &[]mongodbflex.HandlersInfraFlavor{ + flavors: &[]mongodbflex.InstanceFlavor{ {Id: utils.Ptr("bar-1")}, {Id: nil}, {Id: utils.Ptr("foo")}, @@ -213,7 +214,7 @@ func TestValidateFlavorId(t *testing.T) { { description: "invalid flavor", flavorId: "foo", - flavors: &[]mongodbflex.HandlersInfraFlavor{ + flavors: &[]mongodbflex.InstanceFlavor{ {Id: utils.Ptr("bar-1")}, {Id: utils.Ptr("bar-2")}, {Id: utils.Ptr("bar-3")}, @@ -240,7 +241,7 @@ func TestLoadFlavorId(t *testing.T) { description string cpu int64 ram int64 - flavors *[]mongodbflex.HandlersInfraFlavor + flavors *[]mongodbflex.InstanceFlavor isValid bool expectedOutput *string }{ @@ -248,7 +249,7 @@ func TestLoadFlavorId(t *testing.T) { description: "base", cpu: 2, ram: 4, - flavors: &[]mongodbflex.HandlersInfraFlavor{ + flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr("bar-1"), Cpu: utils.Ptr(int64(2)), @@ -279,14 +280,14 @@ func TestLoadFlavorId(t *testing.T) { description: "no flavors", cpu: 2, ram: 4, - flavors: &[]mongodbflex.HandlersInfraFlavor{}, + flavors: &[]mongodbflex.InstanceFlavor{}, isValid: false, }, { description: "flavors with details missing", cpu: 2, ram: 4, - flavors: &[]mongodbflex.HandlersInfraFlavor{ + flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr("bar-1"), Cpu: nil, @@ -310,7 +311,7 @@ func TestLoadFlavorId(t *testing.T) { description: "match with nil id", cpu: 2, ram: 4, - flavors: &[]mongodbflex.HandlersInfraFlavor{ + flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr("bar-1"), Cpu: utils.Ptr(int64(2)), @@ -333,7 +334,7 @@ func TestLoadFlavorId(t *testing.T) { description: "invalid settings", cpu: 2, ram: 4, - flavors: &[]mongodbflex.HandlersInfraFlavor{ + flavors: &[]mongodbflex.InstanceFlavor{ { Id: utils.Ptr("bar-1"), Cpu: utils.Ptr(int64(2)), @@ -411,7 +412,7 @@ func TestGetLatestMongoDBFlexVersion(t *testing.T) { listVersionsResp: tt.listVersionsResp, } - output, err := GetLatestMongoDBVersion(context.Background(), client, testProjectId) + output, err := GetLatestMongoDBVersion(context.Background(), client, testProjectId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -461,7 +462,7 @@ func TestGetInstanceName(t *testing.T) { getInstanceResp: tt.getInstanceResp, } - output, err := GetInstanceName(context.Background(), client, testProjectId, testInstanceId) + output, err := GetInstanceName(context.Background(), client, testProjectId, testInstanceId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -511,7 +512,7 @@ func TestGetUserName(t *testing.T) { getUserResp: tt.getUserResp, } - output, err := GetUserName(context.Background(), client, testProjectId, testInstanceId, testUserId) + output, err := GetUserName(context.Background(), client, testProjectId, testInstanceId, testUserId, testRegion) if tt.isValid && err != nil { t.Errorf("failed on valid input") From 660099369456f2ae36f6c6591bd5eaf73810fc10 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 15 Jul 2025 09:07:57 +0200 Subject: [PATCH 367/619] chore(deps): update renovatebot/github-action action to v43.0.3 (#864) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 2e1f2a8e3..1e857a5f1 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.2 + uses: renovatebot/github-action@v43.0.3 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 75c6a9d02d090eb49243204b8e7ed08de24194c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 07:14:30 +0000 Subject: [PATCH 368/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/loadbalancer (#862) Bumps [github.com/stackitcloud/stackit-sdk-go/services/loadbalancer](https://github.com/stackitcloud/stackit-sdk-go) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/mongodbflex/v1.4.0...services/mongodbflex/v1.5.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/loadbalancer dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 97a3bf5ee..8310cd896 100644 --- a/go.mod +++ b/go.mod @@ -236,7 +236,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 diff --git a/go.sum b/go.sum index f89590d9d..724dd9e92 100644 --- a/go.sum +++ b/go.sum @@ -574,8 +574,8 @@ github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 h1:UJDtK96cjQqp5yWb8T github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 h1:5vxOzwQ+rNm0g9ZLQW/31dqdDqGfw/FQbrjxUUAHtiA= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0/go.mod h1:lUGkcbyMkd4nRBDFmKohIwlgtOZqQo4Ek5S5ajw90Xg= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0 h1:Ef4SyTBjIkfwaws4mssa6AoK+OokHFtr7ZIflUpoXVE= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.4.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0 h1:KgptlhV0LgOevtrfMBd2pm/Hrnz6vNSYgAJo6pT7eMM= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCxpFXN2K7g2ih0gQM6cyZ1VhTmtQfI= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 h1:vxk6ztgzUIPMkfv27NRpniFqCyGGGFsWJQUvFs43bQA= From bd1a0ace740ced2df5cdb90a5ab5993ec4e6ba93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 12:54:47 +0200 Subject: [PATCH 369/619] chore(deps): bump golang.org/x/term from 0.32.0 to 0.33.0 (#860) Bumps [golang.org/x/term](https://github.com/golang/term) from 0.32.0 to 0.33.0. - [Commits](https://github.com/golang/term/compare/v0.32.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 8310cd896..45198f645 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.26.0 golang.org/x/oauth2 v0.30.0 - golang.org/x/term v0.32.0 + golang.org/x/term v0.33.0 golang.org/x/text v0.27.0 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 @@ -245,7 +245,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.33.0 // indirect + golang.org/x/sys v0.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 724dd9e92..4da254def 100644 --- a/go.sum +++ b/go.sum @@ -872,8 +872,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -882,8 +882,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 9cec175a88a71c53f633f7966b3af92c766ee0f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 11:02:33 +0000 Subject: [PATCH 370/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/ske (#859) Bumps [github.com/stackitcloud/stackit-sdk-go/services/ske](https://github.com/stackitcloud/stackit-sdk-go) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/cdn/v1.0.0...services/cdn/v1.1.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/ske dependency-version: 1.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 45198f645..360148168 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/ske v1.0.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.26.0 diff --git a/go.sum b/go.sum index 4da254def..80d9cca6c 100644 --- a/go.sum +++ b/go.sum @@ -608,8 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 h1:2d28WFQ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0/go.mod h1:t77MA8uyEU9KZd1On5JpnxI3xhVPKIS8WutStqvU8Cw= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 h1:h1TsWatlsexLeKdkb3L8chcxaXJOy/cLXctsRxhb4xg= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1/go.mod h1:M4xZ2BnmROvLV2MrAP6A8o9BnyT0CkvpEcP8lBOfRs8= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.0.0 h1:PX8VTo2UhPd6BeEaCHFlpIkDbk9OFQEO6eJJ8JkxesA= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.0.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.1.0 h1:Qj2Ild7NmHVm1rvPZg9Utc862sLJFiAfvRFLG0Qc+Uc= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.1.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 h1:pUl/981oAXPnZd7++69NfEWv6JwW9UpxER16XxQUdOk= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0/go.mod h1:S04/QsQrB2EgYGjl62BO+9QUswrlRBoBosigrhdmccM= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= From d0354c5627ea8445e654ac82f6bdaab88870d6b2 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 17 Jul 2025 09:53:31 +0200 Subject: [PATCH 371/619] fix(deps): update module github.com/spf13/pflag to v1.0.7 (#871) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 360148168..8437a386c 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.9.1 - github.com/spf13/pflag v1.0.6 + github.com/spf13/pflag v1.0.7 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 diff --git a/go.sum b/go.sum index 80d9cca6c..338abe366 100644 --- a/go.sum +++ b/go.sum @@ -556,8 +556,9 @@ github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cA github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= From 5d8a9f9a55be96abec08601dc2956a3b863be367 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 08:01:42 +0000 Subject: [PATCH 372/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/alb (#867) Bumps [github.com/stackitcloud/stackit-sdk-go/services/alb](https://github.com/stackitcloud/stackit-sdk-go) from 0.5.0 to 0.6.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.5.0...core/v0.6.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/alb dependency-version: 0.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8437a386c..9f58687b2 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.7 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.2 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 diff --git a/go.sum b/go.sum index 338abe366..41db70b99 100644 --- a/go.sum +++ b/go.sum @@ -565,8 +565,8 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.2 h1:jPyn+i8rkp2hM80+hOg0B/1EVRbMt778Tr5RWyK1m2E= github.com/stackitcloud/stackit-sdk-go/core v0.17.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0 h1:7UKUi7Od7KpuVjV4I/jUAV5NEatUomwWFd/IRODbioY= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.5.0/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.0 h1:eYP2TSEEZassdyA3V9Ci5jGMvK/WH1/gzTAUfvlpRyk= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.0/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 h1:KXMiTBV4KcOEQRFddtOUFspL+KRvjDQNDIs73bdiey0= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0/go.mod h1:+2mx2MclJFMQ4Y6b20jspYAnIeFJP3/yvO6Gfvcvf6Q= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 h1:x5mx/C2bdtpOH974RofXD0Y8YOyJtYXwIyaCyWOXMwU= From b7897356957481d87bc092c5a51e24a4929ede1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 08:12:17 +0000 Subject: [PATCH 373/619] chore(deps): bump github.com/golang-jwt/jwt/v5 from 5.2.2 to 5.2.3 (#866) Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.2.2 to 5.2.3. - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md) - [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.2...v5.2.3) --- updated-dependencies: - dependency-name: github.com/golang-jwt/jwt/v5 dependency-version: 5.2.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9f58687b2..6ab07093a 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24 require ( github.com/fatih/color v1.18.0 github.com/goccy/go-yaml v1.18.0 - github.com/golang-jwt/jwt/v5 v5.2.2 + github.com/golang-jwt/jwt/v5 v5.2.3 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf diff --git a/go.sum b/go.sum index 41db70b99..ae5aef08a 100644 --- a/go.sum +++ b/go.sum @@ -222,8 +222,8 @@ github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeH github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= +github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= From 0b8327ebfb7062d6c66307cfe4f89e610b55f739 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 10:58:43 +0200 Subject: [PATCH 374/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/observability (#865) Bumps [github.com/stackitcloud/stackit-sdk-go/services/observability](https://github.com/stackitcloud/stackit-sdk-go) from 0.8.0 to 0.9.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.8.0...core/v0.9.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/observability dependency-version: 0.9.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6ab07093a..0bf1e4730 100644 --- a/go.mod +++ b/go.mod @@ -240,7 +240,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index ae5aef08a..20839d0b9 100644 --- a/go.sum +++ b/go.sum @@ -585,8 +585,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.4.0 h1:il4vBOejtX github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.4.0/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 h1:bK5FDpSGfUKDXNkqOoiqOU9hua2YfcdYsGS4zQQ9wg0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0/go.mod h1:Q2SJXlZTksvNAb1QnpGNfDSw/OMPN9uopaKuptUGhO8= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0 h1:8v9Iupkc3meXcVPMpteXDz07YzY2M5jud50vEtAvbs8= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.8.0/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 h1:NuRgx13h3mnzWcRTLPiL5fk06xpl43vaz+QOuHvSEHA= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 h1:+qFjzDDv/0ZHGdVuW2HzAphRBmlc1+abw7k1RaAqmQo= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 h1:DGgKKCh3AmUBqDG0DrsWVcclxSaG82TVEf18A29w+J0= From 32bd967acbf059a2d8441949f6dca7495fa0cfea Mon Sep 17 00:00:00 2001 From: ivan-tejero Date: Thu, 17 Jul 2025 11:51:22 +0200 Subject: [PATCH 375/619] feat(git): add flags for flavor and acl to instance create cmd, add flavor list cmd (#841) --- docs/stackit_git.md | 6 +- ...it_git_create.md => stackit_git_flavor.md} | 19 +- docs/stackit_git_flavor_list.md | 44 ++++ docs/stackit_git_instance.md | 37 +++ docs/stackit_git_instance_create.md | 49 ++++ ...lete.md => stackit_git_instance_delete.md} | 10 +- ...be.md => stackit_git_instance_describe.md} | 8 +- ...t_list.md => stackit_git_instance_list.md} | 8 +- internal/cmd/git/flavor/flavor.go | 28 +++ internal/cmd/git/flavor/list/list.go | 161 ++++++++++++ internal/cmd/git/flavor/list/list_test.go | 237 ++++++++++++++++++ internal/cmd/git/git.go | 12 +- .../cmd/git/{ => instance}/create/create.go | 33 ++- .../git/{ => instance}/create/create_test.go | 14 +- .../cmd/git/{ => instance}/delete/delete.go | 3 +- .../git/{ => instance}/delete/delete_test.go | 0 .../git/{ => instance}/describe/describe.go | 0 .../{ => instance}/describe/describe_test.go | 0 internal/cmd/git/instance/instance.go | 34 +++ internal/cmd/git/{ => instance}/list/list.go | 0 .../cmd/git/{ => instance}/list/list_test.go | 0 21 files changed, 654 insertions(+), 49 deletions(-) rename docs/{stackit_git_create.md => stackit_git_flavor.md} (65%) create mode 100644 docs/stackit_git_flavor_list.md create mode 100644 docs/stackit_git_instance.md create mode 100644 docs/stackit_git_instance_create.md rename docs/{stackit_git_delete.md => stackit_git_instance_delete.md} (72%) rename docs/{stackit_git_describe.md => stackit_git_instance_describe.md} (75%) rename docs/{stackit_git_list.md => stackit_git_instance_list.md} (79%) create mode 100644 internal/cmd/git/flavor/flavor.go create mode 100644 internal/cmd/git/flavor/list/list.go create mode 100644 internal/cmd/git/flavor/list/list_test.go rename internal/cmd/git/{ => instance}/create/create.go (82%) rename internal/cmd/git/{ => instance}/create/create_test.go (94%) rename internal/cmd/git/{ => instance}/delete/delete.go (97%) rename internal/cmd/git/{ => instance}/delete/delete_test.go (100%) rename internal/cmd/git/{ => instance}/describe/describe.go (100%) rename internal/cmd/git/{ => instance}/describe/describe_test.go (100%) create mode 100644 internal/cmd/git/instance/instance.go rename internal/cmd/git/{ => instance}/list/list.go (100%) rename internal/cmd/git/{ => instance}/list/list_test.go (100%) diff --git a/docs/stackit_git.md b/docs/stackit_git.md index 8a959c7d2..2a9b072e2 100644 --- a/docs/stackit_git.md +++ b/docs/stackit_git.md @@ -30,8 +30,6 @@ stackit git [flags] ### SEE ALSO * [stackit](./stackit.md) - Manage STACKIT resources using the command line -* [stackit git create](./stackit_git_create.md) - Creates STACKIT Git instance -* [stackit git delete](./stackit_git_delete.md) - Deletes STACKIT Git instance -* [stackit git describe](./stackit_git_describe.md) - Describes STACKIT Git instance -* [stackit git list](./stackit_git_list.md) - Lists all instances of STACKIT Git. +* [stackit git flavor](./stackit_git_flavor.md) - Provides functionality for STACKIT Git flavors +* [stackit git instance](./stackit_git_instance.md) - Provides functionality for STACKIT Git instances diff --git a/docs/stackit_git_create.md b/docs/stackit_git_flavor.md similarity index 65% rename from docs/stackit_git_create.md rename to docs/stackit_git_flavor.md index fa7a2a97d..c2ec85a08 100644 --- a/docs/stackit_git_create.md +++ b/docs/stackit_git_flavor.md @@ -1,27 +1,19 @@ -## stackit git create +## stackit git flavor -Creates STACKIT Git instance +Provides functionality for STACKIT Git flavors ### Synopsis -Create a STACKIT Git instance by name. +Provides functionality for STACKIT Git flavors. ``` -stackit git create [flags] -``` - -### Examples - -``` - Create a instance with name 'my-new-instance' - $ stackit git create --name my-new-instance +stackit git flavor [flags] ``` ### Options ``` - -h, --help Help for "stackit git create" - --name string The name of the instance. + -h, --help Help for "stackit git flavor" ``` ### Options inherited from parent commands @@ -38,4 +30,5 @@ stackit git create [flags] ### SEE ALSO * [stackit git](./stackit_git.md) - Provides functionality for STACKIT Git +* [stackit git flavor list](./stackit_git_flavor_list.md) - Lists instances flavors of STACKIT Git. diff --git a/docs/stackit_git_flavor_list.md b/docs/stackit_git_flavor_list.md new file mode 100644 index 000000000..a8fc54b0f --- /dev/null +++ b/docs/stackit_git_flavor_list.md @@ -0,0 +1,44 @@ +## stackit git flavor list + +Lists instances flavors of STACKIT Git. + +### Synopsis + +Lists instances flavors of STACKIT Git for the current project. + +``` +stackit git flavor list [flags] +``` + +### Examples + +``` + List STACKIT Git flavors + $ stackit git flavor list + + Lists up to 10 STACKIT Git flavors + $ stackit git flavor list --limit=10 +``` + +### Options + +``` + -h, --help Help for "stackit git flavor list" + --limit int Limit the output to the first n elements +``` + +### 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 git flavor](./stackit_git_flavor.md) - Provides functionality for STACKIT Git flavors + diff --git a/docs/stackit_git_instance.md b/docs/stackit_git_instance.md new file mode 100644 index 000000000..5f7c6d243 --- /dev/null +++ b/docs/stackit_git_instance.md @@ -0,0 +1,37 @@ +## stackit git instance + +Provides functionality for STACKIT Git instances + +### Synopsis + +Provides functionality for STACKIT Git instances. + +``` +stackit git instance [flags] +``` + +### Options + +``` + -h, --help Help for "stackit git instance" +``` + +### 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 git](./stackit_git.md) - Provides functionality for STACKIT Git +* [stackit git instance create](./stackit_git_instance_create.md) - Creates STACKIT Git instance +* [stackit git instance delete](./stackit_git_instance_delete.md) - Deletes STACKIT Git instance +* [stackit git instance describe](./stackit_git_instance_describe.md) - Describes STACKIT Git instance +* [stackit git instance list](./stackit_git_instance_list.md) - Lists all instances of STACKIT Git. + diff --git a/docs/stackit_git_instance_create.md b/docs/stackit_git_instance_create.md new file mode 100644 index 000000000..e5d8bba93 --- /dev/null +++ b/docs/stackit_git_instance_create.md @@ -0,0 +1,49 @@ +## stackit git instance create + +Creates STACKIT Git instance + +### Synopsis + +Create a STACKIT Git instance by name. + +``` +stackit git instance create [flags] +``` + +### Examples + +``` + Create a instance with name 'my-new-instance' + $ stackit git instance create --name my-new-instance + + Create a instance with name 'my-new-instance' and flavor + $ stackit git instance create --name my-new-instance --flavor git-100' + + Create a instance with name 'my-new-instance' and acl + $ stackit git instance create --name my-new-instance --acl 1.1.1.1/1' +``` + +### Options + +``` + --acl strings Acl for the instance. + --flavor string Flavor of the instance. + -h, --help Help for "stackit git instance create" + --name string The name of the instance. +``` + +### 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 git instance](./stackit_git_instance.md) - Provides functionality for STACKIT Git instances + diff --git a/docs/stackit_git_delete.md b/docs/stackit_git_instance_delete.md similarity index 72% rename from docs/stackit_git_delete.md rename to docs/stackit_git_instance_delete.md index 6f863ee60..df0a6d46a 100644 --- a/docs/stackit_git_delete.md +++ b/docs/stackit_git_instance_delete.md @@ -1,4 +1,4 @@ -## stackit git delete +## stackit git instance delete Deletes STACKIT Git instance @@ -7,20 +7,20 @@ Deletes STACKIT Git instance Deletes a STACKIT Git instance by its internal ID. ``` -stackit git delete INSTANCE_ID [flags] +stackit git instance delete INSTANCE_ID [flags] ``` ### Examples ``` Delete a instance with ID "xxx" - $ stackit git delete xxx + $ stackit git instance delete xxx ``` ### Options ``` - -h, --help Help for "stackit git delete" + -h, --help Help for "stackit git instance delete" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit git delete INSTANCE_ID [flags] ### SEE ALSO -* [stackit git](./stackit_git.md) - Provides functionality for STACKIT Git +* [stackit git instance](./stackit_git_instance.md) - Provides functionality for STACKIT Git instances diff --git a/docs/stackit_git_describe.md b/docs/stackit_git_instance_describe.md similarity index 75% rename from docs/stackit_git_describe.md rename to docs/stackit_git_instance_describe.md index e2aedcc40..90716803e 100644 --- a/docs/stackit_git_describe.md +++ b/docs/stackit_git_instance_describe.md @@ -1,4 +1,4 @@ -## stackit git describe +## stackit git instance describe Describes STACKIT Git instance @@ -7,7 +7,7 @@ Describes STACKIT Git instance Describes a STACKIT Git instance by its internal ID. ``` -stackit git describe INSTANCE_ID [flags] +stackit git instance describe INSTANCE_ID [flags] ``` ### Examples @@ -20,7 +20,7 @@ stackit git describe INSTANCE_ID [flags] ### Options ``` - -h, --help Help for "stackit git describe" + -h, --help Help for "stackit git instance describe" ``` ### Options inherited from parent commands @@ -36,5 +36,5 @@ stackit git describe INSTANCE_ID [flags] ### SEE ALSO -* [stackit git](./stackit_git.md) - Provides functionality for STACKIT Git +* [stackit git instance](./stackit_git_instance.md) - Provides functionality for STACKIT Git instances diff --git a/docs/stackit_git_list.md b/docs/stackit_git_instance_list.md similarity index 79% rename from docs/stackit_git_list.md rename to docs/stackit_git_instance_list.md index c0f65927b..96afe06d4 100644 --- a/docs/stackit_git_list.md +++ b/docs/stackit_git_instance_list.md @@ -1,4 +1,4 @@ -## stackit git list +## stackit git instance list Lists all instances of STACKIT Git. @@ -7,7 +7,7 @@ Lists all instances of STACKIT Git. Lists all instances of STACKIT Git for the current project. ``` -stackit git list [flags] +stackit git instance list [flags] ``` ### Examples @@ -23,7 +23,7 @@ stackit git list [flags] ### Options ``` - -h, --help Help for "stackit git list" + -h, --help Help for "stackit git instance list" --limit int Limit the output to the first n elements ``` @@ -40,5 +40,5 @@ stackit git list [flags] ### SEE ALSO -* [stackit git](./stackit_git.md) - Provides functionality for STACKIT Git +* [stackit git instance](./stackit_git_instance.md) - Provides functionality for STACKIT Git instances diff --git a/internal/cmd/git/flavor/flavor.go b/internal/cmd/git/flavor/flavor.go new file mode 100644 index 000000000..c6f4c512f --- /dev/null +++ b/internal/cmd/git/flavor/flavor.go @@ -0,0 +1,28 @@ +package flavor + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/git/flavor/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "flavor", + Short: "Provides functionality for STACKIT Git flavors", + Long: "Provides functionality for STACKIT Git flavors.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand( + list.NewCmd(params), + ) +} diff --git a/internal/cmd/git/flavor/list/list.go b/internal/cmd/git/flavor/list/list.go new file mode 100644 index 000000000..aec140d80 --- /dev/null +++ b/internal/cmd/git/flavor/list/list.go @@ -0,0 +1,161 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/git/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +const limitFlag = "limit" + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists instances flavors of STACKIT Git.", + Long: "Lists instances flavors of STACKIT Git for the current project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List STACKIT Git flavors`, + "$ stackit git flavor list"), + examples.NewExample( + "Lists up to 10 STACKIT Git flavors", + "$ stackit git flavor list --limit=10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get STACKIT Git flavors: %w", err) + } + flavors := *resp.Flavors + if len(flavors) == 0 { + 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 + } + params.Printer.Info("No flavors found for project %q\n", projectLabel) + return nil + } else if model.Limit != nil && len(flavors) > int(*model.Limit) { + flavors = (flavors)[:*model.Limit] + } + return outputResult(params.Printer, model.OutputFormat, flavors) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClient) git.ApiListFlavorsRequest { + return apiClient.ListFlavors(ctx, model.ProjectId) +} + +func outputResult(p *print.Printer, outputFormat string, flavors []git.Flavor) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(flavors, "", " ") + if err != nil { + return fmt.Errorf("marshal Observability flavor list: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(flavors, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal Observability flavor list: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("ID", "DESCRIPTION", "DISPLAY_NAME", "AVAILABLE", "SKU") + for i := range flavors { + flavor := (flavors)[i] + table.AddRow( + utils.PtrString(flavor.Id), + utils.PtrString(flavor.Description), + utils.PtrString(flavor.DisplayName), + utils.PtrString(flavor.Availability), + utils.PtrString(flavor.Sku), + ) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/git/flavor/list/list_test.go b/internal/cmd/git/flavor/list/list_test.go new file mode 100644 index 000000000..1413630b0 --- /dev/null +++ b/internal/cmd/git/flavor/list/list_test.go @@ -0,0 +1,237 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/git" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &git.APIClient{} +var testProjectId = uuid.NewString() + +const ( + testLimit = 10 +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *git.ApiListFlavorsRequest)) git.ApiListFlavorsRequest { + request := testClient.ListFlavors(testCtx, testProjectId) + 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: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "with limit flag", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(testLimit) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(testLimit)) + }), + }, + { + description: "with limit flag == 0", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(0) + }), + isValid: false, + }, + { + description: "with limit flag < 0", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues["limit"] = strconv.Itoa(-1) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInput(p, cmd) + 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) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest git.ApiListFlavorsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + flavors []git.Flavor + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty flavors slice", + args: args{ + flavors: []git.Flavor{}, + }, + wantErr: false, + }, + { + name: "set empty flavors in flavors slice", + args: args{ + flavors: []git.Flavor{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.flavors); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/git/git.go b/internal/cmd/git/git.go index fcacb4fcd..72605d968 100644 --- a/internal/cmd/git/git.go +++ b/internal/cmd/git/git.go @@ -1,10 +1,8 @@ package git import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/git/create" - "github.com/stackitcloud/stackit-cli/internal/cmd/git/delete" - "github.com/stackitcloud/stackit-cli/internal/cmd/git/describe" - "github.com/stackitcloud/stackit-cli/internal/cmd/git/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/git/flavor" + "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -26,9 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand( - list.NewCmd(params), - describe.NewCmd(params), - create.NewCmd(params), - delete.NewCmd(params), + instance.NewCmd(params), + flavor.NewCmd(params), ) } diff --git a/internal/cmd/git/create/create.go b/internal/cmd/git/instance/create/create.go similarity index 82% rename from internal/cmd/git/create/create.go rename to internal/cmd/git/instance/create/create.go index 6df750b37..761c2be61 100644 --- a/internal/cmd/git/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -5,10 +5,9 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -23,13 +22,17 @@ import ( ) const ( - nameFlag = "name" + nameFlag = "name" + flavorFlag = "flavor" + aclFlag = "acl" ) type inputModel struct { *globalflags.GlobalFlagModel - Id *string - Name string + Id *string + Name string + Flavor string + Acl []string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -41,7 +44,15 @@ func NewCmd(params *params.CmdParams) *cobra.Command { Example: examples.Build( examples.NewExample( `Create a instance with name 'my-new-instance'`, - `$ stackit git create --name my-new-instance`, + `$ stackit git instance create --name my-new-instance`, + ), + examples.NewExample( + `Create a instance with name 'my-new-instance' and flavor`, + `$ stackit git instance create --name my-new-instance --flavor git-100'`, + ), + examples.NewExample( + `Create a instance with name 'my-new-instance' and acl`, + `$ stackit git instance create --name my-new-instance --acl 1.1.1.1/1'`, ), ), RunE: func(cmd *cobra.Command, _ []string) (err error) { @@ -95,6 +106,8 @@ func NewCmd(params *params.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().String(nameFlag, "", "The name of the instance.") + cmd.Flags().String(flavorFlag, "", "Flavor of the instance.") + cmd.Flags().StringSlice(aclFlag, []string{}, "Acl for the instance.") if err := flags.MarkFlagsRequired(cmd, nameFlag); err != nil { cobra.CheckErr(err) } @@ -107,10 +120,14 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { return nil, &errors.ProjectIdError{} } name := flags.FlagToStringValue(p, cmd, nameFlag) + flavor := flags.FlagToStringValue(p, cmd, flavorFlag) + acl := flags.FlagToStringSliceValue(p, cmd, aclFlag) model := inputModel{ GlobalFlagModel: globalFlags, Name: name, + Flavor: flavor, + Acl: acl, } if p.IsVerbosityDebug() { @@ -131,7 +148,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClie func createPayload(model *inputModel) git.CreateInstancePayload { return git.CreateInstancePayload{ - Name: &model.Name, + Name: &model.Name, + Flavor: git.CreateInstancePayloadGetFlavorAttributeType(&model.Flavor), + Acl: &model.Acl, } } diff --git a/internal/cmd/git/create/create_test.go b/internal/cmd/git/instance/create/create_test.go similarity index 94% rename from internal/cmd/git/create/create_test.go rename to internal/cmd/git/instance/create/create_test.go index 26499bf8b..5b46e1eef 100644 --- a/internal/cmd/git/create/create_test.go +++ b/internal/cmd/git/instance/create/create_test.go @@ -21,14 +21,18 @@ var ( testClient = &git.APIClient{} testProjectId = uuid.NewString() - testName = "test-instance" + testName = "test-instance" + testFlavor = "git-100" + testAcl = []string{"0.0.0.0/0"} ) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, - nameFlag: testName, + nameFlag: testName, + flavorFlag: testFlavor, + aclFlag: testAcl[0], } for _, mod := range mods { mod(flagValues) @@ -40,6 +44,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, Name: testName, + Flavor: testFlavor, + Acl: testAcl, } for _, mod := range mods { mod(model) @@ -49,7 +55,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func fixtureCreatePayload(mods ...func(payload *git.CreateInstancePayload)) (payload git.CreateInstancePayload) { payload = git.CreateInstancePayload{ - Name: &testName, + Name: &testName, + Flavor: git.CreateInstancePayloadGetFlavorAttributeType(&testFlavor), + Acl: &testAcl, } for _, mod := range mods { mod(&payload) diff --git a/internal/cmd/git/delete/delete.go b/internal/cmd/git/instance/delete/delete.go similarity index 97% rename from internal/cmd/git/delete/delete.go rename to internal/cmd/git/instance/delete/delete.go index 67ae11438..c16a6b09e 100644 --- a/internal/cmd/git/delete/delete.go +++ b/internal/cmd/git/instance/delete/delete.go @@ -35,7 +35,8 @@ func NewCmd(params *params.CmdParams) *cobra.Command { Long: "Deletes a STACKIT Git instance by its internal ID.", Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( - examples.NewExample(`Delete a instance with ID "xxx"`, `$ stackit git delete xxx`), + examples.NewExample(`Delete a instance with ID "xxx"`, + `$ stackit git instance delete xxx`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/git/delete/delete_test.go b/internal/cmd/git/instance/delete/delete_test.go similarity index 100% rename from internal/cmd/git/delete/delete_test.go rename to internal/cmd/git/instance/delete/delete_test.go diff --git a/internal/cmd/git/describe/describe.go b/internal/cmd/git/instance/describe/describe.go similarity index 100% rename from internal/cmd/git/describe/describe.go rename to internal/cmd/git/instance/describe/describe.go diff --git a/internal/cmd/git/describe/describe_test.go b/internal/cmd/git/instance/describe/describe_test.go similarity index 100% rename from internal/cmd/git/describe/describe_test.go rename to internal/cmd/git/instance/describe/describe_test.go diff --git a/internal/cmd/git/instance/instance.go b/internal/cmd/git/instance/instance.go new file mode 100644 index 000000000..b2d66b43a --- /dev/null +++ b/internal/cmd/git/instance/instance.go @@ -0,0 +1,34 @@ +package instance + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "instance", + Short: "Provides functionality for STACKIT Git instances", + Long: "Provides functionality for STACKIT Git instances.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand( + list.NewCmd(params), + describe.NewCmd(params), + create.NewCmd(params), + delete.NewCmd(params), + ) +} diff --git a/internal/cmd/git/list/list.go b/internal/cmd/git/instance/list/list.go similarity index 100% rename from internal/cmd/git/list/list.go rename to internal/cmd/git/instance/list/list.go diff --git a/internal/cmd/git/list/list_test.go b/internal/cmd/git/instance/list/list_test.go similarity index 100% rename from internal/cmd/git/list/list_test.go rename to internal/cmd/git/instance/list/list_test.go From 2f1d07ad5428b7e9ec60fc732b6aa9121f8f340c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 13:22:09 +0200 Subject: [PATCH 376/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex from 1.4.0 to 1.5.0 (#856) Co-authored-by: Ruben Hoenle --- go.mod | 2 +- go.sum | 4 ++-- internal/cmd/mongodbflex/instance/update/update.go | 2 +- .../cmd/mongodbflex/instance/update/update_test.go | 14 +++++++------- internal/pkg/services/mongodbflex/utils/utils.go | 2 +- .../pkg/services/mongodbflex/utils/utils_test.go | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 0bf1e4730..c180d7263 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.4.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 diff --git a/go.sum b/go.sum index 20839d0b9..6b33a98f0 100644 --- a/go.sum +++ b/go.sum @@ -581,8 +581,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCx github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 h1:vxk6ztgzUIPMkfv27NRpniFqCyGGGFsWJQUvFs43bQA= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.4.0 h1:il4vBOejtX0//CWuY6CDpFfPpDIvin5V9QIaKvyXV/M= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.4.0/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.0 h1:0amQ/exKUwmxGNbEGyWJF7D6wBjo59WGsn6yCX6k3zo= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.0/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 h1:bK5FDpSGfUKDXNkqOoiqOU9hua2YfcdYsGS4zQQ9wg0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0/go.mod h1:Q2SJXlZTksvNAb1QnpGNfDSw/OMPN9uopaKuptUGhO8= github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 h1:NuRgx13h3mnzWcRTLPiL5fk06xpl43vaz+QOuHvSEHA= diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index 92dafbb94..5c11a7ee6 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -201,7 +201,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu type MongoDBFlexClient interface { PartialUpdateInstance(ctx context.Context, projectId, instanceId, region string) mongodbflex.ApiPartialUpdateInstanceRequest - GetInstanceExecute(ctx context.Context, projectId, instanceId, region string) (*mongodbflex.GetInstanceResponse, error) + GetInstanceExecute(ctx context.Context, projectId, instanceId, region string) (*mongodbflex.InstanceResponse, error) ListFlavorsExecute(ctx context.Context, projectId, region string) (*mongodbflex.ListFlavorsResponse, error) ListStoragesExecute(ctx context.Context, projectId, flavorId, region string) (*mongodbflex.ListStoragesResponse, error) } diff --git a/internal/cmd/mongodbflex/instance/update/update_test.go b/internal/cmd/mongodbflex/instance/update/update_test.go index 1c0a92f2b..f9bb2dffa 100644 --- a/internal/cmd/mongodbflex/instance/update/update_test.go +++ b/internal/cmd/mongodbflex/instance/update/update_test.go @@ -31,14 +31,14 @@ type mongoDBFlexClientMocked struct { listStoragesFails bool listStoragesResp *mongodbflex.ListStoragesResponse getInstanceFails bool - getInstanceResp *mongodbflex.GetInstanceResponse + getInstanceResp *mongodbflex.InstanceResponse } func (c *mongoDBFlexClientMocked) PartialUpdateInstance(ctx context.Context, projectId, instanceId, region string) mongodbflex.ApiPartialUpdateInstanceRequest { return testClient.PartialUpdateInstance(ctx, projectId, instanceId, region) } -func (c *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*mongodbflex.GetInstanceResponse, error) { +func (c *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*mongodbflex.InstanceResponse, error) { if c.getInstanceFails { return nil, fmt.Errorf("get instance failed") } @@ -354,7 +354,7 @@ func TestBuildRequest(t *testing.T) { model *inputModel expectedRequest mongodbflex.ApiPartialUpdateInstanceRequest getInstanceFails bool - getInstanceResp *mongodbflex.GetInstanceResponse + getInstanceResp *mongodbflex.InstanceResponse listFlavorsFails bool listFlavorsResp *mongodbflex.ListFlavorsResponse listStoragesFails bool @@ -414,7 +414,7 @@ func TestBuildRequest(t *testing.T) { model.StorageClass = utils.Ptr("class") }), isValid: true, - getInstanceResp: &mongodbflex.GetInstanceResponse{ + getInstanceResp: &mongodbflex.InstanceResponse{ Item: &mongodbflex.Instance{ Flavor: &mongodbflex.Flavor{ Id: utils.Ptr(testFlavorId), @@ -442,7 +442,7 @@ func TestBuildRequest(t *testing.T) { model.StorageSize = utils.Ptr(int64(10)) }), isValid: true, - getInstanceResp: &mongodbflex.GetInstanceResponse{ + getInstanceResp: &mongodbflex.InstanceResponse{ Item: &mongodbflex.Instance{ Flavor: &mongodbflex.Flavor{ Id: utils.Ptr(testFlavorId), @@ -528,7 +528,7 @@ func TestBuildRequest(t *testing.T) { model.StorageClass = utils.Ptr("non-existing-class") }, ), - getInstanceResp: &mongodbflex.GetInstanceResponse{ + getInstanceResp: &mongodbflex.InstanceResponse{ Item: &mongodbflex.Instance{ Flavor: &mongodbflex.Flavor{ Id: utils.Ptr(testFlavorId), @@ -551,7 +551,7 @@ func TestBuildRequest(t *testing.T) { model.StorageSize = utils.Ptr(int64(9)) }, ), - getInstanceResp: &mongodbflex.GetInstanceResponse{ + getInstanceResp: &mongodbflex.InstanceResponse{ Item: &mongodbflex.Instance{ Flavor: &mongodbflex.Flavor{ Id: utils.Ptr(testFlavorId), diff --git a/internal/pkg/services/mongodbflex/utils/utils.go b/internal/pkg/services/mongodbflex/utils/utils.go index 52d9aa311..a5cbc7016 100644 --- a/internal/pkg/services/mongodbflex/utils/utils.go +++ b/internal/pkg/services/mongodbflex/utils/utils.go @@ -22,7 +22,7 @@ var instanceTypeToReplicas = map[string]int64{ type MongoDBFlexClient interface { ListVersionsExecute(ctx context.Context, projectId, region string) (*mongodbflex.ListVersionsResponse, error) - GetInstanceExecute(ctx context.Context, projectId, instanceId, region string) (*mongodbflex.GetInstanceResponse, error) + GetInstanceExecute(ctx context.Context, projectId, instanceId, region string) (*mongodbflex.InstanceResponse, error) GetUserExecute(ctx context.Context, projectId, instanceId, userId, region string) (*mongodbflex.GetUserResponse, error) ListRestoreJobsExecute(ctx context.Context, projectId string, instanceId, region string) (*mongodbflex.ListRestoreJobsResponse, error) } diff --git a/internal/pkg/services/mongodbflex/utils/utils_test.go b/internal/pkg/services/mongodbflex/utils/utils_test.go index 4867c5bb3..157bc2803 100644 --- a/internal/pkg/services/mongodbflex/utils/utils_test.go +++ b/internal/pkg/services/mongodbflex/utils/utils_test.go @@ -29,7 +29,7 @@ type mongoDBFlexClientMocked struct { listVersionsFails bool listVersionsResp *mongodbflex.ListVersionsResponse getInstanceFails bool - getInstanceResp *mongodbflex.GetInstanceResponse + getInstanceResp *mongodbflex.InstanceResponse getUserFails bool getUserResp *mongodbflex.GetUserResponse listRestoreJobsFails bool @@ -50,7 +50,7 @@ func (m *mongoDBFlexClientMocked) ListRestoreJobsExecute(_ context.Context, _, _ return m.listRestoreJobsResp, nil } -func (m *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*mongodbflex.GetInstanceResponse, error) { +func (m *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _, _ string) (*mongodbflex.InstanceResponse, error) { if m.getInstanceFails { return nil, fmt.Errorf("could not get instance") } @@ -434,13 +434,13 @@ func TestGetInstanceName(t *testing.T) { tests := []struct { description string getInstanceFails bool - getInstanceResp *mongodbflex.GetInstanceResponse + getInstanceResp *mongodbflex.InstanceResponse isValid bool expectedOutput string }{ { description: "base", - getInstanceResp: &mongodbflex.GetInstanceResponse{ + getInstanceResp: &mongodbflex.InstanceResponse{ Item: &mongodbflex.Instance{ Name: utils.Ptr(testInstanceName), }, From f91849da5e0c2cbab722e1c80f4e687019d6a202 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 18 Jul 2025 14:01:31 +0200 Subject: [PATCH 377/619] chore(deps): update module golang.org/x/tools to v0.35.0 (#861) Co-authored-by: Renovate Bot --- go.mod | 6 ++++-- go.sum | 12 ++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c180d7263..673f2304e 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( ) require ( - golang.org/x/net v0.41.0 // indirect + golang.org/x/net v0.42.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -207,7 +207,9 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.16.0 // indirect - golang.org/x/tools v0.34.0 // indirect + golang.org/x/tools v0.35.0 // indirect + golang.org/x/tools/go/expect v0.1.1-deprecated // indirect + golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect honnef.co/go/tools v0.6.1 // indirect diff --git a/go.sum b/go.sum index 6b33a98f0..a8066afba 100644 --- a/go.sum +++ b/go.sum @@ -795,8 +795,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -962,8 +962,12 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= -golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 5430a95dbec779596bdec6279302cc706421a6f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 21 Jul 2025 12:57:39 +0200 Subject: [PATCH 378/619] fix(ci): mark the workflow as successful on coverage report error (#874) relates to #802 --- .github/workflows/ci.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 14432ab71..50d71d17b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -58,14 +58,15 @@ jobs: name: "Code coverage report" if: github.event_name == 'pull_request' # Do not run when workflow is triggered by push to main branch runs-on: ubuntu-latest - continue-on-error: true # Add this line to prevent pipeline failures in forks needs: main permissions: contents: read actions: read # to download code coverage results from "main" job pull-requests: write # write permission needed to comment on PR steps: - - uses: fgrosse/go-coverage-report@v1.2.0 + - name: Check new code coverage + uses: fgrosse/go-coverage-report@v1.2.0 + continue-on-error: true # Add this line to prevent pipeline failures in forks with: coverage-artifact-name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} - coverage-file-name: ${{ env.CODE_COVERAGE_FILE_NAME }} \ No newline at end of file + coverage-file-name: ${{ env.CODE_COVERAGE_FILE_NAME }} From 231674af0d19d4da1ab38dc8506044b5db0a39ae Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 23 Jul 2025 07:52:11 +0200 Subject: [PATCH 379/619] chore(deps): update renovatebot/github-action action to v43.0.4 (#878) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 1e857a5f1..df77823ed 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.3 + uses: renovatebot/github-action@v43.0.4 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 193ebee981410f8c882b83cd7f92c6bb60496354 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 09:12:59 +0200 Subject: [PATCH 380/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/rabbitmq (#880) Bumps [github.com/stackitcloud/stackit-sdk-go/services/rabbitmq](https://github.com/stackitcloud/stackit-sdk-go) from 0.25.0 to 0.25.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v0.25.0...services/logme/v0.25.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/rabbitmq dependency-version: 0.25.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 673f2304e..2a0c0ea34 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.0 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum index a8066afba..fdd65ebb1 100644 --- a/go.sum +++ b/go.sum @@ -591,8 +591,8 @@ github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 h1:+qFjzDDv/0 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 h1:DGgKKCh3AmUBqDG0DrsWVcclxSaG82TVEf18A29w+J0= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0/go.mod h1:I67K+QjPAIMrW/r/0GOdX2WSmA8J72LNzpe8rElfxFI= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.0 h1:Xhgo0Di6NDjkg0Bf3f6LHlQ09u0Dj/3WdDb0xd47vEU= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.0/go.mod h1:YL0l9l9xzJy2BmV+U9XkcXlQaHbE2KyA37GpGvBXIJ4= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 h1:ALrDCBih8Fu8e6530KdOjuH0iMxOLntO381BbKFlTFY= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1/go.mod h1:+qGWSehoV0Js3FalgvT/bOgPj+UqW4I7lP5s8uAxP+o= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 h1:wdQoQ9RUkpX80twtG9xUghW9Xn1ka9zOjIxJDLbtwSo= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0/go.mod h1:PAQH8+1DDGc6uibvC3nDtfRLu8uxutIr25mPJvrCOy8= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 h1:lxI0LnHcTpnF8g0tHTCQ1UIVLlNHk1W1WAclp3Ut0fw= From 89a50f444a8a29daaf3720c683306287f3be07b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 07:21:14 +0000 Subject: [PATCH 381/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex (#881) Bumps [github.com/stackitcloud/stackit-sdk-go/services/mongodbflex](https://github.com/stackitcloud/stackit-sdk-go) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/mongodbflex/v1.5.0...services/mongodbflex/v1.5.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/mongodbflex dependency-version: 1.5.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2a0c0ea34..329b582e1 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 diff --git a/go.sum b/go.sum index fdd65ebb1..8e6ae9293 100644 --- a/go.sum +++ b/go.sum @@ -581,8 +581,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCx github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 h1:vxk6ztgzUIPMkfv27NRpniFqCyGGGFsWJQUvFs43bQA= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.0 h1:0amQ/exKUwmxGNbEGyWJF7D6wBjo59WGsn6yCX6k3zo= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.0/go.mod h1:U1Zf/S9IuDvRJq1tRKFT/bsJd4qxYzwtukqX3TL++Mw= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 h1:XOpikSY2IXfBJPzUdgBk69iJXFC99xzfYtY1h4bZ5vM= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1/go.mod h1:G7S/hGa6EyX5Avxxw/PIdbdtbFeiXL/T1vUkPOJ120w= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 h1:bK5FDpSGfUKDXNkqOoiqOU9hua2YfcdYsGS4zQQ9wg0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0/go.mod h1:Q2SJXlZTksvNAb1QnpGNfDSw/OMPN9uopaKuptUGhO8= github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 h1:NuRgx13h3mnzWcRTLPiL5fk06xpl43vaz+QOuHvSEHA= From a1859d68604fa353045bc734e4dd2dd82c230880 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 09:36:33 +0200 Subject: [PATCH 382/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/secretsmanager (#882) Bumps [github.com/stackitcloud/stackit-sdk-go/services/secretsmanager](https://github.com/stackitcloud/stackit-sdk-go) from 0.13.0 to 0.13.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.13.0...services/dns/v0.13.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/secretsmanager dependency-version: 0.13.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 329b582e1..eab7753b2 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 diff --git a/go.sum b/go.sum index 8e6ae9293..f38a81443 100644 --- a/go.sum +++ b/go.sum @@ -599,8 +599,8 @@ github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 h1:lxI0L github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0/go.mod h1:TBvZpbCju0Zmq8GoS4CEtUg2MqtdqWrGeEAOXwkJNQo= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 h1:ewFXnESJWsUen0T9sSt0lwL28fhqCVB1HSLdY0szrdA= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0/go.mod h1:m9f9XZDeKpmqE/G0Sj5Rpdsiw+qcUo0Rcm3idAbyp1c= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0 h1:CtCaG8nycfviq/QgNM7OoBWs/Ap9IQvOmvI0tZhYdPI= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.0/go.mod h1:/MiR18oug1V0sxPT4KO6a+LhgPARNBGvgVx3qv3zJ0A= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 h1:WKFzlHllql3JsVcAq+Y1m5pSMkvwp1qH3Vf2N7i8CPg= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1/go.mod h1:WGMFtGugBmUxI+nibI7eUZIQk4AGlDvwqX+m17W1y5w= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1 h1:pvAYt53jUSUf1yHQJ+mcjQ+sgrpUBBqfw1EznGnP5A4= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1/go.mod h1:S/zLsdZvtPXDSYyl7h2GLHhsnVf6AzB96PdslPWevJI= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 h1:poL/Hz3a6OHZ/eKtwMGm5nLqC3fEJjzPQlN/7/+mk8Y= From 8ce470629df6e3066817aa7a5c44a40c335c6310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Thu, 24 Jul 2025 17:24:34 +0200 Subject: [PATCH 383/619] feat(auth): support output format in stackit auth get-access-token command (#889) relates to #888 --- .../auth/get-access-token/get_access_token.go | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index 25576427a..5e5b9d60b 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -1,14 +1,24 @@ package getaccesstoken import ( + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" cliErr "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" ) +type inputModel struct { + *globalflags.GlobalFlagModel +} + func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "get-access-token", @@ -20,7 +30,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Print a short-lived access token`, "$ stackit auth get-access-token"), ), - RunE: func(_ *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + userSessionExpired, err := auth.UserSessionExpired() if err != nil { return err @@ -35,9 +50,52 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - params.Printer.Outputf("%s\n", accessToken) - return nil + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(map[string]string{ + "access_token": accessToken, + }, "", " ") + if err != nil { + return fmt.Errorf("marshal image list: %w", err) + } + params.Printer.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(map[string]string{ + "access_token": accessToken, + }, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal image list: %w", err) + } + params.Printer.Outputln(string(details)) + + return nil + default: + params.Printer.Outputln(accessToken) + + return nil + } }, } return cmd } + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} From 50bcf38753d29cd25a91232a8d83f4d19b01bd85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 15:30:36 +0000 Subject: [PATCH 384/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/objectstorage (#887) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/objectstorage dependency-version: 1.3.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eab7753b2..b1eda20bf 100644 --- a/go.mod +++ b/go.mod @@ -241,7 +241,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 diff --git a/go.sum b/go.sum index f38a81443..40bd86e00 100644 --- a/go.sum +++ b/go.sum @@ -583,8 +583,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 h1:vxk6ztgzUIPMk github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 h1:XOpikSY2IXfBJPzUdgBk69iJXFC99xzfYtY1h4bZ5vM= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1/go.mod h1:G7S/hGa6EyX5Avxxw/PIdbdtbFeiXL/T1vUkPOJ120w= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0 h1:bK5FDpSGfUKDXNkqOoiqOU9hua2YfcdYsGS4zQQ9wg0= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.0/go.mod h1:Q2SJXlZTksvNAb1QnpGNfDSw/OMPN9uopaKuptUGhO8= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc= github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 h1:NuRgx13h3mnzWcRTLPiL5fk06xpl43vaz+QOuHvSEHA= github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 h1:+qFjzDDv/0ZHGdVuW2HzAphRBmlc1+abw7k1RaAqmQo= From 159e902452481ac6b5557ee547aebbdad325046a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 08:11:44 +0200 Subject: [PATCH 385/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serverbackup (#885) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/serverbackup dependency-version: 1.3.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b1eda20bf..dd0750abb 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 diff --git a/go.sum b/go.sum index 40bd86e00..4756c3a45 100644 --- a/go.sum +++ b/go.sum @@ -601,8 +601,8 @@ github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 h1:ewFXnESJWsU github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0/go.mod h1:m9f9XZDeKpmqE/G0Sj5Rpdsiw+qcUo0Rcm3idAbyp1c= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 h1:WKFzlHllql3JsVcAq+Y1m5pSMkvwp1qH3Vf2N7i8CPg= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1/go.mod h1:WGMFtGugBmUxI+nibI7eUZIQk4AGlDvwqX+m17W1y5w= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1 h1:pvAYt53jUSUf1yHQJ+mcjQ+sgrpUBBqfw1EznGnP5A4= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.1/go.mod h1:S/zLsdZvtPXDSYyl7h2GLHhsnVf6AzB96PdslPWevJI= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 h1:tfKC4Z6Uah9AQZrtCn/ytqOgc//ChQRfJ6ozxovgads= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2/go.mod h1:wV7/BUV3BCLq5+E1bHXrKKt/eOPVdWgLArWLAq7rZ/U= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 h1:poL/Hz3a6OHZ/eKtwMGm5nLqC3fEJjzPQlN/7/+mk8Y= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0/go.mod h1:ssbyAHtxyuBvheMEItydM78/JxjDl3naUtllrC7ghDs= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 h1:2d28WFQB9QB3af4uoPFglQDhH1LepEe6F2YoFCBecVI= From 6b1f8971018b9c5b32e032bb707d13276bab3f9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 06:19:33 +0000 Subject: [PATCH 386/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/iaas (#886) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/iaas dependency-version: 0.27.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dd0750abb..7d3cb5f0c 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 diff --git a/go.sum b/go.sum index 4756c3a45..0bae15924 100644 --- a/go.sum +++ b/go.sum @@ -573,8 +573,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 h1:x5mx/C2bdtpOH974R github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 h1:UJDtK96cjQqp5yWb8TxXLG42SOGcnBSgfYO7P3pk/j0= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0 h1:5vxOzwQ+rNm0g9ZLQW/31dqdDqGfw/FQbrjxUUAHtiA= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.0/go.mod h1:lUGkcbyMkd4nRBDFmKohIwlgtOZqQo4Ek5S5ajw90Xg= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1 h1:0RP8DCwSCbl0KBsRI6INFy/8JW7UqlAd2Yr3dWFS3No= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1/go.mod h1:TvqL/TgVrrdDF387gAhO8QQYLxiaOZwgpmyv6s15TU0= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0 h1:KgptlhV0LgOevtrfMBd2pm/Hrnz6vNSYgAJo6pT7eMM= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCxpFXN2K7g2ih0gQM6cyZ1VhTmtQfI= From c43de4ca2d7b42d0de6f965c13072c4c7faa06b2 Mon Sep 17 00:00:00 2001 From: Piet van der Meulen Date: Fri, 25 Jul 2025 12:11:01 +0200 Subject: [PATCH 387/619] feat(mongodb-flex): add readWriteAnyDatabase role (#884) --- docs/stackit_mongodbflex_user_create.md | 2 +- docs/stackit_mongodbflex_user_update.md | 2 +- internal/cmd/mongodbflex/user/create/create.go | 2 +- internal/cmd/mongodbflex/user/update/update.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/stackit_mongodbflex_user_create.md b/docs/stackit_mongodbflex_user_create.md index 8c42b3bb2..99075fee8 100644 --- a/docs/stackit_mongodbflex_user_create.md +++ b/docs/stackit_mongodbflex_user_create.md @@ -29,7 +29,7 @@ stackit mongodbflex user create [flags] --database string The database inside the MongoDB instance that the user has access to. If it does not exist, it will be created once the user writes to it -h, --help Help for "stackit mongodbflex user create" --instance-id string ID of the instance - --role strings Roles of the user, possible values are ["read" "readWrite"] (default [read]) + --role strings Roles of the user, possible values are ["read" "readWrite" "readWriteAnyDatabase"] (default [read]) --username string Username of the user. If not specified, a random username will be assigned ``` diff --git a/docs/stackit_mongodbflex_user_update.md b/docs/stackit_mongodbflex_user_update.md index bcbdfa54f..31a674972 100644 --- a/docs/stackit_mongodbflex_user_update.md +++ b/docs/stackit_mongodbflex_user_update.md @@ -23,7 +23,7 @@ stackit mongodbflex user update USER_ID [flags] --database string The database inside the MongoDB instance that the user has access to. If it does not exist, it will be created once the user writes to it -h, --help Help for "stackit mongodbflex user update" --instance-id string ID of the instance - --role strings Roles of the user, possible values are ["read" "readWrite"] (default []) + --role strings Roles of the user, possible values are ["read" "readWrite" "readWriteAnyDatabase"] (default []) ``` ### Options inherited from parent commands diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index 924f91896..2ddf76d34 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -103,7 +103,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func configureFlags(cmd *cobra.Command) { - roleOptions := []string{"read", "readWrite"} + roleOptions := []string{"read", "readWrite", "readWriteAnyDatabase"} cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance") cmd.Flags().String(usernameFlag, "", "Username of the user. If not specified, a random username will be assigned") diff --git a/internal/cmd/mongodbflex/user/update/update.go b/internal/cmd/mongodbflex/user/update/update.go index 4742a8e82..5f192f377 100644 --- a/internal/cmd/mongodbflex/user/update/update.go +++ b/internal/cmd/mongodbflex/user/update/update.go @@ -97,7 +97,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func configureFlags(cmd *cobra.Command) { - roleOptions := []string{"read", "readWrite"} + roleOptions := []string{"read", "readWrite", "readWriteAnyDatabase"} cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance") cmd.Flags().String(databaseFlag, "", "The database inside the MongoDB instance that the user has access to. If it does not exist, it will be created once the user writes to it") From c31dd87eb817c39ace5a6e81f93726d1254b15d0 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Fri, 25 Jul 2025 13:27:07 +0200 Subject: [PATCH 388/619] docs: Add guide to install the STACKIT CLI as homebrew cask (#879) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Docs: Add guide to uninstall the deprecated formula and reinstall it as cask Co-authored-by: Ruben Hönle --- INSTALLATION.md | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/INSTALLATION.md b/INSTALLATION.md index 35bdd5149..965ceddf9 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -17,7 +17,47 @@ brew tap stackitcloud/tap 2. You can then install the CLI via: ```shell -brew install stackit +brew install --cask stackit +``` + +#### Formula deprecated + +The homebrew formula is deprecated, will no longer be updated and will be removed after 2026-01-22. +You need to install the STACKIT CLI as cask. +Therefor you need to uninstall the formula and reinstall it as cask. + +Your profiles should normally remain. To ensure that nothing will be gone, you should backup them. + +1. Export your existing profiles. This will create a json file in your current directory. +```shell +stackit config profile export default +``` + +2. If you have multiple profiles, then execute the export command for each of them. You can find your profiles via: + +```shell +stackit config profile list +stackit config profile export +``` + +3. Uninstall the formula. +```shell +brew uninstall stackit +``` + +4. Install the STACKIT CLI as cask. +```shell +brew install --cask stackit +``` + +5. Check if your configs are still stored. +```shell +stackit config profile list +``` + +6. In case the profiles are gone, import your profiles via: +```shell +$ stackit config profile import -c @default.json --name myProfile ``` ### Linux From d4663b2fc848068a7d687c964c3cc321ddf01cec Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 28 Jul 2025 08:37:19 +0200 Subject: [PATCH 389/619] fix(deps): update stackit sdk modules (#883) Co-authored-by: Renovate Bot --- go.mod | 38 ++++++++++++++--------------- go.sum | 76 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/go.mod b/go.mod index 7d3cb5f0c..bba753a65 100644 --- a/go.mod +++ b/go.mod @@ -15,24 +15,24 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.7 github.com/spf13/viper v1.20.1 - github.com/stackitcloud/stackit-sdk-go/core v0.17.2 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.0 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 + github.com/stackitcloud/stackit-sdk-go/core v0.17.3 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 + github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/ske v1.1.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.26.0 golang.org/x/oauth2 v0.30.0 @@ -238,13 +238,13 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.34.0 // indirect diff --git a/go.sum b/go.sum index 0bae15924..82df7eb29 100644 --- a/go.sum +++ b/go.sum @@ -563,56 +563,56 @@ github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stackitcloud/stackit-sdk-go/core v0.17.2 h1:jPyn+i8rkp2hM80+hOg0B/1EVRbMt778Tr5RWyK1m2E= -github.com/stackitcloud/stackit-sdk-go/core v0.17.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.0 h1:eYP2TSEEZassdyA3V9Ci5jGMvK/WH1/gzTAUfvlpRyk= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.0/go.mod h1:RBLBx00zF9MoA/mcLoWwYaACFE0xrWp/EHlzo5S7nhA= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0 h1:KXMiTBV4KcOEQRFddtOUFspL+KRvjDQNDIs73bdiey0= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.0/go.mod h1:+2mx2MclJFMQ4Y6b20jspYAnIeFJP3/yvO6Gfvcvf6Q= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0 h1:x5mx/C2bdtpOH974RofXD0Y8YOyJtYXwIyaCyWOXMwU= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.0/go.mod h1:xhAdw016dY/hVsLerlExSMocqCc872+S0y1CdV3jAjU= -github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0 h1:UJDtK96cjQqp5yWb8TxXLG42SOGcnBSgfYO7P3pk/j0= -github.com/stackitcloud/stackit-sdk-go/services/git v0.7.0/go.mod h1:agI7SONeLR/IZL3TOgn1tDzfS63O2rWKQE8+huRjEzU= +github.com/stackitcloud/stackit-sdk-go/core v0.17.3 h1:GsZGmRRc/3GJLmCUnsZswirr5wfLRrwavbnL/renOqg= +github.com/stackitcloud/stackit-sdk-go/core v0.17.3/go.mod h1:HBCXJGPgdRulplDzhrmwC+Dak9B/x0nzNtmOpu+1Ahg= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1 h1:wJC/7mkIppHTBU0awGdLEFcmnjasp43MM9gX6/gdWvA= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1/go.mod h1:UyN4hlkdiK5beDi5j9xHMENxRE9A9dlIWSXO/unhQW8= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 h1:Kzr1G4g9PHI8ePFnHrHZEX06XtEJQYBK9JExje0aXl0= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1/go.mod h1:OwQ+fYpON4WQpEinvI9lCTuuwj9UBCnPPJcnDpK803U= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= +github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 h1:hkFixFnBcQzU4BSIZFITc8N0gK0pUYk7mk0wdUu5Ki8= +github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1/go.mod h1:Ng1EzrRndG3iGXGH90AZJz//wfK+2YOyDwTnTLwX3a4= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1 h1:0RP8DCwSCbl0KBsRI6INFy/8JW7UqlAd2Yr3dWFS3No= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1/go.mod h1:TvqL/TgVrrdDF387gAhO8QQYLxiaOZwgpmyv6s15TU0= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0 h1:KgptlhV0LgOevtrfMBd2pm/Hrnz6vNSYgAJo6pT7eMM= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.0/go.mod h1:FiVhDlw9+yuTiUmnyGLn2qpsLW26w9OC4TS1y78czvg= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0 h1:QKOfaB7EcuJmBCxpFXN2K7g2ih0gQM6cyZ1VhTmtQfI= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.0/go.mod h1:XjDMHhAQogFXsVR+o138CPYG1FOe0/Nl2Vm+fAgzx2A= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0 h1:vxk6ztgzUIPMkfv27NRpniFqCyGGGFsWJQUvFs43bQA= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.0/go.mod h1:Pb8IEV5/jP8k75dVcN5cn3kP7PHTy/4KXXKpG76oj4U= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 h1:OdJEs8eOfrzn9tCBDLxIyP8hX50zPfcXNYnRoQX+chs= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1/go.mod h1:11uzaOPCF9SeDHXEGOPMlHDD3J5r2TnvCGUwW9Igq9c= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1/go.mod h1:ivt8lvnAoBZsde2jSAuicyn6RgTmHvvNAJ3whaUbAD4= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 h1:Db/ebOL2vbpIeh5XB2Ews2B9Lj5DJlMWIEJh60FfZ4Y= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1/go.mod h1:8jdN4v2euK3f9gfdzbRi8e4nBJ8g/Q5YF9aPB4M4fCQ= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 h1:XOpikSY2IXfBJPzUdgBk69iJXFC99xzfYtY1h4bZ5vM= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1/go.mod h1:G7S/hGa6EyX5Avxxw/PIdbdtbFeiXL/T1vUkPOJ120w= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0 h1:NuRgx13h3mnzWcRTLPiL5fk06xpl43vaz+QOuHvSEHA= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.0/go.mod h1:+eNo7SEeVRuW7hgujSabSketScSUKGuC88UznPS+UTE= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0 h1:+qFjzDDv/0ZHGdVuW2HzAphRBmlc1+abw7k1RaAqmQo= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.0/go.mod h1:ifKKKCWL1U435fXGQ375SPX+burtfg1I7EGZ58COzRA= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0 h1:DGgKKCh3AmUBqDG0DrsWVcclxSaG82TVEf18A29w+J0= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.0/go.mod h1:I67K+QjPAIMrW/r/0GOdX2WSmA8J72LNzpe8rElfxFI= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.1 h1:eSiUKN61FJ4x42vgIvhVU7bgmrPbj05xR4y0nnRV5Yg= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.1/go.mod h1:oJku0heeBwsy4IToqhvSdPJI++GUNkBSESxOjiLWRVQ= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1/go.mod h1:hyhw+I19NtjKmRLcUkY4boaTxnYSPFGbpn4RxvGqH2s= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 h1:ALrDCBih8Fu8e6530KdOjuH0iMxOLntO381BbKFlTFY= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1/go.mod h1:+qGWSehoV0Js3FalgvT/bOgPj+UqW4I7lP5s8uAxP+o= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0 h1:wdQoQ9RUkpX80twtG9xUghW9Xn1ka9zOjIxJDLbtwSo= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.0/go.mod h1:PAQH8+1DDGc6uibvC3nDtfRLu8uxutIr25mPJvrCOy8= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0 h1:lxI0LnHcTpnF8g0tHTCQ1UIVLlNHk1W1WAclp3Ut0fw= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.0/go.mod h1:TBvZpbCju0Zmq8GoS4CEtUg2MqtdqWrGeEAOXwkJNQo= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0 h1:ewFXnESJWsUen0T9sSt0lwL28fhqCVB1HSLdY0szrdA= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.0/go.mod h1:m9f9XZDeKpmqE/G0Sj5Rpdsiw+qcUo0Rcm3idAbyp1c= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 h1:8uPt82Ez34OYMOijjEYxB1zUW6kiybkt6veQKl0AL68= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1/go.mod h1:1Y2GEICmZDt+kr8aGnBx/sjYVAIYHmtfC8xYi9oxNEE= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 h1:r7oaINTwLmIG31AaqKTuQHHFF8YNuYGzi+46DOuSjw4= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1/go.mod h1:ipcrPRbwfQXHH18dJVfY7K5ujHF5dTT6isoXgmA7YwQ= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 h1:CPIuqhQw+oPt08I2WLsxJDoVDsPMW2VkvKW7/SlUv10= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1/go.mod h1:tip0Ob6x06luy3CmRrmnCMtU5cha95fQLdvZlno3J4w= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 h1:WKFzlHllql3JsVcAq+Y1m5pSMkvwp1qH3Vf2N7i8CPg= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1/go.mod h1:WGMFtGugBmUxI+nibI7eUZIQk4AGlDvwqX+m17W1y5w= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 h1:tfKC4Z6Uah9AQZrtCn/ytqOgc//ChQRfJ6ozxovgads= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2/go.mod h1:wV7/BUV3BCLq5+E1bHXrKKt/eOPVdWgLArWLAq7rZ/U= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0 h1:poL/Hz3a6OHZ/eKtwMGm5nLqC3fEJjzPQlN/7/+mk8Y= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.0/go.mod h1:ssbyAHtxyuBvheMEItydM78/JxjDl3naUtllrC7ghDs= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0 h1:2d28WFQB9QB3af4uoPFglQDhH1LepEe6F2YoFCBecVI= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.0/go.mod h1:t77MA8uyEU9KZd1On5JpnxI3xhVPKIS8WutStqvU8Cw= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1 h1:h1TsWatlsexLeKdkb3L8chcxaXJOy/cLXctsRxhb4xg= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.1/go.mod h1:M4xZ2BnmROvLV2MrAP6A8o9BnyT0CkvpEcP8lBOfRs8= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.1.0 h1:Qj2Ild7NmHVm1rvPZg9Utc862sLJFiAfvRFLG0Qc+Uc= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.1.0/go.mod h1:V09NmPahuUiuZEogVPgxuVqqti0th5B7TVAjuiM09mE= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0 h1:pUl/981oAXPnZd7++69NfEWv6JwW9UpxER16XxQUdOk= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.0/go.mod h1:S04/QsQrB2EgYGjl62BO+9QUswrlRBoBosigrhdmccM= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 h1:hcHX2n5pUsOcv2PPPbSJph1fQ/I6P7g7781T1f1ycEI= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1/go.mod h1:jZwTg3wU4/UxgNJ7TKlFZ3dTIlnfvppnW8kJTc4UXy8= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1 h1:6kEct2wo84DlHkKJTNcUQbKAwARh/ugOTDR3x5mYCWc= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1/go.mod h1:dScCMWYbsf3B+c6a/5CFoVFcYLqHHkEEc622cHFtGGY= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.2.0 h1:rNlTSWShnlkW4vbBuJ3a1NPwQfN5H1+mpdjngLqFRdo= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.2.0/go.mod h1:UPPntEOhriZ4dZXEkjtfkGLFKvfA7Q/JAPG/zfwcoyc= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 h1:r5808lRhtY8l5anft/UwgJEaef1XsoYObmwd3FVai48= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1/go.mod h1:+LYy2pB+tpF0lkkmCf524wvv2Sa49REgEaNh7JGzN6Y= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From e97da4d92b704146fae207302b730ca88ea78428 Mon Sep 17 00:00:00 2001 From: Mauritz Uphoff <39736813+h3adex@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:56:48 +0200 Subject: [PATCH 390/619] feat(ske): add commands to trigger hibernate, wakeup maintenance, and reconcile (#873) relates to STACKITCLI-53 --------- Co-authored-by: Ruben Hoenle --- docs/stackit_ske_cluster.md | 10 +- docs/stackit_ske_cluster_create.md | 8 +- docs/stackit_ske_cluster_delete.md | 2 +- docs/stackit_ske_cluster_describe.md | 8 +- docs/stackit_ske_cluster_hibernate.md | 40 ++++ docs/stackit_ske_cluster_maintenance.md | 40 ++++ docs/stackit_ske_cluster_reconcile.md | 40 ++++ docs/stackit_ske_cluster_update.md | 6 +- docs/stackit_ske_cluster_wakeup.md | 40 ++++ docs/stackit_ske_kubeconfig.md | 2 +- docs/stackit_ske_kubeconfig_create.md | 4 +- go.mod | 2 +- go.sum | 4 +- internal/cmd/ske/cluster/cluster.go | 8 + internal/cmd/ske/cluster/create/create.go | 8 +- internal/cmd/ske/cluster/delete/delete.go | 2 +- internal/cmd/ske/cluster/describe/describe.go | 8 +- .../cmd/ske/cluster/hibernate/hibernate.go | 124 ++++++++++++ .../ske/cluster/hibernate/hibernate_test.go | 186 +++++++++++++++++ .../ske/cluster/maintenance/maintenance.go | 124 ++++++++++++ .../cluster/maintenance/maintenance_test.go | 187 ++++++++++++++++++ .../cmd/ske/cluster/reconcile/reconcile.go | 110 +++++++++++ .../ske/cluster/reconcile/reconcile_test.go | 187 ++++++++++++++++++ internal/cmd/ske/cluster/update/update.go | 6 +- internal/cmd/ske/cluster/wakeup/wakeup.go | 110 +++++++++++ .../cmd/ske/cluster/wakeup/wakeup_test.go | 185 +++++++++++++++++ internal/cmd/ske/kubeconfig/create/create.go | 4 +- internal/cmd/ske/ske.go | 6 +- 28 files changed, 1423 insertions(+), 38 deletions(-) create mode 100644 docs/stackit_ske_cluster_hibernate.md create mode 100644 docs/stackit_ske_cluster_maintenance.md create mode 100644 docs/stackit_ske_cluster_reconcile.md create mode 100644 docs/stackit_ske_cluster_wakeup.md create mode 100644 internal/cmd/ske/cluster/hibernate/hibernate.go create mode 100644 internal/cmd/ske/cluster/hibernate/hibernate_test.go create mode 100644 internal/cmd/ske/cluster/maintenance/maintenance.go create mode 100644 internal/cmd/ske/cluster/maintenance/maintenance_test.go create mode 100644 internal/cmd/ske/cluster/reconcile/reconcile.go create mode 100644 internal/cmd/ske/cluster/reconcile/reconcile_test.go create mode 100644 internal/cmd/ske/cluster/wakeup/wakeup.go create mode 100644 internal/cmd/ske/cluster/wakeup/wakeup_test.go diff --git a/docs/stackit_ske_cluster.md b/docs/stackit_ske_cluster.md index 7df9ba39e..a575e5495 100644 --- a/docs/stackit_ske_cluster.md +++ b/docs/stackit_ske_cluster.md @@ -30,10 +30,14 @@ stackit ske cluster [flags] ### SEE ALSO * [stackit ske](./stackit_ske.md) - Provides functionality for SKE -* [stackit ske cluster create](./stackit_ske_cluster_create.md) - Creates an SKE cluster +* [stackit ske cluster create](./stackit_ske_cluster_create.md) - Creates a SKE cluster * [stackit ske cluster delete](./stackit_ske_cluster_delete.md) - Deletes a SKE cluster -* [stackit ske cluster describe](./stackit_ske_cluster_describe.md) - Shows details of a SKE cluster +* [stackit ske cluster describe](./stackit_ske_cluster_describe.md) - Shows details of a SKE cluster * [stackit ske cluster generate-payload](./stackit_ske_cluster_generate-payload.md) - Generates a payload to create/update SKE clusters +* [stackit ske cluster hibernate](./stackit_ske_cluster_hibernate.md) - Trigger hibernate for a SKE cluster * [stackit ske cluster list](./stackit_ske_cluster_list.md) - Lists all SKE clusters -* [stackit ske cluster update](./stackit_ske_cluster_update.md) - Updates an SKE cluster +* [stackit ske cluster maintenance](./stackit_ske_cluster_maintenance.md) - Trigger maintenance for a SKE cluster +* [stackit ske cluster reconcile](./stackit_ske_cluster_reconcile.md) - Trigger reconcile for a SKE cluster +* [stackit ske cluster update](./stackit_ske_cluster_update.md) - Updates a SKE cluster +* [stackit ske cluster wakeup](./stackit_ske_cluster_wakeup.md) - Trigger wakeup from hibernation for a SKE cluster diff --git a/docs/stackit_ske_cluster_create.md b/docs/stackit_ske_cluster_create.md index fa4e0b492..3c94a7bdd 100644 --- a/docs/stackit_ske_cluster_create.md +++ b/docs/stackit_ske_cluster_create.md @@ -1,6 +1,6 @@ ## stackit ske cluster create -Creates an SKE cluster +Creates a SKE cluster ### Synopsis @@ -15,13 +15,13 @@ stackit ske cluster create CLUSTER_NAME [flags] ### Examples ``` - Create an SKE cluster using default configuration + Create a SKE cluster using default configuration $ stackit ske cluster create my-cluster - Create an SKE cluster using an API payload sourced from the file "./payload.json" + Create a SKE cluster using an API payload sourced from the file "./payload.json" $ stackit ske cluster create my-cluster --payload @./payload.json - Create an SKE cluster using an API payload provided as a JSON string + Create a SKE cluster using an API payload provided as a JSON string $ stackit ske cluster create my-cluster --payload "{...}" Generate a payload with default values, and adapt it with custom values for the different configuration options diff --git a/docs/stackit_ske_cluster_delete.md b/docs/stackit_ske_cluster_delete.md index ad2915d87..c1c0407a7 100644 --- a/docs/stackit_ske_cluster_delete.md +++ b/docs/stackit_ske_cluster_delete.md @@ -13,7 +13,7 @@ stackit ske cluster delete CLUSTER_NAME [flags] ### Examples ``` - Delete an SKE cluster with name "my-cluster" + Delete a SKE cluster with name "my-cluster" $ stackit ske cluster delete my-cluster ``` diff --git a/docs/stackit_ske_cluster_describe.md b/docs/stackit_ske_cluster_describe.md index eb30860a9..91b3949fc 100644 --- a/docs/stackit_ske_cluster_describe.md +++ b/docs/stackit_ske_cluster_describe.md @@ -1,10 +1,10 @@ ## stackit ske cluster describe -Shows details of a SKE cluster +Shows details of a SKE cluster ### Synopsis -Shows details of a STACKIT Kubernetes Engine (SKE) cluster. +Shows details of a STACKIT Kubernetes Engine (SKE) cluster. ``` stackit ske cluster describe CLUSTER_NAME [flags] @@ -13,10 +13,10 @@ stackit ske cluster describe CLUSTER_NAME [flags] ### Examples ``` - Get details of an SKE cluster with name "my-cluster" + Get details of a SKE cluster with name "my-cluster" $ stackit ske cluster describe my-cluster - Get details of an SKE cluster with name "my-cluster" in JSON format + Get details of a SKE cluster with name "my-cluster" in JSON format $ stackit ske cluster describe my-cluster --output-format json ``` diff --git a/docs/stackit_ske_cluster_hibernate.md b/docs/stackit_ske_cluster_hibernate.md new file mode 100644 index 000000000..20baddd1b --- /dev/null +++ b/docs/stackit_ske_cluster_hibernate.md @@ -0,0 +1,40 @@ +## stackit ske cluster hibernate + +Trigger hibernate for a SKE cluster + +### Synopsis + +Trigger hibernate for a STACKIT Kubernetes Engine (SKE) cluster. + +``` +stackit ske cluster hibernate CLUSTER_NAME [flags] +``` + +### Examples + +``` + Trigger hibernate for a SKE cluster with name "my-cluster" + $ stackit ske cluster hibernate my-cluster +``` + +### Options + +``` + -h, --help Help for "stackit ske cluster hibernate" +``` + +### 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 ske cluster](./stackit_ske_cluster.md) - Provides functionality for SKE cluster + diff --git a/docs/stackit_ske_cluster_maintenance.md b/docs/stackit_ske_cluster_maintenance.md new file mode 100644 index 000000000..0a6c6540c --- /dev/null +++ b/docs/stackit_ske_cluster_maintenance.md @@ -0,0 +1,40 @@ +## stackit ske cluster maintenance + +Trigger maintenance for a SKE cluster + +### Synopsis + +Trigger maintenance for a STACKIT Kubernetes Engine (SKE) cluster. + +``` +stackit ske cluster maintenance CLUSTER_NAME [flags] +``` + +### Examples + +``` + Trigger maintenance for a SKE cluster with name "my-cluster" + $ stackit ske cluster maintenance my-cluster +``` + +### Options + +``` + -h, --help Help for "stackit ske cluster maintenance" +``` + +### 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 ske cluster](./stackit_ske_cluster.md) - Provides functionality for SKE cluster + diff --git a/docs/stackit_ske_cluster_reconcile.md b/docs/stackit_ske_cluster_reconcile.md new file mode 100644 index 000000000..64887316d --- /dev/null +++ b/docs/stackit_ske_cluster_reconcile.md @@ -0,0 +1,40 @@ +## stackit ske cluster reconcile + +Trigger reconcile for a SKE cluster + +### Synopsis + +Trigger reconcile for a STACKIT Kubernetes Engine (SKE) cluster. + +``` +stackit ske cluster reconcile CLUSTER_NAME [flags] +``` + +### Examples + +``` + Trigger reconcile for a SKE cluster with name "my-cluster" + $ stackit ske cluster reconcile my-cluster +``` + +### Options + +``` + -h, --help Help for "stackit ske cluster reconcile" +``` + +### 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 ske cluster](./stackit_ske_cluster.md) - Provides functionality for SKE cluster + diff --git a/docs/stackit_ske_cluster_update.md b/docs/stackit_ske_cluster_update.md index 5209cc5df..24fa95748 100644 --- a/docs/stackit_ske_cluster_update.md +++ b/docs/stackit_ske_cluster_update.md @@ -1,6 +1,6 @@ ## stackit ske cluster update -Updates an SKE cluster +Updates a SKE cluster ### Synopsis @@ -15,10 +15,10 @@ stackit ske cluster update CLUSTER_NAME [flags] ### Examples ``` - Update an SKE cluster using an API payload sourced from the file "./payload.json" + Update a SKE cluster using an API payload sourced from the file "./payload.json" $ stackit ske cluster update my-cluster --payload @./payload.json - Update an SKE cluster using an API payload provided as a JSON string + Update a SKE cluster using an API payload provided as a JSON string $ stackit ske cluster update my-cluster --payload "{...}" Generate a payload with the current values of a cluster, and adapt it with custom values for the different configuration options diff --git a/docs/stackit_ske_cluster_wakeup.md b/docs/stackit_ske_cluster_wakeup.md new file mode 100644 index 000000000..7b07e9965 --- /dev/null +++ b/docs/stackit_ske_cluster_wakeup.md @@ -0,0 +1,40 @@ +## stackit ske cluster wakeup + +Trigger wakeup from hibernation for a SKE cluster + +### Synopsis + +Trigger wakeup from hibernation for a STACKIT Kubernetes Engine (SKE) cluster. + +``` +stackit ske cluster wakeup CLUSTER_NAME [flags] +``` + +### Examples + +``` + Trigger wakeup from hibernation for a SKE cluster with name "my-cluster" + $ stackit ske cluster wakeup my-cluster +``` + +### Options + +``` + -h, --help Help for "stackit ske cluster wakeup" +``` + +### 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 ske cluster](./stackit_ske_cluster.md) - Provides functionality for SKE cluster + diff --git a/docs/stackit_ske_kubeconfig.md b/docs/stackit_ske_kubeconfig.md index 5c7d3adf0..83634e149 100644 --- a/docs/stackit_ske_kubeconfig.md +++ b/docs/stackit_ske_kubeconfig.md @@ -30,6 +30,6 @@ stackit ske kubeconfig [flags] ### SEE ALSO * [stackit ske](./stackit_ske.md) - Provides functionality for SKE -* [stackit ske kubeconfig create](./stackit_ske_kubeconfig_create.md) - Creates or update a kubeconfig for an SKE cluster +* [stackit ske kubeconfig create](./stackit_ske_kubeconfig_create.md) - Creates or update a kubeconfig for a SKE cluster * [stackit ske kubeconfig login](./stackit_ske_kubeconfig_login.md) - Login plugin for kubernetes clients diff --git a/docs/stackit_ske_kubeconfig_create.md b/docs/stackit_ske_kubeconfig_create.md index d3d0e5622..c0f95423b 100644 --- a/docs/stackit_ske_kubeconfig_create.md +++ b/docs/stackit_ske_kubeconfig_create.md @@ -1,10 +1,10 @@ ## stackit ske kubeconfig create -Creates or update a kubeconfig for an SKE cluster +Creates or update a kubeconfig for a SKE cluster ### Synopsis -Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exits in the kubeconfig file the information will be updated. +Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exists in the kubeconfig file the information will be updated. By default, the kubeconfig information of the SKE cluster is merged into the default kubeconfig file of the current user. If the kubeconfig file doesn't exist, a new one will be created. You can override this behavior by specifying a custom filepath with the --filepath flag. diff --git a/go.mod b/go.mod index bba753a65..41c43fc2f 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 - github.com/stackitcloud/stackit-sdk-go/services/ske v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.26.0 diff --git a/go.sum b/go.sum index 82df7eb29..c344eaabc 100644 --- a/go.sum +++ b/go.sum @@ -609,8 +609,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1 h1:6kEct2w github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1/go.mod h1:dScCMWYbsf3B+c6a/5CFoVFcYLqHHkEEc622cHFtGGY= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.2.0 h1:rNlTSWShnlkW4vbBuJ3a1NPwQfN5H1+mpdjngLqFRdo= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.2.0/go.mod h1:UPPntEOhriZ4dZXEkjtfkGLFKvfA7Q/JAPG/zfwcoyc= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0 h1:hPCpRcWEzwzGONZJsKH+j2TjN1LRTH7Tp/q0TyzmL5M= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0/go.mod h1:jDYRbagjOwKEVsvkxdUErXIvvTOLw9WdBVjaXr5YOD8= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 h1:r5808lRhtY8l5anft/UwgJEaef1XsoYObmwd3FVai48= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1/go.mod h1:+LYy2pB+tpF0lkkmCf524wvv2Sa49REgEaNh7JGzN6Y= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= diff --git a/internal/cmd/ske/cluster/cluster.go b/internal/cmd/ske/cluster/cluster.go index 0158b7173..87994c2fa 100644 --- a/internal/cmd/ske/cluster/cluster.go +++ b/internal/cmd/ske/cluster/cluster.go @@ -6,8 +6,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/describe" generatepayload "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/generate-payload" + "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/hibernate" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/maintenance" + "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/reconcile" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/wakeup" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -33,4 +37,8 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(hibernate.NewCmd(params)) + cmd.AddCommand(maintenance.NewCmd(params)) + cmd.AddCommand(reconcile.NewCmd(params)) + cmd.AddCommand(wakeup.NewCmd(params)) } diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 557fb9a3a..af9ba2336 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -40,7 +40,7 @@ type inputModel struct { func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", clusterNameArg), - Short: "Creates an SKE cluster", + Short: "Creates a SKE cluster", Long: fmt.Sprintf("%s\n%s\n%s", "Creates a STACKIT Kubernetes Engine (SKE) cluster.", "The payload can be provided as a JSON string or a file path prefixed with \"@\".", @@ -49,13 +49,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { Args: args.SingleArg(clusterNameArg, nil), Example: examples.Build( examples.NewExample( - `Create an SKE cluster using default configuration`, + `Create a SKE cluster using default configuration`, "$ stackit ske cluster create my-cluster"), examples.NewExample( - `Create an SKE cluster using an API payload sourced from the file "./payload.json"`, + `Create a SKE cluster using an API payload sourced from the file "./payload.json"`, "$ stackit ske cluster create my-cluster --payload @./payload.json"), examples.NewExample( - `Create an SKE cluster using an API payload provided as a JSON string`, + `Create a SKE cluster using an API payload provided as a JSON string`, `$ stackit ske cluster create my-cluster --payload "{...}"`), examples.NewExample( `Generate a payload with default values, and adapt it with custom values for the different configuration options`, diff --git a/internal/cmd/ske/cluster/delete/delete.go b/internal/cmd/ske/cluster/delete/delete.go index b10871bfe..12068d9e3 100644 --- a/internal/cmd/ske/cluster/delete/delete.go +++ b/internal/cmd/ske/cluster/delete/delete.go @@ -35,7 +35,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { Args: args.SingleArg(clusterNameArg, nil), Example: examples.Build( examples.NewExample( - `Delete an SKE cluster with name "my-cluster"`, + `Delete a SKE cluster with name "my-cluster"`, "$ stackit ske cluster delete my-cluster"), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 40bf4897f..04d33baad 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -31,15 +31,15 @@ type inputModel struct { func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", clusterNameArg), - Short: "Shows details of a SKE cluster", - Long: "Shows details of a STACKIT Kubernetes Engine (SKE) cluster.", + Short: "Shows details of a SKE cluster", + Long: "Shows details of a STACKIT Kubernetes Engine (SKE) cluster.", Args: args.SingleArg(clusterNameArg, nil), Example: examples.Build( examples.NewExample( - `Get details of an SKE cluster with name "my-cluster"`, + `Get details of a SKE cluster with name "my-cluster"`, "$ stackit ske cluster describe my-cluster"), examples.NewExample( - `Get details of an SKE cluster with name "my-cluster" in JSON format`, + `Get details of a SKE cluster with name "my-cluster" in JSON format`, "$ stackit ske cluster describe my-cluster --output-format json"), ), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/cmd/ske/cluster/hibernate/hibernate.go b/internal/cmd/ske/cluster/hibernate/hibernate.go new file mode 100644 index 000000000..4c0be63ab --- /dev/null +++ b/internal/cmd/ske/cluster/hibernate/hibernate.go @@ -0,0 +1,124 @@ +package hibernate + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-sdk-go/services/ske" + "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" +) + +const ( + clusterNameArg = "CLUSTER_NAME" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ClusterName string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("hibernate %s", clusterNameArg), + Short: "Trigger hibernate for a SKE cluster", + Long: "Trigger hibernate for a STACKIT Kubernetes Engine (SKE) cluster.", + Args: args.SingleArg(clusterNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Trigger hibernate for a SKE cluster with name "my-cluster"`, + "$ stackit ske cluster hibernate my-cluster"), + ), + 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 + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to trigger hibernate for %q in project %q?", model.ClusterName, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("hibernate SKE cluster: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Hibernating cluster") + _, err = wait.TriggerClusterHibernationWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for SKE cluster hibernation: %w", err) + } + s.Stop() + } + + operationState := "Hibernated" + if model.Async { + operationState = "Triggered hibernation of" + } + params.Printer.Outputf("%s cluster %q\n", operationState, model.ClusterName) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + clusterName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ClusterName: clusterName, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerHibernateRequest { + req := apiClient.TriggerHibernate(ctx, model.ProjectId, model.Region, model.ClusterName) + return req +} diff --git a/internal/cmd/ske/cluster/hibernate/hibernate_test.go b/internal/cmd/ske/cluster/hibernate/hibernate_test.go new file mode 100644 index 000000000..d9d531ef1 --- /dev/null +++ b/internal/cmd/ske/cluster/hibernate/hibernate_test.go @@ -0,0 +1,186 @@ +package hibernate + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/ske" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu01" + testClusterName = "my-cluster" +) + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &ske.APIClient{} +var testProjectId = uuid.NewString() + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testClusterName, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +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, + }, + ClusterName: testClusterName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *ske.ApiTriggerHibernateRequest)) ske.ApiTriggerHibernateRequest { + request := testClient.TriggerHibernate(testCtx, testProjectId, testRegion, testClusterName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "missing project id", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + delete(fv, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "invalid project id - empty string", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + fv[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "invalid uuid format", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + fv[globalflags.ProjectIdFlag] = "not-a-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := &cobra.Command{} + 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) + } + } + + if len(tt.argValues) == 0 { + _, err := parseInput(p, cmd, tt.argValues) + if err == nil && !tt.isValid { + t.Fatalf("expected error due to missing args") + } + return + } + + 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:\n%s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest ske.ApiTriggerHibernateRequest + }{ + { + 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, + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(tt.expectedRequest), + ) + if diff != "" { + t.Fatalf("request mismatch:\n%s", diff) + } + }) + } +} diff --git a/internal/cmd/ske/cluster/maintenance/maintenance.go b/internal/cmd/ske/cluster/maintenance/maintenance.go new file mode 100644 index 000000000..3396ad7c3 --- /dev/null +++ b/internal/cmd/ske/cluster/maintenance/maintenance.go @@ -0,0 +1,124 @@ +package maintenance + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-sdk-go/services/ske" + "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" +) + +const ( + clusterNameArg = "CLUSTER_NAME" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ClusterName string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("maintenance %s", clusterNameArg), + Short: "Trigger maintenance for a SKE cluster", + Long: "Trigger maintenance for a STACKIT Kubernetes Engine (SKE) cluster.", + Args: args.SingleArg(clusterNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Trigger maintenance for a SKE cluster with name "my-cluster"`, + "$ stackit ske cluster maintenance my-cluster"), + ), + 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 + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to trigger maintenance for %q in project %q?", model.ClusterName, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("trigger maintenance SKE cluster: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Performing cluster maintenance") + _, err = wait.TriggerClusterMaintenanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for SKE cluster maintenance to complete: %w", err) + } + s.Stop() + } + + operationState := "Performed maintenance for" + if model.Async { + operationState = "Triggered maintenance for" + } + params.Printer.Outputf("%s cluster %q\n", operationState, model.ClusterName) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + clusterName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ClusterName: clusterName, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerMaintenanceRequest { + req := apiClient.TriggerMaintenance(ctx, model.ProjectId, model.Region, model.ClusterName) + return req +} diff --git a/internal/cmd/ske/cluster/maintenance/maintenance_test.go b/internal/cmd/ske/cluster/maintenance/maintenance_test.go new file mode 100644 index 000000000..fe0ab07cb --- /dev/null +++ b/internal/cmd/ske/cluster/maintenance/maintenance_test.go @@ -0,0 +1,187 @@ +package maintenance + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/ske" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu01" + testClusterName = "my-cluster" +) + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &ske.APIClient{} +var testProjectId = uuid.NewString() + +func fixtureArgValues(mods ...func([]string)) []string { + argValues := []string{ + testClusterName, + } + for _, m := range mods { + m(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + } + for _, m := range mods { + m(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(*inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + ClusterName: testClusterName, + } + for _, m := range mods { + m(model) + } + return model +} + +func fixtureRequest(mods ...func(*ske.ApiTriggerMaintenanceRequest)) ske.ApiTriggerMaintenanceRequest { + request := testClient.TriggerMaintenance(testCtx, testProjectId, testRegion, testClusterName) + for _, m := range mods { + m(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "missing project id", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + delete(fv, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "invalid project id - empty string", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + fv[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "invalid uuid format", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + fv[globalflags.ProjectIdFlag] = "not-a-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := &cobra.Command{} + 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) + } + } + + if len(tt.argValues) == 0 { + _, err := parseInput(p, cmd, tt.argValues) + if err == nil && !tt.isValid { + t.Fatalf("expected error due to missing args") + } + return + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %v", err) + } + + if !tt.isValid { + t.Fatalf("did not fail on invalid input") + } + + diff := cmp.Diff(model, tt.expectedModel) + if diff != "" { + t.Fatalf("input model mismatch:\n%s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest ske.ApiTriggerMaintenanceRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + got := buildRequest(testCtx, tt.model, testClient) + want := tt.expectedRequest + + diff := cmp.Diff(got, want, + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(want), + ) + if diff != "" { + t.Fatalf("request mismatch:\n%s", diff) + } + }) + } +} diff --git a/internal/cmd/ske/cluster/reconcile/reconcile.go b/internal/cmd/ske/cluster/reconcile/reconcile.go new file mode 100644 index 000000000..54c98dae0 --- /dev/null +++ b/internal/cmd/ske/cluster/reconcile/reconcile.go @@ -0,0 +1,110 @@ +package reconcile + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/ske/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-sdk-go/services/ske" + "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" +) + +const ( + clusterNameArg = "CLUSTER_NAME" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ClusterName string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("reconcile %s", clusterNameArg), + Short: "Trigger reconcile for a SKE cluster", + Long: "Trigger reconcile for a STACKIT Kubernetes Engine (SKE) cluster.", + Args: args.SingleArg(clusterNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Trigger reconcile for a SKE cluster with name "my-cluster"`, + "$ stackit ske cluster reconcile my-cluster"), + ), + 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 + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("reconcile SKE cluster: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Performing cluster reconciliation") + _, err = wait.TriggerClusterReconciliationWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for SKE cluster reconciliation: %w", err) + } + s.Stop() + } + + operationState := "Performed reconciliation for" + if model.Async { + operationState = "Triggered reconcile for" + } + params.Printer.Outputf("%s cluster %q\n", operationState, model.ClusterName) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + clusterName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ClusterName: clusterName, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerReconcileRequest { + req := apiClient.TriggerReconcile(ctx, model.ProjectId, model.Region, model.ClusterName) + return req +} diff --git a/internal/cmd/ske/cluster/reconcile/reconcile_test.go b/internal/cmd/ske/cluster/reconcile/reconcile_test.go new file mode 100644 index 000000000..5c96f295b --- /dev/null +++ b/internal/cmd/ske/cluster/reconcile/reconcile_test.go @@ -0,0 +1,187 @@ +package reconcile + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/ske" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu01" + testClusterName = "my-cluster" +) + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &ske.APIClient{} +var testProjectId = uuid.NewString() + +func fixtureArgValues(mods ...func([]string)) []string { + argValues := []string{ + testClusterName, + } + for _, m := range mods { + m(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + } + for _, m := range mods { + m(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(*inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + ClusterName: testClusterName, + } + for _, m := range mods { + m(model) + } + return model +} + +func fixtureRequest(mods ...func(request *ske.ApiTriggerReconcileRequest)) ske.ApiTriggerHibernateRequest { + request := testClient.TriggerReconcile(testCtx, testProjectId, testRegion, testClusterName) + for _, m := range mods { + m(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "missing project id", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + delete(fv, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "invalid project id - empty string", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + fv[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "invalid uuid format", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + fv[globalflags.ProjectIdFlag] = "not-a-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := &cobra.Command{} + 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) + } + } + + if len(tt.argValues) == 0 { + _, err := parseInput(p, cmd, tt.argValues) + if err == nil && !tt.isValid { + t.Fatalf("expected error due to missing args") + } + return + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error parsing input: %v", err) + } + + if !tt.isValid { + t.Fatalf("did not fail on invalid input") + } + + diff := cmp.Diff(model, tt.expectedModel) + if diff != "" { + t.Fatalf("input model mismatch:\n%s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest ske.ApiTriggerHibernateRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + got := buildRequest(testCtx, tt.model, testClient) + want := tt.expectedRequest + + diff := cmp.Diff(got, want, + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(want), + ) + if diff != "" { + t.Fatalf("request mismatch:\n%s", diff) + } + }) + } +} diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index 420c06349..8c32f8d95 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -37,7 +37,7 @@ type inputModel struct { func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", clusterNameArg), - Short: "Updates an SKE cluster", + Short: "Updates a SKE cluster", Long: fmt.Sprintf("%s\n%s\n%s", "Updates a STACKIT Kubernetes Engine (SKE) cluster.", "The payload can be provided as a JSON string or a file path prefixed with \"@\".", @@ -46,10 +46,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { Args: args.SingleArg(clusterNameArg, nil), Example: examples.Build( examples.NewExample( - `Update an SKE cluster using an API payload sourced from the file "./payload.json"`, + `Update a SKE cluster using an API payload sourced from the file "./payload.json"`, "$ stackit ske cluster update my-cluster --payload @./payload.json"), examples.NewExample( - `Update an SKE cluster using an API payload provided as a JSON string`, + `Update a SKE cluster using an API payload provided as a JSON string`, `$ stackit ske cluster update my-cluster --payload "{...}"`), examples.NewExample( `Generate a payload with the current values of a cluster, and adapt it with custom values for the different configuration options`, diff --git a/internal/cmd/ske/cluster/wakeup/wakeup.go b/internal/cmd/ske/cluster/wakeup/wakeup.go new file mode 100644 index 000000000..e7b9b6534 --- /dev/null +++ b/internal/cmd/ske/cluster/wakeup/wakeup.go @@ -0,0 +1,110 @@ +package wakeup + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/ske/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-sdk-go/services/ske" + "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" +) + +const ( + clusterNameArg = "CLUSTER_NAME" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ClusterName string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("wakeup %s", clusterNameArg), + Short: "Trigger wakeup from hibernation for a SKE cluster", + Long: "Trigger wakeup from hibernation for a STACKIT Kubernetes Engine (SKE) cluster.", + Args: args.SingleArg(clusterNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Trigger wakeup from hibernation for a SKE cluster with name "my-cluster"`, + "$ stackit ske cluster wakeup my-cluster"), + ), + 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 + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("wakeup SKE cluster: %w", err) + } + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Performing cluster wakeup") + _, err = wait.TriggerClusterWakeupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for SKE cluster wakeup: %w", err) + } + s.Stop() + } + + operationState := "Performed wakeup of" + if model.Async { + operationState = "Triggered wakeup of" + } + params.Printer.Outputf("%s cluster %q\n", operationState, model.ClusterName) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + clusterName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ClusterName: clusterName, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClient) ske.ApiTriggerWakeupRequest { + req := apiClient.TriggerWakeup(ctx, model.ProjectId, model.Region, model.ClusterName) + return req +} diff --git a/internal/cmd/ske/cluster/wakeup/wakeup_test.go b/internal/cmd/ske/cluster/wakeup/wakeup_test.go new file mode 100644 index 000000000..dd93881c1 --- /dev/null +++ b/internal/cmd/ske/cluster/wakeup/wakeup_test.go @@ -0,0 +1,185 @@ +package wakeup + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/ske" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu01" + testClusterName = "my-cluster" +) + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &ske.APIClient{} +var testProjectId = uuid.NewString() + +func fixtureArgValues(mods ...func([]string)) []string { + argValues := []string{testClusterName} + for _, m := range mods { + m(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(map[string]string)) map[string]string { + flags := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + } + for _, m := range mods { + m(flags) + } + return flags +} + +func fixtureInputModel(mods ...func(*inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + ClusterName: testClusterName, + } + for _, m := range mods { + m(model) + } + return model +} + +func fixtureRequest(mods ...func(*ske.ApiTriggerWakeupRequest)) ske.ApiTriggerWakeupRequest { + req := testClient.TriggerWakeup(testCtx, testProjectId, testRegion, testClusterName) + for _, m := range mods { + m(&req) + } + return req +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "missing project id", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + delete(fv, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "invalid project id - empty string", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + fv[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "invalid uuid format", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(fv map[string]string) { + fv[globalflags.ProjectIdFlag] = "not-a-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := &cobra.Command{} + 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) + } + } + + if len(tt.argValues) == 0 { + _, err := parseInput(p, cmd, tt.argValues) + if err == nil && !tt.isValid { + t.Fatalf("expected failure due to missing args") + } + return + } + + model, err := parseInput(p, cmd, tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("unexpected error: %v", err) + } + + if !tt.isValid { + t.Fatalf("did not fail on invalid input") + } + + diff := cmp.Diff(model, tt.expectedModel) + if diff != "" { + t.Fatalf("input model mismatch:\n%s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest ske.ApiTriggerHibernateRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + got := buildRequest(testCtx, tt.model, testClient) + want := tt.expectedRequest + + diff := cmp.Diff(got, want, + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(want), + ) + if diff != "" { + t.Fatalf("request mismatch:\n%s", diff) + } + }) + } +} diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index fe2907958..681b74db9 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -44,9 +44,9 @@ type inputModel struct { func NewCmd(params *params.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", clusterNameArg), - Short: "Creates or update a kubeconfig for an SKE cluster", + Short: "Creates or update a kubeconfig for a SKE cluster", Long: fmt.Sprintf("%s\n\n%s\n%s\n%s\n%s", - "Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exits in the kubeconfig file the information will be updated.", + "Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exists in the kubeconfig file the information will be updated.", "By default, the kubeconfig information of the SKE cluster is merged into the default kubeconfig file of the current user. If the kubeconfig file doesn't exist, a new one will be created.", "You can override this behavior by specifying a custom filepath with the --filepath flag.\n", "An expiration time can be set for the kubeconfig. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 1h.\n", diff --git a/internal/cmd/ske/ske.go b/internal/cmd/ske/ske.go index 137165e06..e782119db 100644 --- a/internal/cmd/ske/ske.go +++ b/internal/cmd/ske/ske.go @@ -28,11 +28,11 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(cluster.NewCmd(params)) + cmd.AddCommand(credentials.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(disable.NewCmd(params)) cmd.AddCommand(enable.NewCmd(params)) cmd.AddCommand(kubeconfig.NewCmd(params)) - cmd.AddCommand(disable.NewCmd(params)) - cmd.AddCommand(cluster.NewCmd(params)) - cmd.AddCommand(credentials.NewCmd(params)) cmd.AddCommand(options.NewCmd(params)) } From 9e9e67deec7fc1c4a5f184fe1c423e716dc267a3 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 29 Jul 2025 12:05:02 +0200 Subject: [PATCH 391/619] chore(deps): update renovatebot/github-action action to v43.0.5 (#897) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index df77823ed..01da40dbf 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.4 + uses: renovatebot/github-action@v43.0.5 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 2446141aa4db825ac913b6915fe6b396b344711b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 12:16:10 +0200 Subject: [PATCH 392/619] chore(deps): bump github.com/jedib0t/go-pretty/v6 from 6.6.7 to 6.6.8 (#896) Bumps [github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty) from 6.6.7 to 6.6.8. - [Release notes](https://github.com/jedib0t/go-pretty/releases) - [Commits](https://github.com/jedib0t/go-pretty/compare/v6.6.7...v6.6.8) --- updated-dependencies: - dependency-name: github.com/jedib0t/go-pretty/v6 dependency-version: 6.6.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 41c43fc2f..6b73d2617 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.7 + github.com/jedib0t/go-pretty/v6 v6.6.8 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.9.1 diff --git a/go.sum b/go.sum index c344eaabc..503f66c59 100644 --- a/go.sum +++ b/go.sum @@ -342,8 +342,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo= -github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.6.8 h1:JnnzQeRz2bACBobIaa/r+nqjvws4yEhcmaZ4n1QzsEc= +github.com/jedib0t/go-pretty/v6 v6.6.8/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From db88d79c3b6feeffea01497d1a2be5f1dfa0e13b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 17:15:16 +0200 Subject: [PATCH 393/619] chore(deps): bump github.com/golang-jwt/jwt/v5 from 5.2.3 to 5.3.0 (#901) Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.2.3 to 5.3.0. - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md) - [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.3...v5.3.0) --- updated-dependencies: - dependency-name: github.com/golang-jwt/jwt/v5 dependency-version: 5.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6b73d2617..a2d00487f 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24 require ( github.com/fatih/color v1.18.0 github.com/goccy/go-yaml v1.18.0 - github.com/golang-jwt/jwt/v5 v5.2.3 + github.com/golang-jwt/jwt/v5 v5.3.0 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf diff --git a/go.sum b/go.sum index 503f66c59..dd2f02561 100644 --- a/go.sum +++ b/go.sum @@ -222,8 +222,8 @@ github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeH github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= -github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= From 7ba5ffc69f07ba72d8acd61d7aab7c7a5d84de77 Mon Sep 17 00:00:00 2001 From: Kevin Gimbel Date: Mon, 4 Aug 2025 11:21:45 +0200 Subject: [PATCH 394/619] feat(ske): respect KUBECONFIG environment variable (#876) relates to #875 --- docs/stackit_ske_kubeconfig_create.md | 4 +- internal/cmd/ske/kubeconfig/create/create.go | 4 +- internal/pkg/services/ske/utils/utils.go | 6 ++- internal/pkg/services/ske/utils/utils_test.go | 45 +++++++++++++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/docs/stackit_ske_kubeconfig_create.md b/docs/stackit_ske_kubeconfig_create.md index c0f95423b..476d50bab 100644 --- a/docs/stackit_ske_kubeconfig_create.md +++ b/docs/stackit_ske_kubeconfig_create.md @@ -7,7 +7,7 @@ Creates or update a kubeconfig for a SKE cluster Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exists in the kubeconfig file the information will be updated. By default, the kubeconfig information of the SKE cluster is merged into the default kubeconfig file of the current user. If the kubeconfig file doesn't exist, a new one will be created. -You can override this behavior by specifying a custom filepath with the --filepath flag. +You can override this behavior by specifying a custom filepath using the --filepath flag or by setting the KUBECONFIG env variable (fallback). An expiration time can be set for the kubeconfig. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 1h. @@ -47,7 +47,7 @@ stackit ske kubeconfig create CLUSTER_NAME [flags] ``` --disable-writing Disable the writing of kubeconfig. Set the output format to json or yaml using the --output-format flag to display the kubeconfig. -e, --expiration string Expiration time for the kubeconfig in seconds(s), minutes(m), hours(h), days(d) or months(M). Example: 30d. By default, expiration time is 1h - --filepath string Path to create the kubeconfig file. By default, the kubeconfig is created as 'config' in the .kube folder, in the user's home directory. + --filepath string Path to create the kubeconfig file. Will fall back to KUBECONFIG env variable if not set. In case both aren't set, the kubeconfig is created as file named 'config' in the .kube folder in the user's home directory. -h, --help Help for "stackit ske kubeconfig create" -l, --login Create a login kubeconfig that obtains valid credentials via the STACKIT CLI. This flag is mutually exclusive with the expiration flag. --overwrite Overwrite the kubeconfig file. diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index 681b74db9..f420009f0 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -48,7 +48,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { Long: fmt.Sprintf("%s\n\n%s\n%s\n%s\n%s", "Creates a kubeconfig for a STACKIT Kubernetes Engine (SKE) cluster, if the config exists in the kubeconfig file the information will be updated.", "By default, the kubeconfig information of the SKE cluster is merged into the default kubeconfig file of the current user. If the kubeconfig file doesn't exist, a new one will be created.", - "You can override this behavior by specifying a custom filepath with the --filepath flag.\n", + "You can override this behavior by specifying a custom filepath using the --filepath flag or by setting the KUBECONFIG env variable (fallback).\n", "An expiration time can be set for the kubeconfig. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 1h.\n", "Note that the format is , e.g. 30d for 30 days and you can't combine units."), Args: args.SingleArg(clusterNameArg, nil), @@ -170,7 +170,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(disableWritingFlag, false, fmt.Sprintf("Disable the writing of kubeconfig. Set the output format to json or yaml using the --%s flag to display the kubeconfig.", globalflags.OutputFormatFlag)) cmd.Flags().BoolP(loginFlag, "l", false, "Create a login kubeconfig that obtains valid credentials via the STACKIT CLI. This flag is mutually exclusive with the expiration flag.") - cmd.Flags().String(filepathFlag, "", "Path to create the kubeconfig file. By default, the kubeconfig is created as 'config' in the .kube folder, in the user's home directory.") + cmd.Flags().String(filepathFlag, "", "Path to create the kubeconfig file. Will fall back to KUBECONFIG env variable if not set. In case both aren't set, the kubeconfig is created as file named 'config' in the .kube folder in the user's home directory.") cmd.Flags().StringP(expirationFlag, "e", "", "Expiration time for the kubeconfig in seconds(s), minutes(m), hours(h), days(d) or months(M). Example: 30d. By default, expiration time is 1h") cmd.Flags().Bool(overwriteFlag, false, "Overwrite the kubeconfig file.") cmd.MarkFlagsMutuallyExclusive(loginFlag, expirationFlag) diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 4c5604fc4..605ca4158 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -284,8 +284,12 @@ func WriteConfigFile(configPath, data string) error { return nil } -// GetDefaultKubeconfigPath returns the default location for the kubeconfig file. +// GetDefaultKubeconfigPath returns the default location for the kubeconfig file or the value of KUBECONFIG if set. func GetDefaultKubeconfigPath() (string, error) { + if kubeconfigEnv := os.Getenv("KUBECONFIG"); kubeconfigEnv != "" { + return kubeconfigEnv, nil + } + userHome, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("get user home directory: %w", err) diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index 27b9b8d6a..917d590ae 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -698,3 +698,48 @@ func TestGetDefaultKubeconfigPath(t *testing.T) { }) } } + +func TestGetDefaultKubeconfigPathWithEnvVar(t *testing.T) { + tests := []struct { + description string + kubeconfigEnvVar string + expected string + userHome string + }{ + { + description: "base", + kubeconfigEnvVar: "~/.kube/custom/config", + expected: "~/.kube/custom/config", + userHome: "/home/test-user", + }, + { + description: "return user home when environment var is empty", + kubeconfigEnvVar: "", + expected: "/home/test-user/.kube/config", + userHome: "/home/test-user", + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + // Setup environment variables + err := os.Setenv("KUBECONFIG", tt.kubeconfigEnvVar) + if err != nil { + t.Errorf("could not set KUBECONFIG environment variable: %s", err) + } + err = os.Setenv("HOME", tt.userHome) + if err != nil { + t.Errorf("could not set HOME environment variable: %s", err) + } + + output, err := GetDefaultKubeconfigPath() + + if err != nil { + t.Errorf("failed on valid input") + } + if output != tt.expected { + t.Errorf("expected output to be %s, got %s", tt.expected, output) + } + }) + } +} From 8c7662401a6f33b1e11d6439068efd40a8069bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:43:45 +0200 Subject: [PATCH 395/619] fix(cli): stackit auth get-access-token does not work as expected (#922) --- .../cmd/auth/get-access-token/get_access_token.go | 3 +-- internal/pkg/auth/auth.go | 15 +++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index 5e5b9d60b..c0c59e294 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -44,8 +44,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return &cliErr.SessionExpiredError{} } - // Try to get a valid access token, refreshing if necessary - accessToken, err := auth.RefreshAccessToken(params.Printer) + accessToken, err := auth.GetValidAccessToken(params.Printer) if err != nil { return err } diff --git a/internal/pkg/auth/auth.go b/internal/pkg/auth/auth.go index 634813f24..9a9b48817 100644 --- a/internal/pkg/auth/auth.go +++ b/internal/pkg/auth/auth.go @@ -134,15 +134,22 @@ func getEmailFromToken(token string) (string, error) { return claims.Email, nil } -// RefreshAccessToken refreshes the access token if it's expired for the user token flow. -// It returns the new access token or an error if the refresh fails. -func RefreshAccessToken(p *print.Printer) (string, error) { +// GetValidAccessToken returns a valid access token for the current authentication flow. +// For user token flows, it refreshes the token if necessary. +// For service account flows, it returns the current access token. +func GetValidAccessToken(p *print.Printer) (string, error) { flow, err := GetAuthFlow() if err != nil { return "", fmt.Errorf("get authentication flow: %w", err) } + + // For service account flows, just return the current token + if flow == AUTH_FLOW_SERVICE_ACCOUNT_TOKEN || flow == AUTH_FLOW_SERVICE_ACCOUNT_KEY { + return GetAccessToken() + } + if flow != AUTH_FLOW_USER_TOKEN { - return "", fmt.Errorf("token refresh is only supported for user token flow, current flow: %s", flow) + return "", fmt.Errorf("unsupported authentication flow: %s", flow) } // Load tokens from storage From 5d8c4ee6c222fd6370573ee385fdae4858da1ef5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 13 Aug 2025 08:51:02 +0200 Subject: [PATCH 396/619] chore(deps): update module golang.org/x/tools to v0.36.0 (#911) Co-authored-by: Renovate Bot --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index a2d00487f..bc5fc121a 100644 --- a/go.mod +++ b/go.mod @@ -34,16 +34,16 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.26.0 + golang.org/x/mod v0.27.0 golang.org/x/oauth2 v0.30.0 - golang.org/x/term v0.33.0 - golang.org/x/text v0.27.0 + golang.org/x/term v0.34.0 + golang.org/x/text v0.28.0 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 ) require ( - golang.org/x/net v0.42.0 // indirect + golang.org/x/net v0.43.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -207,7 +207,7 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.16.0 // indirect - golang.org/x/tools v0.35.0 // indirect + golang.org/x/tools v0.36.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect google.golang.org/protobuf v1.36.6 // indirect @@ -247,7 +247,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.34.0 // indirect + golang.org/x/sys v0.35.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.32.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index dd2f02561..f8def98fa 100644 --- a/go.sum +++ b/go.sum @@ -753,8 +753,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= -golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -795,8 +795,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -873,8 +873,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -883,8 +883,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= -golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -897,8 +897,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -962,8 +962,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= From 99134f70ababe7c51d82a586d9d5364d192a9031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 09:16:42 +0200 Subject: [PATCH 397/619] chore(deps): bump renovatebot/github-action from 43.0.5 to 43.0.7 (#919) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 43.0.5 to 43.0.7. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v43.0.5...v43.0.7) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 43.0.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 01da40dbf..b6365adf9 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.5 + uses: renovatebot/github-action@v43.0.7 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 6e065f64a586c846771447b5e2afd4941f5fcbcc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 09:25:41 +0200 Subject: [PATCH 398/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serviceaccount (#917) Bumps [github.com/stackitcloud/stackit-sdk-go/services/serviceaccount](https://github.com/stackitcloud/stackit-sdk-go) from 0.9.1 to 0.11.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/dns/v0.9.1...services/ske/v0.11.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/serviceaccount dependency-version: 0.11.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bc5fc121a..17a2b8e21 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 diff --git a/go.sum b/go.sum index f8def98fa..91a0cc7bb 100644 --- a/go.sum +++ b/go.sum @@ -605,8 +605,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 h1:tfKC4Z6Ua github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2/go.mod h1:wV7/BUV3BCLq5+E1bHXrKKt/eOPVdWgLArWLAq7rZ/U= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 h1:hcHX2n5pUsOcv2PPPbSJph1fQ/I6P7g7781T1f1ycEI= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1/go.mod h1:jZwTg3wU4/UxgNJ7TKlFZ3dTIlnfvppnW8kJTc4UXy8= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1 h1:6kEct2wo84DlHkKJTNcUQbKAwARh/ugOTDR3x5mYCWc= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.9.1/go.mod h1:dScCMWYbsf3B+c6a/5CFoVFcYLqHHkEEc622cHFtGGY= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0 h1:u0PjbKDuIVOMm9hyxLeqSM51ExtJXJ+TdSJT5hDW6wk= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0/go.mod h1:QCrAW/Rmf+styT25ke8cUV6hDHpdKNmAY14kkJ3+Fd8= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0 h1:hPCpRcWEzwzGONZJsKH+j2TjN1LRTH7Tp/q0TyzmL5M= From 7869a21826b361ca9f57daac41cee2e57c21dd01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 09:34:52 +0200 Subject: [PATCH 399/619] chore(deps): bump actions/checkout from 4 to 5 (#920) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 4 ++-- .github/workflows/release.yaml | 2 +- .github/workflows/renovate.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 50d71d17b..a9a3dd3fa 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Install go uses: actions/setup-go@v5 @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Check GoReleaser uses: goreleaser/goreleaser-action@v6 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 09d8ce121..1954acadd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -26,7 +26,7 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.OBJECT_STORAGE_SECRET_ACCESS_KEY }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: # Allow goreleaser to access older tag information. fetch-depth: 0 diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index b6365adf9..fcc641580 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Self-hosted Renovate uses: renovatebot/github-action@v43.0.7 with: From b4ddc7990392a3440f8dbc1b5f7d40d19dc41f21 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 13 Aug 2025 10:56:45 +0200 Subject: [PATCH 400/619] fix(deps): update stackit sdk modules (#903) * fix(deps): update stackit sdk modules * chore(linter): fix linter issues for image and volume Signed-off-by: Alexander Dahmen --------- Signed-off-by: Alexander Dahmen Co-authored-by: Renovate Bot Co-authored-by: Alexander Dahmen --- go.mod | 6 +++--- go.sum | 12 ++++++------ internal/cmd/image/list/list.go | 3 ++- internal/cmd/volume/list/list.go | 3 ++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 17a2b8e21..7fe1a21be 100644 --- a/go.mod +++ b/go.mod @@ -20,8 +20,8 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.0 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 @@ -242,7 +242,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.1 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 91a0cc7bb..0fac107be 100644 --- a/go.sum +++ b/go.sum @@ -573,20 +573,20 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4r github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 h1:hkFixFnBcQzU4BSIZFITc8N0gK0pUYk7mk0wdUu5Ki8= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1/go.mod h1:Ng1EzrRndG3iGXGH90AZJz//wfK+2YOyDwTnTLwX3a4= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1 h1:0RP8DCwSCbl0KBsRI6INFy/8JW7UqlAd2Yr3dWFS3No= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.27.1/go.mod h1:TvqL/TgVrrdDF387gAhO8QQYLxiaOZwgpmyv6s15TU0= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.0 h1:j4FKFOVkcTot8xNxpvDsPzIFyjADE4GxXF0rFE6/Uo4= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.0/go.mod h1:b/jgJf7QHdRzU2fmZeJJtu5j0TAevDRghzcn5MyRmOI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 h1:OdJEs8eOfrzn9tCBDLxIyP8hX50zPfcXNYnRoQX+chs= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1/go.mod h1:11uzaOPCF9SeDHXEGOPMlHDD3J5r2TnvCGUwW9Igq9c= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1/go.mod h1:ivt8lvnAoBZsde2jSAuicyn6RgTmHvvNAJ3whaUbAD4= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 h1:Db/ebOL2vbpIeh5XB2Ews2B9Lj5DJlMWIEJh60FfZ4Y= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1/go.mod h1:8jdN4v2euK3f9gfdzbRi8e4nBJ8g/Q5YF9aPB4M4fCQ= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1 h1:XOpikSY2IXfBJPzUdgBk69iJXFC99xzfYtY1h4bZ5vM= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.1/go.mod h1:G7S/hGa6EyX5Avxxw/PIdbdtbFeiXL/T1vUkPOJ120w= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/aGHepE/+gVsvSg1sRkPOyIUI/jkCyUOrWg= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.1 h1:eSiUKN61FJ4x42vgIvhVU7bgmrPbj05xR4y0nnRV5Yg= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.9.1/go.mod h1:oJku0heeBwsy4IToqhvSdPJI++GUNkBSESxOjiLWRVQ= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0 h1:SIctDqGprEoZArWaTds7hzQyh8Pqaz95Nmuj/1QuDEQ= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index 67e0c951c..57280b383 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -166,7 +166,8 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) err default: table := tables.NewTable() table.SetHeader("ID", "NAME", "OS", "ARCHITECTURE", "DISTRIBUTION", "VERSION", "LABELS") - for _, item := range items { + for i := range items { + item := items[i] var ( architecture string = "n/a" os string = "n/a" diff --git a/internal/cmd/volume/list/list.go b/internal/cmd/volume/list/list.go index 7534bb4a3..aac08c50b 100644 --- a/internal/cmd/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -167,7 +167,8 @@ func outputResult(p *print.Printer, outputFormat string, volumes []iaas.Volume) table := tables.NewTable() table.SetHeader("ID", "Name", "Status", "Server", "Availability Zone", "Size (GB)") - for _, volume := range volumes { + for i := range volumes { + volume := volumes[i] table.AddRow( utils.PtrString(volume.Id), utils.PtrString(volume.Name), From 0ac494e8b64004bc6d07aed6b688f9163160163e Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 13 Aug 2025 11:06:20 +0200 Subject: [PATCH 401/619] feat(ske): show cluster errors in table output (#907) Signed-off-by: Lukas Hoehl Co-authored-by: Benjosh95 --- internal/cmd/ske/cluster/describe/describe.go | 19 ++ .../cmd/ske/cluster/describe/describe_test.go | 179 ++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 04d33baad..a983f442e 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/goccy/go-yaml" "github.com/spf13/cobra" @@ -131,11 +132,15 @@ func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) e if cluster.HasStatus() { table.AddRow("STATE", utils.PtrString(cluster.Status.Aggregated)) table.AddSeparator() + if clusterErrs := cluster.Status.GetErrors(); len(clusterErrs) != 0 { + handleClusterErrors(clusterErrs, &table) + } } if cluster.Kubernetes != nil { table.AddRow("VERSION", utils.PtrString(cluster.Kubernetes.Version)) table.AddSeparator() } + table.AddRow("ACL", acl) err := table.Display(p) if err != nil { @@ -145,3 +150,17 @@ func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) e return nil } } + +func handleClusterErrors(clusterErrs []ske.ClusterError, table *tables.Table) { + errs := make([]string, 0, len(clusterErrs)) + for _, e := range clusterErrs { + b := new(strings.Builder) + fmt.Fprint(b, e.GetCode()) + if msg, ok := e.GetMessageOk(); ok { + fmt.Fprintf(b, ": %s", msg) + } + errs = append(errs, b.String()) + } + table.AddRow("ERRORS", strings.Join(errs, "\n")) + table.AddSeparator() +} diff --git a/internal/cmd/ske/cluster/describe/describe_test.go b/internal/cmd/ske/cluster/describe/describe_test.go index df33417ff..a5f7f766e 100644 --- a/internal/cmd/ske/cluster/describe/describe_test.go +++ b/internal/cmd/ske/cluster/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -234,6 +235,184 @@ func TestOutputResult(t *testing.T) { }, wantErr: false, }, + { + name: "cluster with single error", + args: args{ + outputFormat: "", + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Status: &ske.ClusterStatus{ + Errors: &[]ske.ClusterError{ + { + Code: utils.Ptr("SKE_INFRA_SNA_NETWORK_NOT_FOUND"), + Message: utils.Ptr("Network configuration not found"), + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "cluster with multiple errors", + args: args{ + outputFormat: "", + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Status: &ske.ClusterStatus{ + Errors: &[]ske.ClusterError{ + { + Code: utils.Ptr("SKE_INFRA_SNA_NETWORK_NOT_FOUND"), + Message: utils.Ptr("Network configuration not found"), + }, + { + Code: utils.Ptr("SKE_NODE_MACHINE_TYPE_NOT_FOUND"), + Message: utils.Ptr("Specified machine type unavailable"), + }, + { + Code: utils.Ptr("SKE_FETCHING_ERRORS_NOT_POSSIBLE"), + Message: utils.Ptr("Fetching errors not possible"), + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "cluster with error but no message", + args: args{ + outputFormat: "", + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Status: &ske.ClusterStatus{ + Errors: &[]ske.ClusterError{ + { + Code: utils.Ptr("SKE_FETCHING_ERRORS_NOT_POSSIBLE"), + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "cluster with nil errors", + args: args{ + outputFormat: "", + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Status: &ske.ClusterStatus{ + Errors: nil, + }, + }, + }, + wantErr: false, + }, + { + name: "cluster with empty errors array", + args: args{ + outputFormat: "", + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Status: &ske.ClusterStatus{ + Errors: &[]ske.ClusterError{}, + }, + }, + }, + wantErr: false, + }, + { + name: "cluster without status", + args: args{ + outputFormat: "", + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + }, + }, + wantErr: false, + }, + { + name: "JSON output format with errors", + args: args{ + outputFormat: print.JSONOutputFormat, + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Status: &ske.ClusterStatus{ + Errors: &[]ske.ClusterError{ + { + Code: utils.Ptr("SKE_INFRA_SNA_NETWORK_NOT_FOUND"), + Message: utils.Ptr("Network configuration not found"), + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "YAML output format with errors", + args: args{ + outputFormat: print.YAMLOutputFormat, + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Status: &ske.ClusterStatus{ + Errors: &[]ske.ClusterError{ + { + Code: utils.Ptr("SKE_INFRA_SNA_NETWORK_NOT_FOUND"), + Message: utils.Ptr("Network configuration not found"), + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "cluster with kubernetes info and errors", + args: args{ + outputFormat: "", + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Kubernetes: &ske.Kubernetes{ + Version: utils.Ptr("1.28.0"), + }, + Status: &ske.ClusterStatus{ + Errors: &[]ske.ClusterError{ + { + Code: utils.Ptr("SKE_INFRA_SNA_NETWORK_NOT_FOUND"), + Message: utils.Ptr("Network configuration not found"), + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "cluster with extensions and errors", + args: args{ + outputFormat: "", + cluster: &ske.Cluster{ + Name: utils.Ptr("test-cluster"), + Extensions: &ske.Extension{ + Acl: &ske.ACL{ + AllowedCidrs: &[]string{"10.0.0.0/8"}, + Enabled: utils.Ptr(true), + }, + }, + Status: &ske.ClusterStatus{ + Errors: &[]ske.ClusterError{ + { + Code: utils.Ptr("SKE_INFRA_SNA_NETWORK_NOT_FOUND"), + Message: utils.Ptr("Network configuration not found"), + }, + }, + }, + }, + }, + wantErr: false, + }, } p := print.NewPrinter() p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) From 343c352d249218f3f8fc34502bed6a721b16e2b4 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 18 Aug 2025 08:16:26 +0200 Subject: [PATCH 402/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.29.1 (#927) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7fe1a21be..125b89639 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.1 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 diff --git a/go.sum b/go.sum index 0fac107be..25bb26a89 100644 --- a/go.sum +++ b/go.sum @@ -573,8 +573,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4r github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 h1:hkFixFnBcQzU4BSIZFITc8N0gK0pUYk7mk0wdUu5Ki8= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1/go.mod h1:Ng1EzrRndG3iGXGH90AZJz//wfK+2YOyDwTnTLwX3a4= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.0 h1:j4FKFOVkcTot8xNxpvDsPzIFyjADE4GxXF0rFE6/Uo4= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.0/go.mod h1:b/jgJf7QHdRzU2fmZeJJtu5j0TAevDRghzcn5MyRmOI= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.1 h1:GfE+FaeIKSVaKvgzh8Eacum+bQVyRS6ngltkh0qNGtM= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.1/go.mod h1:b/jgJf7QHdRzU2fmZeJJtu5j0TAevDRghzcn5MyRmOI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 h1:OdJEs8eOfrzn9tCBDLxIyP8hX50zPfcXNYnRoQX+chs= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1/go.mod h1:11uzaOPCF9SeDHXEGOPMlHDD3J5r2TnvCGUwW9Igq9c= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= From 97596bdf3960ce5889d0b42a0cf46e10e0177db3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 10:45:44 +0200 Subject: [PATCH 403/619] chore(deps): bump renovatebot/github-action from 43.0.7 to 43.0.8 (#929) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 43.0.7 to 43.0.8. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v43.0.7...v43.0.8) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 43.0.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index fcc641580..f2578c438 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.7 + uses: renovatebot/github-action@v43.0.8 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From eb7c321b89ab97628e2b2ce5468cab7874b1db6b Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Wed, 20 Aug 2025 09:11:12 +0200 Subject: [PATCH 404/619] chore(image): add example how to create an image with uefi disabled (#926) Signed-off-by: Alexander Dahmen --- docs/stackit_image_create.md | 3 +++ internal/cmd/image/create/create.go | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/docs/stackit_image_create.md b/docs/stackit_image_create.md index 1dbfc5278..eb8a0a3e9 100644 --- a/docs/stackit_image_create.md +++ b/docs/stackit_image_create.md @@ -18,6 +18,9 @@ stackit image create [flags] Create an image with name 'my-new-image' from a qcow2 image read from '/my/qcow2/image' with labels describing its contents $ stackit image create --name my-new-image --disk-format=qcow2 --local-file-path=/my/qcow2/image --labels os=linux,distro=alpine,version=3.12 + + Create an image with name 'my-new-image' from a raw disk image located in '/my/raw/image' with uefi disabled + $ stackit image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image --uefi=false ``` ### Options diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 0e0a84cbb..3ffe26a68 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -99,6 +99,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create an image with name 'my-new-image' from a qcow2 image read from '/my/qcow2/image' with labels describing its contents`, `$ stackit image create --name my-new-image --disk-format=qcow2 --local-file-path=/my/qcow2/image --labels os=linux,distro=alpine,version=3.12`, ), + examples.NewExample( + `Create an image with name 'my-new-image' from a raw disk image located in '/my/raw/image' with uefi disabled`, + `$ stackit image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image --uefi=false`, + ), ), RunE: func(cmd *cobra.Command, _ []string) (err error) { ctx := context.Background() From df2b82470fe667ef1006cf51546c23dd52a4220d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:59:46 +0200 Subject: [PATCH 405/619] fix: remove access_token prefix from YAML output in get-access-token (#933) --- .../cmd/auth/get-access-token/get_access_token.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index c0c59e294..f5040d85c 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -59,16 +58,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } params.Printer.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(map[string]string{ - "access_token": accessToken, - }, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal image list: %w", err) - } - params.Printer.Outputln(string(details)) - return nil default: params.Printer.Outputln(accessToken) From d21ed69650453fe3aab6524a4d37c96932826a2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Aug 2025 13:46:13 +0200 Subject: [PATCH 406/619] chore(deps): bump renovatebot/github-action from 43.0.8 to 43.0.9 (#936) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 43.0.8 to 43.0.9. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v43.0.8...v43.0.9) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 43.0.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index f2578c438..4d8f2595d 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.8 + uses: renovatebot/github-action@v43.0.9 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 4bcfd896eb07c9730052b3ceb9e856e2ed4f07b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 08:52:41 +0200 Subject: [PATCH 407/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/observability (#938) Bumps [github.com/stackitcloud/stackit-sdk-go/services/observability](https://github.com/stackitcloud/stackit-sdk-go) from 0.10.0 to 0.11.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.10.0...services/ske/v0.11.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/observability dependency-version: 0.11.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 125b89639..cd28f9a4c 100644 --- a/go.mod +++ b/go.mod @@ -242,7 +242,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 25bb26a89..c9c76e334 100644 --- a/go.sum +++ b/go.sum @@ -585,8 +585,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/a github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0 h1:SIctDqGprEoZArWaTds7hzQyh8Pqaz95Nmuj/1QuDEQ= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.10.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.1 h1:y4CfGRNRGdAV3i6+ATIHsr+n6+As5kL9GBXO7FK6gy8= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.1/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= From 798c0c31448dabf4ae622ae438ada654ba7f1788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 28 Aug 2025 09:07:21 +0200 Subject: [PATCH 408/619] chore(scripts): use bash found in path in shebang (#937) --- scripts/check-docs.sh | 2 +- scripts/publish-apt-packages.sh | 2 +- scripts/replace.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/check-docs.sh b/scripts/check-docs.sh index d81181db9..cb2058804 100755 --- a/scripts/check-docs.sh +++ b/scripts/check-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is used to ensure for PRs the docs are up-to-date via the CI pipeline # Usage: ./check-docs.sh diff --git a/scripts/publish-apt-packages.sh b/scripts/publish-apt-packages.sh index f6ec84174..9766afcd6 100755 --- a/scripts/publish-apt-packages.sh +++ b/scripts/publish-apt-packages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is used to publish new packages to the CLI APT repository # Usage: ./publish-apt-packages.sh diff --git a/scripts/replace.sh b/scripts/replace.sh index 0c37f4b85..9326b1f72 100755 --- a/scripts/replace.sh +++ b/scripts/replace.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Add replace directives to local files to go.work set -eo pipefail From a0eee4ef7bbed38042fa10dc99d0533166671142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 29 Aug 2025 10:53:42 +0200 Subject: [PATCH 409/619] fix(ske): print valid json output when listing clusters (#940) also print valid json output when project has no ske clusters relates to STACKITCLI-240 --- internal/cmd/root.go | 3 +-- internal/cmd/ske/cluster/list/list.go | 26 +++++++++++++--------- internal/cmd/ske/cluster/list/list_test.go | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 750bdfa9a..5803cccbe 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -6,8 +6,6 @@ import ( "strings" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - affinityGroups "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups" "github.com/stackitcloud/stackit-cli/internal/cmd/auth" "github.com/stackitcloud/stackit-cli/internal/cmd/beta" @@ -28,6 +26,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch" "github.com/stackitcloud/stackit-cli/internal/cmd/organization" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex" "github.com/stackitcloud/stackit-cli/internal/cmd/project" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip" diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 31b8f2b7b..8c357924a 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -85,22 +85,21 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("get SKE clusters: %w", err) } clusters := *resp.Items - if len(clusters) == 0 { - 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 - } - params.Printer.Info("No clusters found for project %q\n", projectLabel) - return nil - } // Truncate output if model.Limit != nil && len(clusters) > int(*model.Limit) { clusters = clusters[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, clusters) + projectLabel := model.ProjectId + if len(clusters) == 0 { + projectLabel, err = projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) + } + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, clusters) }, } @@ -148,7 +147,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie return req } -func outputResult(p *print.Printer, outputFormat string, clusters []ske.Cluster) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, clusters []ske.Cluster) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(clusters, "", " ") @@ -167,6 +166,11 @@ func outputResult(p *print.Printer, outputFormat string, clusters []ske.Cluster) return nil default: + if len(clusters) == 0 { + p.Outputf("No clusters found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("NAME", "STATE", "VERSION", "POOLS", "MONITORING") for i := range clusters { diff --git a/internal/cmd/ske/cluster/list/list_test.go b/internal/cmd/ske/cluster/list/list_test.go index e3c1a063c..4f0543544 100644 --- a/internal/cmd/ske/cluster/list/list_test.go +++ b/internal/cmd/ske/cluster/list/list_test.go @@ -226,7 +226,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.clusters); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, "dummy-projectlabel", tt.args.clusters); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From 79cd1483a508b0e1a20692aeff3f0cbcfe8da22c Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 29 Aug 2025 10:59:29 +0200 Subject: [PATCH 410/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.29.2 (#943) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cd28f9a4c..a0e80ac11 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.1 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.2 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 diff --git a/go.sum b/go.sum index c9c76e334..2b64ce4e2 100644 --- a/go.sum +++ b/go.sum @@ -573,8 +573,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4r github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 h1:hkFixFnBcQzU4BSIZFITc8N0gK0pUYk7mk0wdUu5Ki8= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1/go.mod h1:Ng1EzrRndG3iGXGH90AZJz//wfK+2YOyDwTnTLwX3a4= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.1 h1:GfE+FaeIKSVaKvgzh8Eacum+bQVyRS6ngltkh0qNGtM= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.1/go.mod h1:b/jgJf7QHdRzU2fmZeJJtu5j0TAevDRghzcn5MyRmOI= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.2 h1:BvrbqLi9u0943TTkflPDLGbXgqgVzv7oy8tZHD3q3lg= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.2/go.mod h1:b/jgJf7QHdRzU2fmZeJJtu5j0TAevDRghzcn5MyRmOI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 h1:OdJEs8eOfrzn9tCBDLxIyP8hX50zPfcXNYnRoQX+chs= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1/go.mod h1:11uzaOPCF9SeDHXEGOPMlHDD3J5r2TnvCGUwW9Igq9c= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= From 388abee418c70594ad6d0bac422923e847ee45f7 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Tue, 2 Sep 2025 10:13:52 +0200 Subject: [PATCH 411/619] fix(goreleaser): Remove conflicts configuration for homebrew_casks (#945) - remove conflicts_with formula because it is deprecated https://goreleaser.com/deprecations/#homebrew_casksconflictsformula --- .goreleaser.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index f8c772377..8808082eb 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -117,8 +117,6 @@ signs: homebrew_casks: - name: stackit directory: Casks - conflicts: - - formula: stackit repository: owner: stackitcloud name: homebrew-tap From cc2cad24985a18ce6828b5834e73af806970dc50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 09:52:33 +0000 Subject: [PATCH 412/619] chore(deps): bump github.com/spf13/cobra from 1.9.1 to 1.10.1 (#947) --- go.mod | 4 ++-- go.sum | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index a0e80ac11..04b8031de 100644 --- a/go.mod +++ b/go.mod @@ -12,8 +12,8 @@ require ( github.com/jedib0t/go-pretty/v6 v6.6.8 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 - github.com/spf13/cobra v1.9.1 - github.com/spf13/pflag v1.0.7 + github.com/spf13/cobra v1.10.1 + github.com/spf13/pflag v1.0.9 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1 diff --git a/go.sum b/go.sum index 2b64ce4e2..f1e88abfa 100644 --- a/go.sum +++ b/go.sum @@ -553,12 +553,11 @@ github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= -github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= From 825589e247a2f51144f336ce8f9ca722648da981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 10:14:46 +0000 Subject: [PATCH 413/619] chore(deps): bump renovatebot/github-action from 43.0.9 to 43.0.10 (#950) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 4d8f2595d..31c9cb47a 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.9 + uses: renovatebot/github-action@v43.0.10 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From b260b7bd96cee2b7d2b0216c6854f6c58ff41a1d Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 3 Sep 2025 14:19:49 +0200 Subject: [PATCH 414/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/observability to v0.12.0 (#951) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 04b8031de..c2e599b9e 100644 --- a/go.mod +++ b/go.mod @@ -242,7 +242,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.1 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index f1e88abfa..6b21cebd3 100644 --- a/go.sum +++ b/go.sum @@ -584,8 +584,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/a github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.1 h1:y4CfGRNRGdAV3i6+ATIHsr+n6+As5kL9GBXO7FK6gy8= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.11.1/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.12.0 h1:myi6k4LQJJGaMGwzBKp5hlatrCNNf8FR+/gqnzxnGb8= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.12.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= From ab54d0923296ba9003bb6a4464027b0feb8a1ded Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 3 Sep 2025 14:27:51 +0200 Subject: [PATCH 415/619] fix(deps): update module github.com/spf13/pflag to v1.0.10 (#948) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index c2e599b9e..91ba08b53 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.1 - github.com/spf13/pflag v1.0.9 + github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.20.1 github.com/stackitcloud/stackit-sdk-go/core v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1 diff --git a/go.sum b/go.sum index 6b21cebd3..a2aa99036 100644 --- a/go.sum +++ b/go.sum @@ -556,8 +556,9 @@ github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cA github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= From 9dfc1f315fc2921537d93e84e36b36fa01a68bbd Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Wed, 3 Sep 2025 17:30:02 +0200 Subject: [PATCH 416/619] fix: update aptly in release pipeline (#953) * workaround for aptly isn't needed anymore - segmentation fault was fixed in 1.6.1 --- .github/workflows/release.yaml | 7 ++---- aptly.rb | 40 ---------------------------------- 2 files changed, 2 insertions(+), 45 deletions(-) delete mode 100644 aptly.rb diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1954acadd..597131ecb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -61,11 +61,8 @@ jobs: APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} SIGNING_CERTIFICATE_BASE64: ${{ secrets.APPLICATION_ID_CERT }} AUTHKEY_BASE64: ${{ secrets.APPLE_API_KEY }} - # aptly version 1.6.0 results in an segmentation fault. Therefore we fall back to version 1.5.0. - # Since it is not possible to specify a version via brew command a formula was added for aptly 1.5.0 - # (source: https://github.com/Homebrew/homebrew-core/pull/202415/files) - - name: Install Aptly version 1.5.0 - run: brew install aptly.rb + - name: Install Aptly + run: brew install aptly - name: Install Snapcraft uses: samuelmeuli/action-snapcraft@v3 - name: Run GoReleaser diff --git a/aptly.rb b/aptly.rb deleted file mode 100644 index 8b1f49727..000000000 --- a/aptly.rb +++ /dev/null @@ -1,40 +0,0 @@ -class Aptly < Formula - desc "Swiss army knife for Debian repository management" - homepage "https://www.aptly.info/" - url "https://github.com/aptly-dev/aptly/archive/refs/tags/v1.5.0.tar.gz" - sha256 "07e18ce606feb8c86a1f79f7f5dd724079ac27196faa61a2cefa5b599bbb5bb1" - license "MIT" - head "https://github.com/aptly-dev/aptly.git", branch: "master" - - bottle do - rebuild 2 - sha256 cellar: :any_skip_relocation, arm64_sequoia: "f689184731329b1c22f23af361e31cd8aa6992084434d49281227654281a8f45" - sha256 cellar: :any_skip_relocation, arm64_sonoma: "0d022b595e520ea53e23b1dfceb4a45139e7e2ba735994196135c1f9c1a36d4c" - sha256 cellar: :any_skip_relocation, arm64_ventura: "c6fa91fb368a63d5558b8c287b330845e04f90bd4fe7223e161493b01747c869" - sha256 cellar: :any_skip_relocation, arm64_monterey: "19c0c8c0b35c1c5faa2a71fc0bd088725f5623f465369dcca5b2cea59322714c" - sha256 cellar: :any_skip_relocation, arm64_big_sur: "2314abe4aae7ea53660920d311cacccd168045994e1a9eddf12a381b215c1908" - sha256 cellar: :any_skip_relocation, sonoma: "0f077e265538e235ad867b39edc756180c8a0fba7ac5385ab59b18e827519f4c" - sha256 cellar: :any_skip_relocation, ventura: "d132d06243b93952309f3fbe1970d87cde272ea103cf1829c880c1b8a85a12cb" - sha256 cellar: :any_skip_relocation, monterey: "86111a102d0782a77bab0d48015bd275f120a36964d86f8f613f1a8f73d94664" - sha256 cellar: :any_skip_relocation, big_sur: "d622cfe1d925f0058f583b8bf48b0bdcee36a441f1bcf145040e5f93879f8765" - sha256 cellar: :any_skip_relocation, catalina: "5d9d495ec8215cfade3e856528dfa233496849517813b19a9ba8d60cb72c4751" - sha256 cellar: :any_skip_relocation, x86_64_linux: "bbff5503f74ef5dcaae33846e285ecf1a23c23de1c858760ae1789ef6fc99524" - end - - depends_on "go" => :build - - def install - system "go", "generate" if build.head? - system "go", "build", *std_go_args(ldflags: "-s -w -X main.Version=#{version}") - - bash_completion.install "completion.d/aptly" - end - - test do - assert_match "aptly version:", shell_output("#{bin}/aptly version") - - (testpath/".aptly.conf").write("{}") - result = shell_output("#{bin}/aptly -config='#{testpath}/.aptly.conf' mirror list") - assert_match "No mirrors found, create one with", result - end -end \ No newline at end of file From dc56c93ec588b30b44719323ef74f868808399a2 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 4 Sep 2025 13:15:01 +0200 Subject: [PATCH 417/619] fix: s3 publish endpoint could not be parsed (#956) --- .aptly.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.aptly.conf b/.aptly.conf index cbea3aee1..deb53174e 100644 --- a/.aptly.conf +++ b/.aptly.conf @@ -25,7 +25,7 @@ "region": "eu01", "bucket": "distribution", "acl":"public-read", - "endpoint": "object.storage.eu01.onstackit.cloud" + "endpoint": "https://object.storage.eu01.onstackit.cloud" } }, "SwiftPublishEndpoints": {}, From d088df6a2ed13a66a5a6488ef0e90869c36f81c4 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:40:23 +0200 Subject: [PATCH 418/619] fix: release pipeline increase max-tries in download of mirror (#957) --- scripts/publish-apt-packages.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/publish-apt-packages.sh b/scripts/publish-apt-packages.sh index 9766afcd6..02227d012 100755 --- a/scripts/publish-apt-packages.sh +++ b/scripts/publish-apt-packages.sh @@ -27,7 +27,7 @@ aptly mirror create -config "${APTLY_CONFIG_FILE_PATH}" -keyring="${CUSTOM_KEYRI # Update the mirror to the latest state printf "\n>>> Updating mirror \n" -aptly mirror update -keyring="${CUSTOM_KEYRING_FILE}" current +aptly mirror update -keyring="${CUSTOM_KEYRING_FILE}" -max-tries=5 current # Create a snapshot of the mirror printf "\n>>> Creating snapshop from mirror \n" From b373f14508150e3d0412fc07d1f1c24791a4615f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 4 Sep 2025 16:25:38 +0200 Subject: [PATCH 419/619] chore(ci/cd): split apt publishing from release pipeline (#958) --- .github/workflows/release.yaml | 47 +++++++++++++++++++++++++++++---- scripts/publish-apt-packages.sh | 2 -- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 597131ecb..0b91843fd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -21,26 +21,26 @@ jobs: runs-on: macOS-latest env: SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }} - # Needed to publish new packages to our S3-hosted APT repo - AWS_ACCESS_KEY_ID: ${{ secrets.OBJECT_STORAGE_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.OBJECT_STORAGE_SECRET_ACCESS_KEY }} steps: - name: Checkout uses: actions/checkout@v5 with: # Allow goreleaser to access older tag information. fetch-depth: 0 + - name: Install go uses: actions/setup-go@v5 with: go-version-file: "go.mod" cache: true + - name: Import GPG key uses: crazy-max/ghaction-import-gpg@v6 id: import_gpg with: gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.GPG_PASSPHRASE }} + - name: Set up keychain run: | echo -n $SIGNING_CERTIFICATE_BASE64 | base64 -d -o ./ApplicationID.p12 @@ -61,10 +61,9 @@ jobs: APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} SIGNING_CERTIFICATE_BASE64: ${{ secrets.APPLICATION_ID_CERT }} AUTHKEY_BASE64: ${{ secrets.APPLE_API_KEY }} - - name: Install Aptly - run: brew install aptly - name: Install Snapcraft uses: samuelmeuli/action-snapcraft@v3 + - name: Run GoReleaser uses: goreleaser/goreleaser-action@v6 with: @@ -72,6 +71,44 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.CLI_RELEASE }} GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} + + # artifacts need to be passed to the "publish-apt" job somehow + - name: Upload artifacts to workflow + uses: actions/upload-artifact@v4 + with: + name: goreleaser-dist-temp + path: dist + retention-days: 1 + + publish-apt: + name: Publish APT + runs-on: ubuntu-latest + needs: [goreleaser] + env: + # Needed to publish new packages to our S3-hosted APT repo + AWS_ACCESS_KEY_ID: ${{ secrets.OBJECT_STORAGE_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.OBJECT_STORAGE_SECRET_ACCESS_KEY }} + steps: + - name: Checkout + uses: actions/checkout@v5 + + # use the artifacts from the "goreleaser" job + - name: Download artifacts from workflow + uses: actions/download-artifact@v4 + with: + name: goreleaser-dist-temp + path: dist + + - name: Install Aptly + run: brew install aptly + + - name: Import GPG key + uses: crazy-max/ghaction-import-gpg@v6 + id: import_gpg + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + - name: Publish packages to APT repo if: contains(github.ref_name, '-') == false env: diff --git a/scripts/publish-apt-packages.sh b/scripts/publish-apt-packages.sh index 02227d012..9d122d80b 100755 --- a/scripts/publish-apt-packages.sh +++ b/scripts/publish-apt-packages.sh @@ -4,8 +4,6 @@ # Usage: ./publish-apt-packages.sh set -eo pipefail -ROOT_DIR=$(git rev-parse --show-toplevel) - PACKAGES_BUCKET_URL="https://packages.stackit.cloud" PUBLIC_KEY_FILE_PATH="keys/key.gpg" APT_REPO_PATH="apt/cli" From c9d95ae938e9c2420443d730516a89098889f47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 4 Sep 2025 16:53:46 +0200 Subject: [PATCH 420/619] fix(ci/cd): use correct runner type for apt publishing (#962) --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0b91843fd..191e9a1e2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -82,7 +82,7 @@ jobs: publish-apt: name: Publish APT - runs-on: ubuntu-latest + runs-on: macOS-latest needs: [goreleaser] env: # Needed to publish new packages to our S3-hosted APT repo From 0cb04b68e2fc6d1cc2f1530d13332a6bb35a5a08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 17:11:49 +0200 Subject: [PATCH 421/619] chore(deps): bump actions/stale from 9 to 10 (#959) Bumps [actions/stale](https://github.com/actions/stale) from 9 to 10. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v9...v10) --- updated-dependencies: - dependency-name: actions/stale dependency-version: '10' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 3ee54f0da..f5e745a71 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -23,7 +23,7 @@ jobs: timeout-minutes: 10 steps: - name: "Mark old PRs as stale" - uses: actions/stale@v9 + uses: actions/stale@v10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: "This PR was marked as stale after ${{ env.DAYS_BEFORE_PR_STALE }} days of inactivity and will be closed after another ${{ env.DAYS_BEFORE_PR_CLOSE }} days of further inactivity. If this PR should be kept open, just add a comment, remove the stale label or push new commits to it." From b3eb402fe4db01021fbbab8d3cc047211f0d8671 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:18:40 +0000 Subject: [PATCH 422/619] chore(deps): bump actions/setup-go from 5 to 6 (#960) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-go dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a9a3dd3fa..6311125ba 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v5 - name: Install go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version-file: "go.mod" cache: true diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 191e9a1e2..da7d76f13 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -29,7 +29,7 @@ jobs: fetch-depth: 0 - name: Install go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version-file: "go.mod" cache: true From 9c9876636d1ae5fae8226916ebc38fad286eafa8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 08:14:29 +0000 Subject: [PATCH 423/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/observability (#961) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 91ba08b53..9169c13d8 100644 --- a/go.mod +++ b/go.mod @@ -242,7 +242,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.12.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.13.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index a2aa99036..6fd451a8f 100644 --- a/go.sum +++ b/go.sum @@ -585,8 +585,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/a github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.12.0 h1:myi6k4LQJJGaMGwzBKp5hlatrCNNf8FR+/gqnzxnGb8= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.12.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.13.0 h1:nlWoD5DhHmyd1oWVcmvWebNy1T4hoWv3GfwbqDGR0w4= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.13.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= From b6db9f831ce537274928ae4f5eee13ce6c392784 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 5 Sep 2025 10:24:16 +0200 Subject: [PATCH 424/619] chore(cli): Move STACKIT CLI to GA (#944) Signed-off-by: Alexander Dahmen --- .goreleaser.yaml | 6 +++--- INSTALLATION.md | 2 +- README.md | 3 +-- docs/stackit.md | 3 +-- internal/cmd/root.go | 4 ++-- internal/pkg/auth/templates/login-successful.html | 2 +- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 8808082eb..9f9ae85c1 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -124,7 +124,7 @@ homebrew_casks: name: CLI Release Bot email: noreply@stackit.de homepage: "https://github.com/stackitcloud/stackit-cli" - description: "A command-line interface to manage STACKIT resources.\nThis CLI is in a beta state. More services and functionality will be supported soon." + description: "A command-line interface to manage STACKIT resources." license: "Apache-2.0" # If set to auto, the release will not be uploaded to the homebrew tap repo # if the tag has a prerelease indicator (e.g. v0.0.1-alpha1) @@ -144,12 +144,12 @@ snapcrafts: # centre graphical frontends title: STACKIT CLI summary: A command-line interface to manage STACKIT resources. - description: "A command-line interface to manage STACKIT resources.\nThis CLI is in a beta state. More services and functionality will be supported soon." + description: "A command-line interface to manage STACKIT resources." license: Apache-2.0 confinement: classic # Grade "devel" will only release to `edge` and `beta` channels # Grade "stable" will also release to the `candidate` and `stable` channels - grade: devel + grade: stable # Whether to publish the Snap to the store publish: true diff --git a/INSTALLATION.md b/INSTALLATION.md index 965ceddf9..3a5045149 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -67,7 +67,7 @@ $ stackit config profile import -c @default.json --name myProfile The STACKIT CLI is available as a [Snap](https://snapcraft.io/stackit), and can be installed via: ```shell -sudo snap install stackit --beta --classic +sudo snap install stackit --classic ``` or via the [Snap Store](https://snapcraft.io/snap-store) for desktop. diff --git a/README.md b/README.md index fad966e7b..56fa01bcf 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@
-# STACKIT CLI (BETA) +# STACKIT CLI [![Go Report Card](https://goreportcard.com/badge/github.com/stackitcloud/stackit-cli)](https://goreportcard.com/report/github.com/stackitcloud/stackit-cli) ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/stackitcloud/stackit-cli) [![GitHub License](https://img.shields.io/github/license/stackitcloud/stackit-cli)](https://www.apache.org/licenses/LICENSE-2.0) @@ -19,7 +19,6 @@ The STACKIT CLI allows you to manage your STACKIT services and resources as well - DNS zones and record-sets - Databases such as PostgreSQL Flex, MongoDB Flex and SQLServer Flex -This CLI is in a BETA state. More services and functionality will be supported soon. Your feedback is appreciated! Feel free to open [GitHub issues](https://github.com/stackitcloud/stackit-cli) to provide feature requests and bug reports. diff --git a/docs/stackit.md b/docs/stackit.md index 3cc35f2f9..d0ddc4554 100644 --- a/docs/stackit.md +++ b/docs/stackit.md @@ -5,8 +5,7 @@ Manage STACKIT resources using the command line ### Synopsis Manage STACKIT resources using the command line. -This CLI is in a BETA state. -More services and functionality will be supported soon. Your feedback is appreciated! +Your feedback is appreciated! ``` stackit [flags] diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 5803cccbe..4e0ac6ea9 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -54,7 +54,7 @@ func NewRootCmd(version, date string, p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "stackit", Short: "Manage STACKIT resources using the command line", - Long: "Manage STACKIT resources using the command line.\nThis CLI is in a BETA state.\nMore services and functionality will be supported soon. Your feedback is appreciated!", + Long: "Manage STACKIT resources using the command line.\nYour feedback is appreciated!", Args: args.NoArgs, SilenceErrors: true, // Error is beautified in a custom way before being printed SilenceUsage: true, @@ -97,7 +97,7 @@ func NewRootCmd(version, date string, p *print.Printer) *cobra.Command { }, RunE: func(cmd *cobra.Command, _ []string) error { if flags.FlagToBoolValue(p, cmd, "version") { - p.Outputf("STACKIT CLI (beta)\n") + p.Outputf("STACKIT CLI\n") parsedDate, err := time.Parse(time.RFC3339, date) if err != nil { diff --git a/internal/pkg/auth/templates/login-successful.html b/internal/pkg/auth/templates/login-successful.html index d8519cad0..3e2d0a5ba 100644 --- a/internal/pkg/auth/templates/login-successful.html +++ b/internal/pkg/auth/templates/login-successful.html @@ -6,7 +6,7 @@ From 9ab6e2a6c079301e81418c8f06a62d3f1a6a7061 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Fri, 5 Sep 2025 10:31:50 +0200 Subject: [PATCH 425/619] docs: add the envs `STACKIT_SERVICE_ACCOUNT_KEY` and `STACKIT_PRIVATE_KEY` to AUTHENTICATION.md (#963) --- AUTHENTICATION.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/AUTHENTICATION.md b/AUTHENTICATION.md index 1ec7ea3ba..1cf3003f8 100644 --- a/AUTHENTICATION.md +++ b/AUTHENTICATION.md @@ -92,7 +92,12 @@ The expected format of the service account key is a **json** with the following > - setting the environment variable `STACKIT_PRIVATE_KEY_PATH` > - setting `STACKIT_PRIVATE_KEY_PATH` in the credentials file (see above) -4. The CLI will search for the keys and, if valid, will use them to get access and refresh tokens which will be used to authenticate all the requests. +4. Alternative, if you want to pass the keys directly without storing a file on disk: + + - setting the environment variable `STACKIT_SERVICE_ACCOUNT_KEY` with the content of the service account key + - optional: setting the environment variable `STACKIT_PRIVATE_KEY` with the content of the private key + +5. The CLI will search for the keys and, if valid, will use them to get access and refresh tokens which will be used to authenticate all the requests. ### Token flow From 411d8d4b2b5ae3335feedc328ee61cf585f413f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:00:48 +0200 Subject: [PATCH 426/619] chore(deps): bump actions/download-artifact from 4 to 5 (#967) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index da7d76f13..0760269ed 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -94,7 +94,7 @@ jobs: # use the artifacts from the "goreleaser" job - name: Download artifacts from workflow - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: goreleaser-dist-temp path: dist From eb2399bab5e6d0e642ada0493691194db33113d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 14:06:37 +0000 Subject: [PATCH 427/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/observability (#965) Bumps [github.com/stackitcloud/stackit-sdk-go/services/observability](https://github.com/stackitcloud/stackit-sdk-go) from 0.13.0 to 0.14.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.13.0...core/v0.14.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/observability dependency-version: 0.14.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9169c13d8..f16df32e0 100644 --- a/go.mod +++ b/go.mod @@ -242,7 +242,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.13.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 6fd451a8f..3178c8536 100644 --- a/go.sum +++ b/go.sum @@ -585,8 +585,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/a github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.13.0 h1:nlWoD5DhHmyd1oWVcmvWebNy1T4hoWv3GfwbqDGR0w4= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.13.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0 h1:oewwaYjABWbNqDkmSwIXmjDBK4a46+tnznyZSXh3Xk0= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= From e925b899f8c69d89cc11d887cd542bbc20ee68ee Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 8 Sep 2025 09:54:03 +0200 Subject: [PATCH 428/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/ske to v1.4.0 (#968) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f16df32e0..c487eca06 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 - github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.27.0 diff --git a/go.sum b/go.sum index 3178c8536..00b66a78c 100644 --- a/go.sum +++ b/go.sum @@ -609,8 +609,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0 h1:u0PjbK github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0/go.mod h1:QCrAW/Rmf+styT25ke8cUV6hDHpdKNmAY14kkJ3+Fd8= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0 h1:hPCpRcWEzwzGONZJsKH+j2TjN1LRTH7Tp/q0TyzmL5M= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.3.0/go.mod h1:jDYRbagjOwKEVsvkxdUErXIvvTOLw9WdBVjaXr5YOD8= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 h1:V6RFvybDeJvvmT3g7/BZodF0gozz3TEpahbpiTftbeY= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0/go.mod h1:xRBgpJ8P5Nf1T5tD0tGAeNg1FNQzx5VF7qqOXt2Fp3s= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 h1:r5808lRhtY8l5anft/UwgJEaef1XsoYObmwd3FVai48= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1/go.mod h1:+LYy2pB+tpF0lkkmCf524wvv2Sa49REgEaNh7JGzN6Y= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= From 97e4b55a979e676180762a8c0beff28ac95a0063 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 16:10:39 +0200 Subject: [PATCH 429/619] chore(deps): bump renovatebot/github-action from 43.0.10 to 43.0.11 (#973) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 43.0.10 to 43.0.11. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v43.0.10...v43.0.11) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 43.0.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 31c9cb47a..a986c4930 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.10 + uses: renovatebot/github-action@v43.0.11 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From a5438f4cac3a794cb95d04891a83252aa9ae1f1e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 9 Sep 2025 09:02:39 +0200 Subject: [PATCH 430/619] fix(deps): update module github.com/spf13/viper to v1.21.0 (#974) Co-authored-by: Renovate Bot --- go.mod | 17 +++++++++-------- go.sum | 34 ++++++++++++++++++---------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index c487eca06..7b74bbce9 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.1 github.com/spf13/pflag v1.0.10 - github.com/spf13/viper v1.20.1 + github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 @@ -102,7 +102,7 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.12.1 // indirect @@ -183,7 +183,7 @@ require ( github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/stretchr/testify v1.10.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect github.com/tdakkota/asciicheck v0.4.1 // indirect github.com/tetafro/godot v1.5.1 // indirect github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect @@ -205,6 +205,7 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.16.0 // indirect golang.org/x/tools v0.36.0 // indirect @@ -221,7 +222,7 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -234,10 +235,10 @@ require ( github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.7.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/cast v1.7.1 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 diff --git a/go.sum b/go.sum index 00b66a78c..78202de4e 100644 --- a/go.sum +++ b/go.sum @@ -156,8 +156,8 @@ github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47A github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= @@ -207,8 +207,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -520,8 +520,8 @@ github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= -github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= -github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= @@ -545,22 +545,22 @@ github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.3 h1:GsZGmRRc/3GJLmCUnsZswirr5wfLRrwavbnL/renOqg= @@ -629,8 +629,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8= @@ -699,6 +699,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= From 521cee89abb345566ee39938b2d5baeee2264dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 9 Sep 2025 16:47:57 +0200 Subject: [PATCH 431/619] chore(docs): add subcommand registration hint to contribution guide (#979) --- CONTRIBUTION.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index e380d0458..21a668d8c 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -59,6 +59,10 @@ Please remember to always add unit tests for `parseInput`, `buildRequest` (in `b 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). +You may also have to register the `bar` command as a new sub-command: + +https://github.com/stackitcloud/stackit-cli/blob/a5438f4cac3a794cb95d04891a83252aa9ae1f1e/internal/cmd/root.go#L162-L195 + #### Outputs, prints and debug logs The CLI has 4 different verbosity levels: From 352189b011dd2d7852fecd5799924d2e83d9585a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 10 Sep 2025 10:43:31 +0200 Subject: [PATCH 432/619] fix(deps): update stackit sdk modules (#980) * fix(deps): update stackit sdk modules * chore(objectstorage): Attribute expires is now a NullableString Signed-off-by: Alexander Dahmen --------- Signed-off-by: Alexander Dahmen Co-authored-by: Renovate Bot Co-authored-by: Alexander Dahmen --- go.mod | 4 ++-- go.sum | 8 ++++---- internal/cmd/object-storage/credentials/create/create.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 7b74bbce9..8ad2582b8 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 @@ -242,7 +242,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0 github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 diff --git a/go.sum b/go.sum index 78202de4e..f2ab016dc 100644 --- a/go.sum +++ b/go.sum @@ -583,8 +583,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 h1:Db/ebOL2vbpIe github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1/go.mod h1:8jdN4v2euK3f9gfdzbRi8e4nBJ8g/Q5YF9aPB4M4fCQ= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/aGHepE/+gVsvSg1sRkPOyIUI/jkCyUOrWg= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1 h1:4jsFLbDVEosYTgQz6lPds1E9KDOiHwjuhWqcG+lo5B4= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.3.1/go.mod h1:j1SHAS5lN8F9b/iPUOfjAl9QAA9tOT7NKOiDEzcM2zc= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0 h1:g3yNDUc3JydAikezUrI9bQ4nuMJpVeAQ35jOFfFmq1U= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0/go.mod h1:foslkEiICdtHR3v0A/i/Rgo6EP9MMula9XNC9luNOgw= github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0 h1:oewwaYjABWbNqDkmSwIXmjDBK4a46+tnznyZSXh3Xk0= github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= @@ -605,8 +605,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 h1:tfKC4Z6Ua github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2/go.mod h1:wV7/BUV3BCLq5+E1bHXrKKt/eOPVdWgLArWLAq7rZ/U= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 h1:hcHX2n5pUsOcv2PPPbSJph1fQ/I6P7g7781T1f1ycEI= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1/go.mod h1:jZwTg3wU4/UxgNJ7TKlFZ3dTIlnfvppnW8kJTc4UXy8= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0 h1:u0PjbKDuIVOMm9hyxLeqSM51ExtJXJ+TdSJT5hDW6wk= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.0/go.mod h1:QCrAW/Rmf+styT25ke8cUV6hDHpdKNmAY14kkJ3+Fd8= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 h1:crKlHl7QVF97A8CTBK3PBtVpO9c/7qwFvRJi5UN/F7Y= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1/go.mod h1:QCrAW/Rmf+styT25ke8cUV6hDHpdKNmAY14kkJ3+Fd8= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 h1:V6RFvybDeJvvmT3g7/BZodF0gozz3TEpahbpiTftbeY= diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index eaef679f5..5a809c8d1 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -162,8 +162,8 @@ func outputResult(p *print.Printer, outputFormat, credentialsGroupLabel string, return nil default: expireDate := "Never" - if resp.Expires != nil && *resp.Expires != "" { - expireDate = *resp.Expires + if resp.Expires != nil && resp.Expires.IsSet() && *resp.Expires.Get() != "" { + expireDate = *resp.Expires.Get() } p.Outputf("Created credentials in group %q. Credentials ID: %s\n\n", credentialsGroupLabel, utils.PtrString(resp.KeyId)) From 2efac7d043798ad487b6cf6f3a8d06694740d6b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 10 Sep 2025 11:33:42 +0200 Subject: [PATCH 433/619] fix(redis): output valid json on list cmd (#966) relates to STACKITCLI-242 --- internal/cmd/redis/credentials/list/list.go | 25 +++++++++++------- .../cmd/redis/credentials/list/list_test.go | 2 +- internal/cmd/redis/instance/list/list.go | 26 +++++++++++-------- internal/cmd/redis/instance/list/list_test.go | 2 +- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index d7edc501e..e6b4d8c7e 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -69,21 +69,21 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("list Redis credentials: %w", err) } credentials := *resp.CredentialsList + + // Truncate output + if model.Limit != nil && len(credentials) > int(*model.Limit) { + credentials = credentials[:*model.Limit] + } + + instanceLabel := model.InstanceId if len(credentials) == 0 { - instanceLabel, err := redisUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err = redisUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) - instanceLabel = model.InstanceId } - params.Printer.Info("No credentials found for instance %q\n", instanceLabel) - return nil } - // Truncate output - if model.Limit != nil && len(credentials) > int(*model.Limit) { - credentials = credentials[:*model.Limit] - } - return outputResult(params.Printer, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, credentials) }, } configureFlags(cmd) @@ -135,7 +135,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl return req } -func outputResult(p *print.Printer, outputFormat string, credentials []redis.CredentialsListItem) error { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, credentials []redis.CredentialsListItem) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(credentials, "", " ") @@ -154,6 +154,11 @@ func outputResult(p *print.Printer, outputFormat string, credentials []redis.Cre return nil default: + if len(credentials) == 0 { + p.Outputf("No credentials found for instance %q\n", instanceLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID") for i := range credentials { diff --git a/internal/cmd/redis/credentials/list/list_test.go b/internal/cmd/redis/credentials/list/list_test.go index a37f530c4..a6c29f283 100644 --- a/internal/cmd/redis/credentials/list/list_test.go +++ b/internal/cmd/redis/credentials/list/list_test.go @@ -238,7 +238,7 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, "dummy-instance-label", tt.args.credentials); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index cc2bcacbd..1c073147b 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -67,22 +67,21 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("get Redis instances: %w", err) } instances := *resp.Instances - if len(instances) == 0 { - 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 - } - params.Printer.Info("No instances found for project %q\n", projectLabel) - return nil - } // Truncate output if model.Limit != nil && len(instances) > int(*model.Limit) { instances = instances[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, instances) + projectLabel := model.ProjectId + if len(instances) == 0 { + projectLabel, err = projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) + } + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, instances) }, } @@ -130,7 +129,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl return req } -func outputResult(p *print.Printer, outputFormat string, instances []redis.Instance) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []redis.Instance) error { switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instances, "", " ") @@ -149,6 +148,11 @@ func outputResult(p *print.Printer, outputFormat string, instances []redis.Insta return nil default: + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { diff --git a/internal/cmd/redis/instance/list/list_test.go b/internal/cmd/redis/instance/list/list_test.go index aff5c8020..f35a6eddd 100644 --- a/internal/cmd/redis/instance/list/list_test.go +++ b/internal/cmd/redis/instance/list/list_test.go @@ -216,7 +216,7 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, "dummy-project-label", tt.args.instances); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From dd3c5168202cc06101629308b43da875811cbe1a Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Wed, 10 Sep 2025 16:21:06 +0200 Subject: [PATCH 434/619] fix: add completions to linux archives (#982) * fix: add missing completions to linux archives for homebrew distribution --- .goreleaser.yaml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 9f9ae85c1..37412c183 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -48,25 +48,22 @@ builds: - cmd: spctl -a -t open --context context:primary-signature -v dist/{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.dmg output: true # Completion files - - cmd: mkdir -p dist/macos-builds_{{.Target}}/completions - - cmd: sh -c './dist/macos-builds_{{.Target}}/{{.Name}} completion zsh > ./dist/macos-builds_{{.Target}}/completions/stackit.zsh' - - cmd: sh -c './dist/macos-builds_{{.Target}}/{{.Name}} completion bash > ./dist/macos-builds_{{.Target}}/completions/stackit.bash' - - cmd: sh -c './dist/macos-builds_{{.Target}}/{{.Name}} completion fish > ./dist/macos-builds_{{.Target}}/completions/stackit.fish' + - cmd: mkdir -p dist/completions + - cmd: sh -c 'go run main.go completion zsh > ./dist/completions/stackit.zsh' + - cmd: sh -c 'go run main.go completion bash > ./dist/completions/stackit.bash' + - cmd: sh -c 'go run main.go completion fish > ./dist/completions/stackit.fish' archives: + - id: windows-archives + ids: + - windows-builds + formats: [ 'zip' ] - ids: - linux-builds - - windows-builds - formats: [ 'tar.gz' ] - format_overrides: - - goos: windows - formats: [ 'zip' ] - - id: macos-archives - ids: - macos-builds formats: [ 'tar.gz' ] files: - - src: ./dist/macos-builds_{{.Target}}/completions/* + - src: ./dist/completions/* dst: completions - LICENSE.md - README.md From 96571d0d9b5938feff9c0607521fbe9f168e6002 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 12 Sep 2025 07:19:22 +0200 Subject: [PATCH 435/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/iaas to v0.30.0 (#988) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8ad2582b8..cf000c443 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.2 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.30.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 diff --git a/go.sum b/go.sum index f2ab016dc..45fd904a5 100644 --- a/go.sum +++ b/go.sum @@ -573,8 +573,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4r github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 h1:hkFixFnBcQzU4BSIZFITc8N0gK0pUYk7mk0wdUu5Ki8= github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1/go.mod h1:Ng1EzrRndG3iGXGH90AZJz//wfK+2YOyDwTnTLwX3a4= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.2 h1:BvrbqLi9u0943TTkflPDLGbXgqgVzv7oy8tZHD3q3lg= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.29.2/go.mod h1:b/jgJf7QHdRzU2fmZeJJtu5j0TAevDRghzcn5MyRmOI= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.30.0 h1:01+noyCSadNH3ALHufcVXxNs0hBsetzJkOMN1Fe0VLc= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.30.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 h1:OdJEs8eOfrzn9tCBDLxIyP8hX50zPfcXNYnRoQX+chs= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1/go.mod h1:11uzaOPCF9SeDHXEGOPMlHDD3J5r2TnvCGUwW9Igq9c= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= From d1e9eca3fa3b4e6543dafe71d442cbfa0af78f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Fri, 12 Sep 2025 09:47:37 +0200 Subject: [PATCH 436/619] fix: use refresh tokens in curl commands for user token flow (#981) --- .../cmd/auth/get-access-token/get_access_token.go | 3 ++- internal/cmd/curl/curl.go | 13 +++---------- internal/pkg/auth/auth.go | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index f5040d85c..39bb3be7d 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -45,7 +45,8 @@ func NewCmd(params *params.CmdParams) *cobra.Command { accessToken, err := auth.GetValidAccessToken(params.Printer) if err != nil { - return err + params.Printer.Debug(print.ErrorLevel, "get valid access token: %v", err) + return &cliErr.SessionExpiredError{} } switch model.OutputFormat { diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index 15b79627a..afe797a28 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -181,17 +181,10 @@ func getBearerToken(p *print.Printer) (string, error) { return "", &errors.SessionExpiredError{} } - accessToken, err := auth.GetAccessToken() + accessToken, err := auth.GetValidAccessToken(p) if err != nil { - return "", err - } - - accessTokenExpired, err := auth.TokenExpired(accessToken) - if err != nil { - return "", err - } - if accessTokenExpired { - return "", &errors.AccessTokenExpiredError{} + p.Debug(print.ErrorLevel, "get valid access token: %v", err) + return "", &errors.SessionExpiredError{} } return accessToken, nil diff --git a/internal/pkg/auth/auth.go b/internal/pkg/auth/auth.go index 9a9b48817..ea549a2cb 100644 --- a/internal/pkg/auth/auth.go +++ b/internal/pkg/auth/auth.go @@ -202,7 +202,7 @@ func GetValidAccessToken(p *print.Printer) (string, error) { // Refresh the tokens err = refreshTokens(utf) if err != nil { - return "", fmt.Errorf("refresh access token: %w", err) + return "", fmt.Errorf("access token and refresh token expired: %w", err) } // Return the new access token From 6ab82203353f1e1c362424474a9a3a5f3a3ee77b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 16:49:46 +0200 Subject: [PATCH 437/619] chore(deps): bump renovatebot/github-action from 43.0.11 to 43.0.12 (#990) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 43.0.11 to 43.0.12. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v43.0.11...v43.0.12) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 43.0.12 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index a986c4930..758e5a418 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.11 + uses: renovatebot/github-action@v43.0.12 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 813914beab80156cab7d7c16948ca05fa2cdb8c1 Mon Sep 17 00:00:00 2001 From: Kai Kummerer <70690427+Kumm-Kai@users.noreply.github.com> Date: Tue, 16 Sep 2025 11:39:38 +0200 Subject: [PATCH 438/619] fix(ske/login): use region from kubeconfig (#989) * fix STACKITProjectID json key * get region from execCredential cluster config and fallback to region from CLI config --- internal/cmd/ske/kubeconfig/login/login.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/cmd/ske/kubeconfig/login/login.go b/internal/cmd/ske/kubeconfig/login/login.go index 3edc33b1f..e51f69c63 100644 --- a/internal/cmd/ske/kubeconfig/login/login.go +++ b/internal/cmd/ske/kubeconfig/login/login.go @@ -120,11 +120,11 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } type clusterConfig struct { - STACKITProjectID string `json:"stackitProjectId"` + STACKITProjectID string `json:"stackitProjectID"` ClusterName string `json:"clusterName"` + Region string `json:"region"` cacheKey string - Region string } func parseClusterConfig(p *print.Printer, cmd *cobra.Command) (*clusterConfig, error) { @@ -157,8 +157,10 @@ func parseClusterConfig(p *print.Printer, cmd *cobra.Command) (*clusterConfig, e config.cacheKey = fmt.Sprintf("ske-login-%x", sha256.Sum256([]byte(execCredential.Spec.Cluster.Server))) - globalFlags := globalflags.Parse(p, cmd) - config.Region = globalFlags.Region + // NOTE: Fallback if region is not set in the kubeconfig (this was the case in the past) + if config.Region == "" { + config.Region = globalflags.Parse(p, cmd).Region + } return config, nil } From f89f79a35303feacb70c327b33582071ee2ba17e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 09:47:22 +0000 Subject: [PATCH 439/619] chore(deps): bump k8s.io/client-go from 0.32.3 to 0.34.1 (#984) --- go.mod | 23 ++++++++++++----------- go.sum | 54 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index cf000c443..68e4d4bcd 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/stackitcloud/stackit-cli -go 1.24 +go 1.24.0 require ( github.com/fatih/color v1.18.0 @@ -38,8 +38,8 @@ require ( golang.org/x/oauth2 v0.30.0 golang.org/x/term v0.34.0 golang.org/x/text v0.28.0 - k8s.io/apimachinery v0.32.3 - k8s.io/client-go v0.32.3 + k8s.io/apimachinery v0.34.1 + k8s.io/client-go v0.34.1 ) require ( @@ -91,7 +91,7 @@ require ( github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.6 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/ghostiam/protogetter v0.3.15 // indirect github.com/go-critic/go-critic v0.13.0 // indirect @@ -205,6 +205,7 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.16.0 // indirect @@ -216,6 +217,8 @@ require ( honnef.co/go/tools v0.6.1 // indirect mvdan.cc/gofumpt v0.8.0 // indirect mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect ) require ( @@ -226,12 +229,11 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/gofuzz v1.2.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -250,12 +252,11 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.35.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.32.3 // indirect + k8s.io/api v0.34.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) tool ( diff --git a/go.sum b/go.sum index 45fd904a5..197b7cf59 100644 --- a/go.sum +++ b/go.sum @@ -140,8 +140,8 @@ github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42 github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -158,8 +158,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghostiam/protogetter v0.3.15 h1:1KF5sXel0HE48zh1/vn0Loiw25A9ApyseLzQuif1mLY= @@ -271,8 +271,8 @@ github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNF github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -285,12 +285,9 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -432,8 +429,9 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -699,6 +697,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1081,18 +1081,18 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= -k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= -k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= -k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= -k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= +k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= +k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= +k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= +k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= +k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= @@ -1100,9 +1100,11 @@ mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5gin rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= From 7b2e623eef212846434bc22374119a5991d8b87d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 09:56:09 +0000 Subject: [PATCH 440/619] chore(deps): bump golang.org/x/term from 0.34.0 to 0.35.0 (#987) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 68e4d4bcd..a3f7f67f0 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.27.0 golang.org/x/oauth2 v0.30.0 - golang.org/x/term v0.34.0 + golang.org/x/term v0.35.0 golang.org/x/text v0.28.0 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 @@ -250,7 +250,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.35.0 // indirect + golang.org/x/sys v0.36.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 197b7cf59..398d9ec8a 100644 --- a/go.sum +++ b/go.sum @@ -875,8 +875,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -885,8 +885,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From b3152d7b27307294fe111d76a6eef7501f28a7d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 10:05:07 +0000 Subject: [PATCH 441/619] chore(deps): bump golang.org/x/text from 0.28.0 to 0.29.0 (#972) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index a3f7f67f0..38d145f7c 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( golang.org/x/mod v0.27.0 golang.org/x/oauth2 v0.30.0 golang.org/x/term v0.35.0 - golang.org/x/text v0.28.0 + golang.org/x/text v0.29.0 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 ) @@ -208,7 +208,7 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/sync v0.16.0 // indirect + golang.org/x/sync v0.17.0 // indirect golang.org/x/tools v0.36.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect diff --git a/go.sum b/go.sum index 398d9ec8a..07e130051 100644 --- a/go.sum +++ b/go.sum @@ -822,8 +822,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -899,8 +899,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From c8ba019030d0167b1eaf9d69323df31cdf91c811 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 12:30:38 +0200 Subject: [PATCH 442/619] chore(deps): bump golang.org/x/mod from 0.27.0 to 0.28.0 (#971) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 38d145f7c..dce0f7d6c 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.27.0 + golang.org/x/mod v0.28.0 golang.org/x/oauth2 v0.30.0 golang.org/x/term v0.35.0 golang.org/x/text v0.29.0 diff --git a/go.sum b/go.sum index 07e130051..7519c4d0a 100644 --- a/go.sum +++ b/go.sum @@ -755,8 +755,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From fa8dea5b905a5e3510bbc454fc67cd49430cdef0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 10:39:30 +0000 Subject: [PATCH 443/619] chore(deps): bump golang.org/x/oauth2 from 0.30.0 to 0.31.0 (#970) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dce0f7d6c..706e4c843 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.28.0 - golang.org/x/oauth2 v0.30.0 + golang.org/x/oauth2 v0.31.0 golang.org/x/term v0.35.0 golang.org/x/text v0.29.0 k8s.io/apimachinery v0.34.1 diff --git a/go.sum b/go.sum index 7519c4d0a..def1c58e0 100644 --- a/go.sum +++ b/go.sum @@ -805,8 +805,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 9896dba5bd9d2bcc8576ae11647b4e5694c4db43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 19 Sep 2025 17:15:32 +0200 Subject: [PATCH 444/619] chore(flags): add unit test for string to string flag parsing (#983) --- internal/pkg/flags/flag_to_value_test.go | 73 ++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 internal/pkg/flags/flag_to_value_test.go diff --git a/internal/pkg/flags/flag_to_value_test.go b/internal/pkg/flags/flag_to_value_test.go new file mode 100644 index 000000000..5a71f40db --- /dev/null +++ b/internal/pkg/flags/flag_to_value_test.go @@ -0,0 +1,73 @@ +package flags + +import ( + "fmt" + "reflect" + "testing" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func TestFlagToStringToStringPointer(t *testing.T) { + const flagName = "labels" + + tests := []struct { + name string + flagValue *string + want *map[string]string + }{ + { + name: "flag unset", + flagValue: nil, + want: nil, + }, + { + name: "flag set with single value", + flagValue: utils.Ptr("foo=bar"), + want: &map[string]string{ + "foo": "bar", + }, + }, + { + name: "flag set with multiple values", + flagValue: utils.Ptr("foo=bar,label1=value1,label2=value2"), + want: &map[string]string{ + "foo": "bar", + "label1": "value1", + "label2": "value2", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + // create a new, simple test command with a string-to-string flag + cmd := func() *cobra.Command { + cmd := &cobra.Command{ + Use: "greet", + Short: "A simple greeting command", + Long: "A simple greeting command", + Run: func(_ *cobra.Command, _ []string) { + fmt.Println("Hello world") + }, + } + cmd.Flags().StringToString(flagName, nil, "Labels are key-value string pairs.") + return cmd + }() + + // set the flag value if a value use given, else consider the flag unset + if tt.flagValue != nil { + err := cmd.Flags().Set(flagName, *tt.flagValue) + if err != nil { + t.Error(err) + } + } + + if got := FlagToStringToStringPointer(p, cmd, flagName); !reflect.DeepEqual(got, tt.want) { + t.Errorf("FlagToStringToStringPointer() = %v, want %v", got, tt.want) + } + }) + } +} From 5bfe1b3a8a56ba90d8f4eed3201ab226a247ab7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 11:58:00 +0200 Subject: [PATCH 445/619] chore(deps): bump renovatebot/github-action from 43.0.12 to 43.0.13 (#994) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 758e5a418..9b509bd86 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.12 + uses: renovatebot/github-action@v43.0.13 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From f30f1877b493e00dacb512ad13461cf3bc79ebb4 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 23 Sep 2025 12:06:18 +0200 Subject: [PATCH 446/619] chore(deps): update module golang.org/x/tools to v0.44.0 (#986) Co-authored-by: Renovate Bot --- go.mod | 5 +++-- go.sum | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 706e4c843..9b3dcc8ee 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( ) require ( - golang.org/x/net v0.43.0 // indirect + golang.org/x/net v0.44.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -209,7 +209,8 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.17.0 // indirect - golang.org/x/tools v0.36.0 // indirect + golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect + golang.org/x/tools v0.37.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect google.golang.org/protobuf v1.36.6 // indirect diff --git a/go.sum b/go.sum index def1c58e0..34d386281 100644 --- a/go.sum +++ b/go.sum @@ -797,8 +797,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -877,6 +877,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -964,8 +966,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= From a2d59a5533aadad13ae4c48b1f56ae8aa61cd439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:02:22 +0200 Subject: [PATCH 447/619] fix: yaml output of servers userdata is bytearray instead of base64 (#998) --- internal/cmd/server/describe/describe.go | 7 +- internal/cmd/server/list/list.go | 7 +- internal/pkg/utils/utils.go | 97 ++++++++ internal/pkg/utils/utils_test.go | 296 +++++++++++++++++++++++ 4 files changed, 405 insertions(+), 2 deletions(-) diff --git a/internal/cmd/server/describe/describe.go b/internal/cmd/server/describe/describe.go index 85444e6ec..ee6e32ea6 100644 --- a/internal/cmd/server/describe/describe.go +++ b/internal/cmd/server/describe/describe.go @@ -118,7 +118,12 @@ func outputResult(p *print.Printer, outputFormat string, server *iaas.Server) er return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + // This is a temporary workaround to get the desired base64 encoded yaml output for userdata + // and will be replaced by a fix in the Go-SDK + // ref: https://jira.schwarz/browse/STACKITSDK-246 + patchedServer := utils.ConvertToBase64PatchedServer(server) + + details, err := yaml.MarshalWithOptions(patchedServer, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server: %w", err) } diff --git a/internal/cmd/server/list/list.go b/internal/cmd/server/list/list.go index 29eb51222..8c1596cbb 100644 --- a/internal/cmd/server/list/list.go +++ b/internal/cmd/server/list/list.go @@ -158,7 +158,12 @@ func outputResult(p *print.Printer, outputFormat string, servers []iaas.Server) return nil case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(servers, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + // This is a temporary workaround to get the desired base64 encoded yaml output for userdata + // and will be replaced by a fix in the Go-SDK + // ref: https://jira.schwarz/browse/STACKITSDK-246 + patchedServers := utils.ConvertToBase64PatchedServers(servers) + + details, err := yaml.MarshalWithOptions(patchedServers, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) if err != nil { return fmt.Errorf("marshal server: %w", err) } diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index 2db0936b8..4c362fea2 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -13,6 +13,7 @@ import ( "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/config" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) // Ptr Returns the pointer to any type T @@ -153,3 +154,99 @@ func ConvertStringMapToInterfaceMap(m *map[string]string) *map[string]interface{ } return &result } + +// Base64Bytes implements yaml.Marshaler to convert []byte to base64 strings +// ref: https://carlosbecker.com/posts/go-custom-marshaling +type Base64Bytes []byte + +// MarshalYAML implements yaml.Marshaler +func (b Base64Bytes) MarshalYAML() (interface{}, error) { + if len(b) == 0 { + return "", nil + } + return base64.StdEncoding.EncodeToString(b), nil +} + +type Base64PatchedServer struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + AvailabilityZone *string `json:"availabilityZone,omitempty"` + BootVolume *iaas.CreateServerPayloadBootVolume `json:"bootVolume,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + ErrorMessage *string `json:"errorMessage,omitempty"` + PowerStatus *string `json:"powerStatus,omitempty"` + AffinityGroup *string `json:"affinityGroup,omitempty"` + ImageId *string `json:"imageId,omitempty"` + KeypairName *string `json:"keypairName,omitempty"` + MachineType *string `json:"machineType,omitempty"` + Labels *map[string]interface{} `json:"labels,omitempty"` + LaunchedAt *time.Time `json:"launchedAt,omitempty"` + MaintenanceWindow *iaas.ServerMaintenance `json:"maintenanceWindow,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + Networking *iaas.CreateServerPayloadNetworking `json:"networking,omitempty"` + Nics *[]iaas.ServerNetwork `json:"nics,omitempty"` + SecurityGroups *[]string `json:"securityGroups,omitempty"` + ServiceAccountMails *[]string `json:"serviceAccountMails,omitempty"` + UpdatedAt *time.Time `json:"updatedAt,omitempty"` + UserData *Base64Bytes `json:"userData,omitempty"` + Volumes *[]string `json:"volumes,omitempty"` +} + +// ConvertToBase64PatchedServer converts an iaas.Server to Base64PatchedServer +// This is a temporary workaround to get the desired base64 encoded yaml output for userdata +// and will be replaced by a fix in the Go-SDK +// ref: https://jira.schwarz/browse/STACKITSDK-246 +func ConvertToBase64PatchedServer(server *iaas.Server) *Base64PatchedServer { + if server == nil { + return nil + } + + var userData *Base64Bytes + if server.UserData != nil { + userData = Ptr(Base64Bytes(*server.UserData)) + } + + return &Base64PatchedServer{ + Id: server.Id, + Name: server.Name, + Status: server.Status, + AvailabilityZone: server.AvailabilityZone, + BootVolume: server.BootVolume, + CreatedAt: server.CreatedAt, + ErrorMessage: server.ErrorMessage, + PowerStatus: server.PowerStatus, + AffinityGroup: server.AffinityGroup, + ImageId: server.ImageId, + KeypairName: server.KeypairName, + MachineType: server.MachineType, + Labels: server.Labels, + LaunchedAt: server.LaunchedAt, + MaintenanceWindow: server.MaintenanceWindow, + Metadata: server.Metadata, + Networking: server.Networking, + Nics: server.Nics, + SecurityGroups: server.SecurityGroups, + ServiceAccountMails: server.ServiceAccountMails, + UpdatedAt: server.UpdatedAt, + UserData: userData, + Volumes: server.Volumes, + } +} + +// ConvertToBase64PatchedServers converts a slice of iaas.Server to a slice of Base64PatchedServer +// This is a temporary workaround to get the desired base64 encoded yaml output for userdata +// and will be replaced by a fix in the Go-SDK +// ref: https://jira.schwarz/browse/STACKITSDK-246 +func ConvertToBase64PatchedServers(servers []iaas.Server) []Base64PatchedServer { + if servers == nil { + return nil + } + + result := make([]Base64PatchedServer, len(servers)) + for i := range servers { + result[i] = *ConvertToBase64PatchedServer(&servers[i]) + } + + return result +} diff --git a/internal/pkg/utils/utils_test.go b/internal/pkg/utils/utils_test.go index 86588bad8..79fdbae5e 100644 --- a/internal/pkg/utils/utils_test.go +++ b/internal/pkg/utils/utils_test.go @@ -3,8 +3,10 @@ package utils import ( "reflect" "testing" + "time" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -248,3 +250,297 @@ func TestConvertStringMapToInterfaceMap(t *testing.T) { }) } } + +func TestConvertToBase64PatchedServer(t *testing.T) { + now := time.Now() + userData := []byte("test") + emptyUserData := []byte("") + + tests := []struct { + name string + input *iaas.Server + expected *Base64PatchedServer + }{ + { + name: "nil input", + input: nil, + expected: nil, + }, + { + name: "server with user data", + input: &iaas.Server{ + Id: Ptr("server-123"), + Name: Ptr("test-server"), + Status: Ptr("ACTIVE"), + AvailabilityZone: Ptr("eu01-1"), + MachineType: Ptr("t1.1"), + UserData: &userData, + CreatedAt: &now, + PowerStatus: Ptr("RUNNING"), + AffinityGroup: Ptr("group-1"), + ImageId: Ptr("image-123"), + KeypairName: Ptr("keypair-1"), + }, + expected: &Base64PatchedServer{ + Id: Ptr("server-123"), + Name: Ptr("test-server"), + Status: Ptr("ACTIVE"), + AvailabilityZone: Ptr("eu01-1"), + MachineType: Ptr("t1.1"), + UserData: Ptr(Base64Bytes(userData)), + CreatedAt: &now, + PowerStatus: Ptr("RUNNING"), + AffinityGroup: Ptr("group-1"), + ImageId: Ptr("image-123"), + KeypairName: Ptr("keypair-1"), + }, + }, + { + name: "server with empty user data", + input: &iaas.Server{ + Id: Ptr("server-456"), + Name: Ptr("test-server-2"), + Status: Ptr("STOPPED"), + AvailabilityZone: Ptr("eu01-2"), + MachineType: Ptr("t1.2"), + UserData: &emptyUserData, + }, + expected: &Base64PatchedServer{ + Id: Ptr("server-456"), + Name: Ptr("test-server-2"), + Status: Ptr("STOPPED"), + AvailabilityZone: Ptr("eu01-2"), + MachineType: Ptr("t1.2"), + UserData: Ptr(Base64Bytes(emptyUserData)), + }, + }, + { + name: "server without user data", + input: &iaas.Server{ + Id: Ptr("server-789"), + Name: Ptr("test-server-3"), + Status: Ptr("CREATING"), + AvailabilityZone: Ptr("eu01-3"), + MachineType: Ptr("t1.3"), + UserData: nil, + }, + expected: &Base64PatchedServer{ + Id: Ptr("server-789"), + Name: Ptr("test-server-3"), + Status: Ptr("CREATING"), + AvailabilityZone: Ptr("eu01-3"), + MachineType: Ptr("t1.3"), + UserData: nil, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ConvertToBase64PatchedServer(tt.input) + + if result == nil && tt.expected == nil { + return + } + + if (result == nil && tt.expected != nil) || (result != nil && tt.expected == nil) { + t.Errorf("ConvertToBase64PatchedServer() = %v, want %v", result, tt.expected) + return + } + + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("ConvertToBase64PatchedServer() = %v, want %v", result, tt.expected) + } + }) + } +} + +func TestConvertToBase64PatchedServers(t *testing.T) { + now := time.Now() + userData1 := []byte("test1") + userData2 := []byte("test2") + emptyUserData := []byte("") + + tests := []struct { + name string + input []iaas.Server + expected []Base64PatchedServer + }{ + { + name: "nil input", + input: nil, + expected: nil, + }, + { + name: "empty slice", + input: []iaas.Server{}, + expected: []Base64PatchedServer{}, + }, + { + name: "single server with user data", + input: []iaas.Server{ + { + Id: Ptr("server-1"), + Name: Ptr("test-server-1"), + Status: Ptr("ACTIVE"), + MachineType: Ptr("t1.1"), + AvailabilityZone: Ptr("eu01-1"), + UserData: &userData1, + CreatedAt: &now, + }, + }, + expected: []Base64PatchedServer{ + { + Id: Ptr("server-1"), + Name: Ptr("test-server-1"), + Status: Ptr("ACTIVE"), + MachineType: Ptr("t1.1"), + AvailabilityZone: Ptr("eu01-1"), + UserData: Ptr(Base64Bytes(userData1)), + CreatedAt: &now, + }, + }, + }, + { + name: "multiple servers mixed", + input: []iaas.Server{ + { + Id: Ptr("server-1"), + Name: Ptr("test-server-1"), + Status: Ptr("ACTIVE"), + MachineType: Ptr("t1.1"), + AvailabilityZone: Ptr("eu01-1"), + UserData: &userData1, + CreatedAt: &now, + }, + { + Id: Ptr("server-2"), + Name: Ptr("test-server-2"), + Status: Ptr("STOPPED"), + MachineType: Ptr("t1.2"), + AvailabilityZone: Ptr("eu01-2"), + UserData: &userData2, + }, + { + Id: Ptr("server-3"), + Name: Ptr("test-server-3"), + Status: Ptr("CREATING"), + MachineType: Ptr("t1.3"), + AvailabilityZone: Ptr("eu01-3"), + UserData: &emptyUserData, + }, + { + Id: Ptr("server-4"), + Name: Ptr("test-server-4"), + Status: Ptr("ERROR"), + MachineType: Ptr("t1.4"), + AvailabilityZone: Ptr("eu01-4"), + UserData: nil, + }, + }, + expected: []Base64PatchedServer{ + { + Id: Ptr("server-1"), + Name: Ptr("test-server-1"), + Status: Ptr("ACTIVE"), + MachineType: Ptr("t1.1"), + AvailabilityZone: Ptr("eu01-1"), + UserData: Ptr(Base64Bytes(userData1)), + CreatedAt: &now, + }, + { + Id: Ptr("server-2"), + Name: Ptr("test-server-2"), + Status: Ptr("STOPPED"), + MachineType: Ptr("t1.2"), + AvailabilityZone: Ptr("eu01-2"), + UserData: Ptr(Base64Bytes(userData2)), + }, + { + Id: Ptr("server-3"), + Name: Ptr("test-server-3"), + Status: Ptr("CREATING"), + MachineType: Ptr("t1.3"), + AvailabilityZone: Ptr("eu01-3"), + UserData: Ptr(Base64Bytes(emptyUserData)), + }, + { + Id: Ptr("server-4"), + Name: Ptr("test-server-4"), + Status: Ptr("ERROR"), + MachineType: Ptr("t1.4"), + AvailabilityZone: Ptr("eu01-4"), + UserData: nil, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ConvertToBase64PatchedServers(tt.input) + + if result == nil && tt.expected == nil { + return + } + + if (result == nil && tt.expected != nil) || (result != nil && tt.expected == nil) { + t.Errorf("ConvertToBase64PatchedServers() = %v, want %v", result, tt.expected) + return + } + + if len(result) != len(tt.expected) { + t.Errorf("ConvertToBase64PatchedServers() length = %d, want %d", len(result), len(tt.expected)) + return + } + + for i, server := range result { + if !reflect.DeepEqual(server, tt.expected[i]) { + t.Errorf("ConvertToBase64PatchedServers() [%d] = %v, want %v", i, server, tt.expected[i]) + } + } + }) + } +} + +func TestBase64Bytes_MarshalYAML(t *testing.T) { + tests := []struct { + name string + input Base64Bytes + expected interface{} + }{ + { + name: "empty bytes", + input: Base64Bytes{}, + expected: "", + }, + { + name: "nil bytes", + input: Base64Bytes(nil), + expected: "", + }, + { + name: "simple text", + input: Base64Bytes("test"), + expected: "dGVzdA==", + }, + { + name: "special characters", + input: Base64Bytes("test@#$%"), + expected: "dGVzdEAjJCU=", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := tt.input.MarshalYAML() + if err != nil { + t.Errorf("MarshalYAML() error = %v", err) + return + } + if result != tt.expected { + t.Errorf("MarshalYAML() = %v, want %v", result, tt.expected) + } + }) + } +} From ca6dc4be6500739067f6126d6ef0cade12f9cb2a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 25 Sep 2025 16:30:31 +0200 Subject: [PATCH 448/619] fix(deps): update stackit sdk modules (#999) Co-authored-by: Renovate Bot Co-authored-by: Ruben Hoenle --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- internal/cmd/beta/alb/list/list.go | 4 +++- .../pkg/services/load-balancer/utils/utils.go | 4 +++- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 9b3dcc8ee..a9e301c25 100644 --- a/go.mod +++ b/go.mod @@ -16,11 +16,11 @@ require ( github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.17.3 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 - github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.30.0 + github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 @@ -242,7 +242,7 @@ require ( github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0 diff --git a/go.sum b/go.sum index 34d386281..cc8db5fd2 100644 --- a/go.sum +++ b/go.sum @@ -563,18 +563,18 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.17.3 h1:GsZGmRRc/3GJLmCUnsZswirr5wfLRrwavbnL/renOqg= github.com/stackitcloud/stackit-sdk-go/core v0.17.3/go.mod h1:HBCXJGPgdRulplDzhrmwC+Dak9B/x0nzNtmOpu+1Ahg= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1 h1:wJC/7mkIppHTBU0awGdLEFcmnjasp43MM9gX6/gdWvA= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.6.1/go.mod h1:UyN4hlkdiK5beDi5j9xHMENxRE9A9dlIWSXO/unhQW8= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 h1:UM/HvewAgELEvZ4zk++Ykd6jUTSL+asRqtK+DszDOzE= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0/go.mod h1:mOmGoNLPXLJ5tKLnhOnhKW7wL9Giy/4DowiDZNLlQCY= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 h1:Kzr1G4g9PHI8ePFnHrHZEX06XtEJQYBK9JExje0aXl0= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1/go.mod h1:OwQ+fYpON4WQpEinvI9lCTuuwj9UBCnPPJcnDpK803U= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= -github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1 h1:hkFixFnBcQzU4BSIZFITc8N0gK0pUYk7mk0wdUu5Ki8= -github.com/stackitcloud/stackit-sdk-go/services/git v0.7.1/go.mod h1:Ng1EzrRndG3iGXGH90AZJz//wfK+2YOyDwTnTLwX3a4= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.30.0 h1:01+noyCSadNH3ALHufcVXxNs0hBsetzJkOMN1Fe0VLc= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.30.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1 h1:OdJEs8eOfrzn9tCBDLxIyP8hX50zPfcXNYnRoQX+chs= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.5.1/go.mod h1:11uzaOPCF9SeDHXEGOPMlHDD3J5r2TnvCGUwW9Igq9c= +github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0 h1:/weT7P5Uwy1Qlhw0NidqtQBlbbb/dQehweDV/I9ShXg= +github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 h1:dnEjyapuv8WwRN5vE2z6+4/+ZqQTBx+bX27x2nOF7Jw= +github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0/go.mod h1:20QOZ3rBC9wTGgzXzLz9M6YheX0VaxWE0/JI+s8On7k= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1/go.mod h1:ivt8lvnAoBZsde2jSAuicyn6RgTmHvvNAJ3whaUbAD4= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 h1:Db/ebOL2vbpIeh5XB2Ews2B9Lj5DJlMWIEJh60FfZ4Y= diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go index 6df67a81a..a4d1480db 100644 --- a/internal/cmd/beta/alb/list/list.go +++ b/internal/cmd/beta/alb/list/list.go @@ -156,7 +156,9 @@ func outputResult(p *print.Printer, outputFormat string, items []alb.LoadBalance default: table := tables.NewTable() table.SetHeader("NAME", "EXTERNAL ADDRESS", "REGION", "STATUS", "VERSION", "ERRORS") - for _, item := range items { + for i := range items { + item := &items[i] + var errNo int if item.Errors != nil { errNo = len(*item.Errors) diff --git a/internal/pkg/services/load-balancer/utils/utils.go b/internal/pkg/services/load-balancer/utils/utils.go index 4bc13db61..1a5ba6076 100644 --- a/internal/pkg/services/load-balancer/utils/utils.go +++ b/internal/pkg/services/load-balancer/utils/utils.go @@ -159,7 +159,9 @@ func GetUsedObsCredentials(ctx context.Context, apiClient LoadBalancerClient, al } var usedCredentialsRefs []string - for _, loadBalancer := range *loadBalancers.LoadBalancers { + for i := range *loadBalancers.LoadBalancers { + loadBalancer := &(*loadBalancers.LoadBalancers)[i] + if loadBalancer.Options == nil || loadBalancer.Options.Observability == nil { continue } From 95cedde5aef762e7250c6bc1a7e5f3a525099764 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 08:51:56 +0200 Subject: [PATCH 449/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/authorization (#1007) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a9e301c25..e95d8cf67 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 diff --git a/go.sum b/go.sum index cc8db5fd2..61d5cc4f2 100644 --- a/go.sum +++ b/go.sum @@ -565,8 +565,8 @@ github.com/stackitcloud/stackit-sdk-go/core v0.17.3 h1:GsZGmRRc/3GJLmCUnsZswirr5 github.com/stackitcloud/stackit-sdk-go/core v0.17.3/go.mod h1:HBCXJGPgdRulplDzhrmwC+Dak9B/x0nzNtmOpu+1Ahg= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 h1:UM/HvewAgELEvZ4zk++Ykd6jUTSL+asRqtK+DszDOzE= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0/go.mod h1:mOmGoNLPXLJ5tKLnhOnhKW7wL9Giy/4DowiDZNLlQCY= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1 h1:Kzr1G4g9PHI8ePFnHrHZEX06XtEJQYBK9JExje0aXl0= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.8.1/go.mod h1:OwQ+fYpON4WQpEinvI9lCTuuwj9UBCnPPJcnDpK803U= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0 h1:/weT7P5Uwy1Qlhw0NidqtQBlbbb/dQehweDV/I9ShXg= From edf55a4fc5bdd2e68e7d82596fa86cba931c092a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:21:02 +0200 Subject: [PATCH 450/619] chore(deps): update renovatebot/github-action action to v43.0.14 (#1011) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 9b509bd86..f05ae9118 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.13 + uses: renovatebot/github-action@v43.0.14 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 14481e42f57b366c1310e8027c41604b75473351 Mon Sep 17 00:00:00 2001 From: Mauritz Uphoff <39736813+h3adex@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:10:54 +0200 Subject: [PATCH 451/619] feat: provide functionality to list public ip-ranges (#993) Co-authored-by: Benjosh95 --- docs/stackit_public-ip.md | 1 + docs/stackit_public-ip_ranges.md | 34 +++ docs/stackit_public-ip_ranges_list.md | 47 ++++ internal/cmd/public-ip/public-ip.go | 2 + internal/cmd/public-ip/ranges/list/list.go | 149 +++++++++++++ .../cmd/public-ip/ranges/list/list_test.go | 210 ++++++++++++++++++ internal/cmd/public-ip/ranges/ranges.go | 26 +++ internal/pkg/utils/utils.go | 9 + internal/pkg/utils/utils_test.go | 46 ++++ 9 files changed, 524 insertions(+) create mode 100644 docs/stackit_public-ip_ranges.md create mode 100644 docs/stackit_public-ip_ranges_list.md create mode 100644 internal/cmd/public-ip/ranges/list/list.go create mode 100644 internal/cmd/public-ip/ranges/list/list_test.go create mode 100644 internal/cmd/public-ip/ranges/ranges.go diff --git a/docs/stackit_public-ip.md b/docs/stackit_public-ip.md index 99bfd899f..d5dcafd53 100644 --- a/docs/stackit_public-ip.md +++ b/docs/stackit_public-ip.md @@ -36,5 +36,6 @@ stackit public-ip [flags] * [stackit public-ip describe](./stackit_public-ip_describe.md) - Shows details of a Public IP * [stackit public-ip disassociate](./stackit_public-ip_disassociate.md) - Disassociates a Public IP from a network interface or a virtual IP * [stackit public-ip list](./stackit_public-ip_list.md) - Lists all Public IPs of a project +* [stackit public-ip ranges](./stackit_public-ip_ranges.md) - Provides functionality for STACKIT public-ip ranges * [stackit public-ip update](./stackit_public-ip_update.md) - Updates a Public IP diff --git a/docs/stackit_public-ip_ranges.md b/docs/stackit_public-ip_ranges.md new file mode 100644 index 000000000..025ddba9b --- /dev/null +++ b/docs/stackit_public-ip_ranges.md @@ -0,0 +1,34 @@ +## stackit public-ip ranges + +Provides functionality for STACKIT public-ip ranges + +### Synopsis + +Provides functionality for STACKIT public-ip ranges + +``` +stackit public-ip ranges [flags] +``` + +### Options + +``` + -h, --help Help for "stackit public-ip ranges" +``` + +### 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 public-ip](./stackit_public-ip.md) - Provides functionality for public IPs +* [stackit public-ip ranges list](./stackit_public-ip_ranges_list.md) - Lists all STACKIT public-ip ranges + diff --git a/docs/stackit_public-ip_ranges_list.md b/docs/stackit_public-ip_ranges_list.md new file mode 100644 index 000000000..c152b9851 --- /dev/null +++ b/docs/stackit_public-ip_ranges_list.md @@ -0,0 +1,47 @@ +## stackit public-ip ranges list + +Lists all STACKIT public-ip ranges + +### Synopsis + +Lists all STACKIT public-ip ranges. + +``` +stackit public-ip ranges list [flags] +``` + +### Examples + +``` + Lists all STACKIT public-ip ranges + $ stackit public-ip ranges list + + Lists all STACKIT public-ip ranges, piping to a tool like fzf for interactive selection + $ stackit public-ip ranges list -o pretty | fzf + + Lists up to 10 STACKIT public-ip ranges + $ stackit public-ip ranges list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit public-ip ranges list" + --limit int Maximum number of entries to list +``` + +### 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 public-ip ranges](./stackit_public-ip_ranges.md) - Provides functionality for STACKIT public-ip ranges + diff --git a/internal/cmd/public-ip/public-ip.go b/internal/cmd/public-ip/public-ip.go index 3be1ac1c4..d16565288 100644 --- a/internal/cmd/public-ip/public-ip.go +++ b/internal/cmd/public-ip/public-ip.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/disassociate" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/ranges" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -35,4 +36,5 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(update.NewCmd(params)) cmd.AddCommand(associate.NewCmd(params)) cmd.AddCommand(disassociate.NewCmd(params)) + cmd.AddCommand(ranges.NewCmd(params)) } diff --git a/internal/cmd/public-ip/ranges/list/list.go b/internal/cmd/public-ip/ranges/list/list.go new file mode 100644 index 000000000..54168b448 --- /dev/null +++ b/internal/cmd/public-ip/ranges/list/list.go @@ -0,0 +1,149 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all STACKIT public-ip ranges", + Long: "Lists all STACKIT public-ip ranges.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all STACKIT public-ip ranges`, + "$ stackit public-ip ranges list", + ), + examples.NewExample( + `Lists all STACKIT public-ip ranges, piping to a tool like fzf for interactive selection`, + "$ stackit public-ip ranges list -o pretty | fzf", + ), + examples.NewExample( + `Lists up to 10 STACKIT public-ip ranges`, + "$ stackit public-ip ranges list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := apiClient.ListPublicIPRanges(ctx) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list public IP ranges: %w", err) + } + publicIpRanges := utils.GetSliceFromPointer(resp.Items) + + // Truncate output + if model.Limit != nil && len(publicIpRanges) > int(*model.Limit) { + publicIpRanges = publicIpRanges[:*model.Limit] + } + + return outputResult(params.Printer, model.OutputFormat, publicIpRanges) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + if p.IsVerbosityDebug() { + modelStr, err := print.BuildDebugStrFromInputModel(model) + if err != nil { + p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) + } + } + + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat string, publicIpRanges []iaas.PublicNetwork) error { + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(publicIpRanges, "", " ") + if err != nil { + return fmt.Errorf("marshal public IP ranges: %w", err) + } + p.Outputln(string(details)) + + return nil + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(publicIpRanges, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal public IP ranges: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + if len(publicIpRanges) == 0 { + p.Outputln("No public IP ranges found") + return nil + } + + for _, item := range publicIpRanges { + if item.Cidr != nil && *item.Cidr != "" { + p.Outputln(*item.Cidr) + } + } + + return nil + } +} diff --git a/internal/cmd/public-ip/ranges/list/list_test.go b/internal/cmd/public-ip/ranges/list/list_test.go new file mode 100644 index 000000000..f9aa0d6be --- /dev/null +++ b/internal/cmd/public-ip/ranges/list/list_test.go @@ -0,0 +1,210 @@ +package list + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +func TestParseInput(t *testing.T) { + projectId := uuid.New().String() + tests := []struct { + description string + globalFlags map[string]string + expectedModel *inputModel + isValid bool + }{ + { + description: "valid project id", + globalFlags: map[string]string{ + "project-id": projectId, + }, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: projectId, + Verbosity: globalflags.InfoVerbosity, + }, + }, + isValid: true, + }, + { + description: "missing project id does not lead into error", + globalFlags: map[string]string{}, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.InfoVerbosity, + }, + }, + isValid: true, + }, + { + description: "valid input with limit", + globalFlags: map[string]string{ + "limit": "10", + }, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.InfoVerbosity, + }, + Limit: utils.Ptr(int64(10)), + }, + isValid: true, + }, + { + description: "valid input without limit", + globalFlags: map[string]string{}, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.InfoVerbosity, + }, + }, + isValid: true, + }, + { + description: "invalid limit (zero)", + globalFlags: map[string]string{ + "limit": "0", + }, + expectedModel: nil, + isValid: false, + }, + { + description: "invalid limit (negative)", + globalFlags: map[string]string{ + "limit": "-1", + }, + expectedModel: nil, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatal(err) + } + + for flag, value := range tt.globalFlags { + if err := cmd.Flags().Set(flag, value); err != nil { + t.Fatalf("Failed to set global flag %s: %v", flag, err) + } + } + + model, err := parseInput(p, cmd) + if !tt.isValid && err == nil { + t.Fatalf("parseInput() error = %v, wantErr %v", err, !tt.isValid) + } + + if tt.isValid { + if diff := cmp.Diff(model, tt.expectedModel); diff != "" { + t.Fatalf("Model mismatch (-want +got):\n%s", diff) + } + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + name string + outputFormat string + publicIpRanges []iaas.PublicNetwork + expectedOutput string + wantErr bool + }{ + { + name: "JSON output single", + outputFormat: "json", + publicIpRanges: []iaas.PublicNetwork{ + {Cidr: utils.Ptr("192.168.0.0/24")}, + }, + wantErr: false, + }, + { + name: "JSON output multiple", + outputFormat: "json", + publicIpRanges: []iaas.PublicNetwork{ + {Cidr: utils.Ptr("192.168.0.0/24")}, + {Cidr: utils.Ptr("192.167.0.0/24")}, + }, + wantErr: false, + }, + { + name: "YAML output single", + outputFormat: "yaml", + publicIpRanges: []iaas.PublicNetwork{ + {Cidr: utils.Ptr("192.168.0.0/24")}, + }, + wantErr: false, + }, + { + name: "YAML output multiple", + outputFormat: "yaml", + publicIpRanges: []iaas.PublicNetwork{ + {Cidr: utils.Ptr("192.168.0.0/24")}, + {Cidr: utils.Ptr("192.167.0.0/24")}, + }, + wantErr: false, + }, + { + name: "pretty output single", + outputFormat: "pretty", + publicIpRanges: []iaas.PublicNetwork{ + {Cidr: utils.Ptr("192.168.0.0/24")}, + }, + wantErr: false, + }, + { + name: "pretty output multiple", + outputFormat: "pretty", + publicIpRanges: []iaas.PublicNetwork{ + {Cidr: utils.Ptr("192.168.0.0/24")}, + {Cidr: utils.Ptr("192.167.0.0/24")}, + }, + wantErr: false, + }, + { + name: "default output", + outputFormat: "", + publicIpRanges: []iaas.PublicNetwork{ + {Cidr: utils.Ptr("192.168.0.0/24")}, + }, + wantErr: false, + }, + { + name: "empty list", + outputFormat: "json", + publicIpRanges: []iaas.PublicNetwork{}, + wantErr: false, + }, + { + name: "nil CIDR", + outputFormat: "pretty", + publicIpRanges: []iaas.PublicNetwork{ + {Cidr: nil}, + {Cidr: utils.Ptr("192.168.0.0/24")}, + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + err := outputResult(p, tt.outputFormat, tt.publicIpRanges) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/public-ip/ranges/ranges.go b/internal/cmd/public-ip/ranges/ranges.go new file mode 100644 index 000000000..8d616ac5a --- /dev/null +++ b/internal/cmd/public-ip/ranges/ranges.go @@ -0,0 +1,26 @@ +package ranges + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/ranges/list" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "ranges", + Short: "Provides functionality for STACKIT public-ip ranges", + Long: "Provides functionality for STACKIT public-ip ranges", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) +} diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index 4c362fea2..2a68bc14c 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -250,3 +250,12 @@ func ConvertToBase64PatchedServers(servers []iaas.Server) []Base64PatchedServer return result } + +// GetSliceFromPointer returns the value of a pointer to a slice of type T. +// If the pointer is nil, it returns an empty slice. +func GetSliceFromPointer[T any](s *[]T) []T { + if s == nil || *s == nil { + return []T{} + } + return *s +} diff --git a/internal/pkg/utils/utils_test.go b/internal/pkg/utils/utils_test.go index 79fdbae5e..4591c84c9 100644 --- a/internal/pkg/utils/utils_test.go +++ b/internal/pkg/utils/utils_test.go @@ -544,3 +544,49 @@ func TestBase64Bytes_MarshalYAML(t *testing.T) { }) } } +func TestGetSliceFromPointer(t *testing.T) { + tests := []struct { + name string + input *[]string + expected []string + }{ + { + name: "nil pointer", + input: nil, + expected: []string{}, + }, + { + name: "pointer to nil slice", + input: func() *[]string { + var s []string + return &s + }(), + expected: []string{}, + }, + { + name: "empty slice", + input: &[]string{}, + expected: []string{}, + }, + { + name: "populated slice", + input: &[]string{"item1", "item2"}, + expected: []string{"item1", "item2"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := GetSliceFromPointer(tt.input) + + if result == nil { + t.Errorf("GetSliceFromPointer() = %v, want %v", result, tt.expected) + return + } + + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("GetSliceFromPointer() = %v, want %v", result, tt.expected) + } + }) + } +} From f3db2df28663f6187661f617977e006499b0b061 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 16:56:31 +0200 Subject: [PATCH 452/619] chore(deps): bump renovatebot/github-action from 43.0.14 to 43.0.15 (#1013) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 43.0.14 to 43.0.15. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v43.0.14...v43.0.15) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 43.0.15 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index f05ae9118..a3cfc0047 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.14 + uses: renovatebot/github-action@v43.0.15 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 6da7c6d706bd95946622f2db96a9cf08f9e9cffd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 17:57:05 +0200 Subject: [PATCH 453/619] chore(deps): bump renovatebot/github-action from 43.0.15 to 43.0.16 (#1015) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index a3cfc0047..a01117f2a 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.15 + uses: renovatebot/github-action@v43.0.16 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From f533ca87a15c99a3f56535e7460913f4358ab97e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 16:02:59 +0000 Subject: [PATCH 454/619] chore(deps): bump golang.org/x/oauth2 from 0.31.0 to 0.32.0 (#1014) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e95d8cf67..b91fab4bd 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.28.0 - golang.org/x/oauth2 v0.31.0 + golang.org/x/oauth2 v0.32.0 golang.org/x/term v0.35.0 golang.org/x/text v0.29.0 k8s.io/apimachinery v0.34.1 diff --git a/go.sum b/go.sum index 61d5cc4f2..e7b43d4eb 100644 --- a/go.sum +++ b/go.sum @@ -805,8 +805,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= -golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= +golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From e808adecd19f9ac6201adfec2920500dbce22a4f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:15:38 +0200 Subject: [PATCH 455/619] fix(deps): update module golang.org/x/text to v0.30.0 (#1020) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b91fab4bd..4fac0671c 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( golang.org/x/mod v0.28.0 golang.org/x/oauth2 v0.32.0 golang.org/x/term v0.35.0 - golang.org/x/text v0.29.0 + golang.org/x/text v0.30.0 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 ) diff --git a/go.sum b/go.sum index e7b43d4eb..bf4df58b6 100644 --- a/go.sum +++ b/go.sum @@ -901,8 +901,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 5532b96fc1bfe4b48dce79e8f5a45580db7b7d1c Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:24:03 +0200 Subject: [PATCH 456/619] fix(deps): update module golang.org/x/mod to v0.29.0 (#1018) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4fac0671c..a0b8e6145 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.28.0 + golang.org/x/mod v0.29.0 golang.org/x/oauth2 v0.32.0 golang.org/x/term v0.35.0 golang.org/x/text v0.30.0 diff --git a/go.sum b/go.sum index bf4df58b6..6f9d0195b 100644 --- a/go.sum +++ b/go.sum @@ -755,8 +755,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 09b87c3ee44c7559e80865082fe7b9c1f26a03a1 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:47:55 +0200 Subject: [PATCH 457/619] fix(deps): update module golang.org/x/term to v0.36.0 (#1019) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index a0b8e6145..b4802b9b4 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.29.0 golang.org/x/oauth2 v0.32.0 - golang.org/x/term v0.35.0 + golang.org/x/term v0.36.0 golang.org/x/text v0.30.0 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 @@ -251,7 +251,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.36.0 // indirect + golang.org/x/sys v0.37.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 6f9d0195b..521fe8021 100644 --- a/go.sum +++ b/go.sum @@ -875,8 +875,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -887,8 +887,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= -golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From e687b716437db50c39f9cf7d0feaafac55506bc2 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:55:23 +0200 Subject: [PATCH 458/619] chore(deps): update module golang.org/x/tools to v0.38.0 (#1017) Co-authored-by: Renovate Bot --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index b4802b9b4..0baf2a99d 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( ) require ( - golang.org/x/net v0.44.0 // indirect + golang.org/x/net v0.46.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -209,8 +209,8 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.17.0 // indirect - golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect - golang.org/x/tools v0.37.0 // indirect + golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect + golang.org/x/tools v0.38.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect google.golang.org/protobuf v1.36.6 // indirect diff --git a/go.sum b/go.sum index 521fe8021..613c93ed9 100644 --- a/go.sum +++ b/go.sum @@ -797,8 +797,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -877,8 +877,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= -golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= +golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= +golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -966,8 +966,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= From b42533e01a29f6dfdeb04f69f5bcc4dcf4e5f787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 9 Oct 2025 10:58:38 +0200 Subject: [PATCH 459/619] refactor: use a func to print input model debug output (#1016) --- .github/docs/contribution-guide/cmd.go | 10 +--------- CONTRIBUTION.md | 4 ++-- internal/cmd/affinity-groups/create/create.go | 10 +--------- internal/cmd/affinity-groups/delete/delete.go | 10 +--------- internal/cmd/affinity-groups/describe/describe.go | 10 +--------- internal/cmd/affinity-groups/list/list.go | 10 +--------- .../activate_service_account.go | 10 +--------- .../cmd/auth/get-access-token/get_access_token.go | 10 +--------- internal/cmd/beta/alb/create/create.go | 10 +--------- internal/cmd/beta/alb/delete/delete.go | 10 +--------- internal/cmd/beta/alb/describe/describe.go | 10 +--------- internal/cmd/beta/alb/list/list.go | 10 +--------- .../beta/alb/observability-credentials/add/add.go | 10 +--------- .../alb/observability-credentials/delete/delete.go | 10 +--------- .../observability-credentials/describe/describe.go | 10 +--------- .../alb/observability-credentials/list/list.go | 10 +--------- .../alb/observability-credentials/update/update.go | 10 +--------- internal/cmd/beta/alb/plans/plans.go | 10 +--------- internal/cmd/beta/alb/pool/update/update.go | 10 +--------- internal/cmd/beta/alb/quotas/quotas.go | 10 +--------- internal/cmd/beta/alb/template/template.go | 10 +--------- internal/cmd/beta/alb/update/update.go | 10 +--------- .../beta/sqlserverflex/database/create/create.go | 10 +--------- .../beta/sqlserverflex/database/delete/delete.go | 10 +--------- .../sqlserverflex/database/describe/describe.go | 10 +--------- .../cmd/beta/sqlserverflex/database/list/list.go | 10 +--------- .../beta/sqlserverflex/instance/create/create.go | 10 +--------- .../beta/sqlserverflex/instance/delete/delete.go | 10 +--------- .../sqlserverflex/instance/describe/describe.go | 10 +--------- .../cmd/beta/sqlserverflex/instance/list/list.go | 10 +--------- .../beta/sqlserverflex/instance/update/update.go | 10 +--------- internal/cmd/beta/sqlserverflex/options/options.go | 10 +--------- .../cmd/beta/sqlserverflex/user/create/create.go | 10 +--------- .../cmd/beta/sqlserverflex/user/delete/delete.go | 10 +--------- .../beta/sqlserverflex/user/describe/describe.go | 10 +--------- internal/cmd/beta/sqlserverflex/user/list/list.go | 10 +--------- .../user/reset-password/reset_password.go | 10 +--------- internal/cmd/config/profile/create/create.go | 10 +--------- internal/cmd/config/profile/delete/delete.go | 10 +--------- internal/cmd/config/profile/export/export.go | 10 +--------- internal/cmd/config/profile/import/import.go | 10 +--------- internal/cmd/config/profile/set/set.go | 10 +--------- internal/cmd/config/set/set.go | 10 +--------- internal/cmd/config/unset/unset.go | 10 +--------- internal/cmd/curl/curl.go | 10 +--------- internal/cmd/dns/record-set/create/create.go | 10 +--------- internal/cmd/dns/record-set/delete/delete.go | 10 +--------- internal/cmd/dns/record-set/describe/describe.go | 10 +--------- internal/cmd/dns/record-set/list/list.go | 10 +--------- internal/cmd/dns/record-set/update/update.go | 10 +--------- internal/cmd/dns/zone/clone/clone.go | 10 +--------- internal/cmd/dns/zone/create/create.go | 10 +--------- internal/cmd/dns/zone/delete/delete.go | 10 +--------- internal/cmd/dns/zone/describe/describe.go | 10 +--------- internal/cmd/dns/zone/list/list.go | 10 +--------- internal/cmd/dns/zone/update/update.go | 10 +--------- internal/cmd/git/flavor/list/list.go | 10 +--------- internal/cmd/git/instance/create/create.go | 10 +--------- internal/cmd/git/instance/delete/delete.go | 10 +--------- internal/cmd/git/instance/describe/describe.go | 10 +--------- internal/cmd/git/instance/list/list.go | 10 +--------- internal/cmd/image/create/create.go | 10 +--------- internal/cmd/image/delete/delete.go | 10 +--------- internal/cmd/image/describe/describe.go | 10 +--------- internal/cmd/image/list/list.go | 10 +--------- internal/cmd/image/update/update.go | 10 +--------- internal/cmd/key-pair/create/create.go | 10 +--------- internal/cmd/key-pair/delete/delete.go | 10 +--------- internal/cmd/key-pair/describe/describe.go | 10 +--------- internal/cmd/key-pair/list/list.go | 10 +--------- internal/cmd/key-pair/update/update.go | 10 +--------- internal/cmd/load-balancer/create/create.go | 10 +--------- internal/cmd/load-balancer/delete/delete.go | 10 +--------- internal/cmd/load-balancer/describe/describe.go | 10 +--------- .../generate-payload/generate_payload.go | 10 +--------- internal/cmd/load-balancer/list/list.go | 10 +--------- .../observability-credentials/add/add.go | 10 +--------- .../observability-credentials/cleanup/cleanup.go | 10 +--------- .../observability-credentials/delete/delete.go | 10 +--------- .../observability-credentials/describe/describe.go | 10 +--------- .../observability-credentials/list/list.go | 10 +--------- internal/cmd/load-balancer/quota/quota.go | 10 +--------- .../target-pool/add-target/add_target.go | 10 +--------- .../load-balancer/target-pool/describe/describe.go | 10 +--------- .../target-pool/remove-target/remove_target.go | 10 +--------- internal/cmd/load-balancer/update/update.go | 10 +--------- internal/cmd/logme/credentials/create/create.go | 10 +--------- internal/cmd/logme/credentials/delete/delete.go | 10 +--------- .../cmd/logme/credentials/describe/describe.go | 10 +--------- internal/cmd/logme/credentials/list/list.go | 10 +--------- internal/cmd/logme/instance/create/create.go | 10 +--------- internal/cmd/logme/instance/delete/delete.go | 10 +--------- internal/cmd/logme/instance/describe/describe.go | 10 +--------- internal/cmd/logme/instance/list/list.go | 10 +--------- internal/cmd/logme/instance/update/update.go | 10 +--------- internal/cmd/logme/plans/plans.go | 10 +--------- internal/cmd/mariadb/credentials/create/create.go | 10 +--------- internal/cmd/mariadb/credentials/delete/delete.go | 10 +--------- .../cmd/mariadb/credentials/describe/describe.go | 10 +--------- internal/cmd/mariadb/credentials/list/list.go | 10 +--------- internal/cmd/mariadb/instance/create/create.go | 10 +--------- internal/cmd/mariadb/instance/delete/delete.go | 10 +--------- internal/cmd/mariadb/instance/describe/describe.go | 10 +--------- internal/cmd/mariadb/instance/list/list.go | 10 +--------- internal/cmd/mariadb/instance/update/update.go | 10 +--------- internal/cmd/mariadb/plans/plans.go | 10 +--------- .../cmd/mongodbflex/backup/describe/describe.go | 10 +--------- internal/cmd/mongodbflex/backup/list/list.go | 10 +--------- .../backup/restore-jobs/restore_jobs.go | 10 +--------- internal/cmd/mongodbflex/backup/restore/restore.go | 10 +--------- .../cmd/mongodbflex/backup/schedule/schedule.go | 10 +--------- internal/cmd/mongodbflex/instance/create/create.go | 10 +--------- internal/cmd/mongodbflex/instance/delete/delete.go | 10 +--------- .../cmd/mongodbflex/instance/describe/describe.go | 10 +--------- internal/cmd/mongodbflex/instance/list/list.go | 10 +--------- internal/cmd/mongodbflex/instance/update/update.go | 10 +--------- internal/cmd/mongodbflex/options/options.go | 10 +--------- internal/cmd/mongodbflex/user/create/create.go | 10 +--------- internal/cmd/mongodbflex/user/delete/delete.go | 10 +--------- internal/cmd/mongodbflex/user/describe/describe.go | 10 +--------- internal/cmd/mongodbflex/user/list/list.go | 10 +--------- .../user/reset-password/reset_password.go | 10 +--------- internal/cmd/mongodbflex/user/update/update.go | 10 +--------- internal/cmd/network-area/create/create.go | 10 +--------- internal/cmd/network-area/delete/delete.go | 10 +--------- internal/cmd/network-area/describe/describe.go | 10 +--------- internal/cmd/network-area/list/list.go | 10 +--------- .../network-area/network-range/create/create.go | 10 +--------- .../network-area/network-range/delete/delete.go | 10 +--------- .../network-range/describe/describe.go | 10 +--------- .../cmd/network-area/network-range/list/list.go | 10 +--------- internal/cmd/network-area/route/create/create.go | 10 +--------- internal/cmd/network-area/route/delete/delete.go | 10 +--------- .../cmd/network-area/route/describe/describe.go | 10 +--------- internal/cmd/network-area/route/list/list.go | 10 +--------- internal/cmd/network-area/route/update/update.go | 10 +--------- internal/cmd/network-area/update/update.go | 10 +--------- internal/cmd/network-interface/create/create.go | 10 +--------- internal/cmd/network-interface/delete/delete.go | 10 +--------- .../cmd/network-interface/describe/describe.go | 10 +--------- internal/cmd/network-interface/list/list.go | 10 +--------- internal/cmd/network-interface/update/update.go | 10 +--------- internal/cmd/network/create/create.go | 10 +--------- internal/cmd/network/delete/delete.go | 10 +--------- internal/cmd/network/describe/describe.go | 10 +--------- internal/cmd/network/list/list.go | 10 +--------- internal/cmd/network/update/update.go | 10 +--------- .../cmd/object-storage/bucket/create/create.go | 10 +--------- .../cmd/object-storage/bucket/delete/delete.go | 10 +--------- .../cmd/object-storage/bucket/describe/describe.go | 10 +--------- internal/cmd/object-storage/bucket/list/list.go | 10 +--------- .../credentials-group/create/create.go | 10 +--------- .../credentials-group/delete/delete.go | 10 +--------- .../object-storage/credentials-group/list/list.go | 10 +--------- .../object-storage/credentials/create/create.go | 10 +--------- .../object-storage/credentials/delete/delete.go | 10 +--------- .../cmd/object-storage/credentials/list/list.go | 10 +--------- internal/cmd/object-storage/disable/disable.go | 10 +--------- internal/cmd/object-storage/enable/enable.go | 10 +--------- .../cmd/observability/grafana/describe/describe.go | 10 +--------- .../grafana/public-read-access/disable/disable.go | 10 +--------- .../grafana/public-read-access/enable/enable.go | 10 +--------- .../grafana/single-sign-on/disable/disable.go | 10 +--------- .../grafana/single-sign-on/enable/enable.go | 10 +--------- .../cmd/observability/instance/create/create.go | 10 +--------- .../cmd/observability/instance/delete/delete.go | 10 +--------- .../observability/instance/describe/describe.go | 10 +--------- internal/cmd/observability/instance/list/list.go | 10 +--------- .../cmd/observability/instance/update/update.go | 10 +--------- internal/cmd/observability/plans/plans.go | 10 +--------- .../cmd/opensearch/credentials/create/create.go | 10 +--------- .../cmd/opensearch/credentials/delete/delete.go | 10 +--------- .../opensearch/credentials/describe/describe.go | 10 +--------- internal/cmd/opensearch/credentials/list/list.go | 10 +--------- internal/cmd/opensearch/instance/create/create.go | 10 +--------- internal/cmd/opensearch/instance/delete/delete.go | 10 +--------- .../cmd/opensearch/instance/describe/describe.go | 10 +--------- internal/cmd/opensearch/instance/list/list.go | 10 +--------- internal/cmd/opensearch/instance/update/update.go | 10 +--------- internal/cmd/opensearch/plans/plans.go | 10 +--------- internal/cmd/organization/member/add/add.go | 10 +--------- internal/cmd/organization/member/list/list.go | 10 +--------- internal/cmd/organization/member/remove/remove.go | 10 +--------- internal/cmd/organization/role/list/list.go | 10 +--------- internal/cmd/postgresflex/instance/clone/clone.go | 10 +--------- .../cmd/postgresflex/instance/create/create.go | 10 +--------- .../cmd/postgresflex/instance/delete/delete.go | 10 +--------- .../cmd/postgresflex/instance/describe/describe.go | 10 +--------- internal/cmd/postgresflex/instance/list/list.go | 10 +--------- .../cmd/postgresflex/instance/update/update.go | 10 +--------- internal/cmd/postgresflex/options/options.go | 10 +--------- internal/cmd/postgresflex/user/create/create.go | 10 +--------- internal/cmd/postgresflex/user/delete/delete.go | 10 +--------- .../cmd/postgresflex/user/describe/describe.go | 10 +--------- internal/cmd/postgresflex/user/list/list.go | 10 +--------- .../user/reset-password/reset_password.go | 10 +--------- internal/cmd/postgresflex/user/update/update.go | 10 +--------- internal/cmd/project/create/create.go | 10 +--------- internal/cmd/project/delete/delete.go | 10 +--------- internal/cmd/project/describe/describe.go | 10 +--------- internal/cmd/project/list/list.go | 10 +--------- internal/cmd/project/member/add/add.go | 10 +--------- internal/cmd/project/member/list/list.go | 10 +--------- internal/cmd/project/member/remove/remove.go | 10 +--------- internal/cmd/project/role/list/list.go | 10 +--------- internal/cmd/project/update/update.go | 10 +--------- internal/cmd/public-ip/associate/associate.go | 10 +--------- internal/cmd/public-ip/create/create.go | 10 +--------- internal/cmd/public-ip/delete/delete.go | 10 +--------- internal/cmd/public-ip/describe/describe.go | 10 +--------- .../cmd/public-ip/disassociate/disassociate.go | 10 +--------- internal/cmd/public-ip/list/list.go | 10 +--------- internal/cmd/public-ip/ranges/list/list.go | 10 +--------- internal/cmd/public-ip/update/update.go | 10 +--------- internal/cmd/quota/list/list.go | 10 +--------- internal/cmd/rabbitmq/credentials/create/create.go | 10 +--------- internal/cmd/rabbitmq/credentials/delete/delete.go | 10 +--------- .../cmd/rabbitmq/credentials/describe/describe.go | 10 +--------- internal/cmd/rabbitmq/credentials/list/list.go | 10 +--------- internal/cmd/rabbitmq/instance/create/create.go | 10 +--------- internal/cmd/rabbitmq/instance/delete/delete.go | 10 +--------- .../cmd/rabbitmq/instance/describe/describe.go | 10 +--------- internal/cmd/rabbitmq/instance/list/list.go | 10 +--------- internal/cmd/rabbitmq/instance/update/update.go | 10 +--------- internal/cmd/rabbitmq/plans/plans.go | 10 +--------- internal/cmd/redis/credentials/create/create.go | 10 +--------- internal/cmd/redis/credentials/delete/delete.go | 10 +--------- .../cmd/redis/credentials/describe/describe.go | 10 +--------- internal/cmd/redis/credentials/list/list.go | 10 +--------- internal/cmd/redis/instance/create/create.go | 10 +--------- internal/cmd/redis/instance/delete/delete.go | 10 +--------- internal/cmd/redis/instance/describe/describe.go | 10 +--------- internal/cmd/redis/instance/list/list.go | 10 +--------- internal/cmd/redis/instance/update/update.go | 10 +--------- internal/cmd/redis/plans/plans.go | 10 +--------- .../cmd/secrets-manager/instance/create/create.go | 10 +--------- .../cmd/secrets-manager/instance/delete/delete.go | 10 +--------- .../secrets-manager/instance/describe/describe.go | 10 +--------- internal/cmd/secrets-manager/instance/list/list.go | 10 +--------- .../cmd/secrets-manager/instance/update/update.go | 10 +--------- internal/cmd/secrets-manager/user/create/create.go | 10 +--------- internal/cmd/secrets-manager/user/delete/delete.go | 10 +--------- .../cmd/secrets-manager/user/describe/describe.go | 10 +--------- internal/cmd/secrets-manager/user/list/list.go | 10 +--------- internal/cmd/secrets-manager/user/update/update.go | 10 +--------- internal/cmd/security-group/create/create.go | 10 +--------- internal/cmd/security-group/delete/delete.go | 10 +--------- internal/cmd/security-group/describe/describe.go | 10 +--------- internal/cmd/security-group/list/list.go | 10 +--------- internal/cmd/security-group/rule/create/create.go | 10 +--------- internal/cmd/security-group/rule/delete/delete.go | 10 +--------- .../cmd/security-group/rule/describe/describe.go | 10 +--------- internal/cmd/security-group/rule/list/list.go | 10 +--------- internal/cmd/security-group/update/update.go | 10 +--------- internal/cmd/server/backup/create/create.go | 10 +--------- internal/cmd/server/backup/delete/delete.go | 10 +--------- internal/cmd/server/backup/describe/describe.go | 10 +--------- internal/cmd/server/backup/disable/disable.go | 10 +--------- internal/cmd/server/backup/enable/enable.go | 10 +--------- internal/cmd/server/backup/list/list.go | 10 +--------- internal/cmd/server/backup/restore/restore.go | 10 +--------- .../cmd/server/backup/schedule/create/create.go | 10 +--------- .../cmd/server/backup/schedule/delete/delete.go | 10 +--------- .../server/backup/schedule/describe/describe.go | 10 +--------- internal/cmd/server/backup/schedule/list/list.go | 10 +--------- .../cmd/server/backup/schedule/update/update.go | 10 +--------- .../server/backup/volume-backup/delete/delete.go | 10 +--------- .../server/backup/volume-backup/restore/restore.go | 10 +--------- internal/cmd/server/command/create/create.go | 10 +--------- internal/cmd/server/command/describe/describe.go | 10 +--------- internal/cmd/server/command/list/list.go | 10 +--------- .../server/command/template/describe/describe.go | 10 +--------- internal/cmd/server/command/template/list/list.go | 10 +--------- internal/cmd/server/console/console.go | 10 +--------- internal/cmd/server/create/create.go | 10 +--------- internal/cmd/server/deallocate/deallocate.go | 10 +--------- internal/cmd/server/delete/delete.go | 10 +--------- internal/cmd/server/describe/describe.go | 10 +--------- internal/cmd/server/list/list.go | 10 +--------- internal/cmd/server/log/log.go | 10 +--------- .../cmd/server/machine-type/describe/describe.go | 10 +--------- internal/cmd/server/machine-type/list/list.go | 10 +--------- .../cmd/server/network-interface/attach/attach.go | 10 +--------- .../cmd/server/network-interface/detach/detach.go | 10 +--------- internal/cmd/server/network-interface/list/list.go | 10 +--------- internal/cmd/server/os-update/create/create.go | 10 +--------- internal/cmd/server/os-update/describe/describe.go | 10 +--------- internal/cmd/server/os-update/disable/disable.go | 10 +--------- internal/cmd/server/os-update/enable/enable.go | 10 +--------- internal/cmd/server/os-update/list/list.go | 10 +--------- .../cmd/server/os-update/schedule/create/create.go | 10 +--------- .../cmd/server/os-update/schedule/delete/delete.go | 10 +--------- .../server/os-update/schedule/describe/describe.go | 10 +--------- .../cmd/server/os-update/schedule/list/list.go | 10 +--------- .../cmd/server/os-update/schedule/update/update.go | 10 +--------- internal/cmd/server/public-ip/attach/attach.go | 10 +--------- internal/cmd/server/public-ip/detach/detach.go | 10 +--------- internal/cmd/server/reboot/reboot.go | 10 +--------- internal/cmd/server/rescue/rescue.go | 10 +--------- internal/cmd/server/resize/resize.go | 10 +--------- .../cmd/server/service-account/attach/attach.go | 10 +--------- .../cmd/server/service-account/detach/detach.go | 10 +--------- internal/cmd/server/service-account/list/list.go | 10 +--------- internal/cmd/server/start/start.go | 10 +--------- internal/cmd/server/stop/stop.go | 10 +--------- internal/cmd/server/unrescue/unrescue.go | 10 +--------- internal/cmd/server/update/update.go | 10 +--------- internal/cmd/server/volume/attach/attach.go | 10 +--------- internal/cmd/server/volume/describe/describe.go | 10 +--------- internal/cmd/server/volume/detach/detach.go | 10 +--------- internal/cmd/server/volume/list/list.go | 10 +--------- internal/cmd/server/volume/update/update.go | 10 +--------- internal/cmd/service-account/create/create.go | 10 +--------- internal/cmd/service-account/delete/delete.go | 10 +--------- internal/cmd/service-account/get-jwks/get_jwks.go | 10 +--------- internal/cmd/service-account/key/create/create.go | 10 +--------- internal/cmd/service-account/key/delete/delete.go | 10 +--------- .../cmd/service-account/key/describe/describe.go | 10 +--------- internal/cmd/service-account/key/list/list.go | 10 +--------- internal/cmd/service-account/key/update/update.go | 10 +--------- internal/cmd/service-account/list/list.go | 10 +--------- .../cmd/service-account/token/create/create.go | 10 +--------- internal/cmd/service-account/token/list/list.go | 10 +--------- .../cmd/service-account/token/revoke/revoke.go | 10 +--------- internal/cmd/ske/cluster/create/create.go | 10 +--------- internal/cmd/ske/cluster/delete/delete.go | 10 +--------- internal/cmd/ske/cluster/describe/describe.go | 10 +--------- .../cluster/generate-payload/generate_payload.go | 10 +--------- internal/cmd/ske/cluster/hibernate/hibernate.go | 10 +--------- internal/cmd/ske/cluster/list/list.go | 10 +--------- .../cmd/ske/cluster/maintenance/maintenance.go | 10 +--------- internal/cmd/ske/cluster/reconcile/reconcile.go | 10 +--------- internal/cmd/ske/cluster/update/update.go | 10 +--------- internal/cmd/ske/cluster/wakeup/wakeup.go | 10 +--------- .../complete-rotation/complete_rotation.go | 10 +--------- .../credentials/start-rotation/start_rotation.go | 10 +--------- internal/cmd/ske/describe/describe.go | 10 +--------- internal/cmd/ske/disable/disable.go | 10 +--------- internal/cmd/ske/enable/enable.go | 10 +--------- internal/cmd/ske/kubeconfig/create/create.go | 10 +--------- internal/cmd/ske/options/options.go | 10 +--------- internal/cmd/volume/backup/create/create.go | 10 +--------- internal/cmd/volume/backup/delete/delete.go | 10 +--------- internal/cmd/volume/backup/describe/describe.go | 10 +--------- internal/cmd/volume/backup/list/list.go | 10 +--------- internal/cmd/volume/backup/restore/restore.go | 10 +--------- internal/cmd/volume/backup/update/update.go | 10 +--------- internal/cmd/volume/create/create.go | 10 +--------- internal/cmd/volume/delete/delete.go | 10 +--------- internal/cmd/volume/describe/describe.go | 10 +--------- internal/cmd/volume/list/list.go | 10 +--------- .../volume/performance-class/describe/describe.go | 10 +--------- internal/cmd/volume/performance-class/list/list.go | 10 +--------- internal/cmd/volume/resize/resize.go | 10 +--------- internal/cmd/volume/snapshot/create/create.go | 10 +--------- internal/cmd/volume/snapshot/delete/delete.go | 10 +--------- internal/cmd/volume/snapshot/describe/describe.go | 10 +--------- internal/cmd/volume/snapshot/list/list.go | 10 +--------- internal/cmd/volume/snapshot/update/update.go | 10 +--------- internal/cmd/volume/update/update.go | 10 +--------- internal/pkg/print/debug.go | 4 ++-- internal/pkg/print/debug_test.go | 2 +- internal/pkg/print/print.go | 14 +++++++++++++- 363 files changed, 377 insertions(+), 3237 deletions(-) diff --git a/.github/docs/contribution-guide/cmd.go b/.github/docs/contribution-guide/cmd.go index 175a9a6d3..286d6240d 100644 --- a/.github/docs/contribution-guide/cmd.go +++ b/.github/docs/contribution-guide/cmd.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } // Write the input model to the debug logs - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index 21a668d8c..47d79abda 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -53,7 +53,7 @@ Please remember to run `make generate-docs` after your changes to keep the comma Below is a typical structure of a CLI command: -https://github.com/stackitcloud/stackit-cli/blob/85ce44cd18d11169f2548d8657031b5fc6f94740/.github/docs/contribution-guide/cmd.go#L23-L156 +https://github.com/stackitcloud/stackit-cli/blob/main/.github/docs/contribution-guide/cmd.go Please remember to always add unit tests for `parseInput`, `buildRequest` (in `bar_test.go`), and any other util functions used. @@ -87,7 +87,7 @@ If you want to add a command that uses a STACKIT service `foo` that was not yet 1. This is done in `internal/pkg/services/foo/client/client.go` 2. Below is an example of a typical `client.go` file structure: -https://github.com/stackitcloud/stackit-cli/blob/85ce44cd18d11169f2548d8657031b5fc6f94740/.github/docs/contribution-guide/client.go#L12-L35 +https://github.com/stackitcloud/stackit-cli/blob/main/.github/docs/contribution-guide/client.go ### Local development diff --git a/internal/cmd/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go index 60b14fdd1..03a4354f9 100644 --- a/internal/cmd/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -112,15 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Policy: flags.FlagToStringValue(p, cmd, policyFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/affinity-groups/delete/delete.go b/internal/cmd/affinity-groups/delete/delete.go index a05c2e7bc..59532f96d 100644 --- a/internal/cmd/affinity-groups/delete/delete.go +++ b/internal/cmd/affinity-groups/delete/delete.go @@ -101,14 +101,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM AffinityGroupId: cliArgs[0], } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/affinity-groups/describe/describe.go b/internal/cmd/affinity-groups/describe/describe.go index 6abd3980c..936db9605 100644 --- a/internal/cmd/affinity-groups/describe/describe.go +++ b/internal/cmd/affinity-groups/describe/describe.go @@ -84,15 +84,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM AffinityGroupId: cliArgs[0], } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/affinity-groups/list/list.go b/internal/cmd/affinity-groups/list/list.go index 5665a970c..58269d898 100644 --- a/internal/cmd/affinity-groups/list/list.go +++ b/internal/cmd/affinity-groups/list/list.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/auth/activate-service-account/activate_service_account.go b/internal/cmd/auth/activate-service-account/activate_service_account.go index 5ddc73f29..1246dcd98 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account.go @@ -121,15 +121,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { OnlyPrintAccessToken: flags.FlagToBoolValue(p, cmd, onlyPrintAccessTokenFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model } diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index 39bb3be7d..8db52f60e 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -77,14 +77,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go index 2622a3ce4..a9113a5f0 100644 --- a/internal/cmd/beta/alb/create/create.go +++ b/internal/cmd/beta/alb/create/create.go @@ -118,15 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Configuration: flags.FlagToStringPointer(p, cmd, configurationFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/delete/delete.go b/internal/cmd/beta/alb/delete/delete.go index 25886cd40..d7dfe1c50 100644 --- a/internal/cmd/beta/alb/delete/delete.go +++ b/internal/cmd/beta/alb/delete/delete.go @@ -87,15 +87,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Name: loadbalancerName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/describe/describe.go b/internal/cmd/beta/alb/describe/describe.go index 67a10bf4a..8d61212a3 100644 --- a/internal/cmd/beta/alb/describe/describe.go +++ b/internal/cmd/beta/alb/describe/describe.go @@ -81,15 +81,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Name: loadbalancerName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go index a4d1480db..7958a1ad8 100644 --- a/internal/cmd/beta/alb/list/list.go +++ b/internal/cmd/beta/alb/list/list.go @@ -118,15 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/observability-credentials/add/add.go b/internal/cmd/beta/alb/observability-credentials/add/add.go index 86b6ac2b9..7b623ef16 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add.go @@ -96,15 +96,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Password: flags.FlagToStringPointer(p, cmd, passwordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string fo debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete.go b/internal/cmd/beta/alb/observability-credentials/delete/delete.go index ccf998580..8270d4df0 100644 --- a/internal/cmd/beta/alb/observability-credentials/delete/delete.go +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete.go @@ -82,15 +82,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsRef: credentialRef, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe.go b/internal/cmd/beta/alb/observability-credentials/describe/describe.go index 001e20278..882ac0a02 100644 --- a/internal/cmd/beta/alb/observability-credentials/describe/describe.go +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe.go @@ -80,15 +80,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialRef: credentialRef, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/observability-credentials/list/list.go b/internal/cmd/beta/alb/observability-credentials/list/list.go index 32baa31c6..613ba9c24 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list.go @@ -108,15 +108,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.InfoLevel, modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/observability-credentials/update/update.go b/internal/cmd/beta/alb/observability-credentials/update/update.go index 18b68ccb4..e9ff003e8 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) inputM Password: flags.FlagToStringPointer(p, cmd, passwordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return model } diff --git a/internal/cmd/beta/alb/plans/plans.go b/internal/cmd/beta/alb/plans/plans.go index d131422ad..b6698ce2e 100644 --- a/internal/cmd/beta/alb/plans/plans.go +++ b/internal/cmd/beta/alb/plans/plans.go @@ -90,15 +90,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/pool/update/update.go b/internal/cmd/beta/alb/pool/update/update.go index 2dc8cd3a2..857ae2a44 100644 --- a/internal/cmd/beta/alb/pool/update/update.go +++ b/internal/cmd/beta/alb/pool/update/update.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { AlbName: flags.FlagToStringPointer(p, cmd, albNameFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/quotas/quotas.go b/internal/cmd/beta/alb/quotas/quotas.go index c0ce6948b..3eec45f7d 100644 --- a/internal/cmd/beta/alb/quotas/quotas.go +++ b/internal/cmd/beta/alb/quotas/quotas.go @@ -82,15 +82,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/template/template.go b/internal/cmd/beta/alb/template/template.go index c33ca2846..c1dad5350 100644 --- a/internal/cmd/beta/alb/template/template.go +++ b/internal/cmd/beta/alb/template/template.go @@ -112,14 +112,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Type: flags.FlagToStringPointer(p, cmd, typeFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go index 2dcfddbb1..6040762a5 100644 --- a/internal/cmd/beta/alb/update/update.go +++ b/internal/cmd/beta/alb/update/update.go @@ -125,15 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Configuration: flags.FlagToStringPointer(p, cmd, configurationFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index f8ae03ccd..d643d8da7 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Owner: flags.FlagToStringValue(p, cmd, ownerFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete.go b/internal/cmd/beta/sqlserverflex/database/delete/delete.go index 0f2b221f7..bc19533dc 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete.go @@ -104,15 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: flags.FlagToStringValue(p, cmd, instanceIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index 377d90476..7c460f3e5 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -93,15 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: flags.FlagToStringValue(p, cmd, instanceIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index 707922ef9..f8675f0b9 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -120,15 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index b30d7615c..4b31bef84 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -196,15 +196,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { RetentionDays: flags.FlagToInt64Pointer(p, cmd, retentionDaysFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go index ab1742879..0fcd25dd5 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index d8e3a60c3..bed2f269c 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -82,15 +82,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 945eb5024..3b97b8dcb 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index c857aba35..68e76cf25 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -183,15 +183,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index d5d62c10b..f288fd27d 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -190,15 +190,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 7cd803ec7..92e4a1127 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Roles: flags.FlagToStringSlicePointer(p, cmd, rolesFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete.go b/internal/cmd/beta/sqlserverflex/user/delete/delete.go index 8250b1b01..31869cdda 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index 1d94890ac..cd4efd01b 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -102,15 +102,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index c45317bf2..022aade17 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -121,15 +121,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index 35ef24063..027ba4b44 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/config/profile/create/create.go b/internal/cmd/config/profile/create/create.go index 4d93bdd72..608fe85da 100644 --- a/internal/cmd/config/profile/create/create.go +++ b/internal/cmd/config/profile/create/create.go @@ -105,14 +105,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu NoSet: flags.FlagToBoolValue(p, cmd, noSetFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/config/profile/delete/delete.go b/internal/cmd/config/profile/delete/delete.go index 02c04e64a..98b7bf2e2 100644 --- a/internal/cmd/config/profile/delete/delete.go +++ b/internal/cmd/config/profile/delete/delete.go @@ -106,14 +106,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Profile: profile, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/config/profile/export/export.go b/internal/cmd/config/profile/export/export.go index 59389b47a..9051ea368 100644 --- a/internal/cmd/config/profile/export/export.go +++ b/internal/cmd/config/profile/export/export.go @@ -85,14 +85,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model.FilePath = filepath.Join(model.FilePath, exportFileName) } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/config/profile/import/import.go b/internal/cmd/config/profile/import/import.go index 84bd9b3aa..82f8229dd 100644 --- a/internal/cmd/config/profile/import/import.go +++ b/internal/cmd/config/profile/import/import.go @@ -94,14 +94,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return model, nil } diff --git a/internal/cmd/config/profile/set/set.go b/internal/cmd/config/profile/set/set.go index 0784d4654..77101092f 100644 --- a/internal/cmd/config/profile/set/set.go +++ b/internal/cmd/config/profile/set/set.go @@ -90,14 +90,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Profile: profile, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 54f9f527d..841f8e66e 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -246,15 +246,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ProjectIdSet: projectIdSet, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index a288be6a3..e7b6fd6fa 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -294,14 +294,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { TokenCustomEndpoint: flags.FlagToBoolValue(p, cmd, tokenCustomEndpointFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model } diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index afe797a28..57e823f26 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -154,15 +154,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu OutputFile: flags.FlagToStringPointer(p, cmd, outputFileFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 045f6ce29..c1fae768e 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -157,15 +157,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/record-set/delete/delete.go b/internal/cmd/dns/record-set/delete/delete.go index 015b8019d..4dde11375 100644 --- a/internal/cmd/dns/record-set/delete/delete.go +++ b/internal/cmd/dns/record-set/delete/delete.go @@ -131,15 +131,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu RecordSetId: recordSetId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/record-set/describe/describe.go b/internal/cmd/dns/record-set/describe/describe.go index c7d5e8c52..ceaf1a9d9 100644 --- a/internal/cmd/dns/record-set/describe/describe.go +++ b/internal/cmd/dns/record-set/describe/describe.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu RecordSetId: recordSetId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index a1b59553b..cafaf9921 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -165,15 +165,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { PageSize: pageSize, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/record-set/update/update.go b/internal/cmd/dns/record-set/update/update.go index 74630d455..62f01376f 100644 --- a/internal/cmd/dns/record-set/update/update.go +++ b/internal/cmd/dns/record-set/update/update.go @@ -169,15 +169,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu TTL: ttl, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index 7d81f13f8..c8292c59f 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -137,15 +137,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ZoneId: zoneId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 081602f18..ebcbc273e 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -175,15 +175,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ContactEmail: flags.FlagToStringPointer(p, cmd, contactEmailFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/zone/delete/delete.go b/internal/cmd/dns/zone/delete/delete.go index 443bbf186..a3c8ce8dc 100644 --- a/internal/cmd/dns/zone/delete/delete.go +++ b/internal/cmd/dns/zone/delete/delete.go @@ -110,15 +110,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ZoneId: zoneId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/zone/describe/describe.go b/internal/cmd/dns/zone/describe/describe.go index d68bbb177..0caf4ab55 100644 --- a/internal/cmd/dns/zone/describe/describe.go +++ b/internal/cmd/dns/zone/describe/describe.go @@ -82,15 +82,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ZoneId: zoneId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index c3de2d640..c61e58e3f 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -156,15 +156,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { PageSize: pageSize, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/dns/zone/update/update.go b/internal/cmd/dns/zone/update/update.go index d7575c609..161b0e338 100644 --- a/internal/cmd/dns/zone/update/update.go +++ b/internal/cmd/dns/zone/update/update.go @@ -176,15 +176,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ContactEmail: contactEmail, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/git/flavor/list/list.go b/internal/cmd/git/flavor/list/list.go index aec140d80..c562a6b67 100644 --- a/internal/cmd/git/flavor/list/list.go +++ b/internal/cmd/git/flavor/list/list.go @@ -104,15 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index 761c2be61..15a46c1fc 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -130,15 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Acl: acl, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/git/instance/delete/delete.go b/internal/cmd/git/instance/delete/delete.go index c16a6b09e..01f6f3f19 100644 --- a/internal/cmd/git/instance/delete/delete.go +++ b/internal/cmd/git/instance/delete/delete.go @@ -116,15 +116,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM InstanceId: cliArgs[0], } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/git/instance/describe/describe.go b/internal/cmd/git/instance/describe/describe.go index 8e2f266e1..08d9611ae 100644 --- a/internal/cmd/git/instance/describe/describe.go +++ b/internal/cmd/git/instance/describe/describe.go @@ -79,15 +79,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM InstanceId: cliArgs[0], } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/git/instance/list/list.go b/internal/cmd/git/instance/list/list.go index 0057342ff..f0dd2d07b 100644 --- a/internal/cmd/git/instance/list/list.go +++ b/internal/cmd/git/instance/list/list.go @@ -105,15 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 3ffe26a68..fbfe766aa 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -329,15 +329,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Protected: flags.FlagToBoolPointer(p, cmd, protectedFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/image/delete/delete.go b/internal/cmd/image/delete/delete.go index 10a49e46d..80f7f2dc8 100644 --- a/internal/cmd/image/delete/delete.go +++ b/internal/cmd/image/delete/delete.go @@ -93,15 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM ImageId: cliArgs[0], } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/image/describe/describe.go b/internal/cmd/image/describe/describe.go index 9a5e5e918..0a8af40bb 100644 --- a/internal/cmd/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -84,15 +84,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM ImageId: cliArgs[0], } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index 57280b383..cb19bd651 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -125,15 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index e434f1238..434fc0ea8 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -233,15 +233,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM model.Config = nil } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go index a95ee34ec..64c0a63b9 100644 --- a/internal/cmd/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { PublicKey: flags.FlagToStringPointer(p, cmd, publicKeyFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string fo debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/key-pair/delete/delete.go b/internal/cmd/key-pair/delete/delete.go index 376d21174..5d6c5cdb7 100644 --- a/internal/cmd/key-pair/delete/delete.go +++ b/internal/cmd/key-pair/delete/delete.go @@ -82,15 +82,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu KeyPairName: keyPairName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/key-pair/describe/describe.go b/internal/cmd/key-pair/describe/describe.go index 8de535589..36addd3b8 100644 --- a/internal/cmd/key-pair/describe/describe.go +++ b/internal/cmd/key-pair/describe/describe.go @@ -98,15 +98,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu PublicKey: flags.FlagToBoolValue(p, cmd, publicKeyFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/key-pair/list/list.go b/internal/cmd/key-pair/list/list.go index b614cf5c1..e185d6767 100644 --- a/internal/cmd/key-pair/list/list.go +++ b/internal/cmd/key-pair/list/list.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.InfoLevel, modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/key-pair/update/update.go b/internal/cmd/key-pair/update/update.go index b8b7ffbbd..2da8a409c 100644 --- a/internal/cmd/key-pair/update/update.go +++ b/internal/cmd/key-pair/update/update.go @@ -103,15 +103,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) inputM KeyPairName: utils.Ptr(keyPairName), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return model } diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index f59683a47..edc927496 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -143,15 +143,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Payload: payload, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/delete/delete.go b/internal/cmd/load-balancer/delete/delete.go index 84146f875..e2cd2b37c 100644 --- a/internal/cmd/load-balancer/delete/delete.go +++ b/internal/cmd/load-balancer/delete/delete.go @@ -100,15 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu LoadBalancerName: loadBalancerName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index 2b5ff659d..df1403a14 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -82,15 +82,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu LoadBalancerName: loadBalancerName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index 42cbb4a59..a3bffa93e 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -196,15 +196,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { FilePath: flags.FlagToStringPointer(p, cmd, filePathFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index 02a1f30ed..511bee335 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index 533a222f4..7a2cd20ae 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -121,15 +121,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Password: flags.FlagToStringPointer(p, cmd, passwordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go index 3bcf0190a..718884c9c 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go @@ -118,15 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete.go b/internal/cmd/load-balancer/observability-credentials/delete/delete.go index bef2362b9..a26da465f 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete.go @@ -98,15 +98,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsRef: credentialsRef, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index 85c32ba7f..b9559e90a 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -79,15 +79,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsRef: credentialsRef, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 714364c47..138003fdd 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -150,15 +150,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Unused: flags.FlagToBoolValue(p, cmd, unusedFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index 2925d7f52..76b363838 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -69,15 +69,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target.go b/internal/cmd/load-balancer/target-pool/add-target/add_target.go index 46faf8bb9..1612628fd 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target.go @@ -112,15 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu IP: ip, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index ea0f6dace..ed8eddc51 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -103,15 +103,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu LBName: cmd.Flag(lbNameFlag).Value.String(), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go index 3ca65c79b..923521b40 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go @@ -112,15 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu IP: ip, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/load-balancer/update/update.go b/internal/cmd/load-balancer/update/update.go index db183702d..47c4e5d80 100644 --- a/internal/cmd/load-balancer/update/update.go +++ b/internal/cmd/load-balancer/update/update.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Payload: payload, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index c1e44ccff..de6cab21f 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ShowPassword: flags.FlagToBoolValue(p, cmd, showPasswordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/credentials/delete/delete.go b/internal/cmd/logme/credentials/delete/delete.go index fabd2b838..0766f8e5a 100644 --- a/internal/cmd/logme/credentials/delete/delete.go +++ b/internal/cmd/logme/credentials/delete/delete.go @@ -111,15 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/credentials/describe/describe.go b/internal/cmd/logme/credentials/describe/describe.go index 240df0f81..1af434056 100644 --- a/internal/cmd/logme/credentials/describe/describe.go +++ b/internal/cmd/logme/credentials/describe/describe.go @@ -95,15 +95,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index 218dff2d1..d9f572e2f 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -119,15 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index ca00f4cdc..5004c8dfb 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -186,15 +186,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/instance/delete/delete.go b/internal/cmd/logme/instance/delete/delete.go index 905c51bed..f606a2cee 100644 --- a/internal/cmd/logme/instance/delete/delete.go +++ b/internal/cmd/logme/instance/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/instance/describe/describe.go b/internal/cmd/logme/instance/describe/describe.go index bf7892373..9acac7ce7 100644 --- a/internal/cmd/logme/instance/describe/describe.go +++ b/internal/cmd/logme/instance/describe/describe.go @@ -83,15 +83,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index e325aee95..def82f0e0 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/instance/update/update.go b/internal/cmd/logme/instance/update/update.go index a7e3ec443..97e016723 100644 --- a/internal/cmd/logme/instance/update/update.go +++ b/internal/cmd/logme/instance/update/update.go @@ -196,15 +196,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index 8c339a1ee..c8b28f0ba 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index cf42e1ca2..80077c4ce 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -107,15 +107,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ShowPassword: flags.FlagToBoolValue(p, cmd, showPasswordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/credentials/delete/delete.go b/internal/cmd/mariadb/credentials/delete/delete.go index cbce0078d..8b8934e36 100644 --- a/internal/cmd/mariadb/credentials/delete/delete.go +++ b/internal/cmd/mariadb/credentials/delete/delete.go @@ -111,15 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/credentials/describe/describe.go b/internal/cmd/mariadb/credentials/describe/describe.go index 7a03a4377..32d547403 100644 --- a/internal/cmd/mariadb/credentials/describe/describe.go +++ b/internal/cmd/mariadb/credentials/describe/describe.go @@ -95,15 +95,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index f9a3f43d7..a113fd11e 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -118,15 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index b84368fa2..e90e6c0d8 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -186,15 +186,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/instance/delete/delete.go b/internal/cmd/mariadb/instance/delete/delete.go index eaca7989a..2f192e7c3 100644 --- a/internal/cmd/mariadb/instance/delete/delete.go +++ b/internal/cmd/mariadb/instance/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/instance/describe/describe.go b/internal/cmd/mariadb/instance/describe/describe.go index 58f07db66..7775584e3 100644 --- a/internal/cmd/mariadb/instance/describe/describe.go +++ b/internal/cmd/mariadb/instance/describe/describe.go @@ -83,15 +83,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index 7e5b8e0d6..e648f7baa 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/instance/update/update.go b/internal/cmd/mariadb/instance/update/update.go index 26059ff6f..bf16d188d 100644 --- a/internal/cmd/mariadb/instance/update/update.go +++ b/internal/cmd/mariadb/instance/update/update.go @@ -194,15 +194,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index c54703a1e..c8b89e937 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index a1ca3aeaf..e36e875ed 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BackupId: backupId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index 64187cf64..c15bb538b 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -128,15 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index 7f529891e..36e3a7ab7 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index 5c64f6aef..1d547a486 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -171,15 +171,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Timestamp: flags.FlagToStringValue(p, cmd, timestampFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index 9117e83d9..b75275f49 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -87,15 +87,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { InstanceId: *flags.FlagToStringPointer(p, cmd, instanceIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 28a65e394..fae577334 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -195,15 +195,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Type: utils.Ptr(flags.FlagWithDefaultToStringValue(p, cmd, typeFlag)), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/instance/delete/delete.go b/internal/cmd/mongodbflex/instance/delete/delete.go index b63d61d63..5ae1da16a 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete.go +++ b/internal/cmd/mongodbflex/instance/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index 0a5c11e54..7c2c296a0 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -83,15 +83,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index fa30c47ca..a901516bf 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index 5c11a7ee6..3240c7f8e 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -187,15 +187,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Type: instanceType, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 53499547e..513dad9a9 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -125,15 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { FlavorId: flags.FlagToStringPointer(p, cmd, flavorIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index 2ddf76d34..e1e7a00cf 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -128,15 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Roles: flags.FlagWithDefaultToStringSlicePointer(p, cmd, roleFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/user/delete/delete.go b/internal/cmd/mongodbflex/user/delete/delete.go index 05e72686b..b945f5ad3 100644 --- a/internal/cmd/mongodbflex/user/delete/delete.go +++ b/internal/cmd/mongodbflex/user/delete/delete.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/user/describe/describe.go b/internal/cmd/mongodbflex/user/describe/describe.go index 410896fc9..876b63022 100644 --- a/internal/cmd/mongodbflex/user/describe/describe.go +++ b/internal/cmd/mongodbflex/user/describe/describe.go @@ -101,15 +101,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index d9e947e9c..ef184883f 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index c58dfd020..ba0b169c2 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/mongodbflex/user/update/update.go b/internal/cmd/mongodbflex/user/update/update.go index 5f192f377..df408025e 100644 --- a/internal/cmd/mongodbflex/user/update/update.go +++ b/internal/cmd/mongodbflex/user/update/update.go @@ -130,15 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Roles: roles, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index 870e6a439..e6be49171 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -150,15 +150,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/delete/delete.go b/internal/cmd/network-area/delete/delete.go index b545fca4b..d16a9e656 100644 --- a/internal/cmd/network-area/delete/delete.go +++ b/internal/cmd/network-area/delete/delete.go @@ -121,15 +121,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu AreaId: areaId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/describe/describe.go b/internal/cmd/network-area/describe/describe.go index e086f3dd9..49c28d7ce 100644 --- a/internal/cmd/network-area/describe/describe.go +++ b/internal/cmd/network-area/describe/describe.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ShowAttachedProjects: flags.FlagToBoolValue(p, cmd, showAttachedProjectsFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/list/list.go b/internal/cmd/network-area/list/list.go index aef31e48b..94c0ffd8f 100644 --- a/internal/cmd/network-area/list/list.go +++ b/internal/cmd/network-area/list/list.go @@ -137,15 +137,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go index cdc54b800..9dbd2878d 100644 --- a/internal/cmd/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { NetworkRange: flags.FlagToStringPointer(p, cmd, networkRangeFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/network-range/delete/delete.go b/internal/cmd/network-area/network-range/delete/delete.go index feec26e6b..12126917e 100644 --- a/internal/cmd/network-area/network-range/delete/delete.go +++ b/internal/cmd/network-area/network-range/delete/delete.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu NetworkRangeId: networkRangeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/network-range/describe/describe.go b/internal/cmd/network-area/network-range/describe/describe.go index d594ebb64..a16098a9c 100644 --- a/internal/cmd/network-area/network-range/describe/describe.go +++ b/internal/cmd/network-area/network-range/describe/describe.go @@ -92,15 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu NetworkRangeId: networkRangeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go index e4531121f..cb33cccbe 100644 --- a/internal/cmd/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -125,15 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index bc0eaf5c3..82e8e9ae4 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -130,15 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/route/delete/delete.go b/internal/cmd/network-area/route/delete/delete.go index 114a5d11d..254e7fb7a 100644 --- a/internal/cmd/network-area/route/delete/delete.go +++ b/internal/cmd/network-area/route/delete/delete.go @@ -105,15 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu RouteId: routeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/route/describe/describe.go b/internal/cmd/network-area/route/describe/describe.go index e58a3a2d5..89d743d91 100644 --- a/internal/cmd/network-area/route/describe/describe.go +++ b/internal/cmd/network-area/route/describe/describe.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu RouteId: routeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go index 2ea248551..989de2618 100644 --- a/internal/cmd/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -124,15 +124,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go index f644da320..1903833df 100644 --- a/internal/cmd/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Labels: labels, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-area/update/update.go b/internal/cmd/network-area/update/update.go index 0cc0e2e1e..0df8d0880 100644 --- a/internal/cmd/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -138,15 +138,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index f96687591..bd4b71de2 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -192,15 +192,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { model.AllowedAddresses = utils.Ptr(allowedAddressesInner) } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-interface/delete/delete.go b/internal/cmd/network-interface/delete/delete.go index 8450f5abc..043e41217 100644 --- a/internal/cmd/network-interface/delete/delete.go +++ b/internal/cmd/network-interface/delete/delete.go @@ -94,15 +94,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu NicId: nicId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-interface/describe/describe.go b/internal/cmd/network-interface/describe/describe.go index b221a0b1b..0dcb12171 100644 --- a/internal/cmd/network-interface/describe/describe.go +++ b/internal/cmd/network-interface/describe/describe.go @@ -100,15 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu NicId: nicId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go index eeb3c9be6..b40a7fa2e 100644 --- a/internal/cmd/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -133,15 +133,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go index 92b3e02ab..5a85d593a 100644 --- a/internal/cmd/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -184,15 +184,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model.AllowedAddresses = utils.Ptr(allowedAddressesInner) } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index ce5871590..6b4461924 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -185,15 +185,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network/delete/delete.go b/internal/cmd/network/delete/delete.go index 005c3e312..473edf34b 100644 --- a/internal/cmd/network/delete/delete.go +++ b/internal/cmd/network/delete/delete.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu NetworkId: networkId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network/describe/describe.go b/internal/cmd/network/describe/describe.go index b4c12a317..91be6d04e 100644 --- a/internal/cmd/network/describe/describe.go +++ b/internal/cmd/network/describe/describe.go @@ -85,15 +85,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu NetworkId: networkId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network/list/list.go b/internal/cmd/network/list/list.go index 2584d7fd7..c9689f845 100644 --- a/internal/cmd/network/list/list.go +++ b/internal/cmd/network/list/list.go @@ -127,15 +127,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/network/update/update.go b/internal/cmd/network/update/update.go index 712342cfc..8527a901f 100644 --- a/internal/cmd/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -163,15 +163,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index fd899a4d2..b1da202f6 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -110,15 +110,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BucketName: bucketName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/bucket/delete/delete.go b/internal/cmd/object-storage/bucket/delete/delete.go index fa4e68e99..eb47d1bd7 100644 --- a/internal/cmd/object-storage/bucket/delete/delete.go +++ b/internal/cmd/object-storage/bucket/delete/delete.go @@ -101,15 +101,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BucketName: bucketName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index 4112c0674..e5728d549 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -81,15 +81,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BucketName: bucketName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index 8060094c1..d2ec16c9c 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index dac9c248c..a531e49fd 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -93,15 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { CredentialsGroupName: flags.FlagToStringValue(p, cmd, credentialsGroupNameFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/credentials-group/delete/delete.go b/internal/cmd/object-storage/credentials-group/delete/delete.go index ff880c0f7..6a328b875 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete.go @@ -92,15 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsGroupId: credentialsGroupId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index ccea6fc84..166e0b91a 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -105,15 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index 5a809c8d1..b713331c6 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { CredentialsGroupId: flags.FlagToStringValue(p, cmd, credentialsGroupIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/credentials/delete/delete.go b/internal/cmd/object-storage/credentials/delete/delete.go index dea8797b0..5cab91f49 100644 --- a/internal/cmd/object-storage/credentials/delete/delete.go +++ b/internal/cmd/object-storage/credentials/delete/delete.go @@ -108,15 +108,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index 211ac8d77..eaf04b011 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -119,15 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/disable/disable.go b/internal/cmd/object-storage/disable/disable.go index f6b8ee848..f5cec2175 100644 --- a/internal/cmd/object-storage/disable/disable.go +++ b/internal/cmd/object-storage/disable/disable.go @@ -87,15 +87,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/object-storage/enable/enable.go b/internal/cmd/object-storage/enable/enable.go index 6a064bb3c..fe9fa549e 100644 --- a/internal/cmd/object-storage/enable/enable.go +++ b/internal/cmd/object-storage/enable/enable.go @@ -87,15 +87,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index 2ad9103e6..1b425fc20 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -103,15 +103,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ShowPassword: flags.FlagToBoolValue(p, cmd, showPasswordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/grafana/public-read-access/disable/disable.go b/internal/cmd/observability/grafana/public-read-access/disable/disable.go index 5696bf623..bfb42108c 100644 --- a/internal/cmd/observability/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/grafana/public-read-access/enable/enable.go b/internal/cmd/observability/grafana/public-read-access/enable/enable.go index 7cd00b9e2..b868c0535 100644 --- a/internal/cmd/observability/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go index bf6de05a4..a26977645 100644 --- a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go index 84b2bc0c4..f95812d80 100644 --- a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 37f3a8114..bf1a3de39 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -149,15 +149,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { PlanName: planName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/instance/delete/delete.go b/internal/cmd/observability/instance/delete/delete.go index ff0d1bd62..165c74f05 100644 --- a/internal/cmd/observability/instance/delete/delete.go +++ b/internal/cmd/observability/instance/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go index 506bdcbc1..cd65f868a 100644 --- a/internal/cmd/observability/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -81,15 +81,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index 011842a4e..a234f18cc 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/instance/update/update.go b/internal/cmd/observability/instance/update/update.go index b314a6ecc..d4ae51392 100644 --- a/internal/cmd/observability/instance/update/update.go +++ b/internal/cmd/observability/instance/update/update.go @@ -158,15 +158,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceName: instanceName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index 7fe3feabf..3473e645b 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index fdc2760f7..8af402191 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ShowPassword: flags.FlagToBoolValue(p, cmd, showPasswordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/credentials/delete/delete.go b/internal/cmd/opensearch/credentials/delete/delete.go index faccd169e..c513cb55e 100644 --- a/internal/cmd/opensearch/credentials/delete/delete.go +++ b/internal/cmd/opensearch/credentials/delete/delete.go @@ -111,15 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index 92bdf6350..531a9d9cb 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -95,15 +95,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index 0efb58d37..b3a0cbdfc 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -119,15 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index bc41bfbed..6476f8cc3 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -190,15 +190,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/instance/delete/delete.go b/internal/cmd/opensearch/instance/delete/delete.go index e0ed0db20..7d5996c6b 100644 --- a/internal/cmd/opensearch/instance/delete/delete.go +++ b/internal/cmd/opensearch/instance/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index da181a5a4..ef746f2c3 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -83,15 +83,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index e32b425e5..3d27f7c0b 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/instance/update/update.go b/internal/cmd/opensearch/instance/update/update.go index 254a9a41b..3b1114780 100644 --- a/internal/cmd/opensearch/instance/update/update.go +++ b/internal/cmd/opensearch/instance/update/update.go @@ -200,15 +200,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index c096fb230..a4f0b06fb 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/organization/member/add/add.go b/internal/cmd/organization/member/add/add.go index d3dd1f81b..297e64c33 100644 --- a/internal/cmd/organization/member/add/add.go +++ b/internal/cmd/organization/member/add/add.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Role: flags.FlagToStringPointer(p, cmd, roleFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index 6e414d257..b46f7705f 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -124,15 +124,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { SortBy: flags.FlagWithDefaultToStringValue(p, cmd, sortByFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/organization/member/remove/remove.go b/internal/cmd/organization/member/remove/remove.go index 6281b4214..f79075bdb 100644 --- a/internal/cmd/organization/member/remove/remove.go +++ b/internal/cmd/organization/member/remove/remove.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Force: flags.FlagToBoolValue(p, cmd, forceFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index c16d145c2..710738559 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index 2967fdbb3..2b43420ce 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -150,15 +150,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu RecoveryDate: utils.Ptr(recoveryTimestampString), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 7def7878c..d6664835f 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -196,15 +196,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Type: utils.Ptr(flags.FlagWithDefaultToStringValue(p, cmd, typeFlag)), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/instance/delete/delete.go b/internal/cmd/postgresflex/instance/delete/delete.go index 1c892657d..5b8cbbd91 100644 --- a/internal/cmd/postgresflex/instance/delete/delete.go +++ b/internal/cmd/postgresflex/instance/delete/delete.go @@ -159,15 +159,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ForceDelete: flags.FlagToBoolValue(p, cmd, forceDeleteFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/instance/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index 9d58c781b..78898aa7d 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -84,15 +84,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index 2431afa89..90a9a1a40 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 3a50f8dfa..4448ffd00 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -187,15 +187,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Type: instanceType, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index c327e030b..9e988dd6e 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -129,15 +129,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { FlavorId: flags.FlagToStringPointer(p, cmd, flavorIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 00e214089..88d377391 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Roles: flags.FlagWithDefaultToStringSlicePointer(p, cmd, roleFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/user/delete/delete.go b/internal/cmd/postgresflex/user/delete/delete.go index 925453632..38b20dbfe 100644 --- a/internal/cmd/postgresflex/user/delete/delete.go +++ b/internal/cmd/postgresflex/user/delete/delete.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/user/describe/describe.go b/internal/cmd/postgresflex/user/describe/describe.go index fb18ff889..30c96e40f 100644 --- a/internal/cmd/postgresflex/user/describe/describe.go +++ b/internal/cmd/postgresflex/user/describe/describe.go @@ -100,15 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index a493855e2..eb476e916 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -121,15 +121,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index 45255b988..27c955b19 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -116,15 +116,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/postgresflex/user/update/update.go b/internal/cmd/postgresflex/user/update/update.go index 4149a3b78..c8b24f1d3 100644 --- a/internal/cmd/postgresflex/user/update/update.go +++ b/internal/cmd/postgresflex/user/update/update.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Roles: roles, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index 17e9e950e..bbb22d2e3 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -145,15 +145,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/delete/delete.go b/internal/cmd/project/delete/delete.go index 4e83d9324..ce572bfc5 100644 --- a/internal/cmd/project/delete/delete.go +++ b/internal/cmd/project/delete/delete.go @@ -90,15 +90,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index edd17d483..59366914c 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -101,15 +101,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu IncludeParents: flags.FlagToBoolValue(p, cmd, includeParentsFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 364458a7c..9c8118c2f 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -140,15 +140,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { PageSize: pageSize, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/member/add/add.go b/internal/cmd/project/member/add/add.go index 1d40c0ec5..f8491a6de 100644 --- a/internal/cmd/project/member/add/add.go +++ b/internal/cmd/project/member/add/add.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Role: flags.FlagToStringPointer(p, cmd, roleFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index 673b4f755..a40ffae49 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -126,15 +126,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { SortBy: flags.FlagWithDefaultToStringValue(p, cmd, sortByFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/member/remove/remove.go b/internal/cmd/project/member/remove/remove.go index b4030199f..20bf7ee3c 100644 --- a/internal/cmd/project/member/remove/remove.go +++ b/internal/cmd/project/member/remove/remove.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Force: flags.FlagToBoolValue(p, cmd, forceFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index 2f49ba18b..30c1b054b 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/project/update/update.go b/internal/cmd/project/update/update.go index b46641ec4..d8ad38c71 100644 --- a/internal/cmd/project/update/update.go +++ b/internal/cmd/project/update/update.go @@ -143,15 +143,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: labels, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/public-ip/associate/associate.go b/internal/cmd/public-ip/associate/associate.go index 82de08fcb..e2398fe08 100644 --- a/internal/cmd/public-ip/associate/associate.go +++ b/internal/cmd/public-ip/associate/associate.go @@ -108,15 +108,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu PublicIpId: publicIpId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index 9d29b78d2..77564b941 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -111,15 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/public-ip/delete/delete.go b/internal/cmd/public-ip/delete/delete.go index 9cb01d38e..525318184 100644 --- a/internal/cmd/public-ip/delete/delete.go +++ b/internal/cmd/public-ip/delete/delete.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu PublicIpId: publicIpId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/public-ip/describe/describe.go b/internal/cmd/public-ip/describe/describe.go index db2ac5050..f180c7533 100644 --- a/internal/cmd/public-ip/describe/describe.go +++ b/internal/cmd/public-ip/describe/describe.go @@ -86,15 +86,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu PublicIpId: publicIpId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/public-ip/disassociate/disassociate.go b/internal/cmd/public-ip/disassociate/disassociate.go index 7630ce7c5..7af16991d 100644 --- a/internal/cmd/public-ip/disassociate/disassociate.go +++ b/internal/cmd/public-ip/disassociate/disassociate.go @@ -95,15 +95,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu PublicIpId: publicIpId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/public-ip/list/list.go b/internal/cmd/public-ip/list/list.go index 37756c8c2..71c94a776 100644 --- a/internal/cmd/public-ip/list/list.go +++ b/internal/cmd/public-ip/list/list.go @@ -127,15 +127,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/public-ip/ranges/list/list.go b/internal/cmd/public-ip/ranges/list/list.go index 54168b448..6b83d5863 100644 --- a/internal/cmd/public-ip/ranges/list/list.go +++ b/internal/cmd/public-ip/ranges/list/list.go @@ -102,15 +102,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go index 78ae5d13e..0f4fc3400 100644 --- a/internal/cmd/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Labels: labels, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/quota/list/list.go b/internal/cmd/quota/list/list.go index 81397affc..5fb48b92b 100644 --- a/internal/cmd/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -90,15 +90,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index 6195ec768..71d432868 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ShowPassword: flags.FlagToBoolValue(p, cmd, showPasswordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/credentials/delete/delete.go b/internal/cmd/rabbitmq/credentials/delete/delete.go index 9421e898e..20f868ddc 100644 --- a/internal/cmd/rabbitmq/credentials/delete/delete.go +++ b/internal/cmd/rabbitmq/credentials/delete/delete.go @@ -111,15 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/credentials/describe/describe.go b/internal/cmd/rabbitmq/credentials/describe/describe.go index e04eb1c2e..13f631733 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe.go @@ -95,15 +95,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index d31efe256..1d9e5f3a3 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -118,15 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index a5ea1b7af..7bf8a1704 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -190,15 +190,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/instance/delete/delete.go b/internal/cmd/rabbitmq/instance/delete/delete.go index 852fa0d2e..69f955ed5 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete.go +++ b/internal/cmd/rabbitmq/instance/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/instance/describe/describe.go b/internal/cmd/rabbitmq/instance/describe/describe.go index 734bd97ce..be909e8ab 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe.go +++ b/internal/cmd/rabbitmq/instance/describe/describe.go @@ -83,15 +83,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index 4556f201f..841ac94eb 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/instance/update/update.go b/internal/cmd/rabbitmq/instance/update/update.go index b86b9f969..792e82681 100644 --- a/internal/cmd/rabbitmq/instance/update/update.go +++ b/internal/cmd/rabbitmq/instance/update/update.go @@ -200,15 +200,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index 996cea081..70518152e 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index 3e6d2d961..93b2284ee 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -107,15 +107,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ShowPassword: flags.FlagToBoolValue(p, cmd, showPasswordFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/credentials/delete/delete.go b/internal/cmd/redis/credentials/delete/delete.go index 4d438bfba..34d0a12ac 100644 --- a/internal/cmd/redis/credentials/delete/delete.go +++ b/internal/cmd/redis/credentials/delete/delete.go @@ -111,15 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/credentials/describe/describe.go b/internal/cmd/redis/credentials/describe/describe.go index 028554868..65973cc0a 100644 --- a/internal/cmd/redis/credentials/describe/describe.go +++ b/internal/cmd/redis/credentials/describe/describe.go @@ -95,15 +95,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CredentialsId: credentialsId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index e6b4d8c7e..5aa2515d0 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -118,15 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index bece1146e..db8700842 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -186,15 +186,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/instance/delete/delete.go b/internal/cmd/redis/instance/delete/delete.go index 01fa78218..c6d3f271b 100644 --- a/internal/cmd/redis/instance/delete/delete.go +++ b/internal/cmd/redis/instance/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/instance/describe/describe.go b/internal/cmd/redis/instance/describe/describe.go index 22e9e4805..cf9d9adc7 100644 --- a/internal/cmd/redis/instance/describe/describe.go +++ b/internal/cmd/redis/instance/describe/describe.go @@ -83,15 +83,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index 1c073147b..db44022ba 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -112,15 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/instance/update/update.go b/internal/cmd/redis/instance/update/update.go index 6d2e919f7..5b254072e 100644 --- a/internal/cmd/redis/instance/update/update.go +++ b/internal/cmd/redis/instance/update/update.go @@ -194,15 +194,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Version: version, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 7e663c8c3..66b18fb47 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index cd0cfd175..1d17fbefb 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Acls: flags.FlagToStringSlicePointer(p, cmd, aclFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/instance/delete/delete.go b/internal/cmd/secrets-manager/instance/delete/delete.go index 121d5427d..2432c5a5e 100644 --- a/internal/cmd/secrets-manager/instance/delete/delete.go +++ b/internal/cmd/secrets-manager/instance/delete/delete.go @@ -91,15 +91,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index 3aed94fd5..ad9bb5de5 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -89,15 +89,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu InstanceId: instanceId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index 4098a7d76..142beefe4 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/instance/update/update.go b/internal/cmd/secrets-manager/instance/update/update.go index b460360e2..d3caca348 100644 --- a/internal/cmd/secrets-manager/instance/update/update.go +++ b/internal/cmd/secrets-manager/instance/update/update.go @@ -110,15 +110,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Acls: acls, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 5e8e3e25f..6ddfc5e2c 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Write: utils.Ptr(flags.FlagToBoolValue(p, cmd, writeFlag)), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/user/delete/delete.go b/internal/cmd/secrets-manager/user/delete/delete.go index 571ef6130..fb1972dbf 100644 --- a/internal/cmd/secrets-manager/user/delete/delete.go +++ b/internal/cmd/secrets-manager/user/delete/delete.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/user/describe/describe.go b/internal/cmd/secrets-manager/user/describe/describe.go index b11949417..1ebd58e49 100644 --- a/internal/cmd/secrets-manager/user/describe/describe.go +++ b/internal/cmd/secrets-manager/user/describe/describe.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index 7040d69a6..5828940fc 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -121,15 +121,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/secrets-manager/user/update/update.go b/internal/cmd/secrets-manager/user/update/update.go index 07e9b6edd..c41c59b35 100644 --- a/internal/cmd/secrets-manager/user/update/update.go +++ b/internal/cmd/secrets-manager/user/update/update.go @@ -137,15 +137,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UserId: userId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index 1e17b9002..3a352f624 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -112,15 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Stateful: flags.FlagToBoolPointer(p, cmd, statefulFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/delete/delete.go b/internal/cmd/security-group/delete/delete.go index 329e4b026..376435432 100644 --- a/internal/cmd/security-group/delete/delete.go +++ b/internal/cmd/security-group/delete/delete.go @@ -93,15 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM SecurityGroupId: cliArgs[0], } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/describe/describe.go b/internal/cmd/security-group/describe/describe.go index 1ea5bf64d..83186e060 100644 --- a/internal/cmd/security-group/describe/describe.go +++ b/internal/cmd/security-group/describe/describe.go @@ -85,15 +85,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM SecurityGroupId: cliArgs[0], } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/list/list.go b/internal/cmd/security-group/list/list.go index 1459a3c11..b80b8647b 100644 --- a/internal/cmd/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -99,15 +99,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go index d0e7bb008..6e6250faf 100644 --- a/internal/cmd/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -165,15 +165,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ProtocolName: flags.FlagToStringPointer(p, cmd, protocolNameFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/rule/delete/delete.go b/internal/cmd/security-group/rule/delete/delete.go index 6acae57c7..9248663cf 100644 --- a/internal/cmd/security-group/rule/delete/delete.go +++ b/internal/cmd/security-group/rule/delete/delete.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/rule/describe/describe.go b/internal/cmd/security-group/rule/describe/describe.go index 47cd0e554..5cce9ff97 100644 --- a/internal/cmd/security-group/rule/describe/describe.go +++ b/internal/cmd/security-group/rule/describe/describe.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/rule/list/list.go b/internal/cmd/security-group/rule/list/list.go index c0bec27c6..8a4bc3758 100644 --- a/internal/cmd/security-group/rule/list/list.go +++ b/internal/cmd/security-group/rule/list/list.go @@ -132,15 +132,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/security-group/update/update.go b/internal/cmd/security-group/update/update.go index 487dca9e0..d0aae546e 100644 --- a/internal/cmd/security-group/update/update.go +++ b/internal/cmd/security-group/update/update.go @@ -119,15 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM return nil, fmt.Errorf("no flags have been passed") } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index ccabadb65..a7400a73d 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -129,15 +129,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { BackupVolumeIds: flags.FlagToStringSliceValue(p, cmd, backupVolumeIdsFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/delete/delete.go b/internal/cmd/server/backup/delete/delete.go index 5fed34276..f89a451b1 100644 --- a/internal/cmd/server/backup/delete/delete.go +++ b/internal/cmd/server/backup/delete/delete.go @@ -97,15 +97,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/describe/describe.go b/internal/cmd/server/backup/describe/describe.go index b44ec3fbe..0b5c6a23b 100644 --- a/internal/cmd/server/backup/describe/describe.go +++ b/internal/cmd/server/backup/describe/describe.go @@ -94,15 +94,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BackupId: backupId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go index f456647ba..0bc6f6a1c 100644 --- a/internal/cmd/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go index c4a4402b6..4cb0f3667 100644 --- a/internal/cmd/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -107,15 +107,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go index 775f88198..aac8a3010 100644 --- a/internal/cmd/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/restore/restore.go b/internal/cmd/server/backup/restore/restore.go index db9a48bac..ffca1ca53 100644 --- a/internal/cmd/server/backup/restore/restore.go +++ b/internal/cmd/server/backup/restore/restore.go @@ -110,15 +110,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu StartServerAfterRestore: flags.FlagToBoolValue(p, cmd, startServerAfterRestoreFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index c400e4e06..a7af18187 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -143,15 +143,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { BackupVolumeIds: flags.FlagToStringSliceValue(p, cmd, backupVolumeIdsFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/schedule/delete/delete.go b/internal/cmd/server/backup/schedule/delete/delete.go index fbf35a733..3dd8632f4 100644 --- a/internal/cmd/server/backup/schedule/delete/delete.go +++ b/internal/cmd/server/backup/schedule/delete/delete.go @@ -109,15 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/schedule/describe/describe.go b/internal/cmd/server/backup/schedule/describe/describe.go index 49c5fd5ee..f3f827844 100644 --- a/internal/cmd/server/backup/schedule/describe/describe.go +++ b/internal/cmd/server/backup/schedule/describe/describe.go @@ -93,15 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BackupScheduleId: backupScheduleId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go index edb0c4411..f9cecde2f 100644 --- a/internal/cmd/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/schedule/update/update.go b/internal/cmd/server/backup/schedule/update/update.go index bdb3d8040..a3471e41b 100644 --- a/internal/cmd/server/backup/schedule/update/update.go +++ b/internal/cmd/server/backup/schedule/update/update.go @@ -142,15 +142,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BackupVolumeIds: flags.FlagToStringSliceValue(p, cmd, backupVolumeIdsFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/volume-backup/delete/delete.go b/internal/cmd/server/backup/volume-backup/delete/delete.go index d6e040d56..fc3cbced4 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete.go @@ -101,15 +101,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/backup/volume-backup/restore/restore.go b/internal/cmd/server/backup/volume-backup/restore/restore.go index 4d3dd8bc9..d29b21681 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore.go @@ -105,15 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu RestoreVolumeId: flags.FlagToStringValue(p, cmd, restoreVolumeIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index 1a766ef46..a94cbca58 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -131,15 +131,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } model.Params = &parsedParams - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/command/describe/describe.go b/internal/cmd/server/command/describe/describe.go index ba09d2575..f229335fb 100644 --- a/internal/cmd/server/command/describe/describe.go +++ b/internal/cmd/server/command/describe/describe.go @@ -92,15 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CommandId: commandId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/command/list/list.go b/internal/cmd/server/command/list/list.go index a05d1a034..2d5dfd683 100644 --- a/internal/cmd/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/command/template/describe/describe.go b/internal/cmd/server/command/template/describe/describe.go index 7a83bf609..ec23859b4 100644 --- a/internal/cmd/server/command/template/describe/describe.go +++ b/internal/cmd/server/command/template/describe/describe.go @@ -92,15 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu CommandTemplateName: commandTemplateName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/command/template/list/list.go b/internal/cmd/server/command/template/list/list.go index a085c3210..8b03a589a 100644 --- a/internal/cmd/server/command/template/list/list.go +++ b/internal/cmd/server/command/template/list/list.go @@ -102,15 +102,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/console/console.go b/internal/cmd/server/console/console.go index 1462a97ac..261f68b3c 100644 --- a/internal/cmd/server/console/console.go +++ b/internal/cmd/server/console/console.go @@ -93,15 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: serverId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 882c971cb..934123a6f 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -267,15 +267,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Volumes: flags.FlagToStringSlicePointer(p, cmd, volumesFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/deallocate/deallocate.go b/internal/cmd/server/deallocate/deallocate.go index b614ba471..7d1d4e37d 100644 --- a/internal/cmd/server/deallocate/deallocate.go +++ b/internal/cmd/server/deallocate/deallocate.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: serverId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/delete/delete.go b/internal/cmd/server/delete/delete.go index c5aae8216..f2f5e80db 100644 --- a/internal/cmd/server/delete/delete.go +++ b/internal/cmd/server/delete/delete.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: serverId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/describe/describe.go b/internal/cmd/server/describe/describe.go index ee6e32ea6..760444d26 100644 --- a/internal/cmd/server/describe/describe.go +++ b/internal/cmd/server/describe/describe.go @@ -85,15 +85,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: serverId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/list/list.go b/internal/cmd/server/list/list.go index 8c1596cbb..13a4be08f 100644 --- a/internal/cmd/server/list/list.go +++ b/internal/cmd/server/list/list.go @@ -125,15 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/log/log.go b/internal/cmd/server/log/log.go index 11bbfe006..1448a3281 100644 --- a/internal/cmd/server/log/log.go +++ b/internal/cmd/server/log/log.go @@ -125,15 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Length: utils.Ptr(length), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/machine-type/describe/describe.go b/internal/cmd/server/machine-type/describe/describe.go index 522d13bd3..12d3a8a7b 100644 --- a/internal/cmd/server/machine-type/describe/describe.go +++ b/internal/cmd/server/machine-type/describe/describe.go @@ -85,15 +85,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu MachineType: machineType, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go index 5ec90d0c4..55a08109a 100644 --- a/internal/cmd/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/network-interface/attach/attach.go b/internal/cmd/server/network-interface/attach/attach.go index 6f2a64163..739a9169e 100644 --- a/internal/cmd/server/network-interface/attach/attach.go +++ b/internal/cmd/server/network-interface/attach/attach.go @@ -152,15 +152,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Create: create, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/network-interface/detach/detach.go b/internal/cmd/server/network-interface/detach/detach.go index 58024dc3e..7d72df379 100644 --- a/internal/cmd/server/network-interface/detach/detach.go +++ b/internal/cmd/server/network-interface/detach/detach.go @@ -154,15 +154,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Delete: deleteValue, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/network-interface/list/list.go b/internal/cmd/server/network-interface/list/list.go index c3d9769c3..071781da4 100644 --- a/internal/cmd/server/network-interface/list/list.go +++ b/internal/cmd/server/network-interface/list/list.go @@ -125,15 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index 76d97cc01..2cfd7a544 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { MaintenanceWindow: flags.FlagWithDefaultToInt64Value(p, cmd, maintenanceWindowFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/describe/describe.go b/internal/cmd/server/os-update/describe/describe.go index 3c8de58ee..2aa7c1283 100644 --- a/internal/cmd/server/os-update/describe/describe.go +++ b/internal/cmd/server/os-update/describe/describe.go @@ -92,15 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu UpdateId: updateId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go index 510411798..dabf2bacf 100644 --- a/internal/cmd/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -104,15 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go index e796767c6..2697de207 100644 --- a/internal/cmd/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -107,15 +107,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go index 4092be38a..6ec47314e 100644 --- a/internal/cmd/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index cae0f7377..bd3784c49 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -134,15 +134,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Enabled: flags.FlagToBoolValue(p, cmd, enabledFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/schedule/delete/delete.go b/internal/cmd/server/os-update/schedule/delete/delete.go index 0d2762d65..f97ee0ec6 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete.go +++ b/internal/cmd/server/os-update/schedule/delete/delete.go @@ -96,15 +96,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/schedule/describe/describe.go b/internal/cmd/server/os-update/schedule/describe/describe.go index 89aaba7b0..d46eea1bb 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/server/os-update/schedule/describe/describe.go @@ -92,15 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ScheduleId: scheduleId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go index 3f8eeb6cb..201922d21 100644 --- a/internal/cmd/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/os-update/schedule/update/update.go b/internal/cmd/server/os-update/schedule/update/update.go index 3394ba5ba..e9ce126f0 100644 --- a/internal/cmd/server/os-update/schedule/update/update.go +++ b/internal/cmd/server/os-update/schedule/update/update.go @@ -130,15 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Enabled: flags.FlagToBoolPointer(p, cmd, enabledFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/public-ip/attach/attach.go b/internal/cmd/server/public-ip/attach/attach.go index 843c030e7..763583606 100644 --- a/internal/cmd/server/public-ip/attach/attach.go +++ b/internal/cmd/server/public-ip/attach/attach.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu PublicIpId: volumeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/public-ip/detach/detach.go b/internal/cmd/server/public-ip/detach/detach.go index 3c1aa6687..6294187d8 100644 --- a/internal/cmd/server/public-ip/detach/detach.go +++ b/internal/cmd/server/public-ip/detach/detach.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu PublicIpId: publicIpId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/reboot/reboot.go b/internal/cmd/server/reboot/reboot.go index dbdc10ef1..445321295 100644 --- a/internal/cmd/server/reboot/reboot.go +++ b/internal/cmd/server/reboot/reboot.go @@ -111,15 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu HardReboot: flags.FlagToBoolValue(p, cmd, hardRebootFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/rescue/rescue.go b/internal/cmd/server/rescue/rescue.go index 5c4efea4f..65dc2633d 100644 --- a/internal/cmd/server/rescue/rescue.go +++ b/internal/cmd/server/rescue/rescue.go @@ -126,15 +126,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ImageId: flags.FlagToStringPointer(p, cmd, imageIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/resize/resize.go b/internal/cmd/server/resize/resize.go index 57e6ebe1b..f23826188 100644 --- a/internal/cmd/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -126,15 +126,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu MachineType: flags.FlagToStringPointer(p, cmd, machineTypeFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 89232fa88..b80c93df0 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServiceAccMail: serviceAccMail, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 69bc5e4fe..909de016d 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServiceAccMail: serviceAccMail, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/service-account/list/list.go b/internal/cmd/server/service-account/list/list.go index 19bfc8fa0..372e6c975 100644 --- a/internal/cmd/server/service-account/list/list.go +++ b/internal/cmd/server/service-account/list/list.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/start/start.go b/internal/cmd/server/start/start.go index 5a6f9d02a..9ebabdf70 100644 --- a/internal/cmd/server/start/start.go +++ b/internal/cmd/server/start/start.go @@ -105,15 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: serverId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/stop/stop.go b/internal/cmd/server/stop/stop.go index aa510ef01..d91c1931c 100644 --- a/internal/cmd/server/stop/stop.go +++ b/internal/cmd/server/stop/stop.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: serverId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/unrescue/unrescue.go b/internal/cmd/server/unrescue/unrescue.go index 44bf3ace1..47b6cf018 100644 --- a/internal/cmd/server/unrescue/unrescue.go +++ b/internal/cmd/server/unrescue/unrescue.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ServerId: serverId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/update/update.go b/internal/cmd/server/update/update.go index bc6f821a1..e69289375 100644 --- a/internal/cmd/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -114,15 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go index 00217c513..2ba304db3 100644 --- a/internal/cmd/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu VolumeId: volumeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/volume/describe/describe.go b/internal/cmd/server/volume/describe/describe.go index be160a2ca..6aa391a4c 100644 --- a/internal/cmd/server/volume/describe/describe.go +++ b/internal/cmd/server/volume/describe/describe.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu VolumeId: volumeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/volume/detach/detach.go b/internal/cmd/server/volume/detach/detach.go index ebd4fb70d..e081295d6 100644 --- a/internal/cmd/server/volume/detach/detach.go +++ b/internal/cmd/server/volume/detach/detach.go @@ -112,15 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu VolumeId: volumeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go index 1fab049e4..3e69701df 100644 --- a/internal/cmd/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go index 3e2e4ae6b..1371e587c 100644 --- a/internal/cmd/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -119,15 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu VolumeId: volumeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index c998de0f8..6387773ad 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -100,15 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Name: flags.FlagToStringPointer(p, cmd, nameFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/delete/delete.go b/internal/cmd/service-account/delete/delete.go index a92acdb4f..ad0a9dc45 100644 --- a/internal/cmd/service-account/delete/delete.go +++ b/internal/cmd/service-account/delete/delete.go @@ -87,15 +87,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Email: email, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/get-jwks/get_jwks.go b/internal/cmd/service-account/get-jwks/get_jwks.go index 441851bac..a99655c1c 100644 --- a/internal/cmd/service-account/get-jwks/get_jwks.go +++ b/internal/cmd/service-account/get-jwks/get_jwks.go @@ -73,15 +73,7 @@ func parseInput(p *print.Printer, _ *cobra.Command, inputArgs []string) (*inputM Email: email, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/key/create/create.go b/internal/cmd/service-account/key/create/create.go index 1b58d12b8..e25d3fbbc 100644 --- a/internal/cmd/service-account/key/create/create.go +++ b/internal/cmd/service-account/key/create/create.go @@ -140,15 +140,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { PublicKey: flags.FlagToStringPointer(p, cmd, publicKeyFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/key/delete/delete.go b/internal/cmd/service-account/key/delete/delete.go index e780ddd33..61c551652 100644 --- a/internal/cmd/service-account/key/delete/delete.go +++ b/internal/cmd/service-account/key/delete/delete.go @@ -108,15 +108,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu KeyId: keyId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/key/describe/describe.go b/internal/cmd/service-account/key/describe/describe.go index ecf541f3f..8fdc2d7c1 100644 --- a/internal/cmd/service-account/key/describe/describe.go +++ b/internal/cmd/service-account/key/describe/describe.go @@ -98,15 +98,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu KeyId: keyId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index a39782f56..cb10ba912 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/key/update/update.go b/internal/cmd/service-account/key/update/update.go index 62183d56f..ff3387965 100644 --- a/internal/cmd/service-account/key/update/update.go +++ b/internal/cmd/service-account/key/update/update.go @@ -149,15 +149,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Deactivate: deactivate, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index 121b5216d..5806feda7 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -107,15 +107,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index 5b74fdae7..e3e009b51 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { TTLDays: &ttlDays, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index 956b79908..e3a20d9ed 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -128,15 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: limit, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/service-account/token/revoke/revoke.go b/internal/cmd/service-account/token/revoke/revoke.go index 0ac624a89..a3bd60f3a 100644 --- a/internal/cmd/service-account/token/revoke/revoke.go +++ b/internal/cmd/service-account/token/revoke/revoke.go @@ -111,15 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu TokenId: tokenId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index af9ba2336..3c51310cd 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -179,15 +179,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Payload: payload, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/delete/delete.go b/internal/cmd/ske/cluster/delete/delete.go index 12068d9e3..d0ebb34fe 100644 --- a/internal/cmd/ske/cluster/delete/delete.go +++ b/internal/cmd/ske/cluster/delete/delete.go @@ -101,15 +101,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ClusterName: clusterName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index a983f442e..69d357f44 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -81,15 +81,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ClusterName: clusterName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload.go b/internal/cmd/ske/cluster/generate-payload/generate_payload.go index 566e51f33..b03f0d42c 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload.go @@ -117,15 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { FilePath: flags.FlagToStringPointer(p, cmd, filePathFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/hibernate/hibernate.go b/internal/cmd/ske/cluster/hibernate/hibernate.go index 4c0be63ab..1ee7aff06 100644 --- a/internal/cmd/ske/cluster/hibernate/hibernate.go +++ b/internal/cmd/ske/cluster/hibernate/hibernate.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ClusterName: clusterName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 8c357924a..75fc2e125 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -130,15 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Limit: flags.FlagToInt64Pointer(p, cmd, limitFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/maintenance/maintenance.go b/internal/cmd/ske/cluster/maintenance/maintenance.go index 3396ad7c3..bad6c37f4 100644 --- a/internal/cmd/ske/cluster/maintenance/maintenance.go +++ b/internal/cmd/ske/cluster/maintenance/maintenance.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ClusterName: clusterName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/reconcile/reconcile.go b/internal/cmd/ske/cluster/reconcile/reconcile.go index 54c98dae0..719ebeb44 100644 --- a/internal/cmd/ske/cluster/reconcile/reconcile.go +++ b/internal/cmd/ske/cluster/reconcile/reconcile.go @@ -92,15 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ClusterName: clusterName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index 8c32f8d95..512b2f615 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -141,15 +141,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Payload: payload, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/cluster/wakeup/wakeup.go b/internal/cmd/ske/cluster/wakeup/wakeup.go index e7b9b6534..950dbf3b1 100644 --- a/internal/cmd/ske/cluster/wakeup/wakeup.go +++ b/internal/cmd/ske/cluster/wakeup/wakeup.go @@ -92,15 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ClusterName: clusterName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go index 982e9267d..f4a1fcc5b 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go @@ -119,15 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ClusterName: clusterName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation.go b/internal/cmd/ske/credentials/start-rotation/start_rotation.go index a8314ad83..ea65650ea 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation.go @@ -122,15 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu ClusterName: clusterName, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index da717570e..a8abfb2b6 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -70,15 +70,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index ea355ada1..33647becf 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -101,15 +101,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index 91431b5e3..0567a9cab 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -101,15 +101,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { GlobalFlagModel: globalFlags, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index f420009f0..86b282cfa 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -215,15 +215,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Overwrite: flags.FlagToBoolValue(p, cmd, overwriteFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index 91564ceea..e9eeba070 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -119,15 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { VolumeTypes: volumeTypes, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/backup/create/create.go b/internal/cmd/volume/backup/create/create.go index 447a3ea16..5749a1d01 100644 --- a/internal/cmd/volume/backup/create/create.go +++ b/internal/cmd/volume/backup/create/create.go @@ -166,15 +166,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: *labels, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/backup/delete/delete.go b/internal/cmd/volume/backup/delete/delete.go index b40d93ea7..de63990bd 100644 --- a/internal/cmd/volume/backup/delete/delete.go +++ b/internal/cmd/volume/backup/delete/delete.go @@ -107,15 +107,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BackupId: backupId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/backup/describe/describe.go b/internal/cmd/volume/backup/describe/describe.go index d3322f6d0..48ee2ae2a 100644 --- a/internal/cmd/volume/backup/describe/describe.go +++ b/internal/cmd/volume/backup/describe/describe.go @@ -83,15 +83,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BackupId: backupId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/backup/list/list.go b/internal/cmd/volume/backup/list/list.go index f3d7062c7..f3fa7b257 100644 --- a/internal/cmd/volume/backup/list/list.go +++ b/internal/cmd/volume/backup/list/list.go @@ -123,15 +123,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: labelSelector, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/backup/restore/restore.go b/internal/cmd/volume/backup/restore/restore.go index 3249f0560..04301a51d 100644 --- a/internal/cmd/volume/backup/restore/restore.go +++ b/internal/cmd/volume/backup/restore/restore.go @@ -120,15 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu BackupId: backupId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/backup/update/update.go b/internal/cmd/volume/backup/update/update.go index f23bb5108..e53e332a0 100644 --- a/internal/cmd/volume/backup/update/update.go +++ b/internal/cmd/volume/backup/update/update.go @@ -115,15 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Labels: *labels, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index 5519bd5d8..068a06cce 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -155,15 +155,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { SourceType: flags.FlagToStringPointer(p, cmd, sourceTypeFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go index 117c17032..1c94e3dc2 100644 --- a/internal/cmd/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -113,15 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu VolumeId: volumeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/describe/describe.go b/internal/cmd/volume/describe/describe.go index 9d4c06538..8a0db5659 100644 --- a/internal/cmd/volume/describe/describe.go +++ b/internal/cmd/volume/describe/describe.go @@ -86,15 +86,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu VolumeId: volumeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/list/list.go b/internal/cmd/volume/list/list.go index aac08c50b..e45536d36 100644 --- a/internal/cmd/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -124,15 +124,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/performance-class/describe/describe.go b/internal/cmd/volume/performance-class/describe/describe.go index dc7b25ad5..cef47d1e6 100644 --- a/internal/cmd/volume/performance-class/describe/describe.go +++ b/internal/cmd/volume/performance-class/describe/describe.go @@ -86,15 +86,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu VolumePerformanceClass: volumePerformanceClass, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/performance-class/list/list.go b/internal/cmd/volume/performance-class/list/list.go index a6490e75e..e8904a8f4 100644 --- a/internal/cmd/volume/performance-class/list/list.go +++ b/internal/cmd/volume/performance-class/list/list.go @@ -125,15 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/resize/resize.go b/internal/cmd/volume/resize/resize.go index f86f10546..4d1a0d03a 100644 --- a/internal/cmd/volume/resize/resize.go +++ b/internal/cmd/volume/resize/resize.go @@ -106,15 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu VolumeId: volumeId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/snapshot/create/create.go b/internal/cmd/volume/snapshot/create/create.go index 856b0a929..38e92650f 100644 --- a/internal/cmd/volume/snapshot/create/create.go +++ b/internal/cmd/volume/snapshot/create/create.go @@ -147,15 +147,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: *labels, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/snapshot/delete/delete.go b/internal/cmd/volume/snapshot/delete/delete.go index 0a4c17faa..11c4d1f1d 100644 --- a/internal/cmd/volume/snapshot/delete/delete.go +++ b/internal/cmd/volume/snapshot/delete/delete.go @@ -110,15 +110,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu SnapshotId: snapshotId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/snapshot/describe/describe.go b/internal/cmd/volume/snapshot/describe/describe.go index 7ae36212e..9b4f45fad 100644 --- a/internal/cmd/volume/snapshot/describe/describe.go +++ b/internal/cmd/volume/snapshot/describe/describe.go @@ -83,15 +83,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu SnapshotId: snapshotId, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/snapshot/list/list.go b/internal/cmd/volume/snapshot/list/list.go index 83b59987c..d25965c44 100644 --- a/internal/cmd/volume/snapshot/list/list.go +++ b/internal/cmd/volume/snapshot/list/list.go @@ -124,15 +124,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { LabelSelector: labelSelector, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/snapshot/update/update.go b/internal/cmd/volume/snapshot/update/update.go index 543c484d1..889b2cae4 100644 --- a/internal/cmd/volume/snapshot/update/update.go +++ b/internal/cmd/volume/snapshot/update/update.go @@ -120,15 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Labels: *labels, } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/cmd/volume/update/update.go b/internal/cmd/volume/update/update.go index 263f333af..34881f40d 100644 --- a/internal/cmd/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -120,15 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } - if p.IsVerbosityDebug() { - modelStr, err := print.BuildDebugStrFromInputModel(model) - if err != nil { - p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err) - } else { - p.Debug(print.DebugLevel, "parsed input values: %s", modelStr) - } - } - + p.DebugInputModel(model) return &model, nil } diff --git a/internal/pkg/print/debug.go b/internal/pkg/print/debug.go index 60962ba7b..793c54bd3 100644 --- a/internal/pkg/print/debug.go +++ b/internal/pkg/print/debug.go @@ -16,11 +16,11 @@ import ( var defaultHTTPHeaders = []string{"Accept", "Content-Type", "Content-Length", "User-Agent", "Date", "Referrer-Policy", "Traceparent"} -// BuildDebugStrFromInputModel converts an input model to a user-friendly string representation. +// buildDebugStrFromInputModel converts an input model to a user-friendly string representation. // This function converts the input model to a map, removes empty values, and generates a string representation of the map. // The purpose of this function is to provide a more readable output than the default JSON representation. // It is particularly useful when outputting to the slog logger, as the JSON format with escaped quotes does not look good. -func BuildDebugStrFromInputModel(model any) (string, error) { +func buildDebugStrFromInputModel(model any) (string, error) { // Marshaling and Unmarshaling is the best way to convert the struct to a map modelBytes, err := json.Marshal(model) if err != nil { diff --git a/internal/pkg/print/debug_test.go b/internal/pkg/print/debug_test.go index 45ef90482..abc3dedeb 100644 --- a/internal/pkg/print/debug_test.go +++ b/internal/pkg/print/debug_test.go @@ -171,7 +171,7 @@ func TestBuildDebugStrFromInputModel(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { model := tt.model - actual, err := BuildDebugStrFromInputModel(model) + actual, err := buildDebugStrFromInputModel(model) if err != nil { if !tt.isValid { return diff --git a/internal/pkg/print/print.go b/internal/pkg/print/print.go index 63f48fe89..583e975dc 100644 --- a/internal/pkg/print/print.go +++ b/internal/pkg/print/print.go @@ -51,7 +51,7 @@ type Printer struct { Verbosity Level } -// Creates a new printer, including setting up the default logger. +// NewPrinter creates a new printer, including setting up the default logger. func NewPrinter() *Printer { w := os.Stderr logger := slog.New( @@ -228,3 +228,15 @@ func (p *Printer) IsVerbosityWarning() bool { func (p *Printer) IsVerbosityError() bool { return p.Verbosity == ErrorLevel } + +// DebugInputModel prints the given input model in case verbosity level is set to Debug, does nothing otherwise +func (p *Printer) DebugInputModel(model any) { + if p.IsVerbosityDebug() { + modelStr, err := buildDebugStrFromInputModel(model) + if err != nil { + p.Debug(ErrorLevel, "convert model to string for debugging: %v", err) + } else { + p.Debug(DebugLevel, "parsed input values: %s", modelStr) + } + } +} From 45b902059be58540d152e733bda55505f9b96331 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 10 Oct 2025 08:09:16 +0200 Subject: [PATCH 460/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/observability to v0.15.0 (#1022) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0baf2a99d..d152751e2 100644 --- a/go.mod +++ b/go.mod @@ -246,7 +246,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 613c93ed9..a896800c1 100644 --- a/go.sum +++ b/go.sum @@ -583,8 +583,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/a github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0 h1:g3yNDUc3JydAikezUrI9bQ4nuMJpVeAQ35jOFfFmq1U= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0/go.mod h1:foslkEiICdtHR3v0A/i/Rgo6EP9MMula9XNC9luNOgw= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0 h1:oewwaYjABWbNqDkmSwIXmjDBK4a46+tnznyZSXh3Xk0= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.14.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0 h1:MA5i1ScjXLWe5CYeFCLHeZzNS1AH4mbx1kUyiVbxKjI= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= From 570f53d680a290f8902bf614ae8e48b366bd6249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:00:18 +0200 Subject: [PATCH 461/619] feat(distribution): provide rpm packages via rpm repository (#1012) --- .github/workflows/release.yaml | 59 ++++++++++++++++- .goreleaser.yaml | 15 ++--- INSTALLATION.md | 50 ++++++++++++-- scripts/publish-apt-packages.sh | 2 +- scripts/publish-rpm-packages.sh | 112 ++++++++++++++++++++++++++++++++ 5 files changed, 218 insertions(+), 20 deletions(-) create mode 100755 scripts/publish-rpm-packages.sh diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0760269ed..9e453b7fa 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -41,6 +41,15 @@ jobs: gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.GPG_PASSPHRASE }} + # nfpm-rpm signing needs gpg provided as filepath + # https://goreleaser.com/customization/nfpm/ + - name: Create GPG key file + run: | + KEY_PATH="$RUNNER_TEMP/gpg-private-key.asc" + printf '%s' "${{ secrets.GPG_PRIVATE_KEY }}" > "$KEY_PATH" + chmod 600 "$KEY_PATH" + echo "GPG_KEY_PATH=$KEY_PATH" >> "$GITHUB_ENV" + - name: Set up keychain run: | echo -n $SIGNING_CERTIFICATE_BASE64 | base64 -d -o ./ApplicationID.p12 @@ -71,15 +80,22 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.CLI_RELEASE }} GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} + GPG_KEY_PATH: ${{ env.GPG_KEY_PATH }} + # nfpm-rpm signing needs this env to be set. + NFPM_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - # artifacts need to be passed to the "publish-apt" job somehow + - name: Clean up GPG key file + if: always() + run: | + rm -f "$GPG_KEY_PATH" + - name: Upload artifacts to workflow uses: actions/upload-artifact@v4 with: name: goreleaser-dist-temp path: dist retention-days: 1 - + publish-apt: name: Publish APT runs-on: macOS-latest @@ -115,3 +131,42 @@ jobs: GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} GPG_PRIVATE_KEY_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} run: ./scripts/publish-apt-packages.sh + + publish-rpm: + name: Publish RPM + runs-on: ubuntu-latest + needs: [goreleaser] + env: + # Needed to publish new packages to our S3-hosted RPM repo + AWS_ACCESS_KEY_ID: ${{ secrets.OBJECT_STORAGE_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.OBJECT_STORAGE_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: eu01 + AWS_ENDPOINT_URL: https://object.storage.eu01.onstackit.cloud + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Download artifacts from workflow + uses: actions/download-artifact@v5 + with: + name: goreleaser-dist-temp + path: dist + + - name: Install RPM tools + run: | + sudo apt-get update + sudo apt-get install -y createrepo-c + + - name: Import GPG key + uses: crazy-max/ghaction-import-gpg@v6 + id: import_gpg + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + + - name: Publish RPM packages + if: contains(github.ref_name, '-') == false + env: + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + GPG_PRIVATE_KEY_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} + run: ./scripts/publish-rpm-packages.sh \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 37412c183..b86115c5f 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -99,17 +99,10 @@ nfpms: - deb - rpm -signs: - - artifacts: package - args: - [ - "-u", - "{{ .Env.GPG_FINGERPRINT }}", - "--output", - "${signature}", - "--detach-sign", - "${artifact}", - ] + rpm: + # The package is signed if a key_file is set + signature: + key_file: "{{ .Env.GPG_KEY_PATH }}" homebrew_casks: - name: stackit diff --git a/INSTALLATION.md b/INSTALLATION.md index 3a5045149..c2e7bf751 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -130,16 +130,54 @@ asset_filters=["stackit-cli_", "_linux_amd64.tar.gz"] eget stackitcloud/stackit-cli ``` -#### RPM package via dnf, yum and zypper +#### RHEL/Fedora/Rocky/Alma/openSUSE/... (`DNF/YUM/Zypper`) -The STACKIT CLI is available as [RPM Package](https://github.com/stackitcloud/stackit-cli/releases) and can be installed via dnf, yum and zypper package manager. +The STACKIT CLI can be installed through the [`DNF/YUM`](https://docs.fedoraproject.org/en-US/fedora/f40/system-administrators-guide/package-management/DNF/) / [`Zypper`](https://de.opensuse.org/Zypper) package managers. -Just download the rpm package from the [release page](https://github.com/stackitcloud/stackit-cli/releases) and run the install command like the following: +> Requires rpm version 4.15 or newer to support Ed25519 signatures. + +> `$basearch` is supported by modern distributions. On older systems that don't expand `$basearch`, replace it in the `baseurl` with your architecture explicitly (for example, `.../rpm/cli/x86_64` or `.../rpm/cli/aarch64`). + +##### Installation via DNF/YUM + +1. Add the repository: + +```shell +sudo tee /etc/yum.repos.d/stackit.repo > /dev/null << 'EOF' +[stackit] +name=STACKIT CLI +baseurl=https://packages.stackit.cloud/rpm/cli/$basearch +enabled=1 +gpgcheck=1 +gpgkey=https://packages.stackit.cloud/keys/key.gpg +EOF +``` + +2. Install the CLI: + +```shell +sudo dnf install stackit +``` + +##### Installation via Zypper + +1. Add the repository: + +```shell +sudo tee /etc/zypp/repos.d/stackit.repo > /dev/null << 'EOF' +[stackit] +name=STACKIT CLI +baseurl=https://packages.stackit.cloud/rpm/cli/$basearch +enabled=1 +gpgcheck=1 +gpgkey=https://packages.stackit.cloud/keys/key.gpg +EOF +``` + +2. Install the CLI: ```shell -dnf install stackitcli.rpm -yum install stackitcli.rpm -zypper install stackitcli.rpm +sudo zypper install stackit ``` #### Any distribution diff --git a/scripts/publish-apt-packages.sh b/scripts/publish-apt-packages.sh index 9d122d80b..81aa53cb4 100755 --- a/scripts/publish-apt-packages.sh +++ b/scripts/publish-apt-packages.sh @@ -49,4 +49,4 @@ aptly snapshot pull -no-remove -architectures="amd64,i386,arm64" current-snapsho # Publish the new snapshot to the remote repo printf "\n>>> Publishing updated snapshot \n" -aptly publish snapshot -keyring="${CUSTOM_KEYRING_FILE}" -gpg-key="${GPG_PRIVATE_KEY_FINGERPRINT}" -passphrase "${GPG_PASSPHRASE}" -config "${APTLY_CONFIG_FILE_PATH}" updated-snapshot "s3:${APT_BUCKET_NAME}:${APT_REPO_PATH}" +aptly publish snapshot -keyring="${CUSTOM_KEYRING_FILE}" -gpg-key="${GPG_PRIVATE_KEY_FINGERPRINT}" -passphrase "${GPG_PASSPHRASE}" -config "${APTLY_CONFIG_FILE_PATH}" updated-snapshot "s3:${APT_BUCKET_NAME}:${APT_REPO_PATH}" \ No newline at end of file diff --git a/scripts/publish-rpm-packages.sh b/scripts/publish-rpm-packages.sh new file mode 100755 index 000000000..d657d1e0d --- /dev/null +++ b/scripts/publish-rpm-packages.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash + +# This script is used to publish new RPM packages to the CLI RPM repository +# Usage: ./publish-rpm-packages.sh +set -eo pipefail + +PACKAGES_BUCKET_URL="https://packages.stackit.cloud" +PUBLIC_KEY_FILE_PATH="keys/key.gpg" +RPM_REPO_PATH="rpm/cli" +RPM_BUCKET_NAME="distribution" +GORELEASER_PACKAGES_FOLDER="dist/" + +# We need to disable the key database daemon (keyboxd) +# This can be done by removing "use-keyboxd" from ~/.gnupg/common.conf (see https://github.com/gpg/gnupg/blob/master/README) +echo -n >~/.gnupg/common.conf + +# Create RPM repository directory structure +printf ">>> Creating RPM repository structure \n" +mkdir -p rpm-repo/x86_64 +mkdir -p rpm-repo/i386 +mkdir -p rpm-repo/aarch64 + +# Copy RPM packages to appropriate architecture directories +printf "\n>>> Copying RPM packages to architecture directories \n" + +# Copy x86_64 packages (amd64) +for rpm_file in "${GORELEASER_PACKAGES_FOLDER}"*_amd64.rpm; do + if [ -f "$rpm_file" ]; then + cp "$rpm_file" rpm-repo/x86_64/ + printf "Copied %s to x86_64/\n" "$(basename "$rpm_file")" + fi +done + +# Copy i386 packages +for rpm_file in "${GORELEASER_PACKAGES_FOLDER}"*_386.rpm; do + if [ -f "$rpm_file" ]; then + cp "$rpm_file" rpm-repo/i386/ + printf "Copied %s to i386/\n" "$(basename "$rpm_file")" + fi +done + +# Copy aarch64 packages (arm64) +for rpm_file in "${GORELEASER_PACKAGES_FOLDER}"*_arm64.rpm; do + if [ -f "$rpm_file" ]; then + cp "$rpm_file" rpm-repo/aarch64/ + printf "Copied %s to aarch64/\n" "$(basename "$rpm_file")" + fi +done + +# Download existing repository content (RPMs and metadata) if it exists +printf "\n>>> Downloading existing repository content \n" +aws s3 sync s3://${RPM_BUCKET_NAME}/${RPM_REPO_PATH}/ rpm-repo/ --endpoint-url "${AWS_ENDPOINT_URL}" --exclude "*.asc" || echo "No existing repository found, creating new one" + +# Create repository metadata for each architecture +printf "\n>>> Creating repository metadata \n" +for arch in x86_64 i386 aarch64; do + if [ -d "rpm-repo/${arch}" ] && [ -n "$(find "rpm-repo/${arch}" -mindepth 1 -maxdepth 1 -print -quit)" ]; then + printf "Creating metadata for %s...\n" "$arch" + + # List what we're working with + file_list=$(find "rpm-repo/${arch}" -maxdepth 1 -type f -exec basename {} \; | tr '\n' ' ') + printf "Files in %s: %s\n" "$arch" "${file_list% }" + + # Create repository metadata + createrepo_c --update rpm-repo/${arch} + + # Sign the repository metadata + printf "Signing repository metadata for %s...\n" "$arch" + # Remove existing signature file if it exists + rm -f rpm-repo/${arch}/repodata/repomd.xml.asc + gpg --batch --pinentry-mode loopback --detach-sign --armor \ + --local-user "${GPG_PRIVATE_KEY_FINGERPRINT}" \ + --passphrase "${GPG_PASSPHRASE}" \ + rpm-repo/${arch}/repodata/repomd.xml + + # Verify the signature was created + if [ -f "rpm-repo/${arch}/repodata/repomd.xml.asc" ]; then + printf "Repository metadata signed successfully for %s\n" "$arch" + else + printf "WARNING: Repository metadata signature not created for %s\n" "$arch" + fi + else + printf "No packages found for %s, skipping...\n" "$arch" + fi +done + +# Upload the updated repository to S3 in two phases (repodata pointers last) +# clients reading the repo won't see a state where repomd.xml points to files not uploaded yet. +printf "\n>>> Uploading repository to S3 (phase 1: all except repomd*) \n" +aws s3 sync rpm-repo/ s3://${RPM_BUCKET_NAME}/${RPM_REPO_PATH}/ \ + --endpoint-url "${AWS_ENDPOINT_URL}" \ + --delete \ + --exclude "*/repodata/repomd.xml" \ + --exclude "*/repodata/repomd.xml.asc" + +printf "\n>>> Uploading repository to S3 (phase 2: repomd* only) \n" +aws s3 sync rpm-repo/ s3://${RPM_BUCKET_NAME}/${RPM_REPO_PATH}/ \ + --endpoint-url "${AWS_ENDPOINT_URL}" \ + --exclude "*" \ + --include "*/repodata/repomd.xml" \ + --include "*/repodata/repomd.xml.asc" + +# Upload the public key +# Also uploaded in APT publish; intentionally redundant +# Safe to overwrite and ensures updates if APT fails or key changes. +printf "\n>>> Uploading public key \n" +gpg --armor --export "${GPG_PRIVATE_KEY_FINGERPRINT}" > public-key.asc +aws s3 cp public-key.asc s3://${RPM_BUCKET_NAME}/${PUBLIC_KEY_FILE_PATH} --endpoint-url "${AWS_ENDPOINT_URL}" + +printf "\n>>> RPM repository published successfully! \n" +printf "Repository URL: %s/%s/ \n" "$PACKAGES_BUCKET_URL" "$RPM_REPO_PATH" +printf "Public key URL: %s/%s \n" "$PACKAGES_BUCKET_URL" "$PUBLIC_KEY_FILE_PATH" From 85f5d792687442d95ce598c27c542407e68a3154 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:35:05 +0200 Subject: [PATCH 462/619] chore(deps): update renovatebot/github-action action to v43.0.17 (#1025) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index a01117f2a..211759137 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.16 + uses: renovatebot/github-action@v43.0.17 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 1b5d0b2b50808f699c51ab07a635cbe9207f26bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 15 Oct 2025 11:59:32 +0200 Subject: [PATCH 463/619] fix(ske): make generate cluster payload work for eu02 (#1008) relates to STACKITCLI-258 / #997 --- internal/pkg/services/ske/utils/utils.go | 33 +++++++++----- internal/pkg/services/ske/utils/utils_test.go | 45 ++++++++++++++++++- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 605ca4158..904ff97a1 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -6,6 +6,7 @@ import ( "maps" "os" "path/filepath" + "regexp" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -16,13 +17,9 @@ import ( ) const ( - defaultNodepoolAvailabilityZone = "eu01-3" defaultNodepoolCRI = ske.CRINAME_CONTAINERD - defaultNodepoolMachineType = "b1.2" defaultNodepoolMachineImageName = "flatcar" - defaultNodepoolMaxSurge = 1 defaultNodepoolMaxUnavailable = 0 - defaultNodepoolMaximum = 2 defaultNodepoolMinimum = 1 defaultNodepoolName = "pool-default" defaultNodepoolVolumeType = "storage_premium_perf2" @@ -110,22 +107,38 @@ func getDefaultPayloadKubernetes(resp *ske.ProviderOptions) (*ske.Kubernetes, er } func getDefaultPayloadNodepool(resp *ske.ProviderOptions) (*ske.Nodepool, error) { + if resp.AvailabilityZones == nil || len(*resp.AvailabilityZones) == 0 { + return nil, fmt.Errorf("no availability zones found") + } + var availabilityZones []string + for i := range *resp.AvailabilityZones { + azName := (*resp.AvailabilityZones)[i].GetName() + // don't include availability zones like eu01-m, eu02-m, not all flavors are available there + if !regexp.MustCompile(`\w{2}\d{2}-m`).MatchString(azName) { + availabilityZones = append(availabilityZones, azName) + } + } + + if resp.MachineTypes == nil || len(*resp.MachineTypes) == 0 { + return nil, fmt.Errorf("no machine types found") + } + machineType := (*resp.MachineTypes)[0].GetName() + output := &ske.Nodepool{ - AvailabilityZones: &[]string{ - defaultNodepoolAvailabilityZone, - }, + AvailabilityZones: &availabilityZones, Cri: &ske.CRI{ Name: utils.Ptr(defaultNodepoolCRI), }, Machine: &ske.Machine{ - Type: utils.Ptr(defaultNodepoolMachineType), + Type: &machineType, Image: &ske.Image{ Name: utils.Ptr(defaultNodepoolMachineImageName), }, }, - MaxSurge: utils.Ptr(int64(defaultNodepoolMaxSurge)), + // there must be as many nodes as availability zones are given + MaxSurge: utils.Ptr(int64(len(availabilityZones))), MaxUnavailable: utils.Ptr(int64(defaultNodepoolMaxUnavailable)), - Maximum: utils.Ptr(int64(defaultNodepoolMaximum)), + Maximum: utils.Ptr(int64(len(availabilityZones))), Minimum: utils.Ptr(int64(defaultNodepoolMinimum)), Name: utils.Ptr(defaultNodepoolName), Volume: &ske.Volume{ diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index 917d590ae..b150509ec 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -146,6 +146,17 @@ func TestClusterExists(t *testing.T) { func fixtureProviderOptions(mods ...func(*ske.ProviderOptions)) *ske.ProviderOptions { providerOptions := &ske.ProviderOptions{ + AvailabilityZones: &[]ske.AvailabilityZone{ + {Name: utils.Ptr("eu01-m")}, + {Name: utils.Ptr("eu01-1")}, + {Name: utils.Ptr("eu01-2")}, + {Name: utils.Ptr("eu01-3")}, + }, + MachineTypes: &[]ske.MachineType{ + { + Name: utils.Ptr("b1.2"), + }, + }, KubernetesVersions: &[]ske.KubernetesVersion{ { State: utils.Ptr("supported"), @@ -263,6 +274,8 @@ func fixtureGetDefaultPayload(mods ...func(*ske.CreateOrUpdateClusterPayload)) * Nodepools: &[]ske.Nodepool{ { AvailabilityZones: &[]string{ + "eu01-1", + "eu01-2", "eu01-3", }, Cri: &ske.CRI{ @@ -275,9 +288,9 @@ func fixtureGetDefaultPayload(mods ...func(*ske.CreateOrUpdateClusterPayload)) * Name: utils.Ptr("flatcar"), }, }, - MaxSurge: utils.Ptr(int64(1)), + MaxSurge: utils.Ptr(int64(3)), MaxUnavailable: utils.Ptr(int64(0)), - Maximum: utils.Ptr(int64(2)), + Maximum: utils.Ptr(int64(3)), Minimum: utils.Ptr(int64(1)), Name: utils.Ptr("pool-default"), Volume: &ske.Volume{ @@ -312,6 +325,34 @@ func TestGetDefaultPayload(t *testing.T) { listProviderOptionsFails: true, isValid: false, }, + { + description: "availability zones nil", + listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { + po.AvailabilityZones = nil + }), + isValid: false, + }, + { + description: "no availability zones", + listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { + po.AvailabilityZones = &[]ske.AvailabilityZone{} + }), + isValid: false, + }, + { + description: "machine types nil", + listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { + po.MachineTypes = nil + }), + isValid: false, + }, + { + description: "no machine types", + listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { + po.MachineTypes = &[]ske.MachineType{} + }), + isValid: false, + }, { description: "no Kubernetes versions 1", listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { From cfd42a05e19069bbb067e2a9ce1cce0679e9a603 Mon Sep 17 00:00:00 2001 From: Jorge Turrado Ferrero Date: Fri, 17 Oct 2025 14:47:56 +0200 Subject: [PATCH 464/619] feat: Print auth login during `stackit auth login` (#1027) * feat: Print auth login during Successfully logged into STACKIT CLI. Signed-off-by: Jorge Turrado * update message Signed-off-by: Jorge Turrado * update message Signed-off-by: Jorge Turrado --------- Signed-off-by: Jorge Turrado --- internal/pkg/auth/user_login.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index 8ac94743e..2ec2040dd 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -244,6 +244,10 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { return fmt.Errorf("open browser to URL %s: %w", authorizationURL, err) } + // Print the link + p.Outputln("Your browser has been opened to visit:\n") + p.Outputf("%s\n\n", authorizationURL) + // Start the blocking web server loop // It will exit when the handlers get fired and call server.Close() p.Debug(print.DebugLevel, "listening for response from authentication server on %s", redirectURL) From 7b0c48d5c0b06051cb8e9b02e3f87b245de66cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 17 Oct 2025 17:19:14 +0200 Subject: [PATCH 465/619] refactor: implement a new output result func to handle json/yaml output in a central place (#1030) --- .github/docs/contribution-guide/cmd.go | 22 +-- internal/cmd/affinity-groups/create/create.go | 22 +-- .../cmd/affinity-groups/describe/describe.go | 22 +-- internal/cmd/affinity-groups/list/list.go | 23 +-- internal/cmd/beta/alb/create/create.go | 21 +-- internal/cmd/beta/alb/describe/describe.go | 55 ++----- internal/cmd/beta/alb/list/list.go | 23 +-- .../alb/observability-credentials/add/add.go | 25 +--- .../describe/describe.go | 28 +--- .../observability-credentials/list/list.go | 22 +-- .../update/update.go | 24 +--- internal/cmd/beta/alb/plans/plans.go | 23 +-- internal/cmd/beta/alb/pool/update/update.go | 21 +-- internal/cmd/beta/alb/quotas/quotas.go | 23 +-- internal/cmd/beta/alb/update/update.go | 21 +-- .../sqlserverflex/database/create/create.go | 22 +-- .../database/describe/describe.go | 22 +-- .../beta/sqlserverflex/database/list/list.go | 23 +-- .../sqlserverflex/instance/create/create.go | 23 +-- .../instance/describe/describe.go | 22 +-- .../beta/sqlserverflex/instance/list/list.go | 23 +-- .../sqlserverflex/instance/update/update.go | 23 +-- .../cmd/beta/sqlserverflex/options/options.go | 70 ++++----- .../beta/sqlserverflex/user/create/create.go | 23 +-- .../sqlserverflex/user/describe/describe.go | 22 +-- .../cmd/beta/sqlserverflex/user/list/list.go | 23 +-- .../user/reset-password/reset_password.go | 22 +-- internal/cmd/config/profile/list/list.go | 22 +-- internal/cmd/dns/record-set/create/create.go | 23 +-- .../cmd/dns/record-set/describe/describe.go | 22 +-- internal/cmd/dns/record-set/list/list.go | 23 +-- internal/cmd/dns/zone/clone/clone.go | 23 +-- internal/cmd/dns/zone/create/create.go | 23 +-- internal/cmd/dns/zone/describe/describe.go | 22 +-- internal/cmd/dns/zone/list/list.go | 24 +--- internal/cmd/git/flavor/list/list.go | 23 +-- internal/cmd/git/instance/create/create.go | 22 +-- .../cmd/git/instance/describe/describe.go | 22 +-- internal/cmd/git/instance/list/list.go | 23 +-- internal/cmd/image/create/create.go | 22 +-- internal/cmd/image/describe/describe.go | 22 +-- internal/cmd/image/list/list.go | 23 +-- internal/cmd/key-pair/create/create.go | 21 +-- internal/cmd/key-pair/list/list.go | 23 +-- internal/cmd/key-pair/update/update.go | 22 +-- .../cmd/load-balancer/describe/describe.go | 50 ++----- internal/cmd/load-balancer/list/list.go | 23 +-- .../observability-credentials/add/add.go | 23 +-- .../describe/describe.go | 23 +-- .../observability-credentials/list/list.go | 23 +-- internal/cmd/load-balancer/quota/quota.go | 24 +--- .../target-pool/describe/describe.go | 135 ++++++++---------- .../cmd/logme/credentials/create/create.go | 22 +-- .../logme/credentials/describe/describe.go | 23 +-- internal/cmd/logme/credentials/list/list.go | 23 +-- internal/cmd/logme/instance/create/create.go | 23 +-- .../cmd/logme/instance/describe/describe.go | 23 +-- internal/cmd/logme/instance/list/list.go | 23 +-- internal/cmd/logme/plans/plans.go | 23 +-- .../cmd/mariadb/credentials/create/create.go | 22 +-- .../mariadb/credentials/describe/describe.go | 23 +-- internal/cmd/mariadb/credentials/list/list.go | 23 +-- .../cmd/mariadb/instance/create/create.go | 23 +-- .../cmd/mariadb/instance/describe/describe.go | 23 +-- internal/cmd/mariadb/instance/list/list.go | 23 +-- internal/cmd/mariadb/plans/plans.go | 23 +-- .../mongodbflex/backup/describe/describe.go | 23 +-- internal/cmd/mongodbflex/backup/list/list.go | 23 +-- .../backup/restore-jobs/restore_jobs.go | 23 +-- .../mongodbflex/backup/schedule/schedule.go | 23 +-- .../cmd/mongodbflex/instance/create/create.go | 23 +-- .../mongodbflex/instance/describe/describe.go | 23 +-- .../cmd/mongodbflex/instance/list/list.go | 23 +-- .../cmd/mongodbflex/instance/update/update.go | 23 +-- internal/cmd/mongodbflex/options/options.go | 22 +-- .../cmd/mongodbflex/user/create/create.go | 23 +-- .../cmd/mongodbflex/user/describe/describe.go | 23 +-- internal/cmd/mongodbflex/user/list/list.go | 23 +-- .../user/reset-password/reset_password.go | 23 +-- internal/cmd/network-area/create/create.go | 23 +-- .../cmd/network-area/describe/describe.go | 22 +-- internal/cmd/network-area/list/list.go | 23 +-- .../network-range/create/create.go | 23 +-- .../network-range/describe/describe.go | 22 +-- .../network-area/network-range/list/list.go | 23 +-- .../cmd/network-area/route/create/create.go | 23 +-- .../network-area/route/describe/describe.go | 23 +-- internal/cmd/network-area/route/list/list.go | 23 +-- .../cmd/network-area/route/update/update.go | 23 +-- internal/cmd/network-area/update/update.go | 23 +-- .../cmd/network-interface/create/create.go | 23 +-- .../network-interface/describe/describe.go | 23 +-- internal/cmd/network-interface/list/list.go | 23 +-- .../cmd/network-interface/update/update.go | 23 +-- internal/cmd/network/create/create.go | 23 +-- internal/cmd/network/describe/describe.go | 23 +-- internal/cmd/network/list/list.go | 23 +-- .../object-storage/bucket/create/create.go | 23 +-- .../bucket/describe/describe.go | 23 +-- .../cmd/object-storage/bucket/list/list.go | 23 +-- .../credentials-group/create/create.go | 23 +-- .../credentials-group/list/list.go | 23 +-- .../credentials/create/create.go | 23 +-- .../object-storage/credentials/list/list.go | 23 +-- .../credentials/create/create.go | 23 +-- .../observability/credentials/list/list.go | 23 +-- .../grafana/describe/describe.go | 23 +-- .../observability/instance/create/create.go | 23 +-- .../instance/describe/describe.go | 23 +-- .../cmd/observability/instance/list/list.go | 23 +-- internal/cmd/observability/plans/plans.go | 23 +-- .../scrape-config/describe/describe.go | 23 +-- .../observability/scrape-config/list/list.go | 23 +-- .../opensearch/credentials/create/create.go | 22 +-- .../credentials/describe/describe.go | 23 +-- .../cmd/opensearch/credentials/list/list.go | 23 +-- .../cmd/opensearch/instance/create/create.go | 23 +-- .../opensearch/instance/describe/describe.go | 23 +-- internal/cmd/opensearch/instance/list/list.go | 23 +-- internal/cmd/opensearch/plans/plans.go | 23 +-- internal/cmd/organization/member/list/list.go | 24 +--- internal/cmd/organization/role/list/list.go | 24 +--- .../postgresflex/backup/describe/describe.go | 23 +-- internal/cmd/postgresflex/backup/list/list.go | 23 +-- .../cmd/postgresflex/instance/clone/clone.go | 22 +-- .../postgresflex/instance/create/create.go | 23 +-- .../instance/describe/describe.go | 23 +-- .../cmd/postgresflex/instance/list/list.go | 23 +-- .../postgresflex/instance/update/update.go | 23 +-- internal/cmd/postgresflex/options/options.go | 50 ++----- .../cmd/postgresflex/user/create/create.go | 22 +-- .../postgresflex/user/describe/describe.go | 23 +-- internal/cmd/postgresflex/user/list/list.go | 23 +-- .../user/reset-password/reset_password.go | 23 +-- internal/cmd/project/create/create.go | 23 +-- internal/cmd/project/describe/describe.go | 22 +-- internal/cmd/project/list/list.go | 23 +-- internal/cmd/project/member/list/list.go | 24 +--- internal/cmd/project/role/list/list.go | 24 +--- internal/cmd/public-ip/create/create.go | 23 +-- internal/cmd/public-ip/describe/describe.go | 24 +--- internal/cmd/public-ip/list/list.go | 23 +-- internal/cmd/public-ip/ranges/list/list.go | 23 +-- internal/cmd/public-ip/update/update.go | 24 +--- internal/cmd/quota/list/list.go | 24 +--- .../cmd/rabbitmq/credentials/create/create.go | 22 +-- .../rabbitmq/credentials/describe/describe.go | 22 +-- .../cmd/rabbitmq/credentials/list/list.go | 23 +-- .../cmd/rabbitmq/instance/create/create.go | 23 +-- .../rabbitmq/instance/describe/describe.go | 22 +-- internal/cmd/rabbitmq/instance/list/list.go | 23 +-- internal/cmd/rabbitmq/plans/plans.go | 23 +-- .../cmd/redis/credentials/create/create.go | 23 +-- .../redis/credentials/describe/describe.go | 22 +-- internal/cmd/redis/credentials/list/list.go | 23 +-- internal/cmd/redis/instance/create/create.go | 22 +-- .../cmd/redis/instance/describe/describe.go | 22 +-- internal/cmd/redis/instance/list/list.go | 23 +-- internal/cmd/redis/plans/plans.go | 23 +-- .../secrets-manager/instance/create/create.go | 23 +-- .../instance/describe/describe.go | 23 +-- .../cmd/secrets-manager/instance/list/list.go | 23 +-- .../cmd/secrets-manager/user/create/create.go | 23 +-- .../secrets-manager/user/describe/describe.go | 23 +-- .../cmd/secrets-manager/user/list/list.go | 23 +-- internal/cmd/security-group/create/create.go | 23 +-- .../cmd/security-group/describe/describe.go | 23 +-- internal/cmd/security-group/list/list.go | 23 +-- .../cmd/security-group/rule/create/create.go | 23 +-- .../security-group/rule/describe/describe.go | 23 +-- internal/cmd/security-group/rule/list/list.go | 23 +-- internal/cmd/server/backup/create/create.go | 23 +-- .../cmd/server/backup/describe/describe.go | 23 +-- internal/cmd/server/backup/list/list.go | 23 +-- .../server/backup/schedule/create/create.go | 23 +-- .../backup/schedule/describe/describe.go | 23 +-- .../cmd/server/backup/schedule/list/list.go | 23 +-- .../server/backup/schedule/update/update.go | 23 +-- internal/cmd/server/command/create/create.go | 23 +-- .../cmd/server/command/describe/describe.go | 23 +-- internal/cmd/server/command/list/list.go | 23 +-- .../command/template/describe/describe.go | 23 +-- .../cmd/server/command/template/list/list.go | 23 +-- internal/cmd/server/console/console.go | 23 +-- internal/cmd/server/create/create.go | 23 +-- internal/cmd/server/log/log.go | 23 +-- .../server/machine-type/describe/describe.go | 24 +--- internal/cmd/server/machine-type/list/list.go | 23 +-- .../cmd/server/network-interface/list/list.go | 23 +-- .../cmd/server/os-update/create/create.go | 23 +-- .../cmd/server/os-update/describe/describe.go | 23 +-- internal/cmd/server/os-update/list/list.go | 23 +-- .../os-update/schedule/create/create.go | 23 +-- .../os-update/schedule/describe/describe.go | 23 +-- .../server/os-update/schedule/list/list.go | 23 +-- .../os-update/schedule/update/update.go | 23 +-- .../server/service-account/attach/attach.go | 23 +-- .../server/service-account/detach/detach.go | 23 +-- .../cmd/server/service-account/list/list.go | 23 +-- internal/cmd/server/update/update.go | 24 +--- internal/cmd/server/volume/attach/attach.go | 23 +-- .../cmd/server/volume/describe/describe.go | 23 +-- internal/cmd/server/volume/list/list.go | 23 +-- internal/cmd/server/volume/update/update.go | 23 +-- internal/cmd/service-account/create/create.go | 23 +-- internal/cmd/service-account/key/list/list.go | 23 +-- internal/cmd/service-account/list/list.go | 22 +-- .../service-account/token/create/create.go | 23 +-- .../cmd/service-account/token/list/list.go | 23 +-- internal/cmd/ske/cluster/create/create.go | 22 +-- internal/cmd/ske/cluster/describe/describe.go | 23 +-- internal/cmd/ske/cluster/list/list.go | 23 +-- internal/cmd/ske/cluster/update/update.go | 22 +-- internal/cmd/ske/describe/describe.go | 23 +-- internal/cmd/ske/options/options.go | 21 +-- internal/cmd/volume/backup/create/create.go | 23 +-- .../cmd/volume/backup/describe/describe.go | 23 +-- internal/cmd/volume/backup/list/list.go | 23 +-- internal/cmd/volume/backup/update/update.go | 23 +-- internal/cmd/volume/create/create.go | 23 +-- internal/cmd/volume/describe/describe.go | 24 +--- internal/cmd/volume/list/list.go | 23 +-- .../performance-class/describe/describe.go | 24 +--- .../cmd/volume/performance-class/list/list.go | 23 +-- .../cmd/volume/snapshot/describe/describe.go | 23 +-- internal/cmd/volume/snapshot/list/list.go | 23 +-- internal/cmd/volume/update/update.go | 24 +--- internal/pkg/print/print.go | 26 ++++ internal/pkg/print/print_test.go | 76 ++++++++++ 229 files changed, 686 insertions(+), 4859 deletions(-) diff --git a/.github/docs/contribution-guide/cmd.go b/.github/docs/contribution-guide/cmd.go index 286d6240d..1373ebbb0 100644 --- a/.github/docs/contribution-guide/cmd.go +++ b/.github/docs/contribution-guide/cmd.go @@ -2,7 +2,6 @@ package bar import ( "context" - "encoding/json" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "gopkg.in/yaml.v2" // (...) ) @@ -118,22 +116,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *foo.APIClie // Output result based on the configured output format func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, resources []foo.Resource) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resources, "", " ") - if err != nil { - return fmt.Errorf("marshal resource list: %w", err) - } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.Marshal(resources) - if err != nil { - return fmt.Errorf("marshal resource list: %w", err) - } - p.Outputln(string(details)) - return nil - default: + // the output result handles JSON/YAML output, you can pass your own callback func for pretty (default) output format + return p.OutputResult(outputFormat, resources, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATE") for i := range resources { @@ -145,5 +129,5 @@ func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, res return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go index 03a4354f9..30daf9339 100644 --- a/internal/cmd/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -121,21 +119,9 @@ func outputResult(p *print.Printer, model inputModel, resp iaas.AffinityGroup) e if model.GlobalFlagModel != nil { outputFormat = model.GlobalFlagModel.OutputFormat } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal affinity group: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal affinity group: %w", err) - } - p.Outputln(string(details)) - default: + + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created affinity group %q with id %s\n", model.Name, utils.PtrString(resp.Id)) - } - return nil + return nil + }) } diff --git a/internal/cmd/affinity-groups/describe/describe.go b/internal/cmd/affinity-groups/describe/describe.go index 936db9605..7af292d74 100644 --- a/internal/cmd/affinity-groups/describe/describe.go +++ b/internal/cmd/affinity-groups/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -93,20 +91,8 @@ func outputResult(p *print.Printer, model inputModel, resp iaas.AffinityGroup) e if model.GlobalFlagModel != nil { outputFormat = model.GlobalFlagModel.OutputFormat } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal affinity group: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal affinity group: %w", err) - } - p.Outputln(string(details)) - default: + + return p.OutputResult(outputFormat, resp, func() error { table := tables.NewTable() if resp.HasId() { @@ -129,6 +115,6 @@ func outputResult(p *print.Printer, model inputModel, resp iaas.AffinityGroup) e if err := table.Display(p); err != nil { return fmt.Errorf("render table: %w", err) } - } - return nil + return nil + }) } diff --git a/internal/cmd/affinity-groups/list/list.go b/internal/cmd/affinity-groups/list/list.go index 58269d898..36ae4f28c 100644 --- a/internal/cmd/affinity-groups/list/list.go +++ b/internal/cmd/affinity-groups/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -115,20 +113,8 @@ func outputResult(p *print.Printer, model inputModel, items []iaas.AffinityGroup if model.GlobalFlagModel != nil { outputFormat = model.GlobalFlagModel.OutputFormat } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(items, "", " ") - if err != nil { - return fmt.Errorf("marshal affinity groups: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal affinity groups: %w", err) - } - p.Outputln(string(details)) - default: + + return p.OutputResult(outputFormat, items, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "POLICY") for _, item := range items { @@ -143,6 +129,7 @@ func outputResult(p *print.Printer, model inputModel, items []iaas.AffinityGroup if err := table.Display(p); err != nil { return fmt.Errorf("render table: %w", err) } - } - return nil + + return nil + }) } diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go index a9113a5f0..64d3c2871 100644 --- a/internal/cmd/beta/alb/create/create.go +++ b/internal/cmd/beta/alb/create/create.go @@ -162,29 +162,12 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if resp == nil { return fmt.Errorf("create loadbalancer response is empty") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal loadbalancer: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal loadbalancer: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Created" if model.Async { operationState = "Triggered creation of" } p.Outputf("%s application loadbalancer for %q. Name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name)) return nil - } + }) } diff --git a/internal/cmd/beta/alb/describe/describe.go b/internal/cmd/beta/alb/describe/describe.go index 8d61212a3..bccca2ace 100644 --- a/internal/cmd/beta/alb/describe/describe.go +++ b/internal/cmd/beta/alb/describe/describe.go @@ -2,7 +2,6 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" @@ -16,7 +15,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -89,54 +87,27 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClie return apiClient.GetLoadBalancer(ctx, model.ProjectId, model.Region, model.Name) } -func outputResult(p *print.Printer, outputFormat string, response *alb.LoadBalancer) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(response, "", " ") +func outputResult(p *print.Printer, outputFormat string, loadbalancer *alb.LoadBalancer) error { + return p.OutputResult(outputFormat, loadbalancer, func() error { + content := []tables.Table{} - if err != nil { - return fmt.Errorf("marshal loadbalancer: %w", err) + content = append(content, buildLoadBalancerTable(loadbalancer)) + + if loadbalancer.Listeners != nil { + content = append(content, buildListenersTable(*loadbalancer.Listeners)) } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(response, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if loadbalancer.TargetPools != nil { + content = append(content, buildTargetPoolsTable(*loadbalancer.TargetPools)) + } + err := tables.DisplayTables(p, content) if err != nil { - return fmt.Errorf("marshal loadbalancer: %w", err) + return fmt.Errorf("display output: %w", err) } - p.Outputln(string(details)) return nil - default: - if err := outputResultAsTable(p, response); err != nil { - return err - } - } - - return nil -} - -func outputResultAsTable(p *print.Printer, loadbalancer *alb.LoadBalancer) error { - content := []tables.Table{} - - content = append(content, buildLoadBalancerTable(loadbalancer)) - - if loadbalancer.Listeners != nil { - content = append(content, buildListenersTable(*loadbalancer.Listeners)) - } - - if loadbalancer.TargetPools != nil { - content = append(content, buildTargetPoolsTable(*loadbalancer.TargetPools)) - } - - err := tables.DisplayTables(p, content) - if err != nil { - return fmt.Errorf("display output: %w", err) - } - - return nil + }) } func buildLoadBalancerTable(loadbalancer *alb.LoadBalancer) tables.Table { diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go index 7958a1ad8..a16443730 100644 --- a/internal/cmd/beta/alb/list/list.go +++ b/internal/cmd/beta/alb/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -128,24 +126,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClie return request } func outputResult(p *print.Printer, outputFormat string, items []alb.LoadBalancer) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(items, "", " ") - if err != nil { - return fmt.Errorf("marshal loadbalancer list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal loadbalancer list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, items, func() error { table := tables.NewTable() table.SetHeader("NAME", "EXTERNAL ADDRESS", "REGION", "STATUS", "VERSION", "ERRORS") for i := range items { @@ -169,5 +150,5 @@ func outputResult(p *print.Printer, outputFormat string, items []alb.LoadBalance } return nil - } + }) } diff --git a/internal/cmd/beta/alb/observability-credentials/add/add.go b/internal/cmd/beta/alb/observability-credentials/add/add.go index 7b623ef16..8fd15d81d 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add.go @@ -2,7 +2,6 @@ package add import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -13,7 +12,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -115,25 +113,10 @@ func outputResult(p *print.Printer, outputFormat string, item *alb.CreateCredent return fmt.Errorf("no credential found") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(item, "", " ") - if err != nil { - return fmt.Errorf("marshal credential: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(item, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal credential: %w", err) - } - p.Outputln(string(details)) - default: + return p.OutputResult(outputFormat, item, func() error { if item.Credential != nil { - p.Outputf("Created credential %s\n", - utils.PtrString(item.Credential.CredentialsRef), - ) + p.Outputf("Created credential %s\n", utils.PtrString(item.Credential.CredentialsRef)) } - } - return nil + return nil + }) } diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe.go b/internal/cmd/beta/alb/observability-credentials/describe/describe.go index 882ac0a02..2ebf96e4a 100644 --- a/internal/cmd/beta/alb/observability-credentials/describe/describe.go +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe.go @@ -2,7 +2,6 @@ package describe import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -15,7 +14,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -89,26 +87,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClie } func outputResult(p *print.Printer, outputFormat string, response alb.CredentialsResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(response, "", " ") - - if err != nil { - return fmt.Errorf("marshal credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(response, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - - if err != nil { - return fmt.Errorf("marshal credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, response, func() error { table := tables.NewTable() table.AddRow("CREDENTIAL REF", utils.PtrString(response.CredentialsRef)) table.AddSeparator() @@ -120,7 +99,6 @@ func outputResult(p *print.Printer, outputFormat string, response alb.Credential table.AddSeparator() p.Outputln(table.Render()) - } - - return nil + return nil + }) } diff --git a/internal/cmd/beta/alb/observability-credentials/list/list.go b/internal/cmd/beta/alb/observability-credentials/list/list.go index 613ba9c24..dace68982 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list.go @@ -2,7 +2,6 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -17,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -122,22 +120,8 @@ func outputResult(p *print.Printer, outputFormat string, items []alb.Credentials p.Outputln("no credentials found") return nil } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(items, "", " ") - if err != nil { - return fmt.Errorf("marshal credentials: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal credentials: %w", err) - } - p.Outputln(string(details)) - default: + return p.OutputResult(outputFormat, items, func() error { table := tables.NewTable() table.SetHeader("CREDENTIAL REF", "DISPLAYNAME", "USERNAME", "REGION") @@ -151,6 +135,6 @@ func outputResult(p *print.Printer, outputFormat string, items []alb.Credentials } p.Outputln(table.Render()) - } - return nil + return nil + }) } diff --git a/internal/cmd/beta/alb/observability-credentials/update/update.go b/internal/cmd/beta/alb/observability-credentials/update/update.go index e9ff003e8..703fe12a7 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update.go @@ -2,7 +2,6 @@ package update import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -15,7 +14,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -132,23 +130,11 @@ func outputResult(p *print.Printer, model inputModel, response *alb.UpdateCreden outputFormat = model.GlobalFlagModel.OutputFormat } if response == nil { - return fmt.Errorf("no response passewd") + return fmt.Errorf("no response passed") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(response.Credential, "", " ") - if err != nil { - return fmt.Errorf("marshal credential: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(response.Credential, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal credential: %w", err) - } - p.Outputln(string(details)) - default: + + return p.OutputResult(outputFormat, response.Credential, func() error { p.Outputf("Updated credential %q\n", utils.PtrString(model.CredentialsRef)) - } - return nil + return nil + }) } diff --git a/internal/cmd/beta/alb/plans/plans.go b/internal/cmd/beta/alb/plans/plans.go index b6698ce2e..55c4ab6c5 100644 --- a/internal/cmd/beta/alb/plans/plans.go +++ b/internal/cmd/beta/alb/plans/plans.go @@ -2,10 +2,8 @@ package plans import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -101,24 +99,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClie } func outputResult(p *print.Printer, outputFormat string, items []alb.PlanDetails) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(items, "", " ") - if err != nil { - return fmt.Errorf("marshal plans: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal plans: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, items, func() error { table := tables.NewTable() table.SetHeader("PLAN ID", "NAME", "FLAVOR", "MAX CONNS", "DESCRIPTION") for _, item := range items { @@ -135,5 +116,5 @@ func outputResult(p *print.Printer, outputFormat string, items []alb.PlanDetails } return nil - } + }) } diff --git a/internal/cmd/beta/alb/pool/update/update.go b/internal/cmd/beta/alb/pool/update/update.go index 857ae2a44..a3a8aa983 100644 --- a/internal/cmd/beta/alb/pool/update/update.go +++ b/internal/cmd/beta/alb/pool/update/update.go @@ -156,29 +156,12 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if resp == nil { return fmt.Errorf("update target pool response is empty") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal target pool: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal target pool: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Updated" if model.Async { operationState = "Triggered update of" } p.Outputf("%s application target pool for %q. Name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name)) return nil - } + }) } diff --git a/internal/cmd/beta/alb/quotas/quotas.go b/internal/cmd/beta/alb/quotas/quotas.go index 3eec45f7d..9b2729c29 100644 --- a/internal/cmd/beta/alb/quotas/quotas.go +++ b/internal/cmd/beta/alb/quotas/quotas.go @@ -2,10 +2,8 @@ package quotas import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -93,24 +91,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClie } func outputResult(p *print.Printer, outputFormat string, response alb.GetQuotaResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(response, "", " ") - if err != nil { - return fmt.Errorf("marshal quotas: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(response, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal quotas: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, response, func() error { table := tables.NewTable() table.AddRow("REGION", utils.PtrString(response.Region)) table.AddSeparator() @@ -121,5 +102,5 @@ func outputResult(p *print.Printer, outputFormat string, response alb.GetQuotaRe } return nil - } + }) } diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go index 6040762a5..a8b32b156 100644 --- a/internal/cmd/beta/alb/update/update.go +++ b/internal/cmd/beta/alb/update/update.go @@ -192,29 +192,12 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if resp == nil { return fmt.Errorf("update loadbalancer response is empty") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal loadbalancer: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal loadbalancer: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Updated" if model.Async { operationState = "Triggered update of" } p.Outputf("%s application loadbalancer for %q. Name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name)) return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index d643d8da7..8b20bb219 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -129,25 +127,9 @@ func outputResult(p *print.Printer, outputFormat, databaseName string, resp *sql if resp == nil { return fmt.Errorf("sqlserverflex response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex database: %w", err) - } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex database: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created database %q\n", databaseName) return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index 7c460f3e5..ef4afa8fc 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -106,24 +104,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *sqlserverflex.Get if resp == nil || resp.Database == nil { return fmt.Errorf("database response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex database: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex database: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { database := resp.Database table := tables.NewTable() table.AddRow("ID", utils.PtrString(database.Id)) @@ -149,5 +131,5 @@ func outputResult(p *print.Printer, outputFormat string, resp *sqlserverflex.Get } return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index f8675f0b9..990946dad 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -130,24 +128,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl } func outputResult(p *print.Printer, outputFormat string, databases []sqlserverflex.Database) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(databases, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex database list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(databases, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex database list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, databases, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME") for i := range databases { @@ -160,5 +141,5 @@ func outputResult(p *print.Printer, outputFormat string, databases []sqlserverfl } return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 4b31bef84..9acc361b7 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -2,11 +2,9 @@ package create import ( "context" - "encoding/json" "errors" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -264,29 +262,12 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if resp == nil { return fmt.Errorf("sqlserverflex response is empty") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServerFlex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServerFlex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Created" if model.Async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index bed2f269c..d978bcf97 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -95,24 +93,8 @@ func outputResult(p *print.Printer, outputFormat string, instance *sqlserverflex if instance == nil { return fmt.Errorf("instance response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex instance: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { var acls string if instance.Acl != nil && instance.Acl.HasItems() { aclsArray := *instance.Acl.Items @@ -150,5 +132,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *sqlserverflex } return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 3b97b8dcb..3e8606347 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl } func outputResult(p *print.Printer, outputFormat string, instances []sqlserverflex.InstanceListInstance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATUS") for i := range instances { @@ -157,5 +138,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []sqlserverfl } return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index 68e76cf25..ec06d020a 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -2,11 +2,9 @@ package update import ( "context" - "encoding/json" "errors" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -248,29 +246,12 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res if resp == nil { return fmt.Errorf("instance response is empty") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal update SQLServerFlex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal update SQLServerFlex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Updated" if model.Async { operationState = "Triggered update of" } p.Info("%s instance %q\n", operationState, instanceLabel) return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index f288fd27d..a6c126e8b 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -2,10 +2,8 @@ package options import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -276,55 +274,35 @@ func outputResult(p *print.Printer, model *inputModel, flavors *sqlserverflex.Li } } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(options, "", " ") - if err != nil { - return fmt.Errorf("marshal SQL Server Flex options: %w", err) + return p.OutputResult(model.OutputFormat, options, func() error { + content := []tables.Table{} + if model.Flavors && len(*options.Flavors) != 0 { + content = append(content, buildFlavorsTable(*options.Flavors)) } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if model.Versions && len(*options.Versions) != 0 { + content = append(content, buildVersionsTable(*options.Versions)) + } + if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) != 0 { + content = append(content, buildStoragesTable(*options.Storages.Storages)) + } + if model.UserRoles && len(options.UserRoles.UserRoles) != 0 { + content = append(content, buildUserRoles(options.UserRoles)) + } + if model.DBCompatibilities && len(options.DBCompatibilities.DBCompatibilities) != 0 { + content = append(content, buildDBCompatibilitiesTable(options.DBCompatibilities.DBCompatibilities)) + } + // Rendered at last because table is very long + if model.DBCollations && len(options.DBCollations.DBCollations) != 0 { + content = append(content, buildDBCollationsTable(options.DBCollations.DBCollations)) + } + + err := tables.DisplayTables(p, content) if err != nil { - return fmt.Errorf("marshal SQL Server Flex options: %w", err) + return fmt.Errorf("display output: %w", err) } - p.Outputln(string(details)) return nil - default: - return outputResultAsTable(p, model, options) - } -} - -func outputResultAsTable(p *print.Printer, model *inputModel, options *options) error { - content := []tables.Table{} - if model.Flavors && len(*options.Flavors) != 0 { - content = append(content, buildFlavorsTable(*options.Flavors)) - } - if model.Versions && len(*options.Versions) != 0 { - content = append(content, buildVersionsTable(*options.Versions)) - } - if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) != 0 { - content = append(content, buildStoragesTable(*options.Storages.Storages)) - } - if model.UserRoles && len(options.UserRoles.UserRoles) != 0 { - content = append(content, buildUserRoles(options.UserRoles)) - } - if model.DBCompatibilities && len(options.DBCompatibilities.DBCompatibilities) != 0 { - content = append(content, buildDBCompatibilitiesTable(options.DBCompatibilities.DBCompatibilities)) - } - // Rendered at last because table is very long - if model.DBCollations && len(options.DBCollations.DBCollations) != 0 { - content = append(content, buildDBCollationsTable(options.DBCollations.DBCollations)) - } - - err := tables.DisplayTables(p, content) - if err != nil { - return fmt.Errorf("display output: %w", err) - } - - return nil + }) } func buildFlavorsTable(flavors []sqlserverflex.InstanceFlavorEntry) tables.Table { diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 92e4a1127..cb159965f 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -2,11 +2,9 @@ package create import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -140,24 +138,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, use if user == nil { return fmt.Errorf("user response is empty") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(user, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex user: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex user: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, user, func() error { p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) p.Outputf("Username: %s\n", utils.PtrString(user.Username)) p.Outputf("Password: %s\n", utils.PtrString(user.Password)) @@ -175,5 +156,5 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, use } return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index cd4efd01b..93d97acc4 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -115,24 +113,8 @@ func outputResult(p *print.Printer, outputFormat string, user *sqlserverflex.Use if user == nil { return fmt.Errorf("user response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(user, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex user: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex user: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, user, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(user.Id)) table.AddSeparator() @@ -160,5 +142,5 @@ func outputResult(p *print.Printer, outputFormat string, user *sqlserverflex.Use } return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index 022aade17..08950270e 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -131,24 +129,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl } func outputResult(p *print.Printer, outputFormat string, users []sqlserverflex.InstanceListUser) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(users, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex user list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex user list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, users, func() error { table := tables.NewTable() table.SetHeader("ID", "USERNAME") for i := range users { @@ -164,5 +145,5 @@ func outputResult(p *print.Printer, outputFormat string, users []sqlserverflex.I } return nil - } + }) } diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index 027ba4b44..b56538eec 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -2,10 +2,8 @@ package resetpassword import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -130,24 +128,8 @@ func outputResult(p *print.Printer, outputFormat, userLabel, instanceLabel strin if user == nil { return fmt.Errorf("single user response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(user, "", " ") - if err != nil { - return fmt.Errorf("marshal SQLServer Flex reset password: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SQLServer Flex reset password: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, user, func() error { p.Outputf("Reset password for user %q of instance %q\n\n", userLabel, instanceLabel) p.Outputf("Username: %s\n", utils.PtrString(user.Username)) p.Outputf("New password: %s\n", utils.PtrString(user.Password)) @@ -155,5 +137,5 @@ func outputResult(p *print.Printer, outputFormat, userLabel, instanceLabel strin p.Outputf("New URI: %s\n", *user.Uri) } return nil - } + }) } diff --git a/internal/cmd/config/profile/list/list.go b/internal/cmd/config/profile/list/list.go index 86e2f3341..fe90d4619 100644 --- a/internal/cmd/config/profile/list/list.go +++ b/internal/cmd/config/profile/list/list.go @@ -1,11 +1,8 @@ package list import ( - "encoding/json" "fmt" - "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" @@ -93,22 +90,7 @@ func buildOutput(profiles []string, activeProfile string) []profileInfo { } func outputResult(p *print.Printer, outputFormat string, profiles []profileInfo) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(profiles, "", " ") - if err != nil { - return fmt.Errorf("marshal config list: %w", err) - } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(profiles, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal config list: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, profiles, func() error { table := tables.NewTable() table.SetHeader("NAME", "ACTIVE", "EMAIL") for _, profile := range profiles { @@ -129,5 +111,5 @@ func outputResult(p *print.Printer, outputFormat string, profiles []profileInfo) return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index c1fae768e..1320248d4 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -182,29 +180,12 @@ func outputResult(p *print.Printer, model *inputModel, zoneLabel string, resp *d if resp == nil { return fmt.Errorf("record set response is empty") } - 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal DNS record-set: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Created" if model.Async { operationState = "Triggered creation of" } p.Outputf("%s record set for zone %s. Record set ID: %s\n", operationState, zoneLabel, utils.PtrString(resp.Rrset.Id)) return nil - } + }) } diff --git a/internal/cmd/dns/record-set/describe/describe.go b/internal/cmd/dns/record-set/describe/describe.go index ceaf1a9d9..c84e0ab7a 100644 --- a/internal/cmd/dns/record-set/describe/describe.go +++ b/internal/cmd/dns/record-set/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -110,24 +108,8 @@ func outputResult(p *print.Printer, outputFormat string, recordSet *dns.RecordSe if recordSet == nil { return fmt.Errorf("record set response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(recordSet, "", " ") - if err != nil { - return fmt.Errorf("marshal DNS record set: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(recordSet, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal DNS record set: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, recordSet, func() error { recordsData := make([]string, 0, len(*recordSet.Records)) for _, r := range *recordSet.Records { recordsData = append(recordsData, *r.Content) @@ -152,5 +134,5 @@ func outputResult(p *print.Printer, outputFormat string, recordSet *dns.RecordSe } return nil - } + }) } diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index cafaf9921..1d9093de7 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" "math" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -242,24 +240,7 @@ func fetchRecordSets(ctx context.Context, model *inputModel, apiClient dnsClient } func outputResult(p *print.Printer, outputFormat string, recordSets []dns.RecordSet) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(recordSets, "", " ") - if err != nil { - return fmt.Errorf("marshal DNS record set list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(recordSets, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal DNS record set list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, recordSets, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATUS", "TTL", "TYPE", "RECORD DATA") for i := range recordSets { @@ -284,5 +265,5 @@ func outputResult(p *print.Printer, outputFormat string, recordSets []dns.Record } return nil - } + }) } diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index c8292c59f..a50b2fd73 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -2,10 +2,8 @@ package clone import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -156,29 +154,12 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if resp == nil { return fmt.Errorf("dns zone response is empty") } - 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal DNS zone: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Cloned" if model.Async { operationState = "Triggered cloning of" } p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Zone.Id)) return nil - } + }) } diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index ebcbc273e..a28e05622 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -203,29 +201,12 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp if resp == nil { return fmt.Errorf("dns zone response is empty") } - 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal DNS zone: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Created" if model.Async { operationState = "Triggered creation of" } p.Outputf("%s zone for project %q. Zone ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Zone.Id)) return nil - } + }) } diff --git a/internal/cmd/dns/zone/describe/describe.go b/internal/cmd/dns/zone/describe/describe.go index 0caf4ab55..94ccafde1 100644 --- a/internal/cmd/dns/zone/describe/describe.go +++ b/internal/cmd/dns/zone/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -95,24 +93,8 @@ func outputResult(p *print.Printer, outputFormat string, zone *dns.Zone) error { if zone == nil { return fmt.Errorf("zone response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(zone, "", " ") - if err != nil { - return fmt.Errorf("marshal DNS zone: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(zone, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal DNS zone: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, zone, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(zone.Id)) table.AddSeparator() @@ -149,5 +131,5 @@ func outputResult(p *print.Printer, outputFormat string, zone *dns.Zone) error { } return nil - } + }) } diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index c61e58e3f..d39cea62e 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" "math" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -231,25 +229,7 @@ func fetchZones(ctx context.Context, model *inputModel, apiClient dnsClient) ([] } func outputResult(p *print.Printer, outputFormat string, zones []dns.Zone) error { - switch outputFormat { - case print.JSONOutputFormat: - // Show details - details, err := json.MarshalIndent(zones, "", " ") - if err != nil { - return fmt.Errorf("marshal DNS zone list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(zones, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal DNS zone list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, zones, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATE", "TYPE", "DNS NAME", "RECORD COUNT") for i := range zones { @@ -268,5 +248,5 @@ func outputResult(p *print.Printer, outputFormat string, zones []dns.Zone) error } return nil - } + }) } diff --git a/internal/cmd/git/flavor/list/list.go b/internal/cmd/git/flavor/list/list.go index c562a6b67..2b2a5039e 100644 --- a/internal/cmd/git/flavor/list/list.go +++ b/internal/cmd/git/flavor/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -113,24 +111,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClie } func outputResult(p *print.Printer, outputFormat string, flavors []git.Flavor) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(flavors, "", " ") - if err != nil { - return fmt.Errorf("marshal Observability flavor list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(flavors, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Observability flavor list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, flavors, func() error { table := tables.NewTable() table.SetHeader("ID", "DESCRIPTION", "DISPLAY_NAME", "AVAILABLE", "SKU") for i := range flavors { @@ -149,5 +130,5 @@ func outputResult(p *print.Printer, outputFormat string, flavors []git.Flavor) e } return nil - } + }) } diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index 15a46c1fc..d94b99112 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -154,25 +152,9 @@ func outputResult(p *print.Printer, model *inputModel, resp *git.Instance) error if model.GlobalFlagModel != nil { outputFormat = model.OutputFormat } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal instance: %w", err) - } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal iminstanceage: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created instance %q with id %s\n", model.Name, utils.PtrString(model.Id)) return nil - } + }) } diff --git a/internal/cmd/git/instance/describe/describe.go b/internal/cmd/git/instance/describe/describe.go index 08d9611ae..57bd8e859 100644 --- a/internal/cmd/git/instance/describe/describe.go +++ b/internal/cmd/git/instance/describe/describe.go @@ -2,12 +2,10 @@ package describe import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -91,24 +89,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *git.Instance) err if resp == nil { return fmt.Errorf("instance not found") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal instance: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { table := tables.NewTable() if id := resp.Id; id != nil { table.AddRow("ID", *id) @@ -140,5 +122,5 @@ func outputResult(p *print.Printer, outputFormat string, resp *git.Instance) err } return nil - } + }) } diff --git a/internal/cmd/git/instance/list/list.go b/internal/cmd/git/instance/list/list.go index f0dd2d07b..a31337551 100644 --- a/internal/cmd/git/instance/list/list.go +++ b/internal/cmd/git/instance/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -114,24 +112,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClie } func outputResult(p *print.Printer, outputFormat string, instances []git.Instance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal Observability instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Observability instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "URL", "VERSION", "STATE", "CREATED") for i := range instances { @@ -151,5 +132,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []git.Instanc } return nil - } + }) } diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index fbfe766aa..58be504a8 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -3,7 +3,6 @@ package create import ( "bufio" "context" - "encoding/json" goerrors "errors" "fmt" "io" @@ -11,7 +10,6 @@ import ( "os" "time" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -403,25 +401,9 @@ func outputResult(p *print.Printer, model *inputModel, resp *iaas.ImageCreateRes if model.GlobalFlagModel != nil { outputFormat = model.OutputFormat } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal image: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal image: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created image %q with id %s\n", model.Name, utils.PtrString(model.Id)) return nil - } + }) } diff --git a/internal/cmd/image/describe/describe.go b/internal/cmd/image/describe/describe.go index 0a8af40bb..b6d81e06d 100644 --- a/internal/cmd/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -92,24 +90,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *iaas.Image) error if resp == nil { return fmt.Errorf("image not found") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal image: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal image: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { table := tables.NewTable() if id := resp.Id; id != nil { table.AddRow("ID", *id) @@ -169,5 +151,5 @@ func outputResult(p *print.Printer, outputFormat string, resp *iaas.Image) error } return nil - } + }) } diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index cb19bd651..bac3f9c97 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -138,24 +136,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return request } func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(items, "", " ") - if err != nil { - return fmt.Errorf("marshal image list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal image list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, items, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "OS", "ARCHITECTURE", "DISTRIBUTION", "VERSION", "LABELS") for i := range items { @@ -194,5 +175,5 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) err } return nil - } + }) } diff --git a/internal/cmd/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go index 64c0a63b9..acb8a0f29 100644 --- a/internal/cmd/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -2,7 +2,6 @@ package create import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -13,7 +12,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -130,24 +128,11 @@ func outputResult(p *print.Printer, outputFormat string, item *iaas.Keypair) err return fmt.Errorf("no key pair found") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(item, "", " ") - if err != nil { - return fmt.Errorf("marshal key pair: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(item, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal key pair: %w", err) - } - p.Outputln(string(details)) - default: + return p.OutputResult(outputFormat, item, func() error { p.Outputf("Created key pair %q.\nkey pair Fingerprint: %q\n", utils.PtrString(item.Name), utils.PtrString(item.Fingerprint), ) - } - return nil + return nil + }) } diff --git a/internal/cmd/key-pair/list/list.go b/internal/cmd/key-pair/list/list.go index e185d6767..68134bb02 100644 --- a/internal/cmd/key-pair/list/list.go +++ b/internal/cmd/key-pair/list/list.go @@ -2,7 +2,6 @@ package list import ( "context" - "encoding/json" "fmt" "strings" @@ -18,7 +17,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -130,22 +128,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, keyPairs []iaas.Keypair) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(keyPairs, "", " ") - if err != nil { - return fmt.Errorf("marshal key pairs: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keyPairs, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal key pairs: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, keyPairs, func() error { table := tables.NewTable() table.SetHeader("KEY PAIR NAME", "LABELS", "FINGERPRINT", "CREATED AT", "UPDATED AT") @@ -169,6 +152,6 @@ func outputResult(p *print.Printer, outputFormat string, keyPairs []iaas.Keypair } p.Outputln(table.Render()) - } - return nil + return nil + }) } diff --git a/internal/cmd/key-pair/update/update.go b/internal/cmd/key-pair/update/update.go index 2da8a409c..10bce6606 100644 --- a/internal/cmd/key-pair/update/update.go +++ b/internal/cmd/key-pair/update/update.go @@ -2,7 +2,6 @@ package update import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -14,7 +13,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -112,21 +110,9 @@ func outputResult(p *print.Printer, model inputModel, keyPair iaas.Keypair) erro if model.GlobalFlagModel != nil { outputFormat = model.GlobalFlagModel.OutputFormat } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(keyPair, "", " ") - if err != nil { - return fmt.Errorf("marshal key pair: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keyPair, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal key pair: %w", err) - } - p.Outputln(string(details)) - default: + + return p.OutputResult(outputFormat, keyPair, func() error { p.Outputf("Updated labels of key pair %q\n", utils.PtrString(model.KeyPairName)) - } - return nil + return nil + }) } diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index df1403a14..5879fb8f3 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -95,47 +93,25 @@ func outputResult(p *print.Printer, outputFormat string, loadBalancer *loadbalan if loadBalancer == nil { return fmt.Errorf("loadbalancer response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(loadBalancer, "", " ") - if err != nil { - return fmt.Errorf("marshal load balancer: %w", err) + + return p.OutputResult(outputFormat, loadBalancer, func() error { + content := []tables.Table{} + content = append(content, buildLoadBalancerTable(loadBalancer)) + + if loadBalancer.Listeners != nil { + content = append(content, buildListenersTable(*loadBalancer.Listeners)) + } + if loadBalancer.TargetPools != nil { + content = append(content, buildTargetPoolsTable(*loadBalancer.TargetPools)) } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(loadBalancer, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + err := tables.DisplayTables(p, content) if err != nil { - return fmt.Errorf("marshal load balancer: %w", err) + return fmt.Errorf("display output: %w", err) } - p.Outputln(string(details)) return nil - default: - return outputResultAsTable(p, loadBalancer) - } -} - -func outputResultAsTable(p *print.Printer, loadBalancer *loadbalancer.LoadBalancer) error { - content := []tables.Table{} - - content = append(content, buildLoadBalancerTable(loadBalancer)) - - if loadBalancer.Listeners != nil { - content = append(content, buildListenersTable(*loadBalancer.Listeners)) - } - - if loadBalancer.TargetPools != nil { - content = append(content, buildTargetPoolsTable(*loadBalancer.TargetPools)) - } - - err := tables.DisplayTables(p, content) - if err != nil { - return fmt.Errorf("display output: %w", err) - } - - return nil + }) } func buildLoadBalancerTable(loadBalancer *loadbalancer.LoadBalancer) tables.Table { diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index 511bee335..fa31894eb 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -125,24 +123,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalance } func outputResult(p *print.Printer, outputFormat string, loadBalancers []loadbalancer.LoadBalancer) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(loadBalancers, "", " ") - if err != nil { - return fmt.Errorf("marshal load balancer list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(loadBalancers, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal load balancer list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, loadBalancers, func() error { table := tables.NewTable() table.SetHeader("NAME", "STATE", "IP ADDRESS", "LISTENERS", "TARGET POOLS") for i := range loadBalancers { @@ -170,5 +151,5 @@ func outputResult(p *print.Printer, outputFormat string, loadBalancers []loadbal } return nil - } + }) } diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index 7a2cd20ae..cc2715e82 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -2,10 +2,8 @@ package add import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -142,25 +140,8 @@ func outputResult(p *print.Printer, outputFormat, projectLabel string, resp *loa return fmt.Errorf("nil observability credentials response") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal Load Balancer observability credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Load Balancer observability credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Added Load Balancer observability credentials on project %q. Credentials reference: %q\n", projectLabel, utils.PtrString(resp.Credential.CredentialsRef)) return nil - } + }) } diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index b9559e90a..d0d741a08 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -89,24 +87,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalance } func outputResult(p *print.Printer, outputFormat string, credentials *loadbalancer.GetCredentialsResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal Load Balancer observability credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Load Balancer observability credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { if credentials == nil || credentials.Credential == nil { return fmt.Errorf("credentials response is empty") } @@ -124,5 +105,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials *loadbalanc } return nil - } + }) } diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 138003fdd..88f3d3607 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -160,24 +158,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalance } func outputResult(p *print.Printer, outputFormat string, credentials []loadbalancer.CredentialsResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal Load Balancer observability credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Load Balancer observability credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.SetHeader("REFERENCE", "DISPLAY NAME", "USERNAME") for i := range credentials { @@ -190,7 +171,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials []loadbalan } return nil - } + }) } func getFilterOp(used, unused bool) (int, error) { diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index 76b363838..1f84ea3ef 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -2,11 +2,9 @@ package quota import ( "context" - "encoding/json" "fmt" "strconv" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -82,9 +80,8 @@ func outputResult(p *print.Printer, outputFormat string, quota *loadbalancer.Get if quota == nil { return fmt.Errorf("quota response is empty") } - switch outputFormat { - case print.PrettyOutputFormat: + return p.OutputResult(outputFormat, quota, func() error { maxLoadBalancers := "Unlimited" if quota.MaxLoadBalancers != nil && *quota.MaxLoadBalancers != -1 { maxLoadBalancers = strconv.FormatInt(*quota.MaxLoadBalancers, 10) @@ -93,22 +90,5 @@ func outputResult(p *print.Printer, outputFormat string, quota *loadbalancer.Get p.Outputf("Maximum number of load balancers allowed: %s\n", maxLoadBalancers) return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(quota, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal quota: %w", err) - } - p.Outputln(string(details)) - - return nil - default: - details, err := json.MarshalIndent(quota, "", " ") - if err != nil { - return fmt.Errorf("marshal quota: %w", err) - } - - p.Outputln(string(details)) - - return nil - } + }) } diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index ed8eddc51..616323663 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -2,12 +2,10 @@ package describe import ( "context" - "encoding/json" "fmt" "strconv" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -124,90 +122,69 @@ func outputResult(p *print.Printer, outputFormat string, targetPool loadbalancer listener, } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(output, "", " ") - if err != nil { - return fmt.Errorf("marshal load balancer: %w", err) + return p.OutputResult(outputFormat, output, func() error { + sessionPersistence := "None" + if targetPool.SessionPersistence != nil && targetPool.SessionPersistence.UseSourceIpAddress != nil && *targetPool.SessionPersistence.UseSourceIpAddress { + sessionPersistence = "Use Source IP" } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal load balancer: %w", err) + healthCheckInterval := "-" + healthCheckUnhealthyThreshold := "-" + healthCheckHealthyThreshold := "-" + if targetPool.ActiveHealthCheck != nil { + if targetPool.ActiveHealthCheck.Interval != nil { + healthCheckInterval = *targetPool.ActiveHealthCheck.Interval + } + if targetPool.ActiveHealthCheck.UnhealthyThreshold != nil { + healthCheckUnhealthyThreshold = strconv.FormatInt(*targetPool.ActiveHealthCheck.UnhealthyThreshold, 10) + } + if targetPool.ActiveHealthCheck.HealthyThreshold != nil { + healthCheckHealthyThreshold = strconv.FormatInt(*targetPool.ActiveHealthCheck.HealthyThreshold, 10) + } } - p.Outputln(string(details)) - - return nil - default: - return outputResultAsTable(p, targetPool, listener) - } -} - -func outputResultAsTable(p *print.Printer, targetPool loadbalancer.TargetPool, listener *loadbalancer.Listener) error { - sessionPersistence := "None" - if targetPool.SessionPersistence != nil && targetPool.SessionPersistence.UseSourceIpAddress != nil && *targetPool.SessionPersistence.UseSourceIpAddress { - sessionPersistence = "Use Source IP" - } - healthCheckInterval := "-" - healthCheckUnhealthyThreshold := "-" - healthCheckHealthyThreshold := "-" - if targetPool.ActiveHealthCheck != nil { - if targetPool.ActiveHealthCheck.Interval != nil { - healthCheckInterval = *targetPool.ActiveHealthCheck.Interval - } - if targetPool.ActiveHealthCheck.UnhealthyThreshold != nil { - healthCheckUnhealthyThreshold = strconv.FormatInt(*targetPool.ActiveHealthCheck.UnhealthyThreshold, 10) - } - if targetPool.ActiveHealthCheck.HealthyThreshold != nil { - healthCheckHealthyThreshold = strconv.FormatInt(*targetPool.ActiveHealthCheck.HealthyThreshold, 10) + targets := "-" + if targetPool.Targets != nil { + var targetsSlice []string + for _, target := range *targetPool.Targets { + targetStr := fmt.Sprintf("%s (%s)", *target.DisplayName, *target.Ip) + targetsSlice = append(targetsSlice, targetStr) + } + targets = strings.Join(targetsSlice, "\n") } - } - targets := "-" - if targetPool.Targets != nil { - var targetsSlice []string - for _, target := range *targetPool.Targets { - targetStr := fmt.Sprintf("%s (%s)", *target.DisplayName, *target.Ip) - targetsSlice = append(targetsSlice, targetStr) + listenerStr := "-" + if listener != nil { + listenerStr = fmt.Sprintf("%s (Port:%s, Protocol: %s)", + utils.PtrString(listener.Name), + utils.PtrString(listener.Port), + utils.PtrString(listener.Protocol), + ) } - targets = strings.Join(targetsSlice, "\n") - } - listenerStr := "-" - if listener != nil { - listenerStr = fmt.Sprintf("%s (Port:%s, Protocol: %s)", - utils.PtrString(listener.Name), - utils.PtrString(listener.Port), - utils.PtrString(listener.Protocol), - ) - } - - table := tables.NewTable() - table.AddRow("NAME", utils.PtrString(targetPool.Name)) - table.AddSeparator() - table.AddRow("TARGET PORT", utils.PtrString(targetPool.TargetPort)) - table.AddSeparator() - table.AddRow("ATTACHED LISTENER", listenerStr) - table.AddSeparator() - table.AddRow("TARGETS", targets) - table.AddSeparator() - table.AddRow("SESSION PERSISTENCE", sessionPersistence) - table.AddSeparator() - table.AddRow("HEALTH CHECK INTERVAL", healthCheckInterval) - table.AddSeparator() - table.AddRow("HEALTH CHECK DOWN AFTER", healthCheckUnhealthyThreshold) - table.AddSeparator() - table.AddRow("HEALTH CHECK UP AFTER", healthCheckHealthyThreshold) - table.AddSeparator() - - err := p.PagerDisplay(table.Render()) - if err != nil { - return fmt.Errorf("display output: %w", err) - } + table := tables.NewTable() + table.AddRow("NAME", utils.PtrString(targetPool.Name)) + table.AddSeparator() + table.AddRow("TARGET PORT", utils.PtrString(targetPool.TargetPort)) + table.AddSeparator() + table.AddRow("ATTACHED LISTENER", listenerStr) + table.AddSeparator() + table.AddRow("TARGETS", targets) + table.AddSeparator() + table.AddRow("SESSION PERSISTENCE", sessionPersistence) + table.AddSeparator() + table.AddRow("HEALTH CHECK INTERVAL", healthCheckInterval) + table.AddSeparator() + table.AddRow("HEALTH CHECK DOWN AFTER", healthCheckUnhealthyThreshold) + table.AddSeparator() + table.AddRow("HEALTH CHECK UP AFTER", healthCheckHealthyThreshold) + table.AddSeparator() + + err := p.PagerDisplay(table.Render()) + if err != nil { + return fmt.Errorf("display output: %w", err) + } - return nil + return nil + }) } diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index de6cab21f..4808614e9 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,8 @@ func outputResult(p *print.Printer, outputFormat string, showPassword bool, inst if !showPassword && resp.HasRaw() && resp.Raw.Credentials != nil { resp.Raw.Credentials.Password = utils.Ptr("hidden") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal LogMe credentials: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) // The username field cannot be set by the user so we only display it if it's not returned empty if resp.HasRaw() && resp.Raw.Credentials != nil { @@ -157,5 +139,5 @@ func outputResult(p *print.Printer, outputFormat string, showPassword bool, inst } p.Outputf("URI: %s\n", utils.PtrString(resp.Uri)) return nil - } + }) } diff --git a/internal/cmd/logme/credentials/describe/describe.go b/internal/cmd/logme/credentials/describe/describe.go index 1af434056..7ae74bf7d 100644 --- a/internal/cmd/logme/credentials/describe/describe.go +++ b/internal/cmd/logme/credentials/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -109,24 +107,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *logme.Cred return fmt.Errorf("credentials is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal LogMe credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal LogMe credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() @@ -148,5 +129,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials *logme.Cred } return nil - } + }) } diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index d9f572e2f..7455b78db 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -129,24 +127,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl } func outputResult(p *print.Printer, outputFormat string, credentials []logme.CredentialsListItem) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal LogMe credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal LogMe credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.SetHeader("ID") for i := range credentials { @@ -159,5 +140,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials []logme.Cre } return nil - } + }) } diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index 5004c8dfb..aa8f8af04 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "errors" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -249,29 +247,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, projectLabe return fmt.Errorf("response is nil") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal LogMe instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) return nil - } + }) } diff --git a/internal/cmd/logme/instance/describe/describe.go b/internal/cmd/logme/instance/describe/describe.go index 9acac7ce7..7b73a108c 100644 --- a/internal/cmd/logme/instance/describe/describe.go +++ b/internal/cmd/logme/instance/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -97,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *logme.Instanc return fmt.Errorf("instance is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal LogMe instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal LogMe instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() @@ -142,5 +123,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *logme.Instanc } return nil - } + }) } diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index def82f0e0..e1a2a6d6f 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl } func outputResult(p *print.Printer, outputFormat string, instances []logme.Instance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal LogMe instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal LogMe instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { @@ -165,5 +146,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []logme.Insta } return nil - } + }) } diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index c8b28f0ba..6b58ced4a 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -2,10 +2,8 @@ package plans import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl } func outputResult(p *print.Printer, outputFormat string, plans []logme.Offering) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(plans, "", " ") - if err != nil { - return fmt.Errorf("marshal LogMe plans: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal LogMe plans: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, plans, func() error { table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { @@ -166,5 +147,5 @@ func outputResult(p *print.Printer, outputFormat string, plans []logme.Offering) } return nil - } + }) } diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 80077c4ce..3a2fda5da 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -124,24 +122,8 @@ func outputResult(p *print.Printer, outputFormat string, showPassword bool, inst if !showPassword && resp.HasRaw() && resp.Raw.Credentials != nil { resp.Raw.Credentials.Password = utils.Ptr("hidden") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MariaDB credentials list: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) // The username field cannot be set by the user, so we only display it if it's not returned empty if resp.HasRaw() && resp.Raw.Credentials != nil { @@ -158,5 +140,5 @@ func outputResult(p *print.Printer, outputFormat string, showPassword bool, inst } p.Outputf("URI: %s\n", utils.PtrString(resp.Uri)) return nil - } + }) } diff --git a/internal/cmd/mariadb/credentials/describe/describe.go b/internal/cmd/mariadb/credentials/describe/describe.go index 32d547403..121a9228b 100644 --- a/internal/cmd/mariadb/credentials/describe/describe.go +++ b/internal/cmd/mariadb/credentials/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -109,24 +107,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *mariadb.Cr return fmt.Errorf("credentials is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal MariaDB credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MariaDB credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() @@ -146,5 +127,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials *mariadb.Cr } return nil - } + }) } diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index a113fd11e..4495106be 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -128,24 +126,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API } func outputResult(p *print.Printer, outputFormat string, credentials []mariadb.CredentialsListItem) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal MariaDB credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MariaDB credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.SetHeader("ID") for i := range credentials { @@ -158,5 +139,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials []mariadb.C } return nil - } + }) } diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index e90e6c0d8..a7866f6bb 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "errors" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -249,29 +247,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, projectLabe return fmt.Errorf("response is nil") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MariaDB instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) return nil - } + }) } diff --git a/internal/cmd/mariadb/instance/describe/describe.go b/internal/cmd/mariadb/instance/describe/describe.go index 7775584e3..d06c7233c 100644 --- a/internal/cmd/mariadb/instance/describe/describe.go +++ b/internal/cmd/mariadb/instance/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -97,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *mariadb.Insta return fmt.Errorf("instance is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal MariaDB instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MariaDB instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() @@ -144,5 +125,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *mariadb.Insta } return nil - } + }) } diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index e648f7baa..43df97970 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API } func outputResult(p *print.Printer, outputFormat string, instances []mariadb.Instance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal MariaDB instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MariaDB instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { @@ -165,5 +146,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []mariadb.Ins } return nil - } + }) } diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index c8b89e937..d5ebcde6d 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -2,10 +2,8 @@ package plans import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API } func outputResult(p *print.Printer, outputFormat string, plans []mariadb.Offering) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(plans, "", " ") - if err != nil { - return fmt.Errorf("marshal MariaDB plans: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MariaDB plans: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, plans, func() error { table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { @@ -166,5 +147,5 @@ func outputResult(p *print.Printer, outputFormat string, plans []mariadb.Offerin } return nil - } + }) } diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index e36e875ed..9f4ebe522 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -119,24 +117,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex } func outputResult(p *print.Printer, outputFormat, restoreStatus string, backup mongodbflex.Backup) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backup, "", " ") - if err != nil { - return fmt.Errorf("marshal MongoDB Flex backup: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex backup: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, backup, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(backup.Id)) table.AddSeparator() @@ -155,5 +136,5 @@ func outputResult(p *print.Printer, outputFormat, restoreStatus string, backup m } return nil - } + }) } diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index c15bb538b..bd0bb4d22 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -142,24 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []mongodbflex.B return fmt.Errorf("restore jobs is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backups, "", " ") - if err != nil { - return fmt.Errorf("marshal MongoDB Flex backups list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex backups list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, backups, func() error { table := tables.NewTable() table.SetHeader("ID", "CREATED AT", "EXPIRES AT", "BACKUP SIZE", "RESTORE STATUS") for i := range backups { @@ -179,5 +160,5 @@ func outputResult(p *print.Printer, outputFormat string, backups []mongodbflex.B } return nil - } + }) } diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index 36e3a7ab7..6b8ca07ec 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -2,10 +2,8 @@ package restorejobs import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -132,24 +130,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex } func outputResult(p *print.Printer, outputFormat string, restoreJobs []mongodbflex.RestoreInstanceStatus) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(restoreJobs, "", " ") - if err != nil { - return fmt.Errorf("marshal MongoDB Flex restore jobs list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(restoreJobs, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex restore jobs list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, restoreJobs, func() error { table := tables.NewTable() table.SetHeader("ID", "BACKUP ID", "BACKUP INSTANCE ID", "DATE", "STATUS") for i := range restoreJobs { @@ -169,5 +150,5 @@ func outputResult(p *print.Printer, outputFormat string, restoreJobs []mongodbfl } return nil - } + }) } diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index b75275f49..954e1f8d9 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -2,10 +2,8 @@ package schedule import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -119,24 +117,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I output.WeeklySnapshotRetentionWeeks = (*instance.Options)["weeklySnapshotRetentionWeeks"] } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(output, "", " ") - if err != nil { - return fmt.Errorf("marshal MongoDB Flex backup schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex backup schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, output, func() error { table := tables.NewTable() table.AddRow("BACKUP SCHEDULE (UTC)", output.BackupSchedule) table.AddSeparator() @@ -157,5 +138,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I } return nil - } + }) } diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index fae577334..440e19fa8 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -2,11 +2,9 @@ package create import ( "context" - "encoding/json" "errors" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -270,29 +268,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, projectLabe return fmt.Errorf("create instance response is nil") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDBFlex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index 7c2c296a0..7738ec0fd 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -97,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I return fmt.Errorf("instance is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal MongoDB Flex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { var instanceType string if instance.HasReplicas() { var err error @@ -168,5 +149,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *mongodbflex.I } return nil - } + }) } diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index a901516bf..e11dbb065 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -124,24 +122,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex } func outputResult(p *print.Printer, outputFormat string, instances []mongodbflex.InstanceListInstance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal MongoDB Flex instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATUS") for i := range instances { @@ -158,5 +139,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []mongodbflex } return nil - } + }) } diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index 3240c7f8e..ff1d61c39 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -2,11 +2,9 @@ package update import ( "context" - "encoding/json" "errors" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -305,29 +303,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, instanceLab return fmt.Errorf("resp is nil") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal update MongoDBFlex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Updated" if async { operationState = "Triggered update of" } p.Info("%s instance %q\n", operationState, instanceLabel) return nil - } + }) } diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 513dad9a9..f17de9f9c 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -2,12 +2,10 @@ package options import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -182,25 +180,9 @@ func outputResult(p *print.Printer, model *inputModel, flavors *mongodbflex.List } } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(options, "", " ") - if err != nil { - return fmt.Errorf("marshal MongoDB Flex options: %w", err) - } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex options: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, options, func() error { return outputResultAsTable(p, model, options) - } + }) } func outputResultAsTable(p *print.Printer, model *inputModel, options *options) error { diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index e1e7a00cf..46d11c50b 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -147,24 +145,7 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, user *mo return fmt.Errorf("user is nil") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex user: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, user, func() error { p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) p.Outputf("Username: %s\n", utils.PtrString(user.Username)) p.Outputf("Password: %s\n", utils.PtrString(user.Password)) @@ -175,5 +156,5 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, user *mo p.Outputf("URI: %s\n", utils.PtrString(user.Uri)) return nil - } + }) } diff --git a/internal/cmd/mongodbflex/user/describe/describe.go b/internal/cmd/mongodbflex/user/describe/describe.go index 876b63022..5d9a34b3a 100644 --- a/internal/cmd/mongodbflex/user/describe/describe.go +++ b/internal/cmd/mongodbflex/user/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -111,24 +109,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex } func outputResult(p *print.Printer, outputFormat string, user mongodbflex.InstanceResponseUser) error { - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex user: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, user, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(user.Id)) table.AddSeparator() @@ -148,5 +129,5 @@ func outputResult(p *print.Printer, outputFormat string, user mongodbflex.Instan } return nil - } + }) } diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index ef184883f..b4d6eaf28 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -132,24 +130,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex } func outputResult(p *print.Printer, outputFormat string, users []mongodbflex.ListUser) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(users, "", " ") - if err != nil { - return fmt.Errorf("marshal MongoDB Flex user list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex user list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, users, func() error { table := tables.NewTable() table.SetHeader("ID", "USERNAME") for i := range users { @@ -165,5 +146,5 @@ func outputResult(p *print.Printer, outputFormat string, users []mongodbflex.Lis } 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 ba0b169c2..cc0fb810d 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -2,10 +2,8 @@ package resetpassword import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -131,28 +129,11 @@ func outputResult(p *print.Printer, outputFormat, userLabel, instanceLabel strin return fmt.Errorf("user is nil") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal MongoDB Flex reset password: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, user, func() error { p.Outputf("Reset password for user %q of instance %q\n\n", userLabel, instanceLabel) p.Outputf("Username: %s\n", utils.PtrString(user.Username)) p.Outputf("New password: %s\n", utils.PtrString(user.Password)) p.Outputf("New URI: %s\n", utils.PtrString(user.Uri)) return nil - } + }) } diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index e6be49171..4aefc6d5b 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -186,25 +184,8 @@ func outputResult(p *print.Printer, outputFormat, orgLabel string, networkArea * if networkArea == nil { return fmt.Errorf("network area is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(networkArea, "", " ") - if err != nil { - return fmt.Errorf("marshal network area: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network area: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, networkArea, func() error { p.Outputf("Created STACKIT Network Area for organization %q.\nNetwork area ID: %s\n", orgLabel, utils.PtrString(networkArea.AreaId)) return nil - } + }) } diff --git a/internal/cmd/network-area/describe/describe.go b/internal/cmd/network-area/describe/describe.go index 49c28d7ce..b6c086a4b 100644 --- a/internal/cmd/network-area/describe/describe.go +++ b/internal/cmd/network-area/describe/describe.go @@ -2,12 +2,10 @@ package describe import ( "context" - "encoding/json" "errors" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -126,24 +124,8 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo if networkArea == nil { return fmt.Errorf("network area is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(networkArea, "", " ") - if err != nil { - return fmt.Errorf("marshal network area: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network area: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, networkArea, func() error { var routes []string var networkRanges []string @@ -219,5 +201,5 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/network-area/list/list.go b/internal/cmd/network-area/list/list.go index 94c0ffd8f..6dea71c0e 100644 --- a/internal/cmd/network-area/list/list.go +++ b/internal/cmd/network-area/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -150,24 +148,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, networkAreas []iaas.NetworkArea) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(networkAreas, "", " ") - if err != nil { - return fmt.Errorf("marshal network area: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkAreas, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal area: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, networkAreas, func() error { table := tables.NewTable() table.SetHeader("ID", "Name", "Status", "Network Ranges", "# Attached Projects") @@ -191,5 +172,5 @@ func outputResult(p *print.Printer, outputFormat string, networkAreas []iaas.Net p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go index 9dbd2878d..9f073bc22 100644 --- a/internal/cmd/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -132,25 +130,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, networkRange iaas.NetworkRange) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(networkRange, "", " ") - if err != nil { - return fmt.Errorf("marshal network range: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkRange, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network range: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, networkRange, func() error { p.Outputf("Created network range for SNA %q.\nNetwork range ID: %s\n", networkAreaLabel, utils.PtrString(networkRange.NetworkRangeId)) return nil - } + }) } diff --git a/internal/cmd/network-area/network-range/describe/describe.go b/internal/cmd/network-area/network-range/describe/describe.go index a16098a9c..dcc695246 100644 --- a/internal/cmd/network-area/network-range/describe/describe.go +++ b/internal/cmd/network-area/network-range/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -105,24 +103,8 @@ func outputResult(p *print.Printer, outputFormat string, networkRange *iaas.Netw if networkRange == nil { return fmt.Errorf("network range is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(networkRange, "", " ") - if err != nil { - return fmt.Errorf("marshal network range: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkRange, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network range: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, networkRange, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(networkRange.NetworkRangeId)) table.AddSeparator() @@ -133,5 +115,5 @@ func outputResult(p *print.Printer, outputFormat string, networkRange *iaas.Netw return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go index cb33cccbe..51f3aeeea 100644 --- a/internal/cmd/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -134,24 +132,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, networkRanges []iaas.NetworkRange) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(networkRanges, "", " ") - if err != nil { - return fmt.Errorf("marshal network ranges: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkRanges, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network ranges: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, networkRanges, func() error { table := tables.NewTable() table.SetHeader("ID", "Network Range") @@ -161,5 +142,5 @@ func outputResult(p *print.Printer, outputFormat string, networkRanges []iaas.Ne p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index 82e8e9ae4..0dbd0e248 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -150,25 +148,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, route iaas.Route) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(route, "", " ") - if err != nil { - return fmt.Errorf("marshal static route: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal static route: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, route, func() error { p.Outputf("Created static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, utils.PtrString(route.RouteId)) return nil - } + }) } diff --git a/internal/cmd/network-area/route/describe/describe.go b/internal/cmd/network-area/route/describe/describe.go index 89d743d91..2e54ac4c8 100644 --- a/internal/cmd/network-area/route/describe/describe.go +++ b/internal/cmd/network-area/route/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -107,24 +105,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, route iaas.Route) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(route, "", " ") - if err != nil { - return fmt.Errorf("marshal static route: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal static route: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, route, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(route.RouteId)) table.AddSeparator() @@ -145,5 +126,5 @@ func outputResult(p *print.Printer, outputFormat string, route iaas.Route) error return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go index 989de2618..cdc6a67ae 100644 --- a/internal/cmd/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -133,24 +131,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, routes []iaas.Route) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(routes, "", " ") - if err != nil { - return fmt.Errorf("marshal static routes: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(routes, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal static routes: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, routes, func() error { table := tables.NewTable() table.SetHeader("Static Route ID", "Next Hop", "Prefix") @@ -164,5 +145,5 @@ func outputResult(p *print.Printer, outputFormat string, routes []iaas.Route) er p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go index 1903833df..23e6391ff 100644 --- a/internal/cmd/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -2,10 +2,8 @@ package update import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -129,25 +127,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, route iaas.Route) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(route, "", " ") - if err != nil { - return fmt.Errorf("marshal static route: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal static route: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, route, func() error { p.Outputf("Updated static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, utils.PtrString(route.RouteId)) return nil - } + }) } diff --git a/internal/cmd/network-area/update/update.go b/internal/cmd/network-area/update/update.go index 0df8d0880..855da9f10 100644 --- a/internal/cmd/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -2,12 +2,10 @@ package update import ( "context" - "encoding/json" "fmt" rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -162,25 +160,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, projectLabel string, networkArea iaas.NetworkArea) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(networkArea, "", " ") - if err != nil { - return fmt.Errorf("marshal network area: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networkArea, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network area: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, networkArea, func() error { p.Outputf("Updated STACKIT Network Area for project %q.\n", projectLabel) return nil - } + }) } diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index bd4b71de2..c22735b0e 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -2,11 +2,9 @@ package create import ( "context" - "encoding/json" "fmt" "regexp" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -215,25 +213,8 @@ func outputResult(p *print.Printer, outputFormat, projectId string, nic *iaas.NI if nic == nil { return fmt.Errorf("nic is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(nic, "", " ") - if err != nil { - return fmt.Errorf("marshal network interface: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network interface: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, nic, func() error { p.Outputf("Created network interface for project %q.\nNIC ID: %s\n", projectId, utils.PtrString(nic.Id)) return nil - } + }) } diff --git a/internal/cmd/network-interface/describe/describe.go b/internal/cmd/network-interface/describe/describe.go index 0dcb12171..4c1fc6d7d 100644 --- a/internal/cmd/network-interface/describe/describe.go +++ b/internal/cmd/network-interface/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -113,24 +111,7 @@ func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { if nic == nil { return fmt.Errorf("nic is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(nic, "", " ") - if err != nil { - return fmt.Errorf("marshal network interface: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network interface: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, nic, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(nic.Id)) table.AddSeparator() @@ -181,5 +162,5 @@ func outputResult(p *print.Printer, outputFormat string, nic *iaas.NIC) error { return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go index b40a7fa2e..2effcf4a8 100644 --- a/internal/cmd/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -147,24 +145,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, nics []iaas.NIC) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(nics, "", " ") - if err != nil { - return fmt.Errorf("marshal nics: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(nics, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal nics: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, nics, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "NIC SECURITY", "DEVICE ID", "IPv4 ADDRESS", "STATUS", "TYPE") @@ -183,5 +164,5 @@ func outputResult(p *print.Printer, outputFormat string, nics []iaas.NIC) error p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go index 5a85d593a..190946bd7 100644 --- a/internal/cmd/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -2,11 +2,9 @@ package update import ( "context" - "encoding/json" "fmt" "regexp" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -205,25 +203,8 @@ func outputResult(p *print.Printer, outputFormat, projectId string, nic *iaas.NI if nic == nil { return fmt.Errorf("nic is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(nic, "", " ") - if err != nil { - return fmt.Errorf("marshal network interface: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(nic, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network interface: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, nic, func() error { p.Outputf("Updated network interface for project %q.\n", projectId) return nil - } + }) } diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index 6b4461924..2d49bc965 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -243,29 +241,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, projectLabe if network == nil { return fmt.Errorf("network cannot be nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(network, "", " ") - if err != nil { - return fmt.Errorf("marshal network: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(network, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, network, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } p.Outputf("%s network for project %q.\nNetwork ID: %s\n", operationState, projectLabel, utils.PtrString(network.NetworkId)) return nil - } + }) } diff --git a/internal/cmd/network/describe/describe.go b/internal/cmd/network/describe/describe.go index 91be6d04e..e7315519a 100644 --- a/internal/cmd/network/describe/describe.go +++ b/internal/cmd/network/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -97,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) if network == nil { return fmt.Errorf("network cannot be nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(network, "", " ") - if err != nil { - return fmt.Errorf("marshal network: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(network, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, network, func() error { var ipv4nameservers []string if network.Nameservers != nil { ipv4nameservers = append(ipv4nameservers, *network.Nameservers...) @@ -197,5 +178,5 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/network/list/list.go b/internal/cmd/network/list/list.go index c9689f845..97d570f75 100644 --- a/internal/cmd/network/list/list.go +++ b/internal/cmd/network/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -140,24 +138,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(networks, "", " ") - if err != nil { - return fmt.Errorf("marshal network: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(networks, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal network: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, networks, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATUS", "PUBLIC IP", "PREFIXES", "ROUTED") @@ -183,5 +164,5 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index b1da202f6..8d2c6f942 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -124,29 +122,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, bucketName return fmt.Errorf("create bucket response is empty") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Object Storage bucket: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } p.Outputf("%s bucket %q\n", operationState, bucketName) return nil - } + }) } diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index e5728d549..99fa3e52d 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -95,24 +93,7 @@ func outputResult(p *print.Printer, outputFormat string, bucket *objectstorage.B return fmt.Errorf("bucket is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(bucket, "", " ") - if err != nil { - return fmt.Errorf("marshal Object Storage bucket: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(bucket, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Object Storage bucket: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, bucket, func() error { table := tables.NewTable() table.AddRow("Name", utils.PtrString(bucket.Name)) table.AddSeparator() @@ -128,5 +109,5 @@ func outputResult(p *print.Printer, outputFormat string, bucket *objectstorage.B } return nil - } + }) } diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index d2ec16c9c..d0ed623cf 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -127,24 +125,7 @@ func outputResult(p *print.Printer, outputFormat string, buckets []objectstorage return fmt.Errorf("buckets is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(buckets, "", " ") - if err != nil { - return fmt.Errorf("marshal Object Storage bucket list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(buckets, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Object Storage bucket list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, buckets, func() error { table := tables.NewTable() table.SetHeader("NAME", "REGION", "URL (PATH STYLE)", "URL (VIRTUAL HOSTED STYLE)") for i := range buckets { @@ -162,5 +143,5 @@ func outputResult(p *print.Printer, outputFormat string, buckets []objectstorage } 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 a531e49fd..c92f24956 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -110,29 +108,12 @@ func outputResult(p *print.Printer, outputFormat string, resp *objectstorage.Cre return fmt.Errorf("create createndials group response is empty") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Object Storage credentials group: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created credentials group %q. Credentials group ID: %s\n\n", utils.PtrString(resp.CredentialsGroup.DisplayName), utils.PtrString(resp.CredentialsGroup.CredentialsGroupId), ) p.Outputf("URN: %s\n", utils.PtrString(resp.CredentialsGroup.Urn)) return nil - } + }) } diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index 166e0b91a..adc5531d1 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -115,24 +113,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora } func outputResult(p *print.Printer, outputFormat string, credentialsGroups []objectstorage.CredentialsGroup) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentialsGroups, "", " ") - if err != nil { - return fmt.Errorf("marshal Object Storage credentials group list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentialsGroups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Object Storage credentials group list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentialsGroups, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "URN") for i := range credentialsGroups { @@ -148,5 +129,5 @@ func outputResult(p *print.Printer, outputFormat string, credentialsGroups []obj return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index b713331c6..41fde917c 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -2,11 +2,9 @@ package create import ( "context" - "encoding/json" "fmt" "time" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -135,24 +133,7 @@ func outputResult(p *print.Printer, outputFormat, credentialsGroupLabel string, return fmt.Errorf("create access key response is empty") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Object Storage credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { expireDate := "Never" if resp.Expires != nil && resp.Expires.IsSet() && *resp.Expires.Get() != "" { expireDate = *resp.Expires.Get() @@ -164,5 +145,5 @@ func outputResult(p *print.Printer, outputFormat, credentialsGroupLabel string, p.Outputf("Expire Date: %s\n", expireDate) return nil - } + }) } diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index eaf04b011..3fb8b920d 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -130,24 +128,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora } func outputResult(p *print.Printer, outputFormat string, credentials []objectstorage.AccessKey) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal Object Storage credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Object Storage credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.SetHeader("CREDENTIALS ID", "ACCESS KEY ID", "EXPIRES AT") for i := range credentials { @@ -161,5 +142,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials []objectsto return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index 139ed39dd..99b185ba2 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -116,24 +114,7 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, resp *ob return fmt.Errorf("response is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal Observability credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Observability credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created credentials for instance %q.\n\n", instanceLabel) if resp.Credentials != nil { @@ -146,5 +127,5 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, resp *ob p.Outputf("Password: %s\n", utils.PtrString(resp.Credentials.Password)) } return nil - } + }) } diff --git a/internal/cmd/observability/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go index d5cc513fe..f0423793e 100644 --- a/internal/cmd/observability/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -126,24 +124,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *observabili } func outputResult(p *print.Printer, outputFormat string, credentials []observability.ServiceKeysList) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal Observability credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Observability credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.SetHeader("USERNAME") for i := range credentials { @@ -156,5 +137,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials []observabi } return nil - } + }) } diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index 1b425fc20..225bc18ef 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -124,24 +122,7 @@ func outputResult(p *print.Printer, outputFormat string, showPassword bool, graf return fmt.Errorf("grafanaConfigs is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(grafanaConfigs, "", " ") - if err != nil { - return fmt.Errorf("marshal Grafana configs: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(grafanaConfigs, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Grafana configs: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, grafanaConfigs, func() error { initialAdminPassword := utils.PtrString(instance.Instance.GrafanaAdminPassword) if !showPassword { initialAdminPassword = "" @@ -163,5 +144,5 @@ func outputResult(p *print.Printer, outputFormat string, showPassword bool, graf } return nil - } + }) } diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index bf1a3de39..7bd73e90a 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -2,11 +2,9 @@ package create import ( "context" - "encoding/json" "errors" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -198,29 +196,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, projectLabe return fmt.Errorf("resp is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal Observability instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Observability instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.InstanceId)) return nil - } + }) } diff --git a/internal/cmd/observability/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go index cd65f868a..ad204b74e 100644 --- a/internal/cmd/observability/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -95,24 +93,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *observability return fmt.Errorf("instance is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal Observability instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Observability instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(instance.Id)) table.AddSeparator() @@ -144,5 +125,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *observability } return nil - } + }) } diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index a234f18cc..a52ebeb34 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *observabili } func outputResult(p *print.Printer, outputFormat string, instances []observability.ProjectInstanceFull) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal Observability instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Observability instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "PLAN", "STATUS") for i := range instances { @@ -158,5 +139,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []observabili } return nil - } + }) } diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index 3473e645b..62fc0ac86 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -2,7 +2,6 @@ package plans import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -17,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/observability" ) @@ -124,24 +122,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *observabili } func outputResult(p *print.Printer, outputFormat string, plans []observability.Plan) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(plans, "", " ") - if err != nil { - return fmt.Errorf("marshal Observability plans: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Observability plans: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, plans, func() error { table := tables.NewTable() table.SetHeader("ID", "PLAN NAME", "DESCRIPTION") for i := range plans { @@ -160,5 +141,5 @@ func outputResult(p *print.Printer, outputFormat string, plans []observability.P } return nil - } + }) } diff --git a/internal/cmd/observability/scrape-config/describe/describe.go b/internal/cmd/observability/scrape-config/describe/describe.go index 0b7eb0eb5..1558edbbc 100644 --- a/internal/cmd/observability/scrape-config/describe/describe.go +++ b/internal/cmd/observability/scrape-config/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -105,24 +103,7 @@ func outputResult(p *print.Printer, outputFormat string, config *observability.J return fmt.Errorf(`config is nil`) } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(config, "", " ") - if err != nil { - return fmt.Errorf("marshal scrape configuration: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(config, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal scrape configuration: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, config, func() error { saml2Enabled := "Enabled" if config.Params != nil { saml2 := (*config.Params)["saml2"] @@ -187,5 +168,5 @@ func outputResult(p *print.Printer, outputFormat string, config *observability.J } return nil - } + }) } diff --git a/internal/cmd/observability/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go index 95a9770cc..998613343 100644 --- a/internal/cmd/observability/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -129,24 +127,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *observabili } func outputResult(p *print.Printer, outputFormat string, configs []observability.Job) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(configs, "", " ") - if err != nil { - return fmt.Errorf("marshal scrape configurations list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(configs, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal scrape configurations list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, configs, func() error { table := tables.NewTable() table.SetHeader("NAME", "TARGETS", "SCRAPE INTERVAL") for i := range configs { @@ -174,5 +155,5 @@ func outputResult(p *print.Printer, outputFormat string, configs []observability } return nil - } + }) } diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index 8af402191..9600ea189 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,8 @@ func outputResult(p *print.Printer, outputFormat string, showPassword bool, inst if !showPassword { resp.Raw.Credentials.Password = utils.Ptr("hidden") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal OpenSearch credentials: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) // The username field cannot be set by the user so we only display it if it's not returned empty if resp.HasRaw() && resp.Raw.Credentials != nil { @@ -157,5 +139,5 @@ func outputResult(p *print.Printer, outputFormat string, showPassword bool, inst } p.Outputf("URI: %s\n", *resp.Uri) return nil - } + }) } diff --git a/internal/cmd/opensearch/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index 531a9d9cb..2acf9188a 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -109,24 +107,7 @@ func outputResult(p *print.Printer, outputFormat string, credentials *opensearch return fmt.Errorf("credentials is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal OpenSearch credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal OpenSearch credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() @@ -146,5 +127,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials *opensearch } return nil - } + }) } diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index b3a0cbdfc..40efab492 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -2,7 +2,6 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -17,7 +16,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -129,24 +127,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. } func outputResult(p *print.Printer, outputFormat string, credentials []opensearch.CredentialsListItem) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal OpenSearch credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal OpenSearch credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.SetHeader("ID") for i := range credentials { @@ -159,5 +140,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials []opensearc } return nil - } + }) } diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index 6476f8cc3..e9dd330bd 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "errors" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -250,29 +248,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient openSearchCl } func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel, instanceId string, resp *opensearch.CreateInstanceResponse) error { - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal OpenSearch instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if 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/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index ef746f2c3..44aa6cb82 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -97,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *opensearch.In return fmt.Errorf("instance is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal OpenSearch instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal OpenSearch instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() @@ -144,5 +125,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *opensearch.In } return nil - } + }) } diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index 3d27f7c0b..d53244f04 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. } func outputResult(p *print.Printer, outputFormat string, instances []opensearch.Instance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal OpenSearch instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal OpenSearch instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { @@ -158,5 +139,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []opensearch. } return nil - } + }) } diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index a4f0b06fb..e8d8c4983 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -2,10 +2,8 @@ package plans import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. } func outputResult(p *print.Printer, outputFormat string, plans []opensearch.Offering) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(plans, "", " ") - if err != nil { - return fmt.Errorf("marshal OpenSearch plans: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal OpenSearch plans: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, plans, func() error { table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { @@ -166,5 +147,5 @@ func outputResult(p *print.Printer, outputFormat string, plans []opensearch.Offe } return nil - } + }) } diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index b46f7705f..3102c987c 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -2,11 +2,9 @@ package list import ( "context" - "encoding/json" "fmt" "sort" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -149,25 +147,7 @@ func outputResult(p *print.Printer, outputFormat, sortBy string, members []autho } sort.SliceStable(members, sortFn) - switch outputFormat { - case print.JSONOutputFormat: - // Show details - details, err := json.MarshalIndent(members, "", " ") - if err != nil { - return fmt.Errorf("marshal members: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(members, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal members: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, members, func() error { table := tables.NewTable() table.SetHeader("SUBJECT", "ROLE") for i := range members { @@ -191,5 +171,5 @@ func outputResult(p *print.Printer, outputFormat, sortBy string, members []autho } return nil - } + }) } diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index 710738559..9f1523543 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -122,25 +120,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *authorizati } func outputRolesResult(p *print.Printer, outputFormat string, roles []authorization.Role) error { - switch outputFormat { - case print.JSONOutputFormat: - // Show details - details, err := json.MarshalIndent(roles, "", " ") - if err != nil { - return fmt.Errorf("marshal roles: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(roles, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal roles: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, roles, func() error { table := tables.NewTable() table.SetHeader("ROLE NAME", "ROLE DESCRIPTION", "PERMISSION NAME", "PERMISSION DESCRIPTION") for i := range roles { @@ -165,5 +145,5 @@ func outputRolesResult(p *print.Printer, outputFormat string, roles []authorizat } return nil - } + }) } diff --git a/internal/cmd/postgresflex/backup/describe/describe.go b/internal/cmd/postgresflex/backup/describe/describe.go index 5e0ecf5c9..930bf334a 100644 --- a/internal/cmd/postgresflex/backup/describe/describe.go +++ b/internal/cmd/postgresflex/backup/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "time" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -117,24 +115,7 @@ func outputResult(p *print.Printer, outputFormat string, backup postgresflex.Bac } backupExpireDate := backupStartTime.AddDate(backupExpireYearOffset, backupExpireMonthOffset, backupExpireDayOffset).Format(time.DateOnly) - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backup, "", " ") - if err != nil { - return fmt.Errorf("marshal backup for PostgreSQL Flex backup: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal backup for PostgreSQL Flex backup: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, backup, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(backup.Id)) table.AddSeparator() @@ -152,5 +133,5 @@ func outputResult(p *print.Printer, outputFormat string, backup postgresflex.Bac } return nil - } + }) } diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index 5527343ad..f365261a9 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -135,24 +133,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle } func outputResult(p *print.Printer, outputFormat string, backups []postgresflex.Backup) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backups, "", " ") - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex backup list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex backup list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, backups, func() error { table := tables.NewTable() table.SetHeader("ID", "CREATED AT", "EXPIRES AT", "BACKUP SIZE") for i := range backups { @@ -178,5 +159,5 @@ func outputResult(p *print.Printer, outputFormat string, backups []postgresflex. } return nil - } + }) } diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index 2b43420ce..10da911bb 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -2,10 +2,8 @@ package clone import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -202,29 +200,13 @@ func outputResult(p *print.Printer, outputFormat string, async bool, instanceLab if resp == nil { return fmt.Errorf("response not set") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgresFlex instance clone: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Cloned" if 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 d6664835f..3af623ca5 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -2,11 +2,9 @@ package create import ( "context" - "encoding/json" "errors" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -270,29 +268,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, projectLabe if resp == nil { return fmt.Errorf("no response passed") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgresFlex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if 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/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index 78898aa7d..a9480e74e 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -97,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *postgresflex. if instance == nil { return fmt.Errorf("no response passed") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { acls := "" if instance.HasAcl() && instance.Acl.HasItems() { acls = utils.JoinStringPtr(instance.Acl.Items, ",") @@ -163,5 +144,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *postgresflex. } return nil - } + }) } diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index 90a9a1a40..f7115f502 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -125,24 +123,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle } func outputResult(p *print.Printer, outputFormat string, instances []postgresflex.InstanceListInstance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { caser := cases.Title(language.English) table := tables.NewTable() table.SetHeader("ID", "NAME", "STATUS") @@ -160,5 +141,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []postgresfle } return nil - } + }) } diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 4448ffd00..f2784645c 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -2,11 +2,9 @@ package update import ( "context" - "encoding/json" "errors" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -305,29 +303,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, instanceLab return fmt.Errorf("no response passed") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgresFlex instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Updated" if async { operationState = "Triggered update of" } p.Info("%s instance %q\n", operationState, instanceLabel) return nil - } + }) } diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index 9e988dd6e..0e0581c3f 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -2,12 +2,10 @@ package options import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -185,45 +183,25 @@ func outputResult(p *print.Printer, model inputModel, flavors *postgresflex.List } } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(options, "", " ") - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex options: %w", err) + return p.OutputResult(model.OutputFormat, options, func() error { + content := []tables.Table{} + if model.Flavors && len(*options.Flavors) != 0 { + content = append(content, buildFlavorsTable(*options.Flavors)) } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if model.Versions && len(*options.Versions) != 0 { + content = append(content, buildVersionsTable(*options.Versions)) + } + if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) > 0 { + content = append(content, buildStoragesTable(*options.Storages.Storages)) + } + + err := tables.DisplayTables(p, content) if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex options: %w", err) + return fmt.Errorf("display output: %w", err) } - p.Outputln(string(details)) return nil - default: - return outputResultAsTable(p, model, options) - } -} - -func outputResultAsTable(p *print.Printer, model inputModel, options *options) error { - content := []tables.Table{} - if model.Flavors && len(*options.Flavors) != 0 { - content = append(content, buildFlavorsTable(*options.Flavors)) - } - if model.Versions && len(*options.Versions) != 0 { - content = append(content, buildVersionsTable(*options.Versions)) - } - if model.Storages && options.Storages.Storages != nil && len(*options.Storages.Storages.StorageClasses) > 0 { - content = append(content, buildStoragesTable(*options.Storages.Storages)) - } - - err := tables.DisplayTables(p, content) - if err != nil { - return fmt.Errorf("display output: %w", err) - } - - return nil + }) } func buildFlavorsTable(flavors []postgresflex.Flavor) tables.Table { diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 88d377391..f7cc55a35 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -140,24 +138,8 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, resp *po if resp == nil { return fmt.Errorf("no response passed") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgresFlex user: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { if user := resp.Item; user != nil { p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) p.Outputf("Username: %s\n", utils.PtrString(user.Username)) @@ -169,5 +151,5 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, resp *po } return nil - } + }) } diff --git a/internal/cmd/postgresflex/user/describe/describe.go b/internal/cmd/postgresflex/user/describe/describe.go index 30c96e40f..c0f3f450d 100644 --- a/internal/cmd/postgresflex/user/describe/describe.go +++ b/internal/cmd/postgresflex/user/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -110,24 +108,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle } func outputResult(p *print.Printer, outputFormat string, user postgresflex.UserResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(user, "", " ") - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex user: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex user: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, user, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(user.Id)) table.AddSeparator() @@ -145,5 +126,5 @@ func outputResult(p *print.Printer, outputFormat string, user postgresflex.UserR } return nil - } + }) } diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index eb476e916..d62bfd1ed 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -131,24 +129,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle } func outputResult(p *print.Printer, outputFormat string, users []postgresflex.ListUsersResponseItem) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(users, "", " ") - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex user list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex user list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, users, func() error { table := tables.NewTable() table.SetHeader("ID", "USERNAME") for i := range users { @@ -164,5 +145,5 @@ func outputResult(p *print.Printer, outputFormat string, users []postgresflex.Li } 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 27c955b19..0a69b4c94 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -2,10 +2,8 @@ package resetpassword import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -129,24 +127,7 @@ func outputResult(p *print.Printer, outputFormat, userLabel, instanceLabel strin if user == nil { return fmt.Errorf("no response passed") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgresFlex user: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, user, func() error { p.Outputf("Reset password for user %q of instance %q\n\n", userLabel, instanceLabel) if item := user.Item; item != nil { p.Outputf("Username: %s\n", utils.PtrString(item.Username)) @@ -154,5 +135,5 @@ func outputResult(p *print.Printer, outputFormat, userLabel, instanceLabel strin p.Outputf("New URI: %s\n", utils.PtrString(item.Uri)) } return nil - } + }) } diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index bbb22d2e3..5fcd2bec3 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -2,11 +2,9 @@ package create import ( "context" - "encoding/json" "fmt" "regexp" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" @@ -212,25 +210,8 @@ func outputResult(p *print.Printer, model inputModel, resp *resourcemanager.Proj if model.GlobalFlagModel == nil { return fmt.Errorf("globalflags are empty") } - 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal project: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { p.Outputf("Created project under the parent with ID %q. Project ID: %s\n", utils.PtrString(model.ParentId), utils.PtrString(resp.ProjectId)) return nil - } + }) } diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index 59366914c..b1db718bf 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -115,24 +113,8 @@ func outputResult(p *print.Printer, outputFormat string, project *resourcemanage if project == nil { return fmt.Errorf("response not set") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(project, "", " ") - if err != nil { - return fmt.Errorf("marshal project details: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(project, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal project details: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, project, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(project.ProjectId)) table.AddSeparator() @@ -151,5 +133,5 @@ func outputResult(p *print.Printer, outputFormat string, project *resourcemanage } return nil - } + }) } diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 9c8118c2f..8b459dd4c 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -2,11 +2,9 @@ package list import ( "context" - "encoding/json" "fmt" "time" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -213,24 +211,7 @@ func fetchProjects(ctx context.Context, model *inputModel, apiClient resourceMan } func outputResult(p *print.Printer, outputFormat string, projects []resourcemanager.Project) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(projects, "", " ") - if err != nil { - return fmt.Errorf("marshal projects list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(projects, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal projects list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, projects, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATE", "PARENT ID") for i := range projects { @@ -254,5 +235,5 @@ func outputResult(p *print.Printer, outputFormat string, projects []resourcemana } return nil - } + }) } diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index a40ffae49..675ddcd22 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -2,11 +2,9 @@ package list import ( "context" - "encoding/json" "fmt" "sort" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -154,25 +152,7 @@ func outputResult(p *print.Printer, model inputModel, members []authorization.Me } sort.SliceStable(members, sortFn) - switch model.OutputFormat { - case print.JSONOutputFormat: - // Show details - details, err := json.MarshalIndent(members, "", " ") - if err != nil { - return fmt.Errorf("marshal members: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(members, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal members: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, members, func() error { table := tables.NewTable() table.SetHeader("SUBJECT", "ROLE") for i := range members { @@ -196,5 +176,5 @@ func outputResult(p *print.Printer, model inputModel, members []authorization.Me } return nil - } + }) } diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index 30c1b054b..e4dadb288 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -124,25 +122,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *authorizati } func outputRolesResult(p *print.Printer, outputFormat string, roles []authorization.Role) error { - switch outputFormat { - case print.JSONOutputFormat: - // Show details - details, err := json.MarshalIndent(roles, "", " ") - if err != nil { - return fmt.Errorf("marshal roles: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(roles, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal roles: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, roles, func() error { table := tables.NewTable() table.SetHeader("ROLE NAME", "ROLE DESCRIPTION", "PERMISSION NAME", "PERMISSION DESCRIPTION") for i := range roles { @@ -165,5 +145,5 @@ func outputRolesResult(p *print.Printer, outputFormat string, roles []authorizat } return nil - } + }) } diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index 77564b941..831d6eb46 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -127,25 +125,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, projectLabel string, publicIp iaas.PublicIp) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(publicIp, "", " ") - if err != nil { - return fmt.Errorf("marshal public IP: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal public IP: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, publicIp, func() error { p.Outputf("Created public IP for project %q.\nPublic IP ID: %s\n", projectLabel, utils.PtrString(publicIp.Id)) return nil - } + }) } diff --git a/internal/cmd/public-ip/describe/describe.go b/internal/cmd/public-ip/describe/describe.go index f180c7533..4ec7836f2 100644 --- a/internal/cmd/public-ip/describe/describe.go +++ b/internal/cmd/public-ip/describe/describe.go @@ -2,12 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -95,24 +92,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, publicIp iaas.PublicIp) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(publicIp, "", " ") - if err != nil { - return fmt.Errorf("marshal public IP: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal public IP: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, publicIp, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(publicIp.Id)) table.AddSeparator() @@ -138,5 +118,5 @@ func outputResult(p *print.Printer, outputFormat string, publicIp iaas.PublicIp) return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/public-ip/list/list.go b/internal/cmd/public-ip/list/list.go index 71c94a776..c282f26bb 100644 --- a/internal/cmd/public-ip/list/list.go +++ b/internal/cmd/public-ip/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -141,24 +139,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, publicIps []iaas.PublicIp) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(publicIps, "", " ") - if err != nil { - return fmt.Errorf("marshal public IP: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIps, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal public IP: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, publicIps, func() error { table := tables.NewTable() table.SetHeader("ID", "IP ADDRESS", "USED BY") @@ -174,5 +155,5 @@ func outputResult(p *print.Printer, outputFormat string, publicIps []iaas.Public p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/public-ip/ranges/list/list.go b/internal/cmd/public-ip/ranges/list/list.go index 6b83d5863..e959d39f4 100644 --- a/internal/cmd/public-ip/ranges/list/list.go +++ b/internal/cmd/public-ip/ranges/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -107,24 +105,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { } func outputResult(p *print.Printer, outputFormat string, publicIpRanges []iaas.PublicNetwork) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(publicIpRanges, "", " ") - if err != nil { - return fmt.Errorf("marshal public IP ranges: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIpRanges, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal public IP ranges: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, publicIpRanges, func() error { if len(publicIpRanges) == 0 { p.Outputln("No public IP ranges found") return nil @@ -137,5 +118,5 @@ func outputResult(p *print.Printer, outputFormat string, publicIpRanges []iaas.P } return nil - } + }) } diff --git a/internal/cmd/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go index 0f4fc3400..4146fb6ee 100644 --- a/internal/cmd/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -2,11 +2,8 @@ package update import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -130,25 +127,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, model *inputModel, publicIpLabel string, publicIp *iaas.PublicIp) error { - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(publicIp, "", " ") - if err != nil { - return fmt.Errorf("marshal public IP: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(publicIp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal public IP: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, publicIp, func() error { p.Outputf("Updated public IP %q.\n", publicIpLabel) return nil - } + }) } diff --git a/internal/cmd/quota/list/list.go b/internal/cmd/quota/list/list.go index 5fb48b92b..89cb8b90c 100644 --- a/internal/cmd/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -2,11 +2,9 @@ package list import ( "context" - "encoding/json" "fmt" "strconv" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -104,25 +102,7 @@ func outputResult(p *print.Printer, outputFormat string, quotas *iaas.QuotaList) if quotas == nil { return fmt.Errorf("quotas is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(quotas, "", " ") - if err != nil { - return fmt.Errorf("marshal quota list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(quotas, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal quota list: %w", err) - } - p.Outputln(string(details)) - - return nil - - default: + return p.OutputResult(outputFormat, quotas, func() error { table := tables.NewTable() table.SetHeader("NAME", "LIMIT", "CURRENT USAGE", "PERCENT") if val := quotas.BackupGigabytes; val != nil { @@ -167,7 +147,7 @@ func outputResult(p *print.Printer, outputFormat string, quotas *iaas.QuotaList) } return nil - } + }) } func conv(n *int64) string { diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index 71d432868..f4d4830e0 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -131,24 +129,8 @@ func outputResult(p *print.Printer, model inputModel, instanceLabel string, resp } resp.Raw.Credentials.Password = utils.Ptr("hidden") } - 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal RabbitMQ credentials: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) // The username field cannot be set by the user so we only display it if it's not returned empty if resp.HasRaw() && resp.Raw.Credentials != nil { @@ -165,5 +147,5 @@ func outputResult(p *print.Printer, model inputModel, instanceLabel string, resp } p.Outputf("URI: %s\n", utils.PtrString(resp.Uri)) return nil - } + }) } diff --git a/internal/cmd/rabbitmq/credentials/describe/describe.go b/internal/cmd/rabbitmq/credentials/describe/describe.go index 13f631733..fb8d5ea6a 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -108,24 +106,8 @@ func outputResult(p *print.Printer, outputFormat string, credentials *rabbitmq.C if credentials == nil { return fmt.Errorf("no response passed") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal RabbitMQ credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal RabbitMQ credentials: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() @@ -145,5 +127,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials *rabbitmq.C } return nil - } + }) } diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index 1d9e5f3a3..4b638c13c 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -128,24 +126,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP } func outputResult(p *print.Printer, outputFormat string, credentials []rabbitmq.CredentialsListItem) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal RabbitMQ credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal RabbitMQ credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.SetHeader("ID") for i := range credentials { @@ -158,5 +139,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials []rabbitmq. } return nil - } + }) } diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index 7bf8a1704..b20674c33 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "errors" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -260,29 +258,12 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return fmt.Errorf("no response passed") } - 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal RabbitMQ instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { 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/rabbitmq/instance/describe/describe.go b/internal/cmd/rabbitmq/instance/describe/describe.go index be909e8ab..60ca0bad3 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe.go +++ b/internal/cmd/rabbitmq/instance/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -96,24 +94,8 @@ func outputResult(p *print.Printer, outputFormat string, instance *rabbitmq.Inst if instance == nil { return fmt.Errorf("no instance passed") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal RabbitMQ instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal RabbitMQ instance: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() @@ -143,5 +125,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *rabbitmq.Inst } return nil - } + }) } diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index 841ac94eb..53a62a067 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP } func outputResult(p *print.Printer, outputFormat string, instances []rabbitmq.Instance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal RabbitMQ instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal RabbitMQ instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { @@ -167,5 +148,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []rabbitmq.In } return nil - } + }) } diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index 70518152e..1114a9fc1 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -2,10 +2,8 @@ package plans import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -124,24 +122,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP } func outputResult(p *print.Printer, outputFormat string, plans []rabbitmq.Offering) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(plans, "", " ") - if err != nil { - return fmt.Errorf("marshal RabbitMQ plans: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal RabbitMQ plans: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, plans, func() error { table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { @@ -167,5 +148,5 @@ func outputResult(p *print.Printer, outputFormat string, plans []rabbitmq.Offeri } return nil - } + }) } diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index 93b2284ee..5b2d313b4 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -133,24 +131,7 @@ func outputResult(p *print.Printer, model inputModel, instanceLabel string, resp resp.Raw.Credentials.Password = utils.Ptr("hidden") } - 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Redis credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) // The username field cannot be set by the user, so we only display it if it's not returned empty if resp.HasRaw() && resp.Raw.Credentials != nil { @@ -167,5 +148,5 @@ func outputResult(p *print.Printer, model inputModel, instanceLabel string, resp } p.Outputf("URI: %s\n", utils.PtrString(resp.Uri)) return nil - } + }) } diff --git a/internal/cmd/redis/credentials/describe/describe.go b/internal/cmd/redis/credentials/describe/describe.go index 65973cc0a..36ada5448 100644 --- a/internal/cmd/redis/credentials/describe/describe.go +++ b/internal/cmd/redis/credentials/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -108,24 +106,8 @@ func outputResult(p *print.Printer, outputFormat string, credentials *redis.Cred if credentials == nil { return fmt.Errorf("no credentials passed") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal Redis credentials: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Redis credentials: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(credentials.Id)) table.AddSeparator() @@ -145,5 +127,5 @@ func outputResult(p *print.Printer, outputFormat string, credentials *redis.Cred } return nil - } + }) } diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index 5aa2515d0..08f4bf88b 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -128,24 +126,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl } func outputResult(p *print.Printer, outputFormat, instanceLabel string, credentials []redis.CredentialsListItem) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(credentials, "", " ") - if err != nil { - return fmt.Errorf("marshal Redis credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(credentials, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Redis credentials list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, credentials, func() error { if len(credentials) == 0 { p.Outputf("No credentials found for instance %q\n", instanceLabel) return nil @@ -163,5 +144,5 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, credenti } return nil - } + }) } diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index db8700842..6e694b135 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "errors" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -254,29 +252,13 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId if resp == nil { return fmt.Errorf("no response defined") } - 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Redis instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, resp, func() error { 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/instance/describe/describe.go b/internal/cmd/redis/instance/describe/describe.go index cf9d9adc7..36e6d7b76 100644 --- a/internal/cmd/redis/instance/describe/describe.go +++ b/internal/cmd/redis/instance/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -96,24 +94,8 @@ func outputResult(p *print.Printer, outputFormat string, instance *redis.Instanc if instance == nil { return fmt.Errorf("no instance passed") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal Redis instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Redis instance: %w", err) - } - p.Outputln(string(details)) - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() @@ -143,5 +125,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *redis.Instanc } return nil - } + }) } diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index db44022ba..6f98a00f1 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -122,24 +120,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl } func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []redis.Instance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal Redis instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Redis instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { if len(instances) == 0 { p.Outputf("No instances found for project %q\n", projectLabel) return nil @@ -168,5 +149,5 @@ func outputResult(p *print.Printer, outputFormat, projectLabel string, instances } return nil - } + }) } diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 66b18fb47..1fda160e4 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -2,10 +2,8 @@ package plans import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *redis.APICl } func outputResult(p *print.Printer, outputFormat string, plans []redis.Offering) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(plans, "", " ") - if err != nil { - return fmt.Errorf("marshal Redis plans: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(plans, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Redis plans: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, plans, func() error { table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { @@ -166,5 +147,5 @@ func outputResult(p *print.Printer, outputFormat string, plans []redis.Offering) } return nil - } + }) } diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index 1d17fbefb..d22f30292 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -155,25 +153,8 @@ func outputResult(p *print.Printer, outputFormat, projectLabel, instanceId strin return fmt.Errorf("instance is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instance, "", " ") - if err != nil { - return fmt.Errorf("marshal Secrets Manager instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instance, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Secrets Manager instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instance, func() error { p.Outputf("Created instance for project %q. Instance ID: %s\n", projectLabel, instanceId) return nil - } + }) } diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index ad9bb5de5..ed12cb1b0 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -115,24 +113,7 @@ func outputResult(p *print.Printer, outputFormat string, instance *secretsmanage *secretsmanager.ListACLsResponse }{instance, aclList} - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(output, "", " ") - if err != nil { - return fmt.Errorf("marshal Secrets Manager instance: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Secrets Manager instance: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, output, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(instance.Id)) table.AddSeparator() @@ -162,5 +143,5 @@ func outputResult(p *print.Printer, outputFormat string, instance *secretsmanage } return nil - } + }) } diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index 142beefe4..82576c398 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -124,24 +122,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *secretsmana } func outputResult(p *print.Printer, outputFormat string, instances []secretsmanager.Instance) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(instances, "", " ") - if err != nil { - return fmt.Errorf("marshal Secrets Manager instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(instances, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Secrets Manager instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, instances, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATE", "SECRETS") for i := range instances { @@ -159,5 +140,5 @@ func outputResult(p *print.Printer, outputFormat string, instances []secretsmana } return nil - } + }) } diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 6ddfc5e2c..7d9f6d3f7 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -135,24 +133,7 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, user *se return fmt.Errorf("user is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(user, "", " ") - if err != nil { - return fmt.Errorf("marshal Secrets Manager user: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Secrets Manager user: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, user, func() error { p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, utils.PtrString(user.Id)) p.Outputf("Username: %s\n", utils.PtrString(user.Username)) p.Outputf("Password: %s\n", utils.PtrString(user.Password)) @@ -160,5 +141,5 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, user *se p.Outputf("Write Access: %s\n", utils.PtrString(user.Write)) return nil - } + }) } diff --git a/internal/cmd/secrets-manager/user/describe/describe.go b/internal/cmd/secrets-manager/user/describe/describe.go index 1ebd58e49..9a2a30280 100644 --- a/internal/cmd/secrets-manager/user/describe/describe.go +++ b/internal/cmd/secrets-manager/user/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -107,24 +105,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *secretsmana } func outputResult(p *print.Printer, outputFormat string, user secretsmanager.User) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(user, "", " ") - if err != nil { - return fmt.Errorf("marshal Secrets Manager user: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Secrets Manager user: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, user, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(user.Id)) table.AddSeparator() @@ -146,5 +127,5 @@ func outputResult(p *print.Printer, outputFormat string, user secretsmanager.Use } return nil - } + }) } diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index 5828940fc..1c76d15fc 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -131,24 +129,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *secretsmana } func outputResult(p *print.Printer, outputFormat string, users []secretsmanager.User) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(users, "", " ") - if err != nil { - return fmt.Errorf("marshal Secrets Manager user list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(users, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Secrets Manager user list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, users, func() error { table := tables.NewTable() table.SetHeader("ID", "USERNAME", "DESCRIPTION", "WRITE ACCESS") for i := range users { @@ -166,5 +147,5 @@ func outputResult(p *print.Printer, outputFormat string, users []secretsmanager. } return nil - } + }) } diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index 3a352f624..d54b797f3 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -130,25 +128,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, name string, resp iaas.SecurityGroup) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal security group: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal security group: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created security group %q.\nSecurity Group ID %s\n", name, utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/security-group/describe/describe.go b/internal/cmd/security-group/describe/describe.go index 83186e060..80fd5cb0c 100644 --- a/internal/cmd/security-group/describe/describe.go +++ b/internal/cmd/security-group/describe/describe.go @@ -2,7 +2,6 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" @@ -16,7 +15,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -93,24 +91,7 @@ func outputResult(p *print.Printer, outputFormat string, resp *iaas.SecurityGrou if resp == nil { return fmt.Errorf("security group response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal security group: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal security group: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { var content []tables.Table table := tables.NewTable() @@ -209,5 +190,5 @@ func outputResult(p *print.Printer, outputFormat string, resp *iaas.SecurityGrou } return nil - } + }) } diff --git a/internal/cmd/security-group/list/list.go b/internal/cmd/security-group/list/list.go index b80b8647b..9fe33d546 100644 --- a/internal/cmd/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -2,11 +2,9 @@ package list import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -112,24 +110,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return request } func outputResult(p *print.Printer, outputFormat string, items []iaas.SecurityGroup) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(items, "", " ") - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal PostgreSQL Flex instance list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, items, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "STATEFUL", "DESCRIPTION", "LABELS") for _, item := range items { @@ -156,5 +137,5 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.SecurityGr } return nil - } + }) } diff --git a/internal/cmd/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go index 6e6250faf..ede4e39a5 100644 --- a/internal/cmd/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -215,29 +213,12 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, securityGro if securityGroupRule == nil { return fmt.Errorf("security group rule is empty") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(securityGroupRule, "", " ") - if err != nil { - return fmt.Errorf("marshal security group rule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(securityGroupRule, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal security group rule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, securityGroupRule, func() error { operationState := "Created" if model.Async { operationState = "Triggered creation of" } p.Outputf("%s security group rule for security group %q in project %q.\nSecurity group rule ID: %s\n", operationState, securityGroupName, projectLabel, utils.PtrString(securityGroupRule.Id)) return nil - } + }) } diff --git a/internal/cmd/security-group/rule/describe/describe.go b/internal/cmd/security-group/rule/describe/describe.go index 5cce9ff97..23407466d 100644 --- a/internal/cmd/security-group/rule/describe/describe.go +++ b/internal/cmd/security-group/rule/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -109,24 +107,7 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRule *iaas if securityGroupRule == nil { return fmt.Errorf("security group rule is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(securityGroupRule, "", " ") - if err != nil { - return fmt.Errorf("marshal security group rule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(securityGroupRule, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal security group rule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, securityGroupRule, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(securityGroupRule.Id)) table.AddSeparator() @@ -178,5 +159,5 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRule *iaas return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/security-group/rule/list/list.go b/internal/cmd/security-group/rule/list/list.go index 8a4bc3758..9098a19ff 100644 --- a/internal/cmd/security-group/rule/list/list.go +++ b/internal/cmd/security-group/rule/list/list.go @@ -2,7 +2,6 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -18,7 +17,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -141,24 +139,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, securityGroupRules []iaas.SecurityGroupRule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(securityGroupRules, "", " ") - if err != nil { - return fmt.Errorf("marshal security group rules: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(securityGroupRules, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal security group rules: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, securityGroupRules, func() error { table := tables.NewTable() table.SetHeader("ID", "ETHER TYPE", "DIRECTION", "PROTOCOL", "REMOTE SECURITY GROUP ID") @@ -184,5 +165,5 @@ func outputResult(p *print.Printer, outputFormat string, securityGroupRules []ia p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index a7400a73d..441568839 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "fmt" iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -148,25 +146,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku } func outputResult(p *print.Printer, outputFormat, serverLabel string, resp serverbackup.BackupJob) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal server backup: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server backup: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Triggered creation of server backup for server %s. Backup ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/server/backup/describe/describe.go b/internal/cmd/server/backup/describe/describe.go index 0b5c6a23b..5289a31d4 100644 --- a/internal/cmd/server/backup/describe/describe.go +++ b/internal/cmd/server/backup/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strconv" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -104,24 +102,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku } func outputResult(p *print.Printer, outputFormat string, backup serverbackup.Backup) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backup, "", " ") - if err != nil { - return fmt.Errorf("marshal server backup: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server backup: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, backup, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(backup.Id)) table.AddSeparator() @@ -152,5 +133,5 @@ func outputResult(p *print.Printer, outputFormat string, backup serverbackup.Bac } return nil - } + }) } diff --git a/internal/cmd/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go index aac8a3010..453185e56 100644 --- a/internal/cmd/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -132,24 +130,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku } func outputResult(p *print.Printer, outputFormat string, backups []serverbackup.Backup) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backups, "", " ") - if err != nil { - return fmt.Errorf("marshal Server Backup list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Server Backup list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, backups, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "SIZE (GB)", "STATUS", "CREATED AT", "EXPIRES AT", "LAST RESTORED AT", "VOLUME BACKUPS") for i := range backups { @@ -176,5 +157,5 @@ func outputResult(p *print.Printer, outputFormat string, backups []serverbackup. return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index a7af18187..301bc279c 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "fmt" iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -167,25 +165,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku } func outputResult(p *print.Printer, outputFormat, serverLabel string, resp serverbackup.BackupSchedule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal server backup schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server backup schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created server backup schedule for server %s. Backup Schedule ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/server/backup/schedule/describe/describe.go b/internal/cmd/server/backup/schedule/describe/describe.go index f3f827844..4b5b7079f 100644 --- a/internal/cmd/server/backup/schedule/describe/describe.go +++ b/internal/cmd/server/backup/schedule/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -103,24 +101,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku } func outputResult(p *print.Printer, outputFormat string, schedule serverbackup.BackupSchedule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(schedule, "", " ") - if err != nil { - return fmt.Errorf("marshal server backup schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(schedule, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server backup schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, schedule, func() error { table := tables.NewTable() table.AddRow("SCHEDULE ID", utils.PtrString(schedule.Id)) table.AddSeparator() @@ -144,5 +125,5 @@ func outputResult(p *print.Printer, outputFormat string, schedule serverbackup.B } return nil - } + }) } diff --git a/internal/cmd/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go index f9cecde2f..b3a93e3fa 100644 --- a/internal/cmd/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -133,24 +131,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku } func outputResult(p *print.Printer, outputFormat string, schedules []serverbackup.BackupSchedule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(schedules, "", " ") - if err != nil { - return fmt.Errorf("marshal Server Backup Schedules list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(schedules, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Server Backup Schedules list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, schedules, func() error { table := tables.NewTable() table.SetHeader("SCHEDULE ID", "SCHEDULE NAME", "ENABLED", "RRULE", "BACKUP NAME", "BACKUP RETENTION DAYS", "BACKUP VOLUME IDS") for i := range schedules { @@ -180,5 +161,5 @@ func outputResult(p *print.Printer, outputFormat string, schedules []serverbacku return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/backup/schedule/update/update.go b/internal/cmd/server/backup/schedule/update/update.go index a3471e41b..6d9d2aa69 100644 --- a/internal/cmd/server/backup/schedule/update/update.go +++ b/internal/cmd/server/backup/schedule/update/update.go @@ -2,10 +2,8 @@ package update import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -178,25 +176,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverbacku } func outputResult(p *print.Printer, outputFormat string, resp serverbackup.BackupSchedule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal update server backup schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal update server backup schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Info("Updated server backup schedule %s\n", utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index a94cbca58..7e1817b50 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "fmt" iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -145,25 +143,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand. } func outputResult(p *print.Printer, outputFormat, serverLabel string, resp runcommand.NewCommandResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal server command: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server command: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created server command for server %s. Command ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/server/command/describe/describe.go b/internal/cmd/server/command/describe/describe.go index f229335fb..c734cd137 100644 --- a/internal/cmd/server/command/describe/describe.go +++ b/internal/cmd/server/command/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -102,24 +100,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand. } func outputResult(p *print.Printer, outputFormat string, command runcommand.CommandDetails) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(command, "", " ") - if err != nil { - return fmt.Errorf("marshal server command: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(command, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server command: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, command, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(command.Id)) table.AddSeparator() @@ -145,5 +126,5 @@ func outputResult(p *print.Printer, outputFormat string, command runcommand.Comm } return nil - } + }) } diff --git a/internal/cmd/server/command/list/list.go b/internal/cmd/server/command/list/list.go index 2d5dfd683..c3a875043 100644 --- a/internal/cmd/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -132,24 +130,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand. } func outputResult(p *print.Printer, outputFormat string, commands []runcommand.Commands) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(commands, "", " ") - if err != nil { - return fmt.Errorf("marshal server command list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(commands, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server command list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, commands, func() error { table := tables.NewTable() table.SetHeader("ID", "TEMPLATE NAME", "TEMPLATE TITLE", "STATUS", "STARTED_AT", "FINISHED_AT") for i := range commands { @@ -168,5 +149,5 @@ func outputResult(p *print.Printer, outputFormat string, commands []runcommand.C return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/command/template/describe/describe.go b/internal/cmd/server/command/template/describe/describe.go index ec23859b4..120040660 100644 --- a/internal/cmd/server/command/template/describe/describe.go +++ b/internal/cmd/server/command/template/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -102,24 +100,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *runcommand. } func outputResult(p *print.Printer, outputFormat string, commandTemplate runcommand.CommandTemplateSchema) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(commandTemplate, "", " ") - if err != nil { - return fmt.Errorf("marshal server command template: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(commandTemplate, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server command template: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, commandTemplate, func() error { table := tables.NewTable() table.AddRow("NAME", utils.PtrString(commandTemplate.Name)) table.AddSeparator() @@ -143,5 +124,5 @@ func outputResult(p *print.Printer, outputFormat string, commandTemplate runcomm } return nil - } + }) } diff --git a/internal/cmd/server/command/template/list/list.go b/internal/cmd/server/command/template/list/list.go index 8b03a589a..54ff4fd98 100644 --- a/internal/cmd/server/command/template/list/list.go +++ b/internal/cmd/server/command/template/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -112,24 +110,7 @@ func buildRequest(ctx context.Context, _ *inputModel, apiClient *runcommand.APIC } func outputResult(p *print.Printer, outputFormat string, templates []runcommand.CommandTemplate) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(templates, "", " ") - if err != nil { - return fmt.Errorf("marshal server command template list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(templates, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server command template list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, templates, func() error { table := tables.NewTable() table.SetHeader("NAME", "OS TYPE", "TITLE") for i := range templates { @@ -151,5 +132,5 @@ func outputResult(p *print.Printer, outputFormat string, templates []runcommand. return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/console/console.go b/internal/cmd/server/console/console.go index 261f68b3c..45d884cec 100644 --- a/internal/cmd/server/console/console.go +++ b/internal/cmd/server/console/console.go @@ -2,11 +2,9 @@ package console import ( "context" - "encoding/json" "fmt" "net/url" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -102,24 +100,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serverLabel string, serverUrl iaas.ServerConsoleUrl) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(serverUrl, "", " ") - if err != nil { - return fmt.Errorf("marshal url: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serverUrl, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal url: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, serverUrl, func() error { if _, ok := serverUrl.GetUrlOk(); !ok { return fmt.Errorf("server url is nil") } @@ -132,5 +113,5 @@ func outputResult(p *print.Printer, outputFormat, serverLabel string, serverUrl p.Outputf("Remote console URL %q for server %q\n", unescapedURL, serverLabel) return nil - } + }) } diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 934123a6f..b4f012148 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -328,25 +326,8 @@ func outputResult(p *print.Printer, outputFormat, projectLabel string, server *i if server == nil { return fmt.Errorf("server response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(server, "", " ") - if err != nil { - return fmt.Errorf("marshal server: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, server, func() error { p.Outputf("Created server for project %q.\nServer ID: %s\n", projectLabel, utils.PtrString(server.Id)) return nil - } + }) } diff --git a/internal/cmd/server/log/log.go b/internal/cmd/server/log/log.go index 1448a3281..f4015c298 100644 --- a/internal/cmd/server/log/log.go +++ b/internal/cmd/server/log/log.go @@ -2,11 +2,9 @@ package log import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -134,25 +132,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serverLabel, log string) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(log, "", " ") - if err != nil { - return fmt.Errorf("marshal url: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(log, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal url: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, log, func() error { p.Outputf("Log for server %q\n%s", serverLabel, log) return nil - } + }) } diff --git a/internal/cmd/server/machine-type/describe/describe.go b/internal/cmd/server/machine-type/describe/describe.go index 12d3a8a7b..83544b540 100644 --- a/internal/cmd/server/machine-type/describe/describe.go +++ b/internal/cmd/server/machine-type/describe/describe.go @@ -2,11 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -97,24 +94,7 @@ func outputResult(p *print.Printer, outputFormat string, machineType *iaas.Machi if machineType == nil { return fmt.Errorf("api response for machine type is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(machineType, "", " ") - if err != nil { - return fmt.Errorf("marshal server machine type: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(machineType, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server machine type: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, machineType, func() error { table := tables.NewTable() table.AddRow("NAME", utils.PtrString(machineType.Name)) table.AddSeparator() @@ -132,5 +112,5 @@ func outputResult(p *print.Printer, outputFormat string, machineType *iaas.Machi return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go index 55a08109a..7d4f228cd 100644 --- a/internal/cmd/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -126,24 +124,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, machineTypes iaas.MachineTypeListResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(machineTypes, "", " ") - if err != nil { - return fmt.Errorf("marshal machineTypes: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(machineTypes, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal machineTypes: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, machineTypes, func() error { table := tables.NewTable() table.SetTitle("Machine-Types") @@ -160,5 +141,5 @@ func outputResult(p *print.Printer, outputFormat string, machineTypes iaas.Machi } return nil - } + }) } diff --git a/internal/cmd/server/network-interface/list/list.go b/internal/cmd/server/network-interface/list/list.go index 071781da4..3e895c4b4 100644 --- a/internal/cmd/server/network-interface/list/list.go +++ b/internal/cmd/server/network-interface/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -134,24 +132,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serverId string, serverNics []iaas.NIC) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(serverNics, "", " ") - if err != nil { - return fmt.Errorf("marshal server network interfaces: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serverNics, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server network interfaces: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, serverNics, func() error { table := tables.NewTable() table.SetHeader("NIC ID", "SERVER ID") @@ -163,5 +144,5 @@ func outputResult(p *print.Printer, outputFormat, serverId string, serverNics [] p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index 2cfd7a544..3a2709ded 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "fmt" iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -131,25 +129,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat } func outputResult(p *print.Printer, outputFormat, serverLabel string, resp serverupdate.Update) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal server os-update: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server os-update: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Triggered creation of server os-update for server %s. Update ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/server/os-update/describe/describe.go b/internal/cmd/server/os-update/describe/describe.go index 2aa7c1283..5686ff5be 100644 --- a/internal/cmd/server/os-update/describe/describe.go +++ b/internal/cmd/server/os-update/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -102,24 +100,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat } func outputResult(p *print.Printer, outputFormat string, update serverupdate.Update) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(update, "", " ") - if err != nil { - return fmt.Errorf("marshal server update: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(update, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server update: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, update, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(update.Id)) table.AddSeparator() @@ -142,5 +123,5 @@ func outputResult(p *print.Printer, outputFormat string, update serverupdate.Upd } return nil - } + }) } diff --git a/internal/cmd/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go index 6ec47314e..fbb5d0fa6 100644 --- a/internal/cmd/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -2,7 +2,6 @@ package list import ( "context" - "encoding/json" "fmt" "strconv" @@ -19,7 +18,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) @@ -133,24 +131,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat } func outputResult(p *print.Printer, outputFormat string, updates []serverupdate.Update) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(updates, "", " ") - if err != nil { - return fmt.Errorf("marshal server os-update list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(updates, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server os-update list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, updates, func() error { table := tables.NewTable() table.SetHeader("ID", "STATUS", "INSTALLED UPDATES", "FAILED UPDATES", "START DATE", "END DATE") for i := range updates { @@ -182,5 +163,5 @@ func outputResult(p *print.Printer, outputFormat string, updates []serverupdate. return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index bd3784c49..63325c4da 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -150,25 +148,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat } func outputResult(p *print.Printer, outputFormat, serverLabel string, resp serverupdate.UpdateSchedule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal server os-update schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server os-update schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Created server os-update schedule for server %s. os-update Schedule ID: %s\n", serverLabel, utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/server/os-update/schedule/describe/describe.go b/internal/cmd/server/os-update/schedule/describe/describe.go index d46eea1bb..c7e9a9e93 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/server/os-update/schedule/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -102,24 +100,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat } func outputResult(p *print.Printer, outputFormat string, schedule serverupdate.UpdateSchedule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(schedule, "", " ") - if err != nil { - return fmt.Errorf("marshal server os-update schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(schedule, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server os-update schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, schedule, func() error { table := tables.NewTable() table.AddRow("SCHEDULE ID", utils.PtrString(schedule.Id)) table.AddSeparator() @@ -138,5 +119,5 @@ func outputResult(p *print.Printer, outputFormat string, schedule serverupdate.U } return nil - } + }) } diff --git a/internal/cmd/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go index 201922d21..c1c0ed606 100644 --- a/internal/cmd/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -132,24 +130,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat } func outputResult(p *print.Printer, outputFormat string, schedules []serverupdate.UpdateSchedule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(schedules, "", " ") - if err != nil { - return fmt.Errorf("marshal Server os-update Schedules list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(schedules, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal Server os-update Schedules list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, schedules, func() error { table := tables.NewTable() table.SetHeader("SCHEDULE ID", "SCHEDULE NAME", "ENABLED", "RRULE", "MAINTENANCE WINDOW") for i := range schedules { @@ -167,5 +148,5 @@ func outputResult(p *print.Printer, outputFormat string, schedules []serverupdat return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/os-update/schedule/update/update.go b/internal/cmd/server/os-update/schedule/update/update.go index e9ce126f0..78570839e 100644 --- a/internal/cmd/server/os-update/schedule/update/update.go +++ b/internal/cmd/server/os-update/schedule/update/update.go @@ -2,10 +2,8 @@ package update import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -160,25 +158,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serverupdat } func outputResult(p *print.Printer, outputFormat string, resp serverupdate.UpdateSchedule) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal update server os-update schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal update server os-update schedule: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, resp, func() error { p.Info("Updated server os-update schedule %s\n", utils.PtrString(resp.Id)) return nil - } + }) } diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index b80c93df0..3979e0398 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -2,7 +2,6 @@ package attach import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -15,7 +14,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -116,25 +114,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, serviceAccounts iaas.ServiceAccountMailListResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(serviceAccounts, "", " ") - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, serviceAccounts, func() error { p.Outputf("Attached service account %q to server %q\n", serviceAccMail, serverLabel) return nil - } + }) } diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 909de016d..934ed766d 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -2,7 +2,6 @@ package detach import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -15,7 +14,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -116,25 +114,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serviceAccMail, serverLabel string, service iaas.ServiceAccountMailListResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(service, "", " ") - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(service, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, service, func() error { p.Outputf("Detached service account %q from server %q\n", serviceAccMail, serverLabel) return nil - } + }) } diff --git a/internal/cmd/server/service-account/list/list.go b/internal/cmd/server/service-account/list/list.go index 372e6c975..efb454e8c 100644 --- a/internal/cmd/server/service-account/list/list.go +++ b/internal/cmd/server/service-account/list/list.go @@ -2,7 +2,6 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -15,7 +14,6 @@ import ( iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -133,24 +131,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serverId, serverName string, serviceAccounts []string) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(serviceAccounts, "", " ") - if err != nil { - return fmt.Errorf("marshal service accounts list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal service accounts list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, serviceAccounts, func() error { table := tables.NewTable() table.SetHeader("SERVER ID", "SERVER NAME", "SERVICE ACCOUNT") for i := range serviceAccounts { @@ -161,5 +142,5 @@ func outputResult(p *print.Printer, outputFormat, serverId, serverName string, s return fmt.Errorf("rednder table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/update/update.go b/internal/cmd/server/update/update.go index e69289375..5567be1bf 100644 --- a/internal/cmd/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -2,11 +2,8 @@ package update import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -130,25 +127,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serverLabel string, server *iaas.Server) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(server, "", " ") - if err != nil { - return fmt.Errorf("marshal server: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(server, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, server, func() error { p.Outputf("Updated server %q.\n", serverLabel) return nil - } + }) } diff --git a/internal/cmd/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go index 2ba304db3..ba736f285 100644 --- a/internal/cmd/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -2,10 +2,8 @@ package attach import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -136,25 +134,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel string, volume iaas.VolumeAttachment) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(volume, "", " ") - if err != nil { - return fmt.Errorf("marshal server volume: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server volume: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, volume, func() error { p.Outputf("Attached volume %q to server %q\n", volumeLabel, serverLabel) return nil - } + }) } diff --git a/internal/cmd/server/volume/describe/describe.go b/internal/cmd/server/volume/describe/describe.go index 6aa391a4c..2a0a97d24 100644 --- a/internal/cmd/server/volume/describe/describe.go +++ b/internal/cmd/server/volume/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serverLabel, volumeLabel string, volume iaas.VolumeAttachment) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(volume, "", " ") - if err != nil { - return fmt.Errorf("marshal server volume: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server volume: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, volume, func() error { table := tables.NewTable() table.AddRow("SERVER ID", utils.PtrString(volume.ServerId)) table.AddSeparator() @@ -161,5 +142,5 @@ func outputResult(p *print.Printer, outputFormat, serverLabel, volumeLabel strin return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go index 3e69701df..c48eceb5f 100644 --- a/internal/cmd/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -123,24 +121,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, serverLabel string, volumeNames []string, volumes []iaas.VolumeAttachment) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(volumes, "", " ") - if err != nil { - return fmt.Errorf("marshal server volume list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volumes, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server volume list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, volumes, func() error { table := tables.NewTable() table.SetHeader("SERVER ID", "SERVER NAME", "VOLUME ID", "VOLUME NAME") for i := range volumes { @@ -156,5 +137,5 @@ func outputResult(p *print.Printer, outputFormat, serverLabel string, volumeName return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go index 1371e587c..471dde5c0 100644 --- a/internal/cmd/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -2,10 +2,8 @@ package update import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -132,25 +130,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat, volumeLabel, serverLabel string, volume iaas.VolumeAttachment) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(volume, "", " ") - if err != nil { - return fmt.Errorf("marshal server volume: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal server volume: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, volume, func() error { p.Outputf("Updated attached volume %q of server %q\n", volumeLabel, serverLabel) return nil - } + }) } diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index 6387773ad..98389133c 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -117,25 +115,8 @@ func outputResult(p *print.Printer, outputFormat, projectLabel string, serviceAc return fmt.Errorf("service account is nil") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccount, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal service account: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, serviceAccount, func() error { p.Outputf("Created service account for project %q. Email: %s\n", projectLabel, utils.PtrString(serviceAccount.Email)) return nil - } + }) } diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index cb10ba912..e090de0a4 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -133,24 +131,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceacco } func outputResult(p *print.Printer, outputFormat string, keys []serviceaccount.ServiceAccountKeyListResponse) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(keys, "", " ") - if err != nil { - return fmt.Errorf("marshal keys metadata: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keys, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal keys metadata: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, keys, func() error { table := tables.NewTable() table.SetHeader("ID", "ACTIVE", "CREATED_AT", "VALID_UNTIL") for i := range keys { @@ -172,5 +153,5 @@ func outputResult(p *print.Printer, outputFormat string, keys []serviceaccount.S } return nil - } + }) } diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index 5806feda7..49ea386cc 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -117,20 +115,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceacco } func outputResult(p *print.Printer, outputFormat string, serviceAccounts []serviceaccount.ServiceAccount) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(serviceAccounts, "", " ") - if err != nil { - return fmt.Errorf("marshal service accounts list: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(serviceAccounts, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal service accounts list: %w", err) - } - p.Outputln(string(details)) - default: + return p.OutputResult(outputFormat, serviceAccounts, func() error { table := tables.NewTable() table.SetHeader("ID", "EMAIL") for i := range serviceAccounts { @@ -144,7 +129,6 @@ func outputResult(p *print.Printer, outputFormat string, serviceAccounts []servi if err != nil { return fmt.Errorf("render table: %w", err) } - } - - return nil + return nil + }) } diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index e3e009b51..817e1dc27 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -140,27 +138,10 @@ func outputResult(p *print.Printer, outputFormat, serviceAccountEmail string, to return fmt.Errorf("token is nil") } - switch 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 - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(token, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal service account access token: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, token, func() error { p.Outputf("Created access token for service account %s. Token ID: %s\n\n", serviceAccountEmail, utils.PtrString(token.Id)) p.Outputf("Valid until: %s\n", utils.PtrString(token.ValidUntil)) p.Outputf("Token: %s\n", utils.PtrString(token.Token)) return nil - } + }) } diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index e3a20d9ed..c302dec8f 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -138,24 +136,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *serviceacco } func outputResult(p *print.Printer, outputFormat string, tokensMetadata []serviceaccount.AccessTokenMetadata) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(tokensMetadata, "", " ") - if err != nil { - return fmt.Errorf("marshal tokens metadata: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(tokensMetadata, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal tokens metadata: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, tokensMetadata, func() error { table := tables.NewTable() table.SetHeader("ID", "ACTIVE", "CREATED_AT", "VALID_UNTIL") for i := range tokensMetadata { @@ -173,5 +154,5 @@ func outputResult(p *print.Printer, outputFormat string, tokensMetadata []servic } return nil - } + }) } diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 3c51310cd..f1874fb65 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -195,29 +194,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, projectLabe return fmt.Errorf("cluster is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(cluster, "", " ") - if err != nil { - return fmt.Errorf("marshal SKE cluster: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SKE cluster: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, cluster, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, utils.PtrString(cluster.Name)) return nil - } + }) } diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 69d357f44..7bbf9ac6b 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -95,24 +93,7 @@ func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) e return fmt.Errorf("cluster is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(cluster, "", " ") - if err != nil { - return fmt.Errorf("marshal SKE cluster: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SKE cluster: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, cluster, func() error { acl := []string{} if cluster.Extensions != nil && cluster.Extensions.Acl != nil { acl = *cluster.Extensions.Acl.AllowedCidrs @@ -140,7 +121,7 @@ func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) e } return nil - } + }) } func handleClusterErrors(clusterErrs []ske.ClusterError, table *tables.Table) { diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 75fc2e125..d2a3d4d01 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -140,24 +138,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie } func outputResult(p *print.Printer, outputFormat, projectLabel string, clusters []ske.Cluster) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(clusters, "", " ") - if err != nil { - return fmt.Errorf("marshal SKE cluster list: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(clusters, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SKE cluster list: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, clusters, func() error { if len(clusters) == 0 { p.Outputf("No clusters found for project %q\n", projectLabel) return nil @@ -196,5 +177,5 @@ func outputResult(p *print.Printer, outputFormat, projectLabel string, clusters } return nil - } + }) } diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index 512b2f615..81187ccd4 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -157,29 +156,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, clusterName return fmt.Errorf("cluster is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(cluster, "", " ") - if err != nil { - return fmt.Errorf("marshal SKE cluster: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SKE cluster: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, cluster, func() error { operationState := "Updated" if async { operationState = "Triggered update of" } p.Info("%s cluster %q\n", operationState, clusterName) return nil - } + }) } diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index a8abfb2b6..6becf645a 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -2,10 +2,8 @@ package describe import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -84,24 +82,7 @@ func outputResult(p *print.Printer, outputFormat string, project *serviceenablem return fmt.Errorf("project is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(project, "", " ") - if err != nil { - return fmt.Errorf("marshal SKE project details: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(project, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SKE project details: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, project, func() error { table := tables.NewTable() table.AddRow("ID", projectId) table.AddSeparator() @@ -114,5 +95,5 @@ func outputResult(p *print.Printer, outputFormat string, project *serviceenablem } return nil - } + }) } diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index e9eeba070..ed8ed322b 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -7,7 +7,6 @@ import ( "strings" "time" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -156,25 +155,9 @@ func outputResult(p *print.Printer, model *inputModel, options *ske.ProviderOpti options.VolumeTypes = nil } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(options, "", " ") - if err != nil { - return fmt.Errorf("marshal SKE options: %w", err) - } - p.Outputln(string(details)) - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(options, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal SKE options: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, options, func() error { return outputResultAsTable(p, options) - } + }) } func outputResultAsTable(p *print.Printer, options *ske.ProviderOptions) error { diff --git a/internal/cmd/volume/backup/create/create.go b/internal/cmd/volume/backup/create/create.go index 5749a1d01..789c16585 100644 --- a/internal/cmd/volume/backup/create/create.go +++ b/internal/cmd/volume/backup/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -190,29 +188,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, sourceLabel return fmt.Errorf("create backup response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal backup: %w", err) - } - p.Outputln(string(details)) - return nil - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal backup: %w", err) - } - p.Outputln(string(details)) - return nil - - default: + return p.OutputResult(outputFormat, resp, func() error { if async { p.Outputf("Triggered backup of %s in %s. Backup ID: %s\n", sourceLabel, projectLabel, utils.PtrString(resp.Id)) } else { p.Outputf("Created backup of %s in %s. Backup ID: %s\n", sourceLabel, projectLabel, utils.PtrString(resp.Id)) } return nil - } + }) } diff --git a/internal/cmd/volume/backup/describe/describe.go b/internal/cmd/volume/backup/describe/describe.go index 48ee2ae2a..f836b32b2 100644 --- a/internal/cmd/volume/backup/describe/describe.go +++ b/internal/cmd/volume/backup/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -97,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, backup *iaas.Backup) er return fmt.Errorf("backup response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backup, "", " ") - if err != nil { - return fmt.Errorf("marshal backup: %w", err) - } - p.Outputln(string(details)) - return nil - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal backup: %w", err) - } - p.Outputln(string(details)) - return nil - - default: + return p.OutputResult(outputFormat, backup, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(backup.Id)) table.AddSeparator() @@ -150,5 +131,5 @@ func outputResult(p *print.Printer, outputFormat string, backup *iaas.Backup) er } return nil - } + }) } diff --git a/internal/cmd/volume/backup/list/list.go b/internal/cmd/volume/backup/list/list.go index f3fa7b257..af7edc33d 100644 --- a/internal/cmd/volume/backup/list/list.go +++ b/internal/cmd/volume/backup/list/list.go @@ -2,11 +2,9 @@ package list import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -142,24 +140,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []iaas.Backup) return fmt.Errorf("backups is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backups, "", " ") - if err != nil { - return fmt.Errorf("marshal backup list: %w", err) - } - p.Outputln(string(details)) - return nil - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backups, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal backup list: %w", err) - } - p.Outputln(string(details)) - return nil - - default: + return p.OutputResult(outputFormat, backups, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "SIZE", "STATUS", "SNAPSHOT ID", "VOLUME ID", "AVAILABILITY ZONE", "LABELS", "CREATED AT", "UPDATED AT") @@ -190,5 +171,5 @@ func outputResult(p *print.Printer, outputFormat string, backups []iaas.Backup) p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/volume/backup/update/update.go b/internal/cmd/volume/backup/update/update.go index e53e332a0..9ede68fac 100644 --- a/internal/cmd/volume/backup/update/update.go +++ b/internal/cmd/volume/backup/update/update.go @@ -2,10 +2,8 @@ package update import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -136,25 +134,8 @@ func outputResult(p *print.Printer, outputFormat, backupLabel string, backup *ia return fmt.Errorf("backup response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(backup, "", " ") - if err != nil { - return fmt.Errorf("marshal backup: %w", err) - } - p.Outputln(string(details)) - return nil - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(backup, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal backup: %w", err) - } - p.Outputln(string(details)) - return nil - - default: + return p.OutputResult(outputFormat, backup, func() error { p.Outputf("Updated backup %q\n", backupLabel) return nil - } + }) } diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index 068a06cce..df781e7c0 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -2,10 +2,8 @@ package create import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -186,25 +184,8 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, volu if volume == nil { return fmt.Errorf("volume response is empty") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(volume, "", " ") - if err != nil { - return fmt.Errorf("marshal volume: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal volume: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(model.OutputFormat, volume, func() error { p.Outputf("Created volume for project %q.\nVolume ID: %s\n", projectLabel, utils.PtrString(volume.Id)) return nil - } + }) } diff --git a/internal/cmd/volume/describe/describe.go b/internal/cmd/volume/describe/describe.go index 8a0db5659..19e536d7b 100644 --- a/internal/cmd/volume/describe/describe.go +++ b/internal/cmd/volume/describe/describe.go @@ -2,12 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -98,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, volume *iaas.Volume) er if volume == nil { return fmt.Errorf("volume response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(volume, "", " ") - if err != nil { - return fmt.Errorf("marshal volume: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal volume: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, volume, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(volume.Id)) table.AddSeparator() @@ -155,5 +135,5 @@ func outputResult(p *print.Printer, outputFormat string, volume *iaas.Volume) er return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/volume/list/list.go b/internal/cmd/volume/list/list.go index e45536d36..1bf196c95 100644 --- a/internal/cmd/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -138,24 +136,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, volumes []iaas.Volume) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(volumes, "", " ") - if err != nil { - return fmt.Errorf("marshal volume: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volumes, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal volume: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, volumes, func() error { table := tables.NewTable() table.SetHeader("ID", "Name", "Status", "Server", "Availability Zone", "Size (GB)") @@ -174,5 +155,5 @@ func outputResult(p *print.Printer, outputFormat string, volumes []iaas.Volume) p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/volume/performance-class/describe/describe.go b/internal/cmd/volume/performance-class/describe/describe.go index cef47d1e6..24a158239 100644 --- a/internal/cmd/volume/performance-class/describe/describe.go +++ b/internal/cmd/volume/performance-class/describe/describe.go @@ -2,12 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -98,24 +95,7 @@ func outputResult(p *print.Printer, outputFormat string, performanceClass *iaas. if performanceClass == nil { return fmt.Errorf("performanceClass response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(performanceClass, "", " ") - if err != nil { - return fmt.Errorf("marshal volume performance class: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(performanceClass, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal volume performance class: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, performanceClass, func() error { table := tables.NewTable() table.AddRow("NAME", utils.PtrString(performanceClass.Name)) table.AddSeparator() @@ -140,5 +120,5 @@ func outputResult(p *print.Printer, outputFormat string, performanceClass *iaas. return fmt.Errorf("render table: %w", err) } return nil - } + }) } diff --git a/internal/cmd/volume/performance-class/list/list.go b/internal/cmd/volume/performance-class/list/list.go index e8904a8f4..e32ed2c33 100644 --- a/internal/cmd/volume/performance-class/list/list.go +++ b/internal/cmd/volume/performance-class/list/list.go @@ -2,10 +2,8 @@ package list import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -139,24 +137,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } func outputResult(p *print.Printer, outputFormat string, performanceClasses []iaas.VolumePerformanceClass) error { - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(performanceClasses, "", " ") - if err != nil { - return fmt.Errorf("marshal volume performance class: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(performanceClasses, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal volume performance class: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, performanceClasses, func() error { table := tables.NewTable() table.SetHeader("Name", "Description") @@ -167,5 +148,5 @@ func outputResult(p *print.Printer, outputFormat string, performanceClasses []ia p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/volume/snapshot/describe/describe.go b/internal/cmd/volume/snapshot/describe/describe.go index 9b4f45fad..bf78cb603 100644 --- a/internal/cmd/volume/snapshot/describe/describe.go +++ b/internal/cmd/volume/snapshot/describe/describe.go @@ -2,11 +2,9 @@ package describe import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -96,24 +94,7 @@ func outputResult(p *print.Printer, outputFormat string, snapshot *iaas.Snapshot return fmt.Errorf("get snapshot response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(snapshot, "", " ") - if err != nil { - return fmt.Errorf("marshal snapshot: %w", err) - } - p.Outputln(string(details)) - return nil - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(snapshot, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal snapshot: %w", err) - } - p.Outputln(string(details)) - return nil - - default: + return p.OutputResult(outputFormat, snapshot, func() error { table := tables.NewTable() table.AddRow("ID", utils.PtrString(snapshot.Id)) table.AddSeparator() @@ -145,5 +126,5 @@ func outputResult(p *print.Printer, outputFormat string, snapshot *iaas.Snapshot } return nil - } + }) } diff --git a/internal/cmd/volume/snapshot/list/list.go b/internal/cmd/volume/snapshot/list/list.go index d25965c44..2b38252a5 100644 --- a/internal/cmd/volume/snapshot/list/list.go +++ b/internal/cmd/volume/snapshot/list/list.go @@ -2,11 +2,9 @@ package list import ( "context" - "encoding/json" "fmt" "strings" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -141,24 +139,7 @@ func outputResult(p *print.Printer, outputFormat string, snapshots []iaas.Snapsh return fmt.Errorf("list snapshots response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(snapshots, "", " ") - if err != nil { - return fmt.Errorf("marshal snapshots: %w", err) - } - p.Outputln(string(details)) - return nil - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(snapshots, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal snapshots: %w", err) - } - p.Outputln(string(details)) - return nil - - default: + return p.OutputResult(outputFormat, snapshots, func() error { table := tables.NewTable() table.SetHeader("ID", "NAME", "SIZE", "STATUS", "VOLUME ID", "LABELS", "CREATED AT", "UPDATED AT") @@ -186,5 +167,5 @@ func outputResult(p *print.Printer, outputFormat string, snapshots []iaas.Snapsh p.Outputln(table.Render()) return nil - } + }) } diff --git a/internal/cmd/volume/update/update.go b/internal/cmd/volume/update/update.go index 34881f40d..0af92ab77 100644 --- a/internal/cmd/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -2,11 +2,8 @@ package update import ( "context" - "encoding/json" "fmt" - "github.com/goccy/go-yaml" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -140,25 +137,8 @@ func outputResult(p *print.Printer, outputFormat, volumeLabel string, volume *ia if volume == nil { return fmt.Errorf("volume response is empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(volume, "", " ") - if err != nil { - return fmt.Errorf("marshal volume: %w", err) - } - p.Outputln(string(details)) - - return nil - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(volume, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal volume: %w", err) - } - p.Outputln(string(details)) - - return nil - default: + return p.OutputResult(outputFormat, volume, func() error { p.Outputf("Updated volume %q.\n", volumeLabel) return nil - } + }) } diff --git a/internal/pkg/print/print.go b/internal/pkg/print/print.go index 583e975dc..d8e06a25c 100644 --- a/internal/pkg/print/print.go +++ b/internal/pkg/print/print.go @@ -2,10 +2,13 @@ package print import ( "bufio" + "encoding/json" "errors" "fmt" "syscall" + "github.com/goccy/go-yaml" + "log/slog" "os" "os/exec" @@ -240,3 +243,26 @@ func (p *Printer) DebugInputModel(model any) { } } } + +func (p *Printer) OutputResult(outputFormat string, output any, prettyOutputFunc func() error) error { + switch outputFormat { + case JSONOutputFormat: + details, err := json.MarshalIndent(output, "", " ") + if err != nil { + return fmt.Errorf("marshal json: %w", err) + } + p.Outputln(string(details)) + + return nil + case YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(output, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal yaml: %w", err) + } + p.Outputln(string(details)) + + return nil + default: + return prettyOutputFunc() + } +} diff --git a/internal/pkg/print/print_test.go b/internal/pkg/print/print_test.go index 5c68dc2cf..8cb2e8ee2 100644 --- a/internal/pkg/print/print_test.go +++ b/internal/pkg/print/print_test.go @@ -860,3 +860,79 @@ func TestIsVerbosityError(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + output any + prettyOutputFunc func() error + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "output format is JSON", + args: args{ + outputFormat: JSONOutputFormat, + output: struct{}{}, + }, + }, + { + name: "output format is JSON and output is nil", + args: args{ + outputFormat: JSONOutputFormat, + output: nil, + }, + }, + { + name: "output format is YAML", + args: args{ + outputFormat: YAMLOutputFormat, + output: struct{}{}, + }, + }, + { + name: "output format is YAML and output is nil", + args: args{ + outputFormat: YAMLOutputFormat, + output: nil, + }, + }, + { + name: "should return error of pretty output func", + args: args{ + outputFormat: PrettyOutputFormat, + output: struct{}{}, + prettyOutputFunc: func() error { + return fmt.Errorf("dummy error") + }, + }, + wantErr: true, + }, + { + name: "success of pretty output func", + args: args{ + outputFormat: PrettyOutputFormat, + output: struct{}{}, + prettyOutputFunc: func() error { + return nil + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &cobra.Command{} + p := &Printer{ + Cmd: cmd, + Verbosity: ErrorLevel, + } + + if err := p.OutputResult(tt.args.outputFormat, tt.args.output, tt.args.prettyOutputFunc); (err != nil) != tt.wantErr { + t.Errorf("OutputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 2e98c40ddd79c828337a01eec0706d4dd7c8c7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 20 Oct 2025 10:52:06 +0200 Subject: [PATCH 466/619] fix(mongodbflex): print valid JSON for list cmds (#1032) relates to STACKITCLI-244 --- internal/cmd/mongodbflex/backup/list/list.go | 15 ++++++------ .../cmd/mongodbflex/backup/list/list_test.go | 9 +++---- .../cmd/mongodbflex/instance/list/list.go | 24 ++++++++++--------- .../mongodbflex/instance/list/list_test.go | 3 ++- internal/cmd/mongodbflex/user/list/list.go | 24 ++++++++++--------- .../cmd/mongodbflex/user/list/list_test.go | 7 +++--- 6 files changed, 45 insertions(+), 37 deletions(-) diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index bd0bb4d22..ab22427bf 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -74,11 +74,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get backups for MongoDB Flex instance %q: %w", instanceLabel, err) } - if resp.Items == nil || len(*resp.Items) == 0 { - cmd.Printf("No backups found for instance %q\n", instanceLabel) - return nil - } - backups := *resp.Items + backups := utils.GetSliceFromPointer(resp.Items) restoreJobs, err := apiClient.ListRestoreJobs(ctx, model.ProjectId, *model.InstanceId, model.Region).Execute() if err != nil { @@ -90,7 +86,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { backups = backups[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, backups, restoreJobs) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, backups, restoreJobs) }, } @@ -135,12 +131,17 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex return req } -func outputResult(p *print.Printer, outputFormat string, backups []mongodbflex.Backup, restoreJobs *mongodbflex.ListRestoreJobsResponse) error { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, backups []mongodbflex.Backup, restoreJobs *mongodbflex.ListRestoreJobsResponse) error { if restoreJobs == nil { return fmt.Errorf("restore jobs is empty") } return p.OutputResult(outputFormat, backups, func() error { + if len(backups) == 0 { + p.Outputf("No backups found for instance %q\n", instanceLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "CREATED AT", "EXPIRES AT", "BACKUP SIZE", "RESTORE STATUS") for i := range backups { diff --git a/internal/cmd/mongodbflex/backup/list/list_test.go b/internal/cmd/mongodbflex/backup/list/list_test.go index 8b6ce7a25..8b2e9b177 100644 --- a/internal/cmd/mongodbflex/backup/list/list_test.go +++ b/internal/cmd/mongodbflex/backup/list/list_test.go @@ -215,9 +215,10 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - outputFormat string - backups []mongodbflex.Backup - restoreJobs *mongodbflex.ListRestoreJobsResponse + outputFormat string + instanceLabel string + backups []mongodbflex.Backup + restoreJobs *mongodbflex.ListRestoreJobsResponse } tests := []struct { name string @@ -256,7 +257,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.backups, tt.args.restoreJobs); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.backups, tt.args.restoreJobs); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index e11dbb065..798bd544c 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -65,23 +65,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get MongoDB Flex instances: %w", err) } - if resp.Items == nil || len(*resp.Items) == 0 { - 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 - } - params.Printer.Info("No instances found for project %q\n", projectLabel) - return nil + instances := utils.GetSliceFromPointer(resp.Items) + + 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 } - instances := *resp.Items // Truncate output if model.Limit != nil && len(instances) > int(*model.Limit) { instances = instances[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, projectLabel, instances) }, } @@ -121,8 +118,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex return req } -func outputResult(p *print.Printer, outputFormat string, instances []mongodbflex.InstanceListInstance) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []mongodbflex.InstanceListInstance) error { return p.OutputResult(outputFormat, instances, func() error { + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "STATUS") for i := range instances { diff --git a/internal/cmd/mongodbflex/instance/list/list_test.go b/internal/cmd/mongodbflex/instance/list/list_test.go index 9c558f205..1f14f2d89 100644 --- a/internal/cmd/mongodbflex/instance/list/list_test.go +++ b/internal/cmd/mongodbflex/instance/list/list_test.go @@ -195,6 +195,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string instanceList []mongodbflex.InstanceListInstance } tests := []struct { @@ -226,7 +227,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.instanceList); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.instanceList); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index b4d6eaf28..b6fb8ad7a 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -68,23 +68,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get MongoDB Flex users: %w", err) } - if resp.Items == nil || len(*resp.Items) == 0 { - instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) - if err != nil { - params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) - instanceLabel = *model.InstanceId - } - params.Printer.Info("No users found for instance %q\n", instanceLabel) - return nil + users := utils.GetSliceFromPointer(resp.Items) + + instanceLabel, err := mongodbflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) + instanceLabel = *model.InstanceId } - users := *resp.Items // Truncate output if model.Limit != nil && len(users) > int(*model.Limit) { users = users[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, users) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, users) }, } @@ -129,8 +126,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mongodbflex return req } -func outputResult(p *print.Printer, outputFormat string, users []mongodbflex.ListUser) error { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, users []mongodbflex.ListUser) error { return p.OutputResult(outputFormat, users, func() error { + if len(users) == 0 { + p.Outputf("No users found for instance %q\n", instanceLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "USERNAME") for i := range users { diff --git a/internal/cmd/mongodbflex/user/list/list_test.go b/internal/cmd/mongodbflex/user/list/list_test.go index 45d28d41d..3345bae43 100644 --- a/internal/cmd/mongodbflex/user/list/list_test.go +++ b/internal/cmd/mongodbflex/user/list/list_test.go @@ -211,8 +211,9 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - outputFormat string - users []mongodbflex.ListUser + outputFormat string + instanceLabel string + users []mongodbflex.ListUser } tests := []struct { name string @@ -243,7 +244,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.users); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From 4725975b8aedb09a8fce802d7cdea63dafc187a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 20 Oct 2025 12:16:21 +0200 Subject: [PATCH 467/619] refactor: centralize logic for parseInput tests (#1033) --- internal/cmd/affinity-groups/create/create.go | 6 +- .../cmd/affinity-groups/create/create_test.go | 40 +------- internal/cmd/affinity-groups/list/list.go | 6 +- .../cmd/affinity-groups/list/list_test.go | 40 +------- .../activate_service_account.go | 11 ++- .../activate_service_account_test.go | 35 +------ .../auth/get-access-token/get_access_token.go | 6 +- internal/cmd/beta/alb/create/create.go | 6 +- internal/cmd/beta/alb/create/create_test.go | 43 +-------- internal/cmd/beta/alb/delete/delete_test.go | 52 +---------- .../cmd/beta/alb/describe/describe_test.go | 50 +--------- internal/cmd/beta/alb/list/list.go | 6 +- internal/cmd/beta/alb/list/list_test.go | 41 +-------- .../alb/observability-credentials/add/add.go | 6 +- .../observability-credentials/add/add_test.go | 43 +-------- .../describe/describe_test.go | 50 +--------- .../observability-credentials/list/list.go | 6 +- .../list/list_test.go | 43 +-------- .../update/update_test.go | 1 + internal/cmd/beta/alb/plans/plans.go | 6 +- internal/cmd/beta/alb/plans/plans_test.go | 41 +-------- internal/cmd/beta/alb/pool/update/update.go | 6 +- .../cmd/beta/alb/pool/update/update_test.go | 43 +-------- internal/cmd/beta/alb/quotas/quotas.go | 6 +- internal/cmd/beta/alb/quotas/quotas_test.go | 41 +-------- internal/cmd/beta/alb/template/template.go | 6 +- .../cmd/beta/alb/template/template_test.go | 44 +-------- internal/cmd/beta/alb/update/update.go | 6 +- internal/cmd/beta/alb/update/update_test.go | 43 +-------- .../database/create/create_test.go | 50 +--------- .../database/delete/delete_test.go | 52 +---------- .../database/describe/describe_test.go | 50 +--------- .../beta/sqlserverflex/database/list/list.go | 6 +- .../sqlserverflex/database/list/list_test.go | 46 +--------- .../sqlserverflex/instance/create/create.go | 6 +- .../instance/create/create_test.go | 55 +---------- .../instance/delete/delete_test.go | 52 +---------- .../instance/describe/describe_test.go | 50 +--------- .../beta/sqlserverflex/instance/list/list.go | 6 +- .../sqlserverflex/instance/list/list_test.go | 46 +--------- .../cmd/beta/sqlserverflex/options/options.go | 6 +- .../sqlserverflex/options/options_test.go | 44 +-------- .../beta/sqlserverflex/user/create/create.go | 6 +- .../sqlserverflex/user/create/create_test.go | 46 +--------- .../sqlserverflex/user/delete/delete_test.go | 52 +---------- .../user/describe/describe_test.go | 50 +--------- .../cmd/beta/sqlserverflex/user/list/list.go | 6 +- .../beta/sqlserverflex/user/list/list_test.go | 46 +--------- .../reset-password/reset_password_test.go | 50 +--------- .../cmd/config/profile/create/create_test.go | 55 +---------- .../cmd/config/profile/delete/delete_test.go | 55 +---------- .../cmd/config/profile/export/export_test.go | 55 +---------- internal/cmd/config/profile/import/import.go | 6 +- .../cmd/config/profile/import/import_test.go | 46 +--------- internal/cmd/config/profile/set/set_test.go | 55 +---------- internal/cmd/config/set/set.go | 6 +- internal/cmd/config/set/set_test.go | 47 +--------- internal/cmd/dns/record-set/create/create.go | 6 +- .../cmd/dns/record-set/create/create_test.go | 55 +---------- .../cmd/dns/record-set/delete/delete_test.go | 52 +---------- .../dns/record-set/describe/describe_test.go | 50 +--------- internal/cmd/dns/record-set/list/list.go | 6 +- internal/cmd/dns/record-set/list/list_test.go | 43 +-------- internal/cmd/dns/zone/clone/clone_test.go | 50 +--------- internal/cmd/dns/zone/create/create.go | 6 +- internal/cmd/dns/zone/create/create_test.go | 55 +---------- internal/cmd/dns/zone/delete/delete_test.go | 52 +---------- .../cmd/dns/zone/describe/describe_test.go | 50 +--------- internal/cmd/dns/zone/list/list.go | 6 +- internal/cmd/dns/zone/list/list_test.go | 43 +-------- internal/cmd/git/flavor/list/list.go | 6 +- internal/cmd/git/flavor/list/list_test.go | 43 +-------- internal/cmd/git/instance/create/create.go | 6 +- .../cmd/git/instance/create/create_test.go | 48 +--------- .../cmd/git/instance/delete/delete_test.go | 1 + .../git/instance/describe/describe_test.go | 1 + internal/cmd/git/instance/list/list.go | 6 +- internal/cmd/git/instance/list/list_test.go | 43 +-------- internal/cmd/image/create/create.go | 6 +- internal/cmd/image/create/create_test.go | 48 +--------- internal/cmd/image/delete/delete_test.go | 1 + internal/cmd/image/describe/describe_test.go | 1 + internal/cmd/image/list/list.go | 6 +- internal/cmd/image/list/list_test.go | 41 +-------- internal/cmd/image/update/update_test.go | 1 + internal/cmd/key-pair/create/create.go | 6 +- internal/cmd/key-pair/create/create_test.go | 43 +-------- .../cmd/key-pair/describe/describe_test.go | 50 +--------- internal/cmd/key-pair/list/list.go | 6 +- internal/cmd/key-pair/list/list_test.go | 43 +-------- internal/cmd/load-balancer/create/create.go | 6 +- .../cmd/load-balancer/create/create_test.go | 55 +---------- .../cmd/load-balancer/delete/delete_test.go | 52 +---------- .../load-balancer/describe/describe_test.go | 50 +--------- .../generate-payload/generate_payload.go | 6 +- .../generate-payload/generate_payload_test.go | 51 +---------- internal/cmd/load-balancer/list/list.go | 6 +- internal/cmd/load-balancer/list/list_test.go | 43 +-------- .../observability-credentials/add/add.go | 6 +- .../observability-credentials/add/add_test.go | 43 +-------- .../cleanup/cleanup.go | 6 +- .../cleanup/cleanup_test.go | 52 +---------- .../delete/delete_test.go | 52 +---------- .../describe/describe_test.go | 50 +--------- .../observability-credentials/list/list.go | 6 +- .../list/list_test.go | 51 +---------- .../update/update_test.go | 52 +---------- internal/cmd/load-balancer/quota/quota.go | 6 +- .../cmd/load-balancer/quota/quota_test.go | 43 +-------- .../cmd/load-balancer/update/update_test.go | 52 +---------- .../cmd/logme/credentials/create/create.go | 6 +- .../logme/credentials/create/create_test.go | 43 +-------- .../logme/credentials/delete/delete_test.go | 52 +---------- .../credentials/describe/describe_test.go | 50 +--------- internal/cmd/logme/credentials/list/list.go | 6 +- .../cmd/logme/credentials/list/list_test.go | 43 +-------- internal/cmd/logme/instance/create/create.go | 6 +- .../cmd/logme/instance/create/create_test.go | 66 ++------------ .../cmd/logme/instance/delete/delete_test.go | 52 +---------- .../logme/instance/describe/describe_test.go | 50 +--------- internal/cmd/logme/instance/list/list.go | 6 +- internal/cmd/logme/instance/list/list_test.go | 46 +--------- internal/cmd/logme/plans/plans.go | 6 +- internal/cmd/logme/plans/plans_test.go | 46 +--------- .../cmd/mariadb/credentials/create/create.go | 6 +- .../mariadb/credentials/create/create_test.go | 43 +-------- .../mariadb/credentials/delete/delete_test.go | 52 +---------- .../credentials/describe/describe_test.go | 50 +--------- internal/cmd/mariadb/credentials/list/list.go | 6 +- .../cmd/mariadb/credentials/list/list_test.go | 43 +-------- .../cmd/mariadb/instance/create/create.go | 6 +- .../mariadb/instance/create/create_test.go | 66 ++------------ .../mariadb/instance/delete/delete_test.go | 52 +---------- .../instance/describe/describe_test.go | 50 +--------- internal/cmd/mariadb/instance/list/list.go | 6 +- .../cmd/mariadb/instance/list/list_test.go | 46 +--------- internal/cmd/mariadb/plans/plans.go | 6 +- internal/cmd/mariadb/plans/plans_test.go | 46 +--------- .../backup/describe/describe_test.go | 50 +--------- internal/cmd/mongodbflex/backup/list/list.go | 6 +- .../cmd/mongodbflex/backup/list/list_test.go | 43 +-------- .../backup/restore-jobs/restore_jobs.go | 6 +- .../backup/restore-jobs/restore_jobs_test.go | 43 +-------- .../cmd/mongodbflex/backup/restore/restore.go | 6 +- .../backup/restore/restore_test.go | 53 +---------- .../mongodbflex/backup/schedule/schedule.go | 6 +- .../backup/schedule/schedule_test.go | 46 +--------- .../backup/update-schedule/update_schedule.go | 6 +- .../update-schedule/update_schedule_test.go | 42 +-------- .../cmd/mongodbflex/instance/create/create.go | 6 +- .../instance/create/create_test.go | 55 +---------- .../instance/delete/delete_test.go | 52 +---------- .../instance/describe/describe_test.go | 50 +--------- .../cmd/mongodbflex/instance/list/list.go | 6 +- .../mongodbflex/instance/list/list_test.go | 46 +--------- internal/cmd/mongodbflex/options/options.go | 6 +- .../cmd/mongodbflex/options/options_test.go | 44 +-------- .../cmd/mongodbflex/user/create/create.go | 6 +- .../mongodbflex/user/create/create_test.go | 46 +--------- .../mongodbflex/user/delete/delete_test.go | 52 +---------- .../user/describe/describe_test.go | 50 +--------- internal/cmd/mongodbflex/user/list/list.go | 6 +- .../cmd/mongodbflex/user/list/list_test.go | 46 +--------- .../reset-password/reset_password_test.go | 50 +--------- .../mongodbflex/user/update/update_test.go | 52 +---------- internal/cmd/network-area/create/create.go | 6 +- .../cmd/network-area/create/create_test.go | 43 +-------- .../cmd/network-area/delete/delete_test.go | 52 +---------- .../network-area/describe/describe_test.go | 50 +--------- internal/cmd/network-area/list/list.go | 6 +- internal/cmd/network-area/list/list_test.go | 43 +-------- .../network-range/create/create.go | 6 +- .../network-range/create/create_test.go | 43 +-------- .../network-area/network-range/list/list.go | 6 +- .../network-range/list/list_test.go | 43 +-------- .../cmd/network-area/route/create/create.go | 6 +- .../network-area/route/create/create_test.go | 43 +-------- internal/cmd/network-area/route/list/list.go | 6 +- .../cmd/network-area/route/list/list_test.go | 43 +-------- .../cmd/network-interface/create/create.go | 6 +- .../network-interface/create/create_test.go | 43 +-------- internal/cmd/network-interface/list/list.go | 6 +- .../cmd/network-interface/list/list_test.go | 43 +-------- internal/cmd/network/create/create.go | 6 +- internal/cmd/network/create/create_test.go | 43 +-------- internal/cmd/network/delete/delete_test.go | 52 +---------- .../cmd/network/describe/describe_test.go | 50 +--------- internal/cmd/network/list/list.go | 6 +- internal/cmd/network/list/list_test.go | 43 +-------- .../bucket/create/create_test.go | 50 +--------- .../bucket/delete/delete_test.go | 52 +---------- .../bucket/describe/describe_test.go | 50 +--------- .../cmd/object-storage/bucket/list/list.go | 6 +- .../object-storage/bucket/list/list_test.go | 46 +--------- .../credentials-group/create/create.go | 6 +- .../credentials-group/create/create_test.go | 43 +-------- .../credentials-group/delete/delete_test.go | 52 +---------- .../credentials-group/list/list.go | 6 +- .../credentials-group/list/list_test.go | 43 +-------- .../credentials/create/create.go | 6 +- .../credentials/create/create_test.go | 43 +-------- .../credentials/delete/delete_test.go | 52 +---------- .../object-storage/credentials/list/list.go | 6 +- .../credentials/list/list_test.go | 43 +-------- .../cmd/object-storage/disable/disable.go | 6 +- .../object-storage/disable/disable_test.go | 45 +-------- internal/cmd/object-storage/enable/enable.go | 6 +- .../cmd/object-storage/enable/enable_test.go | 45 +-------- .../credentials/create/create.go | 6 +- .../credentials/create/create_test.go | 42 +-------- .../observability/credentials/list/list.go | 6 +- .../credentials/list/list_test.go | 42 +-------- .../disable/disable_test.go | 52 +---------- .../public-read-access/enable/enable_test.go | 52 +---------- .../single-sign-on/disable/disable_test.go | 52 +---------- .../single-sign-on/enable/enable_test.go | 52 +---------- .../observability/instance/create/create.go | 6 +- .../instance/create/create_test.go | 43 +-------- .../instance/delete/delete_test.go | 52 +---------- .../instance/describe/describe_test.go | 50 +--------- .../cmd/observability/instance/list/list.go | 6 +- .../observability/instance/list/list_test.go | 45 +-------- .../instance/update/update_test.go | 52 +---------- internal/cmd/observability/plans/plans.go | 6 +- .../cmd/observability/plans/plans_test.go | 46 +--------- .../scrape-config/create/create.go | 6 +- .../scrape-config/create/create_test.go | 53 +---------- .../generate-payload/generate_payload.go | 6 +- .../generate-payload/generate_payload_test.go | 51 +---------- .../observability/scrape-config/list/list.go | 6 +- .../scrape-config/list/list_test.go | 46 +--------- .../opensearch/credentials/create/create.go | 6 +- .../credentials/create/create_test.go | 43 +-------- .../credentials/delete/delete_test.go | 52 +---------- .../credentials/describe/describe_test.go | 50 +--------- .../cmd/opensearch/credentials/list/list.go | 6 +- .../opensearch/credentials/list/list_test.go | 43 +-------- .../cmd/opensearch/instance/create/create.go | 6 +- .../opensearch/instance/create/create_test.go | 78 ++-------------- .../opensearch/instance/delete/delete_test.go | 52 +---------- .../instance/describe/describe_test.go | 50 +--------- internal/cmd/opensearch/instance/list/list.go | 6 +- .../cmd/opensearch/instance/list/list_test.go | 46 +--------- internal/cmd/opensearch/plans/plans.go | 6 +- internal/cmd/opensearch/plans/plans_test.go | 46 +--------- .../cmd/organization/member/add/add_test.go | 52 +---------- internal/cmd/organization/member/list/list.go | 6 +- .../cmd/organization/member/list/list_test.go | 46 +--------- .../organization/member/remove/remove_test.go | 52 +---------- internal/cmd/organization/role/list/list.go | 6 +- .../cmd/organization/role/list/list_test.go | 46 +--------- internal/cmd/postgresflex/backup/list/list.go | 6 +- .../cmd/postgresflex/backup/list/list_test.go | 43 +-------- .../backup/update-schedule/update_schedule.go | 6 +- .../update-schedule/update_schedule_test.go | 42 +-------- .../postgresflex/instance/clone/clone_test.go | 50 +--------- .../postgresflex/instance/create/create.go | 6 +- .../instance/create/create_test.go | 55 +---------- .../instance/delete/delete_test.go | 52 +---------- .../instance/describe/describe_test.go | 50 +--------- .../cmd/postgresflex/instance/list/list.go | 6 +- .../postgresflex/instance/list/list_test.go | 46 +--------- internal/cmd/postgresflex/options/options.go | 6 +- .../cmd/postgresflex/options/options_test.go | 44 +-------- .../cmd/postgresflex/user/create/create.go | 6 +- .../postgresflex/user/create/create_test.go | 46 +--------- .../postgresflex/user/delete/delete_test.go | 52 +---------- .../user/describe/describe_test.go | 50 +--------- internal/cmd/postgresflex/user/list/list.go | 6 +- .../cmd/postgresflex/user/list/list_test.go | 46 +--------- .../reset-password/reset_password_test.go | 50 +--------- .../postgresflex/user/update/update_test.go | 52 +---------- internal/cmd/project/create/create.go | 6 +- internal/cmd/project/create/create_test.go | 55 +---------- internal/cmd/project/delete/delete.go | 6 +- internal/cmd/project/delete/delete_test.go | 45 +-------- .../cmd/project/describe/describe_test.go | 50 +--------- internal/cmd/project/list/list.go | 6 +- internal/cmd/project/list/list_test.go | 66 ++------------ internal/cmd/project/member/add/add_test.go | 52 +---------- internal/cmd/project/member/list/list.go | 6 +- internal/cmd/project/member/list/list_test.go | 46 +--------- .../cmd/project/member/remove/remove_test.go | 52 +---------- internal/cmd/project/role/list/list.go | 6 +- internal/cmd/project/role/list/list_test.go | 46 +--------- internal/cmd/project/update/update.go | 6 +- internal/cmd/project/update/update_test.go | 57 +----------- internal/cmd/public-ip/create/create.go | 6 +- internal/cmd/public-ip/create/create_test.go | 43 +-------- internal/cmd/public-ip/delete/delete_test.go | 52 +---------- .../cmd/public-ip/describe/describe_test.go | 50 +--------- internal/cmd/public-ip/list/list.go | 6 +- internal/cmd/public-ip/list/list_test.go | 43 +-------- internal/cmd/public-ip/ranges/list/list.go | 6 +- .../cmd/public-ip/ranges/list/list_test.go | 42 +++------ internal/cmd/quota/list/list.go | 6 +- internal/cmd/quota/list/list_test.go | 41 +-------- .../cmd/rabbitmq/credentials/create/create.go | 6 +- .../credentials/create/create_test.go | 43 +-------- .../credentials/delete/delete_test.go | 52 +---------- .../credentials/describe/describe_test.go | 50 +--------- .../cmd/rabbitmq/credentials/list/list.go | 6 +- .../rabbitmq/credentials/list/list_test.go | 43 +-------- .../cmd/rabbitmq/instance/create/create.go | 6 +- .../rabbitmq/instance/create/create_test.go | 78 ++-------------- .../rabbitmq/instance/delete/delete_test.go | 52 +---------- .../instance/describe/describe_test.go | 50 +--------- internal/cmd/rabbitmq/instance/list/list.go | 6 +- .../cmd/rabbitmq/instance/list/list_test.go | 46 +--------- internal/cmd/rabbitmq/plans/plans.go | 6 +- internal/cmd/rabbitmq/plans/plans_test.go | 46 +--------- .../cmd/redis/credentials/create/create.go | 6 +- .../redis/credentials/create/create_test.go | 43 +-------- .../redis/credentials/delete/delete_test.go | 52 +---------- .../credentials/describe/describe_test.go | 50 +--------- internal/cmd/redis/credentials/list/list.go | 6 +- .../cmd/redis/credentials/list/list_test.go | 43 +-------- internal/cmd/redis/instance/create/create.go | 6 +- .../cmd/redis/instance/create/create_test.go | 66 ++------------ .../cmd/redis/instance/delete/delete_test.go | 52 +---------- .../redis/instance/describe/describe_test.go | 50 +--------- internal/cmd/redis/instance/list/list.go | 6 +- internal/cmd/redis/instance/list/list_test.go | 46 +--------- internal/cmd/redis/plans/plans.go | 6 +- internal/cmd/redis/plans/plans_test.go | 46 +--------- .../secrets-manager/instance/create/create.go | 6 +- .../instance/create/create_test.go | 55 +---------- .../instance/delete/delete_test.go | 52 +---------- .../instance/describe/describe_test.go | 50 +--------- .../cmd/secrets-manager/instance/list/list.go | 6 +- .../instance/list/list_test.go | 46 +--------- .../cmd/secrets-manager/user/create/create.go | 6 +- .../user/create/create_test.go | 46 +--------- .../user/delete/delete_test.go | 52 +---------- .../user/describe/describe_test.go | 50 +--------- .../cmd/secrets-manager/user/list/list.go | 6 +- .../secrets-manager/user/list/list_test.go | 46 +--------- internal/cmd/security-group/create/create.go | 6 +- .../cmd/security-group/create/create_test.go | 41 +-------- .../cmd/security-group/delete/delete_test.go | 1 + .../security-group/describe/describe_test.go | 1 + internal/cmd/security-group/list/list.go | 6 +- internal/cmd/security-group/list/list_test.go | 41 +-------- .../cmd/security-group/rule/create/create.go | 6 +- .../security-group/rule/create/create_test.go | 51 +---------- .../rule/describe/describe_test.go | 50 +--------- internal/cmd/security-group/rule/list/list.go | 6 +- .../cmd/security-group/rule/list/list_test.go | 43 +-------- .../cmd/security-group/update/update_test.go | 1 + internal/cmd/server/backup/create/create.go | 6 +- .../cmd/server/backup/create/create_test.go | 43 +-------- .../cmd/server/backup/delete/delete_test.go | 52 +---------- .../server/backup/describe/describe_test.go | 50 +--------- internal/cmd/server/backup/disable/disable.go | 6 +- .../cmd/server/backup/disable/disable_test.go | 61 +++---------- internal/cmd/server/backup/enable/enable.go | 6 +- .../cmd/server/backup/enable/enable_test.go | 61 +++---------- internal/cmd/server/backup/list/list.go | 6 +- internal/cmd/server/backup/list/list_test.go | 43 +-------- .../cmd/server/backup/restore/restore_test.go | 52 +---------- .../server/backup/schedule/create/create.go | 6 +- .../backup/schedule/create/create_test.go | 43 +-------- .../backup/schedule/delete/delete_test.go | 52 +---------- .../backup/schedule/describe/describe_test.go | 50 +--------- .../cmd/server/backup/schedule/list/list.go | 6 +- .../server/backup/schedule/list/list_test.go | 43 +-------- .../volume-backup/delete/delete_test.go | 52 +---------- .../volume-backup/restore/restore_test.go | 52 +---------- internal/cmd/server/command/create/create.go | 6 +- .../cmd/server/command/create/create_test.go | 43 +-------- .../server/command/describe/describe_test.go | 50 +--------- internal/cmd/server/command/list/list.go | 6 +- internal/cmd/server/command/list/list_test.go | 43 +-------- .../template/describe/describe_test.go | 50 +--------- .../cmd/server/command/template/list/list.go | 6 +- .../server/command/template/list/list_test.go | 43 +-------- internal/cmd/server/console/console_test.go | 50 +--------- internal/cmd/server/create/create.go | 6 +- internal/cmd/server/create/create_test.go | 50 ++-------- .../cmd/server/deallocate/deallocate_test.go | 52 +---------- internal/cmd/server/delete/delete_test.go | 52 +---------- internal/cmd/server/describe/describe_test.go | 50 +--------- internal/cmd/server/list/list.go | 6 +- internal/cmd/server/list/list_test.go | 43 +-------- internal/cmd/server/log/log_test.go | 50 +--------- .../machine-type/describe/describe_test.go | 50 +--------- internal/cmd/server/machine-type/list/list.go | 6 +- .../cmd/server/machine-type/list/list_test.go | 43 +-------- .../server/network-interface/attach/attach.go | 6 +- .../network-interface/attach/attach_test.go | 53 +---------- .../server/network-interface/detach/detach.go | 6 +- .../network-interface/detach/detach_test.go | 53 +---------- .../cmd/server/network-interface/list/list.go | 6 +- .../network-interface/list/list_test.go | 43 +-------- .../cmd/server/os-update/create/create.go | 6 +- .../server/os-update/create/create_test.go | 43 +-------- .../os-update/describe/describe_test.go | 50 +--------- .../cmd/server/os-update/disable/disable.go | 6 +- .../server/os-update/disable/disable_test.go | 61 +++---------- .../cmd/server/os-update/enable/enable.go | 6 +- .../server/os-update/enable/enable_test.go | 61 +++---------- internal/cmd/server/os-update/list/list.go | 6 +- .../cmd/server/os-update/list/list_test.go | 43 +-------- .../os-update/schedule/create/create.go | 6 +- .../os-update/schedule/create/create_test.go | 43 +-------- .../os-update/schedule/delete/delete_test.go | 52 +---------- .../schedule/describe/describe_test.go | 50 +--------- .../server/os-update/schedule/list/list.go | 6 +- .../os-update/schedule/list/list_test.go | 43 +-------- internal/cmd/server/reboot/reboot_test.go | 52 +---------- internal/cmd/server/rescue/rescue_test.go | 52 +---------- internal/cmd/server/resize/resize_test.go | 52 +---------- .../cmd/server/service-account/list/list.go | 6 +- .../server/service-account/list/list_test.go | 43 +-------- internal/cmd/server/start/start_test.go | 52 +---------- internal/cmd/server/stop/stop_test.go | 52 +---------- internal/cmd/server/unrescue/unrescue_test.go | 52 +---------- internal/cmd/server/volume/list/list.go | 6 +- internal/cmd/server/volume/list/list_test.go | 43 +-------- internal/cmd/service-account/create/create.go | 6 +- .../cmd/service-account/create/create_test.go | 43 +-------- .../cmd/service-account/delete/delete_test.go | 52 +---------- .../cmd/service-account/key/create/create.go | 6 +- .../service-account/key/create/create_test.go | 45 +-------- .../service-account/key/delete/delete_test.go | 52 +---------- .../key/describe/describe_test.go | 50 +--------- internal/cmd/service-account/key/list/list.go | 6 +- .../cmd/service-account/key/list/list_test.go | 46 +--------- .../service-account/key/update/update_test.go | 52 +---------- internal/cmd/service-account/list/list.go | 6 +- .../cmd/service-account/list/list_test.go | 46 +--------- .../service-account/token/create/create.go | 6 +- .../token/create/create_test.go | 43 +-------- .../cmd/service-account/token/list/list.go | 6 +- .../service-account/token/list/list_test.go | 46 +--------- .../token/revoke/revoke_test.go | 52 +---------- .../cmd/ske/cluster/create/create_test.go | 59 +----------- .../cmd/ske/cluster/delete/delete_test.go | 52 +---------- .../cmd/ske/cluster/describe/describe_test.go | 50 +--------- .../generate-payload/generate_payload.go | 6 +- .../generate-payload/generate_payload_test.go | 51 +---------- internal/cmd/ske/cluster/list/list.go | 6 +- internal/cmd/ske/cluster/list/list_test.go | 46 +--------- .../cmd/ske/cluster/update/update_test.go | 50 +--------- .../complete_rotation_test.go | 52 +---------- .../start-rotation/start_rotation_test.go | 52 +---------- internal/cmd/ske/describe/describe.go | 6 +- internal/cmd/ske/describe/describe_test.go | 44 +-------- internal/cmd/ske/disable/disable.go | 6 +- internal/cmd/ske/disable/disable_test.go | 45 +-------- internal/cmd/ske/enable/enable.go | 6 +- internal/cmd/ske/enable/enable_test.go | 45 +-------- .../cmd/ske/kubeconfig/create/create_test.go | 50 +--------- internal/cmd/ske/options/options.go | 6 +- internal/cmd/ske/options/options_test.go | 43 +-------- internal/cmd/volume/backup/create/create.go | 6 +- .../cmd/volume/backup/create/create_test.go | 43 +-------- .../cmd/volume/backup/delete/delete_test.go | 44 +-------- .../volume/backup/describe/describe_test.go | 42 +-------- internal/cmd/volume/backup/list/list.go | 6 +- internal/cmd/volume/backup/list/list_test.go | 46 +--------- .../cmd/volume/backup/restore/restore_test.go | 44 +-------- .../cmd/volume/backup/update/update_test.go | 44 +-------- internal/cmd/volume/create/create.go | 6 +- internal/cmd/volume/create/create_test.go | 43 +-------- internal/cmd/volume/delete/delete_test.go | 52 +---------- internal/cmd/volume/describe/describe_test.go | 50 +--------- internal/cmd/volume/list/list.go | 6 +- internal/cmd/volume/list/list_test.go | 43 +-------- .../describe/describe_test.go | 51 +---------- .../cmd/volume/performance-class/list/list.go | 6 +- .../performance-class/list/list_test.go | 43 +-------- internal/cmd/volume/snapshot/create/create.go | 6 +- .../cmd/volume/snapshot/create/create_test.go | 45 +-------- .../cmd/volume/snapshot/delete/delete_test.go | 44 +-------- .../volume/snapshot/describe/describe_test.go | 42 +-------- internal/cmd/volume/snapshot/list/list.go | 6 +- .../cmd/volume/snapshot/list/list_test.go | 35 +------ .../cmd/volume/snapshot/update/update_test.go | 44 +-------- internal/pkg/testutils/testutils.go | 91 +++++++++++++++++++ 480 files changed, 1480 insertions(+), 14225 deletions(-) create mode 100644 internal/pkg/testutils/testutils.go diff --git a/internal/cmd/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go index 30daf9339..89e7659bb 100644 --- a/internal/cmd/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -40,9 +40,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit affinity-group create --name AFFINITY_GROUP_NAME --policy soft-affinity", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -98,7 +98,7 @@ func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClie return req } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/affinity-groups/create/create_test.go b/internal/cmd/affinity-groups/create/create_test.go index 0f71d31db..ba70232d0 100644 --- a/internal/cmd/affinity-groups/create/create_test.go +++ b/internal/cmd/affinity-groups/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -80,6 +81,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateAffinityGroupPayload)) iaas func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -120,43 +122,7 @@ func TestParseInput(t *testing.T) { } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Fatalf("configure global flags: %v", err) - } - - for flag, value := range tt.flagValues { - if err := cmd.Flags().Set(flag, value); err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", flag, value, err) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/affinity-groups/list/list.go b/internal/cmd/affinity-groups/list/list.go index 36ae4f28c..75d0e667e 100644 --- a/internal/cmd/affinity-groups/list/list.go +++ b/internal/cmd/affinity-groups/list/list.go @@ -42,9 +42,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit affinity-group list --limit=10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -85,7 +85,7 @@ func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClie return apiClient.ListAffinityGroups(ctx, model.ProjectId) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/affinity-groups/list/list_test.go b/internal/cmd/affinity-groups/list/list_test.go index b44af626c..23c643f1b 100644 --- a/internal/cmd/affinity-groups/list/list_test.go +++ b/internal/cmd/affinity-groups/list/list_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -63,6 +64,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListAffinityGroupsRequest)) ia func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -105,43 +107,7 @@ func TestParseInput(t *testing.T) { } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Fatalf("configure global flags: %v", err) - } - - for flag, value := range tt.flagValues { - if err := cmd.Flags().Set(flag, value); err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", flag, value, err) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/auth/activate-service-account/activate_service_account.go b/internal/cmd/auth/activate-service-account/activate_service_account.go index 1246dcd98..a3cf1ee46 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account.go @@ -58,8 +58,11 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit auth activate-service-account --service-account-token my-service-account-token --only-print-access-token", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { - model := parseInput(params.Printer, cmd) + RunE: func(cmd *cobra.Command, args []string) error { + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return err + } tokenCustomEndpoint := viper.GetString(config.TokenCustomEndpointKey) if !model.OnlyPrintAccessToken { @@ -113,7 +116,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(onlyPrintAccessTokenFlag, false, "If this is set to true the credentials are not stored in either the keyring or a file") } -func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { model := inputModel{ ServiceAccountToken: flags.FlagToStringValue(p, cmd, serviceAccountTokenFlag), ServiceAccountKeyPath: flags.FlagToStringValue(p, cmd, serviceAccountKeyPathFlag), @@ -122,7 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { } p.DebugInputModel(model) - return &model + return &model, nil } func storeCustomEndpoint(tokenCustomEndpoint string) error { diff --git a/internal/cmd/auth/activate-service-account/activate_service_account_test.go b/internal/cmd/auth/activate-service-account/activate_service_account_test.go index 84532195c..026ba8dce 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account_test.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account_test.go @@ -3,15 +3,12 @@ package activateserviceaccount import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/spf13/viper" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/zalando/go-keyring" - - "github.com/google/go-cmp/cmp" ) var testTokenCustomEndpoint = "token_url" @@ -45,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string tokenCustomEndpoint string isValid bool @@ -106,32 +104,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - model := parseInput(p, cmd) - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index 8db52f60e..a26b71b20 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -29,8 +29,8 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Print a short-lived access token`, "$ stackit auth get-access-token"), ), - RunE: func(cmd *cobra.Command, _ []string) error { - model, err := parseInput(params.Printer, cmd) + RunE: func(cmd *cobra.Command, args []string) error { + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) model := inputModel{ diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go index 64d3c2871..33551e3ac 100644 --- a/internal/cmd/beta/alb/create/create.go +++ b/internal/cmd/beta/alb/create/create.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create an application loadbalancer from a configuration file`, "$ stackit beta alb create --configuration my-loadbalancer.json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -107,7 +107,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/alb/create/create_test.go b/internal/cmd/beta/alb/create/create_test.go index 82517b0f5..a3b7c0725 100644 --- a/internal/cmd/beta/alb/create/create_test.go +++ b/internal/cmd/beta/alb/create/create_test.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -79,6 +80,7 @@ func fixtureRequest(mods ...func(request *alb.ApiCreateLoadBalancerRequest)) alb func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -134,46 +136,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/delete/delete_test.go b/internal/cmd/beta/alb/delete/delete_test.go index ce6808fbd..6c5290a52 100644 --- a/internal/cmd/beta/alb/delete/delete_test.go +++ b/internal/cmd/beta/alb/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -112,54 +111,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argsValues) - 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.argsValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argsValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/describe/describe_test.go b/internal/cmd/beta/alb/describe/describe_test.go index 4d1195313..9132fc5af 100644 --- a/internal/cmd/beta/alb/describe/describe_test.go +++ b/internal/cmd/beta/alb/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -112,54 +113,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argsValues) - 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.argsValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argsValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go index a16443730..2c4d8924d 100644 --- a/internal/cmd/beta/alb/list/list.go +++ b/internal/cmd/beta/alb/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit beta alb list --limit=10`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/alb/list/list_test.go b/internal/cmd/beta/alb/list/list_test.go index f0fb05146..c623ea0b8 100644 --- a/internal/cmd/beta/alb/list/list_test.go +++ b/internal/cmd/beta/alb/list/list_test.go @@ -9,6 +9,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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/uuid" @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *alb.ApiListLoadBalancersRequest)) alb. func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -99,44 +101,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/observability-credentials/add/add.go b/internal/cmd/beta/alb/observability-credentials/add/add.go index 8fd15d81d..1b430cdf6 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add.go @@ -40,10 +40,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Add observability credentials to a load balancer with username "xxx" and display name "yyy", providing the path to a file with the password as flag`, "$ stackit beta alb observability-credentials add --username xxx --password @./password.txt --display-name yyy"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -84,7 +84,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(flags.MarkFlagsRequired(cmd, usernameFlag, displaynameFlag)) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) model := inputModel{ diff --git a/internal/cmd/beta/alb/observability-credentials/add/add_test.go b/internal/cmd/beta/alb/observability-credentials/add/add_test.go index b5fa2bac6..fb81d7a34 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add_test.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -82,6 +83,7 @@ func fixturePayload(mods ...func(payload *alb.CreateCredentialsPayload)) alb.Cre func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -101,46 +103,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go b/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go index 79412281b..df4d70fe1 100644 --- a/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -112,54 +113,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argsValues) - 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.argsValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argsValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/observability-credentials/list/list.go b/internal/cmd/beta/alb/observability-credentials/list/list.go index dace68982..961455b53 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit beta alb observability-credentials list --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -90,7 +90,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Number of credentials to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) diff --git a/internal/cmd/beta/alb/observability-credentials/list/list_test.go b/internal/cmd/beta/alb/observability-credentials/list/list_test.go index 77863ded8..e8054a4e8 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list_test.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -65,6 +66,7 @@ func fixtureRequest(mods ...func(request *alb.ApiListCredentialsRequest)) alb.Ap func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -120,46 +122,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %v", err) - } - - if !tt.isValid { - t.Fatal("did not fail on invalid input") - } - diff := cmp.Diff(model, tt.expectedModel) - if diff != "" { - t.Fatalf("data does not match: %s", diff) - } + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/observability-credentials/update/update_test.go b/internal/cmd/beta/alb/observability-credentials/update/update_test.go index 4d3780ba1..1fd029be1 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update_test.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update_test.go @@ -84,6 +84,7 @@ func fixturePayload(mods ...func(payload *alb.UpdateCredentialsPayload)) alb.Upd func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string args []string isValid bool diff --git a/internal/cmd/beta/alb/plans/plans.go b/internal/cmd/beta/alb/plans/plans.go index 55c4ab6c5..6bb5e01fc 100644 --- a/internal/cmd/beta/alb/plans/plans.go +++ b/internal/cmd/beta/alb/plans/plans.go @@ -34,9 +34,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit beta alb plans`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/alb/plans/plans_test.go b/internal/cmd/beta/alb/plans/plans_test.go index 84b5c9002..1a31d711b 100644 --- a/internal/cmd/beta/alb/plans/plans_test.go +++ b/internal/cmd/beta/alb/plans/plans_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -55,6 +56,7 @@ func fixtureRequest(mods ...func(request *alb.ApiListPlansRequest)) alb.ApiListP func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -95,44 +97,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/pool/update/update.go b/internal/cmd/beta/alb/pool/update/update.go index a3a8aa983..ca294f052 100644 --- a/internal/cmd/beta/alb/pool/update/update.go +++ b/internal/cmd/beta/alb/pool/update/update.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Update an application target pool from a configuration file (the name of the pool is read from the file)`, "$ stackit beta alb update --configuration my-target-pool.json --name my-load-balancer"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/alb/pool/update/update_test.go b/internal/cmd/beta/alb/pool/update/update_test.go index f279c1f01..15bc4f4a9 100644 --- a/internal/cmd/beta/alb/pool/update/update_test.go +++ b/internal/cmd/beta/alb/pool/update/update_test.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -85,6 +86,7 @@ func fixtureRequest(mods ...func(request *alb.ApiUpdateTargetPoolRequest)) alb.A func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -142,46 +144,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/quotas/quotas.go b/internal/cmd/beta/alb/quotas/quotas.go index 9b2729c29..3f9a63002 100644 --- a/internal/cmd/beta/alb/quotas/quotas.go +++ b/internal/cmd/beta/alb/quotas/quotas.go @@ -33,9 +33,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit beta alb quotas`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/alb/quotas/quotas_test.go b/internal/cmd/beta/alb/quotas/quotas_test.go index 6240e20d3..ee63dffcd 100644 --- a/internal/cmd/beta/alb/quotas/quotas_test.go +++ b/internal/cmd/beta/alb/quotas/quotas_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -55,6 +56,7 @@ func fixtureRequest(mods ...func(request *alb.ApiGetQuotaRequest)) alb.ApiGetQuo func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -95,44 +97,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/template/template.go b/internal/cmd/beta/alb/template/template.go index c1dad5350..a57b83f67 100644 --- a/internal/cmd/beta/alb/template/template.go +++ b/internal/cmd/beta/alb/template/template.go @@ -53,8 +53,8 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit beta alb template --format=json --type pool`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { - model, err := parseInput(params.Printer, cmd) + RunE: func(cmd *cobra.Command, args []string) error { + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -100,7 +100,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().VarP(flags.EnumFlag(true, "alb", "alb", "pool"), typeFlag, "t", "Defines the output type ('alb' or 'pool'), default is 'alb'") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/alb/template/template_test.go b/internal/cmd/beta/alb/template/template_test.go index be7bed72d..7f73d3f7d 100644 --- a/internal/cmd/beta/alb/template/template_test.go +++ b/internal/cmd/beta/alb/template/template_test.go @@ -3,12 +3,10 @@ package template import ( "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" - "github.com/google/go-cmp/cmp" "github.com/google/uuid" ) @@ -41,6 +39,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -138,44 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go index a8b32b156..c1c576f06 100644 --- a/internal/cmd/beta/alb/update/update.go +++ b/internal/cmd/beta/alb/update/update.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Update an application loadbalancer from a configuration file`, "$ stackit beta alb update --configuration my-loadbalancer.json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -114,7 +114,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/alb/update/update_test.go b/internal/cmd/beta/alb/update/update_test.go index 5749b8b86..dc8f5986a 100644 --- a/internal/cmd/beta/alb/update/update_test.go +++ b/internal/cmd/beta/alb/update/update_test.go @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) @@ -82,6 +83,7 @@ func fixtureRequest(mods ...func(request *alb.ApiUpdateLoadBalancerRequest)) alb func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -137,46 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/database/create/create_test.go b/internal/cmd/beta/sqlserverflex/database/create/create_test.go index c6359313e..23001c28c 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/sqlserverflex" ) @@ -177,54 +178,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go index 53a099f48..ab137dcd0 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/sqlserverflex" "github.com/google/go-cmp/cmp" @@ -160,54 +159,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go index 919b1e3c5..b77f11679 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/sqlserverflex" ) @@ -159,54 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index 990946dad..38f630a3f 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 SQLServer Flex databases of instance with ID "xxx"`, "$ stackit beta sqlserverflex database list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -98,7 +98,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/sqlserverflex/database/list/list_test.go b/internal/cmd/beta/sqlserverflex/database/list/list_test.go index 0aa4979f7..ae340d0db 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -63,6 +63,7 @@ func fixtureRequest(mods ...func(request *sqlserverflex.ApiListDatabasesRequest) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -138,48 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 9acc361b7..cc5f2214d 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -82,10 +82,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a SQLServer Flex instance with name "my-instance", specify flavor by CPU and RAM, set storage size to 20 GB, and restrict access to a specific range of IP addresses. Other parameters are set to default values`, `$ stackit beta sqlserverflex instance create --name my-instance --cpu 1 --ram 4 --storage-size 20 --acl 1.2.3.0/24`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -156,7 +156,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go index 851d3d1fd..40481f963 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -131,6 +132,7 @@ func fixturePayload(mods ...func(payload *sqlserverflex.CreateInstancePayload)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -251,56 +253,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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) }) } } diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go index ae971f31d..fe66b190b 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -139,54 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go index 7412418c6..66676b001 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/sqlserverflex" ) @@ -138,54 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 3e8606347..76cf59d8a 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 SQLServer Flex instances`, "$ stackit beta sqlserverflex instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go index be4b5debe..59711594b 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *sqlserverflex.ApiListInstancesRequest) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index a6c126e8b..9352e53b5 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -106,9 +106,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List SQL Server Flex user roles and database compatibilities for a given instance. The IDs of existing instances can be obtained by running "$ stackit beta sqlserverflex instance list"`, "$ stackit beta sqlserverflex options --user-roles --db-compatibilities --instance-id "), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -143,7 +143,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(instanceIdFlag, "", `The instance ID to show user roles, database collations and database compatibilities for. Only relevant when "--user-roles", "--db-collations" or "--db-compatibilities" is passed`) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) flavors := flags.FlagToBoolValue(p, cmd, flavorsFlag) diff --git a/internal/cmd/beta/sqlserverflex/options/options_test.go b/internal/cmd/beta/sqlserverflex/options/options_test.go index 1f527d85e..61b24b242 100644 --- a/internal/cmd/beta/sqlserverflex/options/options_test.go +++ b/internal/cmd/beta/sqlserverflex/options/options_test.go @@ -5,11 +5,11 @@ import ( "fmt" "testing" - "github.com/google/go-cmp/cmp" "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -158,6 +158,7 @@ func fixtureInputModelAllTrue(mods ...func(model *inputModel)) *inputModel { func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -263,46 +264,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index cb159965f..5160873f2 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -55,9 +55,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "##STACKIT_LoginManager##,##STACKIT_DatabaseManager##"`), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -107,7 +107,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/sqlserverflex/user/create/create_test.go b/internal/cmd/beta/sqlserverflex/user/create/create_test.go index 4c294d6d9..ad5df9a27 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -70,6 +70,7 @@ func fixtureRequest(mods ...func(request *sqlserverflex.ApiCreateUserRequest)) s func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -139,48 +140,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go b/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go index c4345ba6a..9220bcbfc 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -154,54 +153,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go index 8f44c6db7..e67aeb3b9 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/sqlserverflex" ) @@ -153,54 +154,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index 08950270e..0c131e32b 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit beta sqlserverflex user list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -99,7 +99,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/beta/sqlserverflex/user/list/list_test.go b/internal/cmd/beta/sqlserverflex/user/list/list_test.go index 7ec60722f..ef80e6252 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) @@ -63,6 +63,7 @@ func fixtureRequest(mods ...func(request *sqlserverflex.ApiListUsersRequest)) sq func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -131,48 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go index eeeb230a1..b15b7069e 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/sqlserverflex" ) @@ -153,54 +154,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/config/profile/create/create_test.go b/internal/cmd/config/profile/create/create_test.go index 6bf77a7ae..a2edcfe47 100644 --- a/internal/cmd/config/profile/create/create_test.go +++ b/internal/cmd/config/profile/create/create_test.go @@ -3,12 +3,8 @@ package create import ( "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - - "github.com/google/go-cmp/cmp" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" ) const testProfile = "test-profile" @@ -105,54 +101,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/config/profile/delete/delete_test.go b/internal/cmd/config/profile/delete/delete_test.go index 66374b69d..e3ea1bf51 100644 --- a/internal/cmd/config/profile/delete/delete_test.go +++ b/internal/cmd/config/profile/delete/delete_test.go @@ -3,12 +3,8 @@ package delete import ( "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - - "github.com/google/go-cmp/cmp" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" ) const testProfile = "test-profile" @@ -81,54 +77,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/config/profile/export/export_test.go b/internal/cmd/config/profile/export/export_test.go index 5975cf783..dc67621da 100644 --- a/internal/cmd/config/profile/export/export_test.go +++ b/internal/cmd/config/profile/export/export_test.go @@ -4,12 +4,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - - "github.com/google/go-cmp/cmp" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" ) const ( @@ -103,54 +99,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argsValues) - 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.argsValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argsValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/config/profile/import/import.go b/internal/cmd/config/profile/import/import.go index 82f8229dd..a499f0da0 100644 --- a/internal/cmd/config/profile/import/import.go +++ b/internal/cmd/config/profile/import/import.go @@ -41,8 +41,8 @@ func NewCmd(params *params.CmdParams) *cobra.Command { ), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { - model, err := parseInput(params.Printer, cmd) + RunE: func(cmd *cobra.Command, args []string) error { + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -70,7 +70,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(cmd.MarkFlagRequired(configFlag)) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) model := &inputModel{ diff --git a/internal/cmd/config/profile/import/import_test.go b/internal/cmd/config/profile/import/import_test.go index 121b7adb9..e676f1b14 100644 --- a/internal/cmd/config/profile/import/import_test.go +++ b/internal/cmd/config/profile/import/import_test.go @@ -5,11 +5,8 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - - "github.com/google/go-cmp/cmp" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" ) const testProfile = "test-profile" @@ -49,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -75,45 +73,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - t.Fatalf("error parsing input: %v", err) - } - } - - if !tt.isValid { - t.Fatalf("did not fail on invalid input") - } - diff := cmp.Diff(tt.expectedModel, model) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/config/profile/set/set_test.go b/internal/cmd/config/profile/set/set_test.go index 67b5f0789..a2ccdbbff 100644 --- a/internal/cmd/config/profile/set/set_test.go +++ b/internal/cmd/config/profile/set/set_test.go @@ -3,12 +3,8 @@ package set import ( "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - - "github.com/google/go-cmp/cmp" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" ) const testProfile = "test-profile" @@ -81,54 +77,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 841f8e66e..5e4dfa540 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -76,8 +76,8 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Set the DNS custom endpoint. This endpoint will be used on all calls to the DNS API (unless overridden by the "STACKIT_DNS_CUSTOM_ENDPOINT" environment variable)`, "$ stackit config set --dns-custom-endpoint https://dns.stackit.cloud"), ), - RunE: func(cmd *cobra.Command, _ []string) error { - model, err := parseInput(params.Printer, cmd) + RunE: func(cmd *cobra.Command, args []string) error { + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -217,7 +217,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { sessionTimeLimit, err := parseSessionTimeLimit(p, cmd) if err != nil { return nil, &errors.FlagValidationError{ diff --git a/internal/cmd/config/set/set_test.go b/internal/cmd/config/set/set_test.go index 8015fddff..c13c84d5c 100644 --- a/internal/cmd/config/set/set_test.go +++ b/internal/cmd/config/set/set_test.go @@ -3,19 +3,17 @@ package set import ( "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "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" - "github.com/google/go-cmp/cmp" "github.com/google/uuid" ) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -123,46 +121,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 1320248d4..96a5fc8e7 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -53,9 +53,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a DNS record set with name "my-rr" with records "1.2.3.4" and "5.6.7.8" in zone with ID "xxx"`, "$ stackit dns record-set create --zone-id xxx --name my-rr --record 1.2.3.4 --record 5.6.7.8"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -123,7 +123,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/dns/record-set/create/create_test.go b/internal/cmd/dns/record-set/create/create_test.go index 789e46626..d284504bf 100644 --- a/internal/cmd/dns/record-set/create/create_test.go +++ b/internal/cmd/dns/record-set/create/create_test.go @@ -12,6 +12,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -86,6 +87,7 @@ func fixtureRequest(mods ...func(request *dns.ApiCreateRecordSetRequest)) dns.Ap func TestParseInput(t *testing.T) { var tests = []struct { description string + argValues []string flagValues map[string]string recordFlagValues []string isValid bool @@ -267,56 +269,9 @@ func TestParseInput(t *testing.T) { } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.recordFlagValues { - err := cmd.Flags().Set(recordFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", recordFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + recordFlag: tt.recordFlagValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/dns/record-set/delete/delete_test.go b/internal/cmd/dns/record-set/delete/delete_test.go index 55b534fde..c02628dd1 100644 --- a/internal/cmd/dns/record-set/delete/delete_test.go +++ b/internal/cmd/dns/record-set/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/dns/record-set/describe/describe_test.go b/internal/cmd/dns/record-set/describe/describe_test.go index 55a032bd8..45d58c2a1 100644 --- a/internal/cmd/dns/record-set/describe/describe_test.go +++ b/internal/cmd/dns/record-set/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/dns" ) @@ -164,54 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index 1d9093de7..eedc2a59e 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -72,9 +72,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List the deleted DNS record-sets for zone with ID "xxx"`, "$ stackit dns record-set list --zone-id xxx --deleted"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -123,7 +123,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/dns/record-set/list/list_test.go b/internal/cmd/dns/record-set/list/list_test.go index 122a2b29d..6eaf5504b 100644 --- a/internal/cmd/dns/record-set/list/list_test.go +++ b/internal/cmd/dns/record-set/list/list_test.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/dns" @@ -72,6 +73,7 @@ func fixtureRequest(mods ...func(request *dns.ApiListRecordSetsRequest)) dns.Api func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -214,46 +216,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/dns/zone/clone/clone_test.go b/internal/cmd/dns/zone/clone/clone_test.go index 01f738f3a..b17d634fe 100644 --- a/internal/cmd/dns/zone/clone/clone_test.go +++ b/internal/cmd/dns/zone/clone/clone_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -169,54 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index a28e05622..0658ceb8b 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -68,9 +68,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a DNS zone with name "my-zone", DNS name "www.my-zone.com" and default time to live of 1000ms`, "$ stackit dns zone create --name my-zone --dns-name www.my-zone.com --default-ttl 1000"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -145,7 +145,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/dns/zone/create/create_test.go b/internal/cmd/dns/zone/create/create_test.go index 536711d80..8c7f58bc0 100644 --- a/internal/cmd/dns/zone/create/create_test.go +++ b/internal/cmd/dns/zone/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) @@ -97,6 +98,7 @@ func fixtureRequest(mods ...func(request *dns.ApiCreateZoneRequest)) dns.ApiCrea func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string primaryFlagValues []string isValid bool @@ -215,56 +217,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.primaryFlagValues { - err := cmd.Flags().Set(primaryFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", primaryFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + primaryFlag: tt.primaryFlagValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/dns/zone/delete/delete_test.go b/internal/cmd/dns/zone/delete/delete_test.go index 77cb37649..a4b967998 100644 --- a/internal/cmd/dns/zone/delete/delete_test.go +++ b/internal/cmd/dns/zone/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/dns/zone/describe/describe_test.go b/internal/cmd/dns/zone/describe/describe_test.go index ed58cbb14..69a7f0587 100644 --- a/internal/cmd/dns/zone/describe/describe_test.go +++ b/internal/cmd/dns/zone/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/dns" ) @@ -137,54 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index d39cea62e..e86c8ec78 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -68,9 +68,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List DNS zones, including deleted`, "$ stackit dns zone list --include-deleted"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -115,7 +115,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(pageSizeFlag, pageSizeDefault, "Number of items fetched in each API call. Does not affect the number of items in the command output") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/dns/zone/list/list_test.go b/internal/cmd/dns/zone/list/list_test.go index 844c2afa6..bb46d6aea 100644 --- a/internal/cmd/dns/zone/list/list_test.go +++ b/internal/cmd/dns/zone/list/list_test.go @@ -14,6 +14,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/dns" @@ -69,6 +70,7 @@ func fixtureRequest(mods ...func(request *dns.ApiListZonesRequest)) dns.ApiListZ func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -209,46 +211,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/git/flavor/list/list.go b/internal/cmd/git/flavor/list/list.go index 2b2a5039e..68b674830 100644 --- a/internal/cmd/git/flavor/list/list.go +++ b/internal/cmd/git/flavor/list/list.go @@ -41,9 +41,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit git flavor list --limit=10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -83,7 +83,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/git/flavor/list/list_test.go b/internal/cmd/git/flavor/list/list_test.go index 1413630b0..d5a6e2f54 100644 --- a/internal/cmd/git/flavor/list/list_test.go +++ b/internal/cmd/git/flavor/list/list_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/git" ) @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *git.ApiListFlavorsRequest)) git.ApiLis func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -123,46 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index d94b99112..296a44598 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -53,9 +53,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit git instance create --name my-new-instance --acl 1.1.1.1/1'`, ), ), - RunE: func(cmd *cobra.Command, _ []string) (err error) { + RunE: func(cmd *cobra.Command, args []string) (err error) { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -111,7 +111,7 @@ func configureFlags(cmd *cobra.Command) { } } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { diff --git a/internal/cmd/git/instance/create/create_test.go b/internal/cmd/git/instance/create/create_test.go index 5b46e1eef..955e5132f 100644 --- a/internal/cmd/git/instance/create/create_test.go +++ b/internal/cmd/git/instance/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/git" ) @@ -79,6 +80,7 @@ func fixtureRequest(mods ...func(request *git.ApiCreateInstanceRequest)) git.Api func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -126,51 +128,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateFlagGroups(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flag groups: %v", err) - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/git/instance/delete/delete_test.go b/internal/cmd/git/instance/delete/delete_test.go index 8c90a4f1d..13609df4e 100644 --- a/internal/cmd/git/instance/delete/delete_test.go +++ b/internal/cmd/git/instance/delete/delete_test.go @@ -55,6 +55,7 @@ func fixtureRequest(mods ...func(request *git.ApiDeleteInstanceRequest)) git.Api func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string args []string isValid bool diff --git a/internal/cmd/git/instance/describe/describe_test.go b/internal/cmd/git/instance/describe/describe_test.go index 17cd8dae8..5e1825565 100644 --- a/internal/cmd/git/instance/describe/describe_test.go +++ b/internal/cmd/git/instance/describe/describe_test.go @@ -54,6 +54,7 @@ func fixtureRequest(mods ...func(request *git.ApiGetInstanceRequest)) git.ApiGet func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool args []string diff --git a/internal/cmd/git/instance/list/list.go b/internal/cmd/git/instance/list/list.go index a31337551..1499ecfdf 100644 --- a/internal/cmd/git/instance/list/list.go +++ b/internal/cmd/git/instance/list/list.go @@ -42,9 +42,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit git instance list --limit=10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -84,7 +84,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/git/instance/list/list_test.go b/internal/cmd/git/instance/list/list_test.go index f73297388..8d6ac21a6 100644 --- a/internal/cmd/git/instance/list/list_test.go +++ b/internal/cmd/git/instance/list/list_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/git" ) @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *git.ApiListInstancesRequest)) git.ApiL func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -123,46 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 58be504a8..9ad653d18 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -102,9 +102,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit image create --name my-new-image --disk-format=raw --local-file-path=/my/raw/image --uefi=false`, ), ), - RunE: func(cmd *cobra.Command, _ []string) (err error) { + RunE: func(cmd *cobra.Command, args []string) (err error) { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -292,7 +292,7 @@ func configureFlags(cmd *cobra.Command) { cmd.MarkFlagsRequiredTogether(rescueBusFlag, rescueDeviceFlag) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/image/create/create_test.go b/internal/cmd/image/create/create_test.go index 45a926fbf..545586502 100644 --- a/internal/cmd/image/create/create_test.go +++ b/internal/cmd/image/create/create_test.go @@ -12,6 +12,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -172,6 +173,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateImageRequest)) iaas.ApiC func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -277,51 +279,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateFlagGroups(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flag groups: %v", err) - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/image/delete/delete_test.go b/internal/cmd/image/delete/delete_test.go index 93b2a656a..2b4f74c1e 100644 --- a/internal/cmd/image/delete/delete_test.go +++ b/internal/cmd/image/delete/delete_test.go @@ -57,6 +57,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiDeleteImageRequest)) iaas.ApiD func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string args []string isValid bool diff --git a/internal/cmd/image/describe/describe_test.go b/internal/cmd/image/describe/describe_test.go index a5e421a9d..076010d69 100644 --- a/internal/cmd/image/describe/describe_test.go +++ b/internal/cmd/image/describe/describe_test.go @@ -57,6 +57,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiGetImageRequest)) iaas.ApiGetI func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool args []string diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index bac3f9c97..a0949187f 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -50,9 +50,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit image list --limit=10`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -103,7 +103,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/image/list/list_test.go b/internal/cmd/image/list/list_test.go index 6437127df..bdfc4c6ed 100644 --- a/internal/cmd/image/list/list_test.go +++ b/internal/cmd/image/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -64,6 +65,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListImagesRequest)) iaas.ApiLi func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -124,44 +126,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/image/update/update_test.go b/internal/cmd/image/update/update_test.go index 5e4d620ca..a40748f3b 100644 --- a/internal/cmd/image/update/update_test.go +++ b/internal/cmd/image/update/update_test.go @@ -168,6 +168,7 @@ func fixtureRequest(mods ...func(*iaas.ApiUpdateImageRequest)) iaas.ApiUpdateIma func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string args []string isValid bool diff --git a/internal/cmd/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go index acb8a0f29..b7170f539 100644 --- a/internal/cmd/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -53,9 +53,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit key-pair create --public-key `ssh-rsa xxx` --labels key=value,key1=value1", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) model := inputModel{ diff --git a/internal/cmd/key-pair/create/create_test.go b/internal/cmd/key-pair/create/create_test.go index 32a0516b6..a14818f72 100644 --- a/internal/cmd/key-pair/create/create_test.go +++ b/internal/cmd/key-pair/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -78,6 +79,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateKeyPairPayload)) iaas.Creat func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -123,46 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/key-pair/describe/describe_test.go b/internal/cmd/key-pair/describe/describe_test.go index c3dd4ffaa..7af2ff2e8 100644 --- a/internal/cmd/key-pair/describe/describe_test.go +++ b/internal/cmd/key-pair/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -108,54 +109,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argsValues) - 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.argsValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argsValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/key-pair/list/list.go b/internal/cmd/key-pair/list/list.go index 68134bb02..eecec55f0 100644 --- a/internal/cmd/key-pair/list/list.go +++ b/internal/cmd/key-pair/list/list.go @@ -56,9 +56,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit key-pair list --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -98,7 +98,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter by label") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) diff --git a/internal/cmd/key-pair/list/list_test.go b/internal/cmd/key-pair/list/list_test.go index 6679cee0d..bc9da640f 100644 --- a/internal/cmd/key-pair/list/list_test.go +++ b/internal/cmd/key-pair/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListKeyPairsRequest)) iaas.Api func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -116,46 +118,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %v", err) - } - - if !tt.isValid { - t.Fatal("did not fail on invalid input") - } - diff := cmp.Diff(model, tt.expectedModel) - if diff != "" { - t.Fatalf("data does not match: %s", diff) - } + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index edc927496..a6b2adc73 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -58,9 +58,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { ``, `$ stackit load-balancer create --payload @./payload.json`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -122,7 +122,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/load-balancer/create/create_test.go b/internal/cmd/load-balancer/create/create_test.go index 66cdb2754..ac22f6c6d 100644 --- a/internal/cmd/load-balancer/create/create_test.go +++ b/internal/cmd/load-balancer/create/create_test.go @@ -6,9 +6,8 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -210,6 +209,7 @@ func fixtureRequest(mods ...func(request *loadbalancer.ApiCreateLoadBalancerRequ func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -277,56 +277,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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, - cmpopts.EquateComparable(testCtx), - ) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/delete/delete_test.go b/internal/cmd/load-balancer/delete/delete_test.go index 17cca82cb..61e9a941b 100644 --- a/internal/cmd/load-balancer/delete/delete_test.go +++ b/internal/cmd/load-balancer/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -130,54 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/describe/describe_test.go b/internal/cmd/load-balancer/describe/describe_test.go index 2aebb5e61..a7b9a4e36 100644 --- a/internal/cmd/load-balancer/describe/describe_test.go +++ b/internal/cmd/load-balancer/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/loadbalancer" ) @@ -129,54 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index a3bffa93e..b7bfac451 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -134,9 +134,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Generate a payload with values of an existing load balancer, and preview it in the terminal`, `$ stackit load-balancer generate-payload --lb-name xxx`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -181,7 +181,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(filePathFlag, "f", "", "If set, writes the payload to the given file. If unset, writes the payload to the standard output") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) loadBalancerName := flags.FlagToStringPointer(p, cmd, loadBalancerNameFlag) diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go index 66a0891ec..516d41c92 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -69,6 +70,7 @@ func fixtureRequest(mods ...func(request *loadbalancer.ApiGetLoadBalancerRequest func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -132,54 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index fa31894eb..a56de2041 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 load balancers `, "$ stackit load-balancer list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -94,7 +94,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/load-balancer/list/list_test.go b/internal/cmd/load-balancer/list/list_test.go index f43d4ae62..ee948a6f3 100644 --- a/internal/cmd/load-balancer/list/list_test.go +++ b/internal/cmd/load-balancer/list/list_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *loadbalancer.ApiListLoadBalancersReque func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -116,46 +118,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index cc2715e82..ece99c961 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Add observability credentials to a load balancer with username "xxx" and display name "yyy", providing the path to a file with the password as flag`, "$ stackit load-balancer observability-credentials add --username xxx --password @./password.txt --display-name yyy"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -106,7 +106,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/load-balancer/observability-credentials/add/add_test.go b/internal/cmd/load-balancer/observability-credentials/add/add_test.go index bedebaf95..b1e71cf16 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add_test.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -71,6 +72,7 @@ func fixtureRequest(mods ...func(request *loadbalancer.ApiCreateCredentialsReque func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -125,46 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go index 718884c9c..5a521bb9f 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go @@ -33,9 +33,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Delete observability credentials unused by any Load Balancer`, "$ stackit load-balancer observability-credentials cleanup"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -108,7 +108,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go index 7154b55ee..338dcaa08 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/loadbalancer" "github.com/google/go-cmp/cmp" @@ -116,54 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go b/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go index 4730f6a31..c53114075 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/loadbalancer" "github.com/google/go-cmp/cmp" @@ -136,54 +135,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go index 55335f68b..69cfd3bef 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/loadbalancer" ) @@ -135,54 +136,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 88f3d3607..537edc93f 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -57,9 +57,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 Load Balancer observability credentials`, "$ stackit load-balancer observability-credentials list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -127,7 +127,7 @@ func configureFlags(cmd *cobra.Command) { cmd.MarkFlagsMutuallyExclusive(usedFlag, unusedFlag) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/load-balancer/observability-credentials/list/list_test.go b/internal/cmd/load-balancer/observability-credentials/list/list_test.go index 00d107c2e..475f4bf8f 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list_test.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" lbUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) @@ -63,6 +64,7 @@ func fixtureRequest(mods ...func(request *loadbalancer.ApiListCredentialsRequest func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -145,54 +147,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/observability-credentials/update/update_test.go b/internal/cmd/load-balancer/observability-credentials/update/update_test.go index 5aa4faa50..563b489d6 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update_test.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update_test.go @@ -5,9 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -180,54 +179,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index 1f84ea3ef..0549fe177 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -32,9 +32,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Get the configured load balancer quota for the project`, "$ stackit load-balancer quota"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/load-balancer/quota/quota_test.go b/internal/cmd/load-balancer/quota/quota_test.go index 16c14e857..634da62e0 100644 --- a/internal/cmd/load-balancer/quota/quota_test.go +++ b/internal/cmd/load-balancer/quota/quota_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/loadbalancer" ) @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *loadbalancer.ApiGetQuotaRequest)) load func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -94,46 +96,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/load-balancer/update/update_test.go b/internal/cmd/load-balancer/update/update_test.go index b57d57336..23504dcfd 100644 --- a/internal/cmd/load-balancer/update/update_test.go +++ b/internal/cmd/load-balancer/update/update_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -300,54 +299,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 4808614e9..1df3832a2 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -43,9 +43,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create credentials for a LogMe instance and show the password in the output`, "$ stackit logme credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/logme/credentials/create/create_test.go b/internal/cmd/logme/credentials/create/create_test.go index d577d1422..a266eaac7 100644 --- a/internal/cmd/logme/credentials/create/create_test.go +++ b/internal/cmd/logme/credentials/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *logme.ApiCreateCredentialsRequest)) lo func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -130,46 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/logme/credentials/delete/delete_test.go b/internal/cmd/logme/credentials/delete/delete_test.go index 96aff20b2..466250e72 100644 --- a/internal/cmd/logme/credentials/delete/delete_test.go +++ b/internal/cmd/logme/credentials/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/logme/credentials/describe/describe_test.go b/internal/cmd/logme/credentials/describe/describe_test.go index ae7f38696..324b92dd6 100644 --- a/internal/cmd/logme/credentials/describe/describe_test.go +++ b/internal/cmd/logme/credentials/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index 7455b78db..2d0065a72 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 credentials' IDs for a LogMe instance`, "$ stackit logme credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/logme/credentials/list/list_test.go b/internal/cmd/logme/credentials/list/list_test.go index 55c522bbf..fc6c5069b 100644 --- a/internal/cmd/logme/credentials/list/list_test.go +++ b/internal/cmd/logme/credentials/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *logme.ApiListCredentialsRequest)) logm func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -137,46 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index aa8f8af04..fb5ea3e60 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -71,9 +71,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a LogMe instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit logme instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -148,7 +148,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/logme/instance/create/create_test.go b/internal/cmd/logme/instance/create/create_test.go index 9f452d086..23616f5f8 100644 --- a/internal/cmd/logme/instance/create/create_test.go +++ b/internal/cmd/logme/instance/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -108,6 +109,7 @@ func fixtureRequest(mods ...func(request *logme.ApiCreateInstanceRequest)) logme func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string sgwAclValues []string syslogValues []string @@ -262,66 +264,10 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.sgwAclValues { - err := cmd.Flags().Set(sgwAclFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", sgwAclFlag, value, err) - } - } - - for _, value := range tt.syslogValues { - err := cmd.Flags().Set(syslogFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", syslogFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + sgwAclFlag: tt.sgwAclValues, + syslogFlag: tt.syslogValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/logme/instance/delete/delete_test.go b/internal/cmd/logme/instance/delete/delete_test.go index dde9637bb..f2d599f6e 100644 --- a/internal/cmd/logme/instance/delete/delete_test.go +++ b/internal/cmd/logme/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/logme/instance/describe/describe_test.go b/internal/cmd/logme/instance/describe/describe_test.go index 00041b4a9..3e7967085 100644 --- a/internal/cmd/logme/instance/describe/describe_test.go +++ b/internal/cmd/logme/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index e1a2a6d6f..201d49d53 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 LogMe instances`, "$ stackit logme instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/logme/instance/list/list_test.go b/internal/cmd/logme/instance/list/list_test.go index 0168ee409..b3a95fc2b 100644 --- a/internal/cmd/logme/instance/list/list_test.go +++ b/internal/cmd/logme/instance/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/logme" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *logme.ApiListInstancesRequest)) logme. func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index 6b58ced4a..72a601109 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 LogMe service plans`, "$ stackit logme plans --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/logme/plans/plans_test.go b/internal/cmd/logme/plans/plans_test.go index 6feb2a2a5..83980c517 100644 --- a/internal/cmd/logme/plans/plans_test.go +++ b/internal/cmd/logme/plans/plans_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/logme" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *logme.ApiListOfferingsRequest)) logme. func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 3a2fda5da..274b8b740 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -44,9 +44,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create credentials for a MariaDB instance and show the password in the output`, "$ stackit mariadb credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -93,7 +93,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mariadb/credentials/create/create_test.go b/internal/cmd/mariadb/credentials/create/create_test.go index 5516a2415..3ab58f4c3 100644 --- a/internal/cmd/mariadb/credentials/create/create_test.go +++ b/internal/cmd/mariadb/credentials/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *mariadb.ApiCreateCredentialsRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -130,46 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/credentials/delete/delete_test.go b/internal/cmd/mariadb/credentials/delete/delete_test.go index 81da9d7b3..5f8ba6638 100644 --- a/internal/cmd/mariadb/credentials/delete/delete_test.go +++ b/internal/cmd/mariadb/credentials/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/credentials/describe/describe_test.go b/internal/cmd/mariadb/credentials/describe/describe_test.go index 522049aec..7f233f5c4 100644 --- a/internal/cmd/mariadb/credentials/describe/describe_test.go +++ b/internal/cmd/mariadb/credentials/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index 4495106be..b52bf3720 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 credentials' IDs for a MariaDB instance`, "$ stackit mariadb credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -96,7 +96,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mariadb/credentials/list/list_test.go b/internal/cmd/mariadb/credentials/list/list_test.go index c4fbce7b2..1a56a7b6b 100644 --- a/internal/cmd/mariadb/credentials/list/list_test.go +++ b/internal/cmd/mariadb/credentials/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *mariadb.ApiListCredentialsRequest)) ma func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -137,46 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index a7866f6bb..e55787006 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -71,9 +71,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a MariaDB instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit mariadb instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -148,7 +148,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/mariadb/instance/create/create_test.go b/internal/cmd/mariadb/instance/create/create_test.go index 33dedf860..86cfb1daa 100644 --- a/internal/cmd/mariadb/instance/create/create_test.go +++ b/internal/cmd/mariadb/instance/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -108,6 +109,7 @@ func fixtureRequest(mods ...func(request *mariadb.ApiCreateInstanceRequest)) mar func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string sgwAclValues []string syslogValues []string @@ -262,66 +264,10 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.sgwAclValues { - err := cmd.Flags().Set(sgwAclFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", sgwAclFlag, value, err) - } - } - - for _, value := range tt.syslogValues { - err := cmd.Flags().Set(syslogFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", syslogFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + sgwAclFlag: tt.sgwAclValues, + syslogFlag: tt.syslogValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/instance/delete/delete_test.go b/internal/cmd/mariadb/instance/delete/delete_test.go index 737f2affc..c3930a9c8 100644 --- a/internal/cmd/mariadb/instance/delete/delete_test.go +++ b/internal/cmd/mariadb/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/instance/describe/describe_test.go b/internal/cmd/mariadb/instance/describe/describe_test.go index 3d5cc03ec..4aa17ccc9 100644 --- a/internal/cmd/mariadb/instance/describe/describe_test.go +++ b/internal/cmd/mariadb/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index 43df97970..56e1b0e43 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 MariaDB instances`, "$ stackit mariadb instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mariadb/instance/list/list_test.go b/internal/cmd/mariadb/instance/list/list_test.go index 7f199d16c..14587ff87 100644 --- a/internal/cmd/mariadb/instance/list/list_test.go +++ b/internal/cmd/mariadb/instance/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *mariadb.ApiListInstancesRequest)) mari func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index d5ebcde6d..e66d67052 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 MariaDB service plans`, "$ stackit mariadb plans --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mariadb/plans/plans_test.go b/internal/cmd/mariadb/plans/plans_test.go index f80f6c9cd..f63a84125 100644 --- a/internal/cmd/mariadb/plans/plans_test.go +++ b/internal/cmd/mariadb/plans/plans_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *mariadb.ApiListOfferingsRequest)) mari func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/backup/describe/describe_test.go b/internal/cmd/mongodbflex/backup/describe/describe_test.go index f69454e9b..f83ef4d0a 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe_test.go +++ b/internal/cmd/mongodbflex/backup/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -163,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index ab22427bf..5287336ed 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit mongodbflex backup list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -102,7 +102,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/backup/list/list_test.go b/internal/cmd/mongodbflex/backup/list/list_test.go index 8b2e9b177..a6d13d8e4 100644 --- a/internal/cmd/mongodbflex/backup/list/list_test.go +++ b/internal/cmd/mongodbflex/backup/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -66,6 +67,7 @@ func fixtureRequest(mods ...func(request *mongodbflex.ApiListBackupsRequest)) mo func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -141,46 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index 6b8ca07ec..c078ed2cd 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit mongodbflex backup restore-jobs --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -100,7 +100,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go index fd00003a4..7b6419bbe 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -66,6 +67,7 @@ func fixtureRequest(mods ...func(request *mongodbflex.ApiListRestoreJobsRequest) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -141,46 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index 1d547a486..d853f953b 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -56,10 +56,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Restore a MongoDB Flex instance with ID "yyy", using backup from instance with ID "zzz" with backup ID "xxx"`, `$ stackit mongodbflex backup restore --instance-id zzz --backup-instance-id yyy --backup-id xxx`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -148,7 +148,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/backup/restore/restore_test.go b/internal/cmd/mongodbflex/backup/restore/restore_test.go index 27b1d3181..1fed3553f 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore_test.go +++ b/internal/cmd/mongodbflex/backup/restore/restore_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -88,6 +87,7 @@ func fixtureCloneRequest(mods ...func(request mongodbflex.ApiCloneInstanceReques func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -171,54 +171,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flag groups: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index 954e1f8d9..3a34a9e58 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -41,9 +41,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Get details of the backup schedule of a MongoDB Flex instance with ID "xxx" in JSON format`, "$ stackit mongodbflex backup schedule --instance-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -74,7 +74,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go index 1f67e3e64..ab81c09e8 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go @@ -7,11 +7,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -64,6 +64,7 @@ func fixtureRequest(mods ...func(request *mongodbflex.ApiGetInstanceRequest)) mo func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -125,48 +126,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go index af23cdef6..111ba4281 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go @@ -67,10 +67,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit mongodbflex backup update-schedule --instance-id xxx --store-for-days 5"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -131,7 +131,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule_test.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule_test.go index 77b6c5c2c..649f46738 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule_test.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" @@ -106,6 +107,7 @@ func fixtureInstance(mods ...func(instance *mongodbflex.Instance)) *mongodbflex. func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -175,45 +177,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := NewCmd(nil) - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(nil, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 440e19fa8..39fe64514 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -72,10 +72,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a MongoDB Flex instance with name "my-instance", allow access to a specific range of IP addresses, specify flavor by CPU and RAM and set storage size to 20 GB. Other parameters are set to default values`, `$ stackit mongodbflex instance create --name my-instance --cpu 1 --ram 4 --acl 1.2.3.0/24 --storage-size 20`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -156,7 +156,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/instance/create/create_test.go b/internal/cmd/mongodbflex/instance/create/create_test.go index 8d2bd7aba..794b5b9fd 100644 --- a/internal/cmd/mongodbflex/instance/create/create_test.go +++ b/internal/cmd/mongodbflex/instance/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -128,6 +129,7 @@ func fixturePayload(mods ...func(payload *mongodbflex.CreateInstancePayload)) mo func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -254,56 +256,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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) }) } } diff --git a/internal/cmd/mongodbflex/instance/delete/delete_test.go b/internal/cmd/mongodbflex/instance/delete/delete_test.go index 8add607ed..52435d690 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete_test.go +++ b/internal/cmd/mongodbflex/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -142,54 +141,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/instance/describe/describe_test.go b/internal/cmd/mongodbflex/instance/describe/describe_test.go index aa0235465..b63b62933 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe_test.go +++ b/internal/cmd/mongodbflex/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -142,54 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index 798bd544c..1a7d398c7 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 MongoDB Flex instances`, "$ stackit mongodbflex instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -90,7 +90,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/instance/list/list_test.go b/internal/cmd/mongodbflex/instance/list/list_test.go index 1f14f2d89..7ec79019f 100644 --- a/internal/cmd/mongodbflex/instance/list/list_test.go +++ b/internal/cmd/mongodbflex/instance/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -64,6 +64,7 @@ func fixtureRequest(mods ...func(request *mongodbflex.ApiListInstancesRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -118,48 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index f17de9f9c..9d65ea4ef 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -62,9 +62,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List MongoDB Flex storage options for a given flavor. The flavor ID can be retrieved by running "$ stackit mongodbflex options --flavors"`, "$ stackit mongodbflex options --storages --flavor-id "), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -95,7 +95,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(flavorIdFlag, "", `The flavor ID to show storages for. Only relevant when "--storages" is passed`) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) flavors := flags.FlagToBoolValue(p, cmd, flavorsFlag) versions := flags.FlagToBoolValue(p, cmd, versionsFlag) diff --git a/internal/cmd/mongodbflex/options/options_test.go b/internal/cmd/mongodbflex/options/options_test.go index 35ab363dc..57f549b0b 100644 --- a/internal/cmd/mongodbflex/options/options_test.go +++ b/internal/cmd/mongodbflex/options/options_test.go @@ -8,9 +8,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" - "github.com/google/go-cmp/cmp" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -105,6 +105,7 @@ func fixtureInputModelAllTrue(mods ...func(model *inputModel)) *inputModel { func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -167,46 +168,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index 46d11c50b..f589c3996 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -57,9 +57,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit mongodbflex user create --instance-id xxx --role read --database default"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -112,7 +112,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/user/create/create_test.go b/internal/cmd/mongodbflex/user/create/create_test.go index db666260b..7e210559e 100644 --- a/internal/cmd/mongodbflex/user/create/create_test.go +++ b/internal/cmd/mongodbflex/user/create/create_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -77,6 +77,7 @@ func fixtureRequest(mods ...func(request *mongodbflex.ApiCreateUserRequest)) mon func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -166,48 +167,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/user/delete/delete_test.go b/internal/cmd/mongodbflex/user/delete/delete_test.go index 1a20490f1..e324f0010 100644 --- a/internal/cmd/mongodbflex/user/delete/delete_test.go +++ b/internal/cmd/mongodbflex/user/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -169,54 +168,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/user/describe/describe_test.go b/internal/cmd/mongodbflex/user/describe/describe_test.go index 5315f8b8a..604758d1d 100644 --- a/internal/cmd/mongodbflex/user/describe/describe_test.go +++ b/internal/cmd/mongodbflex/user/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -169,54 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index b6fb8ad7a..94fcfcdd1 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit mongodbflex user list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/mongodbflex/user/list/list_test.go b/internal/cmd/mongodbflex/user/list/list_test.go index 3345bae43..d480ed651 100644 --- a/internal/cmd/mongodbflex/user/list/list_test.go +++ b/internal/cmd/mongodbflex/user/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) @@ -67,6 +67,7 @@ func fixtureRequest(mods ...func(request *mongodbflex.ApiListUsersRequest)) mong func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -135,48 +136,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go index 349baec27..0836c789e 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -169,54 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/mongodbflex/user/update/update_test.go b/internal/cmd/mongodbflex/user/update/update_test.go index 3f12bda1a..0d110a06c 100644 --- a/internal/cmd/mongodbflex/user/update/update_test.go +++ b/internal/cmd/mongodbflex/user/update/update_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -201,54 +200,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index 4aefc6d5b..fa97908d9 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -68,9 +68,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -132,7 +132,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) model := inputModel{ diff --git a/internal/cmd/network-area/create/create_test.go b/internal/cmd/network-area/create/create_test.go index 7b9d235cd..a731541fd 100644 --- a/internal/cmd/network-area/create/create_test.go +++ b/internal/cmd/network-area/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -105,6 +106,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaPayload)) iaas.C func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -193,46 +195,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-area/delete/delete_test.go b/internal/cmd/network-area/delete/delete_test.go index 4b8077590..1ee322dc3 100644 --- a/internal/cmd/network-area/delete/delete_test.go +++ b/internal/cmd/network-area/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -136,54 +135,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-area/describe/describe_test.go b/internal/cmd/network-area/describe/describe_test.go index 7160f6a01..70e63e145 100644 --- a/internal/cmd/network-area/describe/describe_test.go +++ b/internal/cmd/network-area/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -149,54 +150,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-area/list/list.go b/internal/cmd/network-area/list/list.go index 6dea71c0e..6184148aa 100644 --- a/internal/cmd/network-area/list/list.go +++ b/internal/cmd/network-area/list/list.go @@ -58,9 +58,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit network-area list --organization-id xxx --label-selector yyy", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -118,7 +118,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) if limit != nil && *limit < 1 { diff --git a/internal/cmd/network-area/list/list_test.go b/internal/cmd/network-area/list/list_test.go index d41ae9ad8..41c51e380 100644 --- a/internal/cmd/network-area/list/list_test.go +++ b/internal/cmd/network-area/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -61,6 +62,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreasRequest)) iaas func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -130,46 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go index 9f073bc22..ec7f1dbcf 100644 --- a/internal/cmd/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -43,9 +43,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit network-area network-range create --network-area-id xxx --organization-id yyy --network-range "1.1.1.0/24"`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -103,7 +103,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) model := inputModel{ diff --git a/internal/cmd/network-area/network-range/create/create_test.go b/internal/cmd/network-area/network-range/create/create_test.go index 478854cc2..6edc6b23b 100644 --- a/internal/cmd/network-area/network-range/create/create_test.go +++ b/internal/cmd/network-area/network-range/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -76,6 +77,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaRangePayload)) i func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -145,46 +147,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go index 51f3aeeea..967ffbb9c 100644 --- a/internal/cmd/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -53,9 +53,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit network-area network-range list --network-area-id xxx --organization-id yyy --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -106,7 +106,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) if limit != nil && *limit < 1 { diff --git a/internal/cmd/network-area/network-range/list/list_test.go b/internal/cmd/network-area/network-range/list/list_test.go index 4e7b52627..f8525e39b 100644 --- a/internal/cmd/network-area/network-range/list/list_test.go +++ b/internal/cmd/network-area/network-range/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -60,6 +61,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreaRangesRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -140,46 +142,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index 0dbd0e248..f8548316c 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -54,9 +54,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -116,7 +116,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) model := inputModel{ diff --git a/internal/cmd/network-area/route/create/create_test.go b/internal/cmd/network-area/route/create/create_test.go index a1ab93772..1bc7cb161 100644 --- a/internal/cmd/network-area/route/create/create_test.go +++ b/internal/cmd/network-area/route/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -79,6 +80,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaRoutePayload)) i func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -180,46 +182,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go index cdc6a67ae..2af24763a 100644 --- a/internal/cmd/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -52,9 +52,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit network-area route list --network-area-id xxx --organization-id yyy --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -105,7 +105,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) if limit != nil && *limit < 1 { diff --git a/internal/cmd/network-area/route/list/list_test.go b/internal/cmd/network-area/route/list/list_test.go index 2d66bad9f..8681aa87d 100644 --- a/internal/cmd/network-area/route/list/list_test.go +++ b/internal/cmd/network-area/route/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -60,6 +61,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreaRoutesRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -140,46 +142,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index c22735b0e..1fc368ffa 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -64,9 +64,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit network-interface create --network-id xxx --allowed-addresses "1.1.1.1,8.8.8.8,9.9.9.9" --labels key=value,key2=value2 --name NAME --security-groups "UUID1,UUID2" --nic-security`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -121,7 +121,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/network-interface/create/create_test.go b/internal/cmd/network-interface/create/create_test.go index f05ed584e..82e5b628a 100644 --- a/internal/cmd/network-interface/create/create_test.go +++ b/internal/cmd/network-interface/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -105,6 +106,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateNicPayload)) iaas.CreateNic func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -190,46 +192,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go index 2effcf4a8..cd683883a 100644 --- a/internal/cmd/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -56,9 +56,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit network-interface list --network-id xxx --limit 10`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -110,7 +110,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/network-interface/list/list_test.go b/internal/cmd/network-interface/list/list_test.go index 3e976c5db..68df78a25 100644 --- a/internal/cmd/network-interface/list/list_test.go +++ b/internal/cmd/network-interface/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -66,6 +67,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListNicsRequest)) iaas.ApiList func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -135,46 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index 2d49bc965..acb1bc7e1 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -86,9 +86,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -160,7 +160,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/network/create/create_test.go b/internal/cmd/network/create/create_test.go index 63c6a3635..6fd5c6a9a 100644 --- a/internal/cmd/network/create/create_test.go +++ b/internal/cmd/network/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -123,6 +124,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.Creat func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -258,46 +260,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network/delete/delete_test.go b/internal/cmd/network/delete/delete_test.go index 630a0f3fb..20c5eed47 100644 --- a/internal/cmd/network/delete/delete_test.go +++ b/internal/cmd/network/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network/describe/describe_test.go b/internal/cmd/network/describe/describe_test.go index 9c3b62d35..098baa905 100644 --- a/internal/cmd/network/describe/describe_test.go +++ b/internal/cmd/network/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/network/list/list.go b/internal/cmd/network/list/list.go index 97d570f75..a0c871466 100644 --- a/internal/cmd/network/list/list.go +++ b/internal/cmd/network/list/list.go @@ -55,9 +55,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit network list --label-selector xxx", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -105,7 +105,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter by label") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/network/list/list_test.go b/internal/cmd/network/list/list_test.go index c0f1ac4c3..f408eeb78 100644 --- a/internal/cmd/network/list/list_test.go +++ b/internal/cmd/network/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -63,6 +64,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListNetworksRequest)) iaas.Api func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -132,46 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/bucket/create/create_test.go b/internal/cmd/object-storage/bucket/create/create_test.go index 344c228d5..b6e926cd2 100644 --- a/internal/cmd/object-storage/bucket/create/create_test.go +++ b/internal/cmd/object-storage/bucket/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -136,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/bucket/delete/delete_test.go b/internal/cmd/object-storage/bucket/delete/delete_test.go index 6e06d4adc..2dfe69ec6 100644 --- a/internal/cmd/object-storage/bucket/delete/delete_test.go +++ b/internal/cmd/object-storage/bucket/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -136,54 +135,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/bucket/describe/describe_test.go b/internal/cmd/object-storage/bucket/describe/describe_test.go index 9e376132d..df76123d2 100644 --- a/internal/cmd/object-storage/bucket/describe/describe_test.go +++ b/internal/cmd/object-storage/bucket/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -136,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index d0ed623cf..fd0ec0552 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 Object Storage buckets`, "$ stackit object-storage bucket list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/object-storage/bucket/list/list_test.go b/internal/cmd/object-storage/bucket/list/list_test.go index eb50f0ca7..3d70ff50b 100644 --- a/internal/cmd/object-storage/bucket/list/list_test.go +++ b/internal/cmd/object-storage/bucket/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) @@ -64,6 +64,7 @@ func fixtureRequest(mods ...func(request *objectstorage.ApiListBucketsRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -118,48 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index c92f24956..b4f8a850c 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -38,9 +38,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create credentials group to hold Object Storage access credentials`, "$ stackit object-storage credentials-group create --name example"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -80,7 +80,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/object-storage/credentials-group/create/create_test.go b/internal/cmd/object-storage/credentials-group/create/create_test.go index f23487603..23908c876 100644 --- a/internal/cmd/object-storage/credentials-group/create/create_test.go +++ b/internal/cmd/object-storage/credentials-group/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -75,6 +76,7 @@ func fixtureRequest(mods ...func(request *objectstorage.ApiCreateCredentialsGrou func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -122,46 +124,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/credentials-group/delete/delete_test.go b/internal/cmd/object-storage/credentials-group/delete/delete_test.go index a5097a0b7..901fc4304 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete_test.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -142,54 +141,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index adc5531d1..800b0f742 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -44,9 +44,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 credentials groups`, "$ stackit object-storage credentials-group list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -84,7 +84,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/object-storage/credentials-group/list/list_test.go b/internal/cmd/object-storage/credentials-group/list/list_test.go index b0570483b..587e6842a 100644 --- a/internal/cmd/object-storage/credentials-group/list/list_test.go +++ b/internal/cmd/object-storage/credentials-group/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -63,6 +64,7 @@ func fixtureRequest(mods ...func(request *objectstorage.ApiListCredentialsGroups func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -117,46 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index 41fde917c..e7f9fdcfc 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create credentials for a credentials group with ID "xxx", including a specific expiration date`, "$ stackit object-storage credentials create --credentials-group-id xxx --expire-date 2024-03-06T00:00:00.000Z"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -95,7 +95,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/object-storage/credentials/create/create_test.go b/internal/cmd/object-storage/credentials/create/create_test.go index c2efbf566..f3c0bdd60 100644 --- a/internal/cmd/object-storage/credentials/create/create_test.go +++ b/internal/cmd/object-storage/credentials/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -89,6 +90,7 @@ func fixtureRequest(mods ...func(request *objectstorage.ApiCreateAccessKeyReques func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -181,46 +183,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/credentials/delete/delete_test.go b/internal/cmd/object-storage/credentials/delete/delete_test.go index 1ba508df1..d5ff9e4e5 100644 --- a/internal/cmd/object-storage/credentials/delete/delete_test.go +++ b/internal/cmd/object-storage/credentials/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -161,54 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index 3fb8b920d..0ebc5efea 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 credentials for a credentials group with ID "xxx"`, "$ stackit object-storage credentials list --credentials-group-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/object-storage/credentials/list/list_test.go b/internal/cmd/object-storage/credentials/list/list_test.go index 6f6fb41a3..119f7c7c0 100644 --- a/internal/cmd/object-storage/credentials/list/list_test.go +++ b/internal/cmd/object-storage/credentials/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -67,6 +68,7 @@ func fixtureRequest(mods ...func(request *objectstorage.ApiListAccessKeysRequest func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -142,46 +144,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/disable/disable.go b/internal/cmd/object-storage/disable/disable.go index f5cec2175..12a0f16de 100644 --- a/internal/cmd/object-storage/disable/disable.go +++ b/internal/cmd/object-storage/disable/disable.go @@ -32,9 +32,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Disable Object Storage functionality for your project.`, "$ stackit object-storage disable"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -77,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/object-storage/disable/disable_test.go b/internal/cmd/object-storage/disable/disable_test.go index cb65e8961..5b5a2ea7f 100644 --- a/internal/cmd/object-storage/disable/disable_test.go +++ b/internal/cmd/object-storage/disable/disable_test.go @@ -5,12 +5,11 @@ import ( "testing" "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) @@ -60,6 +59,7 @@ func fixtureRequest(mods ...func(request *objectstorage.ApiDisableServiceRequest func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -100,46 +100,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/object-storage/enable/enable.go b/internal/cmd/object-storage/enable/enable.go index fe9fa549e..e6a1ade29 100644 --- a/internal/cmd/object-storage/enable/enable.go +++ b/internal/cmd/object-storage/enable/enable.go @@ -32,9 +32,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Enable Object Storage functionality for your project`, "$ stackit object-storage enable"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -77,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/object-storage/enable/enable_test.go b/internal/cmd/object-storage/enable/enable_test.go index 562bb6907..59e88e9e0 100644 --- a/internal/cmd/object-storage/enable/enable_test.go +++ b/internal/cmd/object-storage/enable/enable_test.go @@ -5,12 +5,11 @@ import ( "testing" "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) @@ -60,6 +59,7 @@ func fixtureRequest(mods ...func(request *objectstorage.ApiEnableServiceRequest) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -100,46 +100,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index 99b185ba2..f9cd2feb4 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -41,9 +41,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create credentials for Observability instance with ID "xxx"`, "$ stackit observability credentials create --instance-id xxx"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/observability/credentials/create/create_test.go b/internal/cmd/observability/credentials/create/create_test.go index 16fcc439d..43ba6f271 100644 --- a/internal/cmd/observability/credentials/create/create_test.go +++ b/internal/cmd/observability/credentials/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/observability" "github.com/google/go-cmp/cmp" @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *observability.ApiCreateCredentialsRequ func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -120,45 +122,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := NewCmd(nil) - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(nil, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go index f0423793e..5e7e7a3ad 100644 --- a/internal/cmd/observability/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List the usernames of up to 10 credentials for an Observability instance`, "$ stackit observability credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/observability/credentials/list/list_test.go b/internal/cmd/observability/credentials/list/list_test.go index 64d92b12f..ceed7952d 100644 --- a/internal/cmd/observability/credentials/list/list_test.go +++ b/internal/cmd/observability/credentials/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *observability.ApiListCredentialsReques func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -137,45 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := NewCmd(nil) - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(nil, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go b/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go index 9dc5019d2..58fdfd098 100644 --- a/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable_test.go @@ -5,9 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -186,54 +185,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go b/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go index 6d1fbea0a..1f3d0fb89 100644 --- a/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable_test.go @@ -5,9 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -186,54 +185,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go index e536ab098..224c73cca 100644 --- a/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable_test.go @@ -5,9 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -186,54 +185,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go index 033227257..f13a2db25 100644 --- a/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable_test.go @@ -5,10 +5,9 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" observabilityUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/observability/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" @@ -186,54 +185,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 7bd73e90a..84e8b1b6b 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -51,9 +51,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create an Observability instance with name "my-instance" and specify plan by ID`, "$ stackit observability instance create --name my-instance --plan-id xxx"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -120,7 +120,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/observability/instance/create/create_test.go b/internal/cmd/observability/instance/create/create_test.go index 6cdeda809..382cbeb0a 100644 --- a/internal/cmd/observability/instance/create/create_test.go +++ b/internal/cmd/observability/instance/create/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -99,6 +100,7 @@ func fixturePlansResponse(mods ...func(response *observability.PlansResponse)) * func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -175,46 +177,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/instance/delete/delete_test.go b/internal/cmd/observability/instance/delete/delete_test.go index d8432900f..5d6bce774 100644 --- a/internal/cmd/observability/instance/delete/delete_test.go +++ b/internal/cmd/observability/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/instance/describe/describe_test.go b/internal/cmd/observability/instance/describe/describe_test.go index 62f60d451..1aa4cc756 100644 --- a/internal/cmd/observability/instance/describe/describe_test.go +++ b/internal/cmd/observability/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index a52ebeb34..ff124b8fb 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 Observability instances`, "$ stackit observability instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/observability/instance/list/list_test.go b/internal/cmd/observability/instance/list/list_test.go index 33157c100..f4c1b20b7 100644 --- a/internal/cmd/observability/instance/list/list_test.go +++ b/internal/cmd/observability/instance/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/observability" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *observability.ApiListInstancesRequest) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,47 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/instance/update/update_test.go b/internal/cmd/observability/instance/update/update_test.go index fd798093c..6a576ce5d 100644 --- a/internal/cmd/observability/instance/update/update_test.go +++ b/internal/cmd/observability/instance/update/update_test.go @@ -5,9 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -240,54 +239,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index 62fc0ac86..322bebb0d 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 Observability service plans`, "$ stackit observability plans --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -93,7 +93,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/observability/plans/plans_test.go b/internal/cmd/observability/plans/plans_test.go index 2228a0402..36026aecf 100644 --- a/internal/cmd/observability/plans/plans_test.go +++ b/internal/cmd/observability/plans/plans_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/observability" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *observability.ApiListPlansRequest)) ob func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go index d11d4b575..43ff12a8f 100644 --- a/internal/cmd/observability/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -60,9 +60,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { ``, `$ stackit observability scrape-config create --payload @./payload.json --instance-id xxx`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -136,7 +136,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/observability/scrape-config/create/create_test.go b/internal/cmd/observability/scrape-config/create/create_test.go index 533bf457b..9d4ab9ba9 100644 --- a/internal/cmd/observability/scrape-config/create/create_test.go +++ b/internal/cmd/observability/scrape-config/create/create_test.go @@ -5,6 +5,8 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -146,6 +148,7 @@ func fixtureRequest(mods ...func(request *observability.ApiCreateScrapeConfigReq func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -230,55 +233,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := NewCmd(nil) - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(nil, cmd) - 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, - cmpopts.EquateComparable(testCtx), - ) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go index 487fa32b3..5476fbd94 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go @@ -60,9 +60,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Generate an Update payload with the values of an existing configuration named "my-config" for Observability instance xxx, and preview it in the terminal`, `$ stackit observability scrape-config generate-payload --job-name my-config --instance-id xxx`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -102,7 +102,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(filePathFlag, "f", "", "If set, writes the payload to the given file. If unset, writes the payload to the standard output") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) jobName := flags.FlagToStringPointer(p, cmd, jobNameFlag) diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go index e9a3a076b..07be71444 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -69,6 +71,7 @@ func fixtureRequest(mods ...func(request *observability.ApiGetScrapeConfigReques func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -171,53 +174,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := NewCmd(nil) - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(nil, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/observability/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go index 998613343..1002a87d8 100644 --- a/internal/cmd/observability/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 scrape configurations of Observability instance "xxx"`, "$ stackit observability scrape-config list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -100,7 +100,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/observability/scrape-config/list/list_test.go b/internal/cmd/observability/scrape-config/list/list_test.go index 35e53001b..371944178 100644 --- a/internal/cmd/observability/scrape-config/list/list_test.go +++ b/internal/cmd/observability/scrape-config/list/list_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -12,7 +14,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/observability" ) @@ -63,6 +64,7 @@ func fixtureRequest(mods ...func(request *observability.ApiListScrapeConfigsRequ func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -138,47 +140,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(nil, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index 9600ea189..c74347c51 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -43,9 +43,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create credentials for an OpenSearch instance and show the password in the output`, "$ stackit opensearch credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/opensearch/credentials/create/create_test.go b/internal/cmd/opensearch/credentials/create/create_test.go index 6928feefc..8943eede7 100644 --- a/internal/cmd/opensearch/credentials/create/create_test.go +++ b/internal/cmd/opensearch/credentials/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *opensearch.ApiCreateCredentialsRequest func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -130,46 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/credentials/delete/delete_test.go b/internal/cmd/opensearch/credentials/delete/delete_test.go index 350175fd2..53b987e9f 100644 --- a/internal/cmd/opensearch/credentials/delete/delete_test.go +++ b/internal/cmd/opensearch/credentials/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/credentials/describe/describe_test.go b/internal/cmd/opensearch/credentials/describe/describe_test.go index 50ce776b5..c1c2f3b2d 100644 --- a/internal/cmd/opensearch/credentials/describe/describe_test.go +++ b/internal/cmd/opensearch/credentials/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index 40efab492..2e5451ec2 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 credentials' IDs for an OpenSearch instance`, "$ stackit opensearch credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/opensearch/credentials/list/list_test.go b/internal/cmd/opensearch/credentials/list/list_test.go index bfe0ea554..8375506e1 100644 --- a/internal/cmd/opensearch/credentials/list/list_test.go +++ b/internal/cmd/opensearch/credentials/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *opensearch.ApiListCredentialsRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -137,46 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index e9dd330bd..826c6990f 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -73,9 +73,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create an OpenSearch instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit opensearch instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -151,7 +151,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/opensearch/instance/create/create_test.go b/internal/cmd/opensearch/instance/create/create_test.go index e6028b4d9..fe8afe7d3 100644 --- a/internal/cmd/opensearch/instance/create/create_test.go +++ b/internal/cmd/opensearch/instance/create/create_test.go @@ -5,6 +5,8 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -111,6 +113,7 @@ func fixtureRequest(mods ...func(request *opensearch.ApiCreateInstanceRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string sgwAclValues []string pluginValues []string @@ -277,76 +280,11 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.sgwAclValues { - err := cmd.Flags().Set(sgwAclFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", sgwAclFlag, value, err) - } - } - - for _, value := range tt.pluginValues { - err := cmd.Flags().Set(pluginFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", pluginFlag, value, err) - } - } - - for _, value := range tt.syslogValues { - err := cmd.Flags().Set(syslogFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", syslogFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + sgwAclFlag: tt.sgwAclValues, + pluginFlag: tt.pluginValues, + syslogFlag: tt.syslogValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/instance/delete/delete_test.go b/internal/cmd/opensearch/instance/delete/delete_test.go index 217ff1b1d..c6ab9693d 100644 --- a/internal/cmd/opensearch/instance/delete/delete_test.go +++ b/internal/cmd/opensearch/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/instance/describe/describe_test.go b/internal/cmd/opensearch/instance/describe/describe_test.go index 6e17a8e85..8ae93fa8f 100644 --- a/internal/cmd/opensearch/instance/describe/describe_test.go +++ b/internal/cmd/opensearch/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index d53244f04..03e18c79d 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 OpenSearch instances`, "$ stackit opensearch instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/opensearch/instance/list/list_test.go b/internal/cmd/opensearch/instance/list/list_test.go index 766115689..86ac78970 100644 --- a/internal/cmd/opensearch/instance/list/list_test.go +++ b/internal/cmd/opensearch/instance/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *opensearch.ApiListInstancesRequest)) o func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index e8d8c4983..45a026ab9 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 OpenSearch service plans`, "$ stackit opensearch plans --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/opensearch/plans/plans_test.go b/internal/cmd/opensearch/plans/plans_test.go index 0b4f95cec..4cafef6ba 100644 --- a/internal/cmd/opensearch/plans/plans_test.go +++ b/internal/cmd/opensearch/plans/plans_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *opensearch.ApiListOfferingsRequest)) o func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/organization/member/add/add_test.go b/internal/cmd/organization/member/add/add_test.go index a98f06ecc..dfe3300f0 100644 --- a/internal/cmd/organization/member/add/add_test.go +++ b/internal/cmd/organization/member/add/add_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -125,54 +124,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index 3102c987c..d4989bc76 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -54,9 +54,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 members of an organization`, "$ stackit organization member list --organization-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -103,7 +103,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) diff --git a/internal/cmd/organization/member/list/list_test.go b/internal/cmd/organization/member/list/list_test.go index ff90898b2..37f13746b 100644 --- a/internal/cmd/organization/member/list/list_test.go +++ b/internal/cmd/organization/member/list/list_test.go @@ -7,11 +7,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -56,6 +56,7 @@ func fixtureRequest(mods ...func(request *authorization.ApiListMembersRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -125,48 +126,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/organization/member/remove/remove_test.go b/internal/cmd/organization/member/remove/remove_test.go index 1b2a3e702..81f1a368c 100644 --- a/internal/cmd/organization/member/remove/remove_test.go +++ b/internal/cmd/organization/member/remove/remove_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index 9f1523543..9603d0212 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 roles and permissions of an organization`, "$ stackit organization role list --organization-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -94,7 +94,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) diff --git a/internal/cmd/organization/role/list/list_test.go b/internal/cmd/organization/role/list/list_test.go index 5633b3f60..7e2dcb518 100644 --- a/internal/cmd/organization/role/list/list_test.go +++ b/internal/cmd/organization/role/list/list_test.go @@ -7,11 +7,11 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -55,6 +55,7 @@ func fixtureRequest(mods ...func(request *authorization.ApiListRolesRequest)) au func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -95,48 +96,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index f365261a9..cfd5718d5 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -54,9 +54,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit postgresflex backup list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -106,7 +106,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/postgresflex/backup/list/list_test.go b/internal/cmd/postgresflex/backup/list/list_test.go index 9dee772fe..4ac63c37c 100644 --- a/internal/cmd/postgresflex/backup/list/list_test.go +++ b/internal/cmd/postgresflex/backup/list/list_test.go @@ -5,6 +5,8 @@ import ( "testing" "time" + "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" @@ -63,6 +65,7 @@ func fixtureRequest(mods ...func(request *postgresflex.ApiListBackupsRequest)) p func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -138,45 +141,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := NewCmd(nil) - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(nil, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go index 376b04bae..9d8bf59fc 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go @@ -41,10 +41,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit postgresflex backup update-schedule --instance-id xxx --schedule '6 6 * * *'"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule_test.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule_test.go index 446f96226..18ed95ae6 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule_test.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" @@ -73,6 +74,7 @@ func fixtureRequest(mods ...func(request *postgresflex.ApiUpdateBackupScheduleRe func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -142,45 +144,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := NewCmd(nil) - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(nil, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/instance/clone/clone_test.go b/internal/cmd/postgresflex/instance/clone/clone_test.go index 04dbd1954..5f2a60189 100644 --- a/internal/cmd/postgresflex/instance/clone/clone_test.go +++ b/internal/cmd/postgresflex/instance/clone/clone_test.go @@ -12,6 +12,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -302,54 +303,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 3af623ca5..1e3172a3b 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -73,10 +73,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a PostgreSQL Flex instance with name "my-instance", allow access to a specific range of IP addresses, specify flavor by CPU and RAM and set storage size to 20 GB. Other parameters are set to default values`, `$ stackit postgresflex instance create --name my-instance --cpu 2 --ram 4 --acl 1.2.3.0/24 --storage-size 20`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -157,7 +157,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/postgresflex/instance/create/create_test.go b/internal/cmd/postgresflex/instance/create/create_test.go index 32d63d5d8..09b6b2311 100644 --- a/internal/cmd/postgresflex/instance/create/create_test.go +++ b/internal/cmd/postgresflex/instance/create/create_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -124,6 +125,7 @@ func fixturePayload(mods ...func(payload *postgresflex.CreateInstancePayload)) p func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -250,56 +252,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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) }) } } diff --git a/internal/cmd/postgresflex/instance/delete/delete_test.go b/internal/cmd/postgresflex/instance/delete/delete_test.go index 13f33bfbd..fdbe26f4c 100644 --- a/internal/cmd/postgresflex/instance/delete/delete_test.go +++ b/internal/cmd/postgresflex/instance/delete/delete_test.go @@ -5,9 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -171,54 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/instance/describe/describe_test.go b/internal/cmd/postgresflex/instance/describe/describe_test.go index 69e100822..9331b81d4 100644 --- a/internal/cmd/postgresflex/instance/describe/describe_test.go +++ b/internal/cmd/postgresflex/instance/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/postgresflex" ) @@ -138,54 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index f7115f502..148a31d46 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 PostgreSQL Flex instances`, "$ stackit postgresflex instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -94,7 +94,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/postgresflex/instance/list/list_test.go b/internal/cmd/postgresflex/instance/list/list_test.go index 3cfc85652..c8c2d8a7a 100644 --- a/internal/cmd/postgresflex/instance/list/list_test.go +++ b/internal/cmd/postgresflex/instance/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *postgresflex.ApiListInstancesRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index 0e0581c3f..d5afbbbf5 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -63,9 +63,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List PostgreSQL Flex storage options for a given flavor. The flavor ID can be retrieved by running "$ stackit postgresflex options --flavors"`, "$ stackit postgresflex options --storages --flavor-id "), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -96,7 +96,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(flavorIdFlag, "", `The flavor ID to show storages for. Only relevant when "--storages" is passed`) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/postgresflex/options/options_test.go b/internal/cmd/postgresflex/options/options_test.go index 54df1ccf9..4f7f5c67f 100644 --- a/internal/cmd/postgresflex/options/options_test.go +++ b/internal/cmd/postgresflex/options/options_test.go @@ -5,11 +5,11 @@ import ( "fmt" "testing" - "github.com/google/go-cmp/cmp" "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -113,6 +113,7 @@ func fixtureInputModelAllTrue(mods ...func(model *inputModel)) *inputModel { func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -175,46 +176,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index f7cc55a35..73682a34a 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -55,9 +55,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit postgresflex user create --instance-id xxx --username johndoe --role createdb"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -108,7 +108,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/postgresflex/user/create/create_test.go b/internal/cmd/postgresflex/user/create/create_test.go index e75d785e9..bbd08e214 100644 --- a/internal/cmd/postgresflex/user/create/create_test.go +++ b/internal/cmd/postgresflex/user/create/create_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -70,6 +70,7 @@ func fixtureRequest(mods ...func(request *postgresflex.ApiCreateUserRequest)) po func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -149,48 +150,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/user/delete/delete_test.go b/internal/cmd/postgresflex/user/delete/delete_test.go index 867635736..a3ff66105 100644 --- a/internal/cmd/postgresflex/user/delete/delete_test.go +++ b/internal/cmd/postgresflex/user/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -160,54 +159,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/user/describe/describe_test.go b/internal/cmd/postgresflex/user/describe/describe_test.go index 8b91301b7..ad6a2377f 100644 --- a/internal/cmd/postgresflex/user/describe/describe_test.go +++ b/internal/cmd/postgresflex/user/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/postgresflex" ) @@ -159,54 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index d62bfd1ed..420619f46 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit postgresflex user list --instance-id xxx --limit 10"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -99,7 +99,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/postgresflex/user/list/list_test.go b/internal/cmd/postgresflex/user/list/list_test.go index 20adc9e13..8985f945f 100644 --- a/internal/cmd/postgresflex/user/list/list_test.go +++ b/internal/cmd/postgresflex/user/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -63,6 +63,7 @@ func fixtureRequest(mods ...func(request *postgresflex.ApiListUsersRequest)) pos func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -131,48 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go index b12c31d3a..51572b406 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/postgresflex" ) @@ -159,54 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/postgresflex/user/update/update_test.go b/internal/cmd/postgresflex/user/update/update_test.go index 787dc992d..c20ded9b7 100644 --- a/internal/cmd/postgresflex/user/update/update_test.go +++ b/internal/cmd/postgresflex/user/update/update_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -169,54 +168,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index 5fcd2bec3..c70e58e92 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -63,9 +63,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a STACKIT project with a network area`, "$ stackit project create --parent-id xxxx --name my-project --network-area-id yyyy"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -111,7 +111,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) labels := flags.FlagToStringToStringPointer(p, cmd, labelFlag) diff --git a/internal/cmd/project/create/create_test.go b/internal/cmd/project/create/create_test.go index f6cf9fbde..3503b0b68 100644 --- a/internal/cmd/project/create/create_test.go +++ b/internal/cmd/project/create/create_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "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" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" "github.com/zalando/go-keyring" @@ -86,6 +87,7 @@ func fixtureRequest(mods ...func(request *resourcemanager.ApiCreateProjectReques func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string labelValues []string isValid bool @@ -177,56 +179,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.labelValues { - err := cmd.Flags().Set(labelFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", labelFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + labelFlag: tt.labelValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/project/delete/delete.go b/internal/cmd/project/delete/delete.go index ce572bfc5..eff9d2615 100644 --- a/internal/cmd/project/delete/delete.go +++ b/internal/cmd/project/delete/delete.go @@ -35,9 +35,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Delete a STACKIT project by explicitly providing the project ID`, "$ stackit project delete --project-id xxx"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -80,7 +80,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/project/delete/delete_test.go b/internal/cmd/project/delete/delete_test.go index b53ede53d..f14e83869 100644 --- a/internal/cmd/project/delete/delete_test.go +++ b/internal/cmd/project/delete/delete_test.go @@ -5,12 +5,11 @@ import ( "testing" "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" ) @@ -55,6 +54,7 @@ func fixtureRequest(mods ...func(request *resourcemanager.ApiDeleteProjectReques func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -74,46 +74,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/project/describe/describe_test.go b/internal/cmd/project/describe/describe_test.go index f32dbc491..2afd90610 100644 --- a/internal/cmd/project/describe/describe_test.go +++ b/internal/cmd/project/describe/describe_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" ) @@ -137,54 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 8b459dd4c..fe7f8503a 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -62,9 +62,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all STACKIT projects that a certain user is a member of`, "$ stackit project list --member example@email.com"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -101,7 +101,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(pageSizeFlag, pageSizeDefault, "Number of items fetched in each API call. Does not affect the number of items in the command output") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) creationTimeAfter, err := flags.FlagToDateTimePointer(p, cmd, creationTimeAfterFlag, creationTimeAfterFormat) diff --git a/internal/cmd/project/list/list_test.go b/internal/cmd/project/list/list_test.go index 6d187a9bc..baf7fed6d 100644 --- a/internal/cmd/project/list/list_test.go +++ b/internal/cmd/project/list/list_test.go @@ -9,6 +9,8 @@ import ( "testing" "time" + "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" @@ -81,6 +83,7 @@ func fixtureRequest(mods ...func(request *resourcemanager.ApiListProjectsRequest func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string projectIdLikevalues *[]string isValid bool @@ -194,66 +197,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - if tt.projectIdLikevalues != nil { - for _, value := range *tt.projectIdLikevalues { - err := cmd.Flags().Set(projectIdLikeFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", projectIdLikeFlag, value, err) - } - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating one of required flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + projectIdLikeFlag: utils.GetSliceFromPointer(tt.projectIdLikevalues), + }, tt.isValid) }) } } diff --git a/internal/cmd/project/member/add/add_test.go b/internal/cmd/project/member/add/add_test.go index 9d24461bf..fa8cb5f04 100644 --- a/internal/cmd/project/member/add/add_test.go +++ b/internal/cmd/project/member/add/add_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -124,54 +123,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index 675ddcd22..04d141e3b 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -53,9 +53,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 members of a project`, "$ stackit project member list --project-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -103,7 +103,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Var(flags.EnumFlag(false, "subject", sortByFlagOptions...), sortByFlag, fmt.Sprintf("Sort entries by a specific field, one of %q", sortByFlagOptions)) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/project/member/list/list_test.go b/internal/cmd/project/member/list/list_test.go index a710f7b5d..14167c407 100644 --- a/internal/cmd/project/member/list/list_test.go +++ b/internal/cmd/project/member/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *authorization.ApiListMembersRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -129,48 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/project/member/remove/remove_test.go b/internal/cmd/project/member/remove/remove_test.go index c3cb414e1..d0fc6d8f0 100644 --- a/internal/cmd/project/member/remove/remove_test.go +++ b/internal/cmd/project/member/remove/remove_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -137,54 +136,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index e4dadb288..a2d65e21d 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 roles and permissions of a project`, "$ stackit project role list --project-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -94,7 +94,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/project/role/list/list_test.go b/internal/cmd/project/role/list/list_test.go index b1f14f432..66f51f7df 100644 --- a/internal/cmd/project/role/list/list_test.go +++ b/internal/cmd/project/role/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) @@ -59,6 +59,7 @@ func fixtureRequest(mods ...func(request *authorization.ApiListRolesRequest)) au func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -99,48 +100,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/project/update/update.go b/internal/cmd/project/update/update.go index d8ad38c71..7523ff5e1 100644 --- a/internal/cmd/project/update/update.go +++ b/internal/cmd/project/update/update.go @@ -54,9 +54,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Update the name of a STACKIT project by explicitly providing the project ID`, "$ stackit project update --name my-updated-project --project-id xxx"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -102,7 +102,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a project. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/project/update/update_test.go b/internal/cmd/project/update/update_test.go index 289a3b752..a2f70d560 100644 --- a/internal/cmd/project/update/update_test.go +++ b/internal/cmd/project/update/update_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -66,6 +65,7 @@ func fixtureRequest(mods ...func(request *resourcemanager.ApiPartialUpdateProjec func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string labelValues []string isValid bool @@ -131,56 +131,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.labelValues { - err := cmd.Flags().Set(labelFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", labelFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + labelFlag: tt.labelValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index 831d6eb46..1929e81e6 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit public-ip create --associated-resource-id xxx --labels key=value,foo=bar`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -97,7 +97,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a public IP. E.g. '--labels key1=value1,key2=value2,...'") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/public-ip/create/create_test.go b/internal/cmd/public-ip/create/create_test.go index be2653938..5e946f386 100644 --- a/internal/cmd/public-ip/create/create_test.go +++ b/internal/cmd/public-ip/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -79,6 +80,7 @@ func fixturePayload(mods ...func(payload *iaas.CreatePublicIPPayload)) iaas.Crea func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -142,46 +144,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/public-ip/delete/delete_test.go b/internal/cmd/public-ip/delete/delete_test.go index 667578fb0..115c9d2e7 100644 --- a/internal/cmd/public-ip/delete/delete_test.go +++ b/internal/cmd/public-ip/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/public-ip/describe/describe_test.go b/internal/cmd/public-ip/describe/describe_test.go index f69ba8dbb..05ceefe6e 100644 --- a/internal/cmd/public-ip/describe/describe_test.go +++ b/internal/cmd/public-ip/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/public-ip/list/list.go b/internal/cmd/public-ip/list/list.go index c282f26bb..4501c1cab 100644 --- a/internal/cmd/public-ip/list/list.go +++ b/internal/cmd/public-ip/list/list.go @@ -55,9 +55,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit public-ip list --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -105,7 +105,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter by label") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/public-ip/list/list_test.go b/internal/cmd/public-ip/list/list_test.go index a6fe99a48..1d6f7b20d 100644 --- a/internal/cmd/public-ip/list/list_test.go +++ b/internal/cmd/public-ip/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -63,6 +64,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListPublicIPsRequest)) iaas.Ap func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -132,46 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/public-ip/ranges/list/list.go b/internal/cmd/public-ip/ranges/list/list.go index e959d39f4..7188146f6 100644 --- a/internal/cmd/public-ip/ranges/list/list.go +++ b/internal/cmd/public-ip/ranges/list/list.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit public-ip ranges list --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -84,7 +84,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) diff --git a/internal/cmd/public-ip/ranges/list/list_test.go b/internal/cmd/public-ip/ranges/list/list_test.go index f9aa0d6be..20af8f19f 100644 --- a/internal/cmd/public-ip/ranges/list/list_test.go +++ b/internal/cmd/public-ip/ranges/list/list_test.go @@ -3,7 +3,8 @@ package list import ( "testing" - "github.com/google/go-cmp/cmp" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -16,13 +17,14 @@ func TestParseInput(t *testing.T) { projectId := uuid.New().String() tests := []struct { description string - globalFlags map[string]string + argValues []string + flagValues map[string]string expectedModel *inputModel isValid bool }{ { description: "valid project id", - globalFlags: map[string]string{ + flagValues: map[string]string{ "project-id": projectId, }, expectedModel: &inputModel{ @@ -35,7 +37,7 @@ func TestParseInput(t *testing.T) { }, { description: "missing project id does not lead into error", - globalFlags: map[string]string{}, + flagValues: map[string]string{}, expectedModel: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.InfoVerbosity, @@ -45,7 +47,7 @@ func TestParseInput(t *testing.T) { }, { description: "valid input with limit", - globalFlags: map[string]string{ + flagValues: map[string]string{ "limit": "10", }, expectedModel: &inputModel{ @@ -58,7 +60,7 @@ func TestParseInput(t *testing.T) { }, { description: "valid input without limit", - globalFlags: map[string]string{}, + flagValues: map[string]string{}, expectedModel: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.InfoVerbosity, @@ -68,7 +70,7 @@ func TestParseInput(t *testing.T) { }, { description: "invalid limit (zero)", - globalFlags: map[string]string{ + flagValues: map[string]string{ "limit": "0", }, expectedModel: nil, @@ -76,7 +78,7 @@ func TestParseInput(t *testing.T) { }, { description: "invalid limit (negative)", - globalFlags: map[string]string{ + flagValues: map[string]string{ "limit": "-1", }, expectedModel: nil, @@ -86,29 +88,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatal(err) - } - - for flag, value := range tt.globalFlags { - if err := cmd.Flags().Set(flag, value); err != nil { - t.Fatalf("Failed to set global flag %s: %v", flag, err) - } - } - - model, err := parseInput(p, cmd) - if !tt.isValid && err == nil { - t.Fatalf("parseInput() error = %v, wantErr %v", err, !tt.isValid) - } - - if tt.isValid { - if diff := cmp.Diff(model, tt.expectedModel); diff != "" { - t.Fatalf("Model mismatch (-want +got):\n%s", diff) - } - } + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/quota/list/list.go b/internal/cmd/quota/list/list.go index 89cb8b90c..84835b555 100644 --- a/internal/cmd/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -34,9 +34,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit quota list`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/quota/list/list_test.go b/internal/cmd/quota/list/list_test.go index ab2cdd8ea..973f28abb 100644 --- a/internal/cmd/quota/list/list_test.go +++ b/internal/cmd/quota/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -55,6 +56,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListQuotasRequest)) iaas.ApiLi func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -95,44 +97,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index f4d4830e0..9f22b594a 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -43,9 +43,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create credentials for a RabbitMQ instance and show the password in the output`, "$ stackit rabbitmq credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/rabbitmq/credentials/create/create_test.go b/internal/cmd/rabbitmq/credentials/create/create_test.go index 84e65eaa0..b4f28de99 100644 --- a/internal/cmd/rabbitmq/credentials/create/create_test.go +++ b/internal/cmd/rabbitmq/credentials/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/rabbitmq" ) @@ -58,6 +59,7 @@ func fixtureRequest(mods ...func(request *rabbitmq.ApiCreateCredentialsRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -129,46 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/credentials/delete/delete_test.go b/internal/cmd/rabbitmq/credentials/delete/delete_test.go index e716f7c72..6d6a46340 100644 --- a/internal/cmd/rabbitmq/credentials/delete/delete_test.go +++ b/internal/cmd/rabbitmq/credentials/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/credentials/describe/describe_test.go b/internal/cmd/rabbitmq/credentials/describe/describe_test.go index a40cd610d..15bf51687 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe_test.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/rabbitmq" ) @@ -164,54 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index 4b638c13c..efa8fc187 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 credentials' IDs for a RabbitMQ instance`, "$ stackit rabbitmq credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -96,7 +96,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/rabbitmq/credentials/list/list_test.go b/internal/cmd/rabbitmq/credentials/list/list_test.go index 77f7f2f5e..ed752b64d 100644 --- a/internal/cmd/rabbitmq/credentials/list/list_test.go +++ b/internal/cmd/rabbitmq/credentials/list/list_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -61,6 +62,7 @@ func fixtureRequest(mods ...func(request *rabbitmq.ApiListCredentialsRequest)) r func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -136,46 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index b20674c33..143264140 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -73,9 +73,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a RabbitMQ instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit rabbitmq instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -151,7 +151,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/rabbitmq/instance/create/create_test.go b/internal/cmd/rabbitmq/instance/create/create_test.go index aa39a62e8..a1b4585c4 100644 --- a/internal/cmd/rabbitmq/instance/create/create_test.go +++ b/internal/cmd/rabbitmq/instance/create/create_test.go @@ -5,6 +5,8 @@ import ( "fmt" "testing" + "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" @@ -110,6 +112,7 @@ func fixtureRequest(mods ...func(request *rabbitmq.ApiCreateInstanceRequest)) ra func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string sgwAclValues []string pluginValues []string @@ -276,76 +279,11 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.sgwAclValues { - err := cmd.Flags().Set(sgwAclFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", sgwAclFlag, value, err) - } - } - - for _, value := range tt.pluginValues { - err := cmd.Flags().Set(pluginFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", pluginFlag, value, err) - } - } - - for _, value := range tt.syslogValues { - err := cmd.Flags().Set(syslogFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", syslogFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + sgwAclFlag: tt.sgwAclValues, + syslogFlag: tt.syslogValues, + pluginFlag: tt.pluginValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/instance/delete/delete_test.go b/internal/cmd/rabbitmq/instance/delete/delete_test.go index 8064098ad..24fbaeac9 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete_test.go +++ b/internal/cmd/rabbitmq/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/instance/describe/describe_test.go b/internal/cmd/rabbitmq/instance/describe/describe_test.go index 8fe1f8288..620119e9b 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe_test.go +++ b/internal/cmd/rabbitmq/instance/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/rabbitmq" ) @@ -137,54 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index 53a62a067..61bc42e5b 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 RabbitMQ instances`, "$ stackit rabbitmq instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/rabbitmq/instance/list/list_test.go b/internal/cmd/rabbitmq/instance/list/list_test.go index bbfefdfff..6160eb6cc 100644 --- a/internal/cmd/rabbitmq/instance/list/list_test.go +++ b/internal/cmd/rabbitmq/instance/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -59,6 +59,7 @@ func fixtureRequest(mods ...func(request *rabbitmq.ApiListInstancesRequest)) rab func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -113,48 +114,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index 1114a9fc1..09f0220ab 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 RabbitMQ service plans`, "$ stackit rabbitmq plans --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -93,7 +93,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/rabbitmq/plans/plans_test.go b/internal/cmd/rabbitmq/plans/plans_test.go index d5f0f9aee..2089d4414 100644 --- a/internal/cmd/rabbitmq/plans/plans_test.go +++ b/internal/cmd/rabbitmq/plans/plans_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) @@ -59,6 +59,7 @@ func fixtureRequest(mods ...func(request *rabbitmq.ApiListOfferingsRequest)) rab func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -113,48 +114,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index 5b2d313b4..2b8e011da 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -44,9 +44,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create credentials for a Redis instance and show the password in the output`, "$ stackit redis credentials create --instance-id xxx --show-password"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -93,7 +93,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/redis/credentials/create/create_test.go b/internal/cmd/redis/credentials/create/create_test.go index 070229478..fc968ce32 100644 --- a/internal/cmd/redis/credentials/create/create_test.go +++ b/internal/cmd/redis/credentials/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/redis" ) @@ -58,6 +59,7 @@ func fixtureRequest(mods ...func(request *redis.ApiCreateCredentialsRequest)) re func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -129,46 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/redis/credentials/delete/delete_test.go b/internal/cmd/redis/credentials/delete/delete_test.go index d8b2c4632..08960a15d 100644 --- a/internal/cmd/redis/credentials/delete/delete_test.go +++ b/internal/cmd/redis/credentials/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/redis/credentials/describe/describe_test.go b/internal/cmd/redis/credentials/describe/describe_test.go index fc8edb1b8..b98c36631 100644 --- a/internal/cmd/redis/credentials/describe/describe_test.go +++ b/internal/cmd/redis/credentials/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/redis" ) @@ -164,54 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index 08f4bf88b..8f2dc6945 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 credentials' IDs for a Redis instance`, "$ stackit redis credentials list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -96,7 +96,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/redis/credentials/list/list_test.go b/internal/cmd/redis/credentials/list/list_test.go index a6c29f283..cd986c587 100644 --- a/internal/cmd/redis/credentials/list/list_test.go +++ b/internal/cmd/redis/credentials/list/list_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -61,6 +62,7 @@ func fixtureRequest(mods ...func(request *redis.ApiListCredentialsRequest)) redi func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -136,46 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index 6e694b135..d5a410d35 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -71,9 +71,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a Redis instance with name "my-instance" and specify IP range which is allowed to access it`, "$ stackit redis instance create --name my-instance --plan-id xxx --acl 1.2.3.0/24"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -148,7 +148,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/redis/instance/create/create_test.go b/internal/cmd/redis/instance/create/create_test.go index 814673259..6316e50b6 100644 --- a/internal/cmd/redis/instance/create/create_test.go +++ b/internal/cmd/redis/instance/create/create_test.go @@ -11,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -107,6 +108,7 @@ func fixtureRequest(mods ...func(request *redis.ApiCreateInstanceRequest)) redis func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string sgwAclValues []string syslogValues []string @@ -261,66 +263,10 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.sgwAclValues { - err := cmd.Flags().Set(sgwAclFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", sgwAclFlag, value, err) - } - } - - for _, value := range tt.syslogValues { - err := cmd.Flags().Set(syslogFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", syslogFlag, value, err) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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{ + sgwAclFlag: tt.sgwAclValues, + syslogFlag: tt.syslogValues, + }, tt.isValid) }) } } diff --git a/internal/cmd/redis/instance/delete/delete_test.go b/internal/cmd/redis/instance/delete/delete_test.go index bb0da281f..6372daa5b 100644 --- a/internal/cmd/redis/instance/delete/delete_test.go +++ b/internal/cmd/redis/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/redis/instance/describe/describe_test.go b/internal/cmd/redis/instance/describe/describe_test.go index 651164b98..9c1bf4e39 100644 --- a/internal/cmd/redis/instance/describe/describe_test.go +++ b/internal/cmd/redis/instance/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/redis" ) @@ -137,54 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index 6f98a00f1..571004f47 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 Redis instances`, "$ stackit redis instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -91,7 +91,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/redis/instance/list/list_test.go b/internal/cmd/redis/instance/list/list_test.go index f35a6eddd..fea12c21f 100644 --- a/internal/cmd/redis/instance/list/list_test.go +++ b/internal/cmd/redis/instance/list/list_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -59,6 +59,7 @@ func fixtureRequest(mods ...func(request *redis.ApiListInstancesRequest)) redis. func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -113,48 +114,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 1fda160e4..83125b63a 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 Redis service plans`, "$ stackit redis plans --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/redis/plans/plans_test.go b/internal/cmd/redis/plans/plans_test.go index 8ea65f786..919b8d01f 100644 --- a/internal/cmd/redis/plans/plans_test.go +++ b/internal/cmd/redis/plans/plans_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) @@ -59,6 +59,7 @@ func fixtureRequest(mods ...func(request *redis.ApiListOfferingsRequest)) redis. func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -113,48 +114,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index d22f30292..8f5401d9a 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -45,10 +45,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a Secrets Manager instance with name "my-instance" and specify IP range which is allowed to access it`, `$ stackit secrets-manager instance create --name my-instance --acl 1.2.3.0/24`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -108,7 +108,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/secrets-manager/instance/create/create_test.go b/internal/cmd/secrets-manager/instance/create/create_test.go index 02a895c01..641767b53 100644 --- a/internal/cmd/secrets-manager/instance/create/create_test.go +++ b/internal/cmd/secrets-manager/instance/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/secretsmanager" ) @@ -77,6 +78,7 @@ func fixtureUpdateACLsRequest(mods ...func(request *secretsmanager.ApiUpdateACLs func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -184,56 +186,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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) }) } } diff --git a/internal/cmd/secrets-manager/instance/delete/delete_test.go b/internal/cmd/secrets-manager/instance/delete/delete_test.go index fe6eae032..6a1909548 100644 --- a/internal/cmd/secrets-manager/instance/delete/delete_test.go +++ b/internal/cmd/secrets-manager/instance/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/secrets-manager/instance/describe/describe_test.go b/internal/cmd/secrets-manager/instance/describe/describe_test.go index 2cadb3be2..25ee15d66 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe_test.go +++ b/internal/cmd/secrets-manager/instance/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -146,54 +147,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index 82576c398..9cd6b24ad 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -45,9 +45,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 Secrets Manager instances`, "$ stackit secrets-manager instance list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -93,7 +93,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/secrets-manager/instance/list/list_test.go b/internal/cmd/secrets-manager/instance/list/list_test.go index 6ea677137..2b416584d 100644 --- a/internal/cmd/secrets-manager/instance/list/list_test.go +++ b/internal/cmd/secrets-manager/instance/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/secretsmanager" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *secretsmanager.ApiListInstancesRequest func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -124,48 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 7d9f6d3f7..153bb5035 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -51,9 +51,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit secrets-manager user create --instance-id xxx --write"), ), Args: args.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -102,7 +102,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/secrets-manager/user/create/create_test.go b/internal/cmd/secrets-manager/user/create/create_test.go index a64b826ba..bbc606f1e 100644 --- a/internal/cmd/secrets-manager/user/create/create_test.go +++ b/internal/cmd/secrets-manager/user/create/create_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/secretsmanager" ) @@ -70,6 +70,7 @@ func fixtureRequest(mods ...func(request *secretsmanager.ApiCreateUserRequest)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -153,48 +154,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/secrets-manager/user/delete/delete_test.go b/internal/cmd/secrets-manager/user/delete/delete_test.go index 0827ebf88..8b66aa96a 100644 --- a/internal/cmd/secrets-manager/user/delete/delete_test.go +++ b/internal/cmd/secrets-manager/user/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -153,54 +152,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/secrets-manager/user/describe/describe_test.go b/internal/cmd/secrets-manager/user/describe/describe_test.go index 53c14c586..f65790dfe 100644 --- a/internal/cmd/secrets-manager/user/describe/describe_test.go +++ b/internal/cmd/secrets-manager/user/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -165,54 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index 1c76d15fc..249b0cee5 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 Secrets Manager users with ID "xxx"`, "$ stackit secrets-manager user list --instance-id xxx --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -99,7 +99,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/secrets-manager/user/list/list_test.go b/internal/cmd/secrets-manager/user/list/list_test.go index d2de82297..cd395dc64 100644 --- a/internal/cmd/secrets-manager/user/list/list_test.go +++ b/internal/cmd/secrets-manager/user/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/secretsmanager" ) @@ -63,6 +63,7 @@ func fixtureRequest(mods ...func(request *secretsmanager.ApiListUsersRequest)) s func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -131,48 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index d54b797f3..9598ef794 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -42,9 +42,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { examples.NewExample(`Create a named group`, `$ stackit security-group create --name my-new-group`), examples.NewExample(`Create a named group with labels`, `$ stackit security-group create --name my-new-group --labels label1=value1,label2=value2`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -94,7 +94,7 @@ func configureFlags(cmd *cobra.Command) { } } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/security-group/create/create_test.go b/internal/cmd/security-group/create/create_test.go index 7b9cbd21e..3f936f5ab 100644 --- a/internal/cmd/security-group/create/create_test.go +++ b/internal/cmd/security-group/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -89,6 +90,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateSecurityGroupRequest)) i func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -168,44 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/security-group/delete/delete_test.go b/internal/cmd/security-group/delete/delete_test.go index ec7143cbf..5a4787576 100644 --- a/internal/cmd/security-group/delete/delete_test.go +++ b/internal/cmd/security-group/delete/delete_test.go @@ -57,6 +57,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiDeleteSecurityGroupRequest)) i func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string args []string isValid bool diff --git a/internal/cmd/security-group/describe/describe_test.go b/internal/cmd/security-group/describe/describe_test.go index f9b5f7fba..62bf425be 100644 --- a/internal/cmd/security-group/describe/describe_test.go +++ b/internal/cmd/security-group/describe/describe_test.go @@ -56,6 +56,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiGetSecurityGroupRequest)) iaas func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool args []string diff --git a/internal/cmd/security-group/list/list.go b/internal/cmd/security-group/list/list.go index 9fe33d546..ae9ecdd10 100644 --- a/internal/cmd/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -39,9 +39,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { examples.NewExample(`List all groups`, `$ stackit security-group list`), examples.NewExample(`List groups with labels`, `$ stackit security-group list --label-selector label1=value1,label2=value2`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -86,7 +86,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter by label") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/security-group/list/list_test.go b/internal/cmd/security-group/list/list_test.go index bade91812..806ab98e3 100644 --- a/internal/cmd/security-group/list/list_test.go +++ b/internal/cmd/security-group/list/list_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListSecurityGroupsRequest)) ia func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -119,44 +121,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) - if err := globalflags.Configure(cmd.Flags()); err != nil { - t.Errorf("cannot 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) - } - } - - if err := cmd.ValidateRequiredFlags(); err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go index ede4e39a5..cee025e98 100644 --- a/internal/cmd/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -75,9 +75,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit security-group rule create --security-group-id xxx --direction ingress --protocol-number 1`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -141,7 +141,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/security-group/rule/create/create_test.go b/internal/cmd/security-group/rule/create/create_test.go index 6c1521899..2432c55ae 100644 --- a/internal/cmd/security-group/rule/create/create_test.go +++ b/internal/cmd/security-group/rule/create/create_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "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" @@ -121,6 +123,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateSecurityGroupRulePayload)) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -243,53 +246,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flag groups: %v", err) - } - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/security-group/rule/describe/describe_test.go b/internal/cmd/security-group/rule/describe/describe_test.go index 66b536f5c..68c84b395 100644 --- a/internal/cmd/security-group/rule/describe/describe_test.go +++ b/internal/cmd/security-group/rule/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -165,54 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/security-group/rule/list/list.go b/internal/cmd/security-group/rule/list/list.go index 9098a19ff..4984d6b17 100644 --- a/internal/cmd/security-group/rule/list/list.go +++ b/internal/cmd/security-group/rule/list/list.go @@ -53,9 +53,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit security-group rule list --security-group-id xxx --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -110,7 +110,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/security-group/rule/list/list_test.go b/internal/cmd/security-group/rule/list/list_test.go index 0b7a49b25..ab41b1d87 100644 --- a/internal/cmd/security-group/rule/list/list_test.go +++ b/internal/cmd/security-group/rule/list/list_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -61,6 +62,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListSecurityGroupRulesRequest) func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -141,46 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/security-group/update/update_test.go b/internal/cmd/security-group/update/update_test.go index 1d89a9e48..e7c6c4f00 100644 --- a/internal/cmd/security-group/update/update_test.go +++ b/internal/cmd/security-group/update/update_test.go @@ -87,6 +87,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiUpdateSecurityGroupRequest)) i func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string args []string isValid bool diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index 441568839..824bbb0b9 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -53,10 +53,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a Server Backup with name "mybackup" and retention period of 5 days`, `$ stackit server backup create --server-id xxx --name=mybackup --retention-period=5`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -113,7 +113,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/server/backup/create/create_test.go b/internal/cmd/server/backup/create/create_test.go index 71a50ff6b..9f7799a7f 100644 --- a/internal/cmd/server/backup/create/create_test.go +++ b/internal/cmd/server/backup/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -82,6 +83,7 @@ func fixturePayload(mods ...func(payload *serverbackup.CreateBackupPayload)) ser func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -131,46 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/delete/delete_test.go b/internal/cmd/server/backup/delete/delete_test.go index d1de3562f..1b90f5c00 100644 --- a/internal/cmd/server/backup/delete/delete_test.go +++ b/internal/cmd/server/backup/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -130,54 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/describe/describe_test.go b/internal/cmd/server/backup/describe/describe_test.go index c706734f1..2e3c10af2 100644 --- a/internal/cmd/server/backup/describe/describe_test.go +++ b/internal/cmd/server/backup/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -130,54 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go index 0bc6f6a1c..18acc9627 100644 --- a/internal/cmd/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -40,9 +40,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Disable Server Backup functionality for your server.`, "$ stackit server backup disable --server-id=zzz"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -103,7 +103,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/backup/disable/disable_test.go b/internal/cmd/server/backup/disable/disable_test.go index 7b13233e1..9e74ae6ee 100644 --- a/internal/cmd/server/backup/disable/disable_test.go +++ b/internal/cmd/server/backup/disable/disable_test.go @@ -5,12 +5,11 @@ import ( "testing" "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) @@ -26,6 +25,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -59,17 +59,23 @@ func fixtureRequest(mods ...func(request *serverbackup.ApiDisableServiceResource func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel }{ { - description: "base", - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.ServerId = "" + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "server id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" }), + isValid: false, }, { description: "no values", @@ -101,46 +107,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go index 4cb0f3667..8194ca95e 100644 --- a/internal/cmd/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -40,9 +40,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Enable Server Backup functionality for your server`, "$ stackit server backup enable --server-id=zzz"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -96,7 +96,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/backup/enable/enable_test.go b/internal/cmd/server/backup/enable/enable_test.go index b4cc1cb77..b7035a762 100644 --- a/internal/cmd/server/backup/enable/enable_test.go +++ b/internal/cmd/server/backup/enable/enable_test.go @@ -5,12 +5,11 @@ import ( "testing" "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) @@ -26,6 +25,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -59,17 +59,23 @@ func fixtureRequest(mods ...func(request *serverbackup.ApiEnableServiceResourceR func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel }{ { - description: "base", - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.ServerId = "" + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "server id is missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" }), + isValid: false, }, { description: "no values", @@ -101,46 +107,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go index 453185e56..58259611f 100644 --- a/internal/cmd/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all backups for a server with ID "xxx" in JSON format`, "$ stackit server backup list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -100,7 +100,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/backup/list/list_test.go b/internal/cmd/server/backup/list/list_test.go index 218a17c6e..a265c6779 100644 --- a/internal/cmd/server/backup/list/list_test.go +++ b/internal/cmd/server/backup/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -63,6 +64,7 @@ func fixtureRequest(mods ...func(request *serverbackup.ApiListBackupsRequest)) s func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -117,46 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/restore/restore_test.go b/internal/cmd/server/backup/restore/restore_test.go index ff14455c2..9f890f3c2 100644 --- a/internal/cmd/server/backup/restore/restore_test.go +++ b/internal/cmd/server/backup/restore/restore_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -132,54 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index 301bc279c..658ab27ee 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -61,10 +61,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a Server Backup Schedule with name "myschedule", backup name "mybackup" and retention period of 5 days`, `$ stackit server backup schedule create --server-id xxx --backup-name=mybackup --backup-schedule-name=myschedule --backup-retention-period=5`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -124,7 +124,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/server/backup/schedule/create/create_test.go b/internal/cmd/server/backup/schedule/create/create_test.go index ceb92188b..5f4d51733 100644 --- a/internal/cmd/server/backup/schedule/create/create_test.go +++ b/internal/cmd/server/backup/schedule/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -93,6 +94,7 @@ func fixturePayload(mods ...func(payload *serverbackup.CreateBackupSchedulePaylo func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -142,46 +144,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/schedule/delete/delete_test.go b/internal/cmd/server/backup/schedule/delete/delete_test.go index 26c218485..5e0f108ca 100644 --- a/internal/cmd/server/backup/schedule/delete/delete_test.go +++ b/internal/cmd/server/backup/schedule/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -130,54 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/schedule/describe/describe_test.go b/internal/cmd/server/backup/schedule/describe/describe_test.go index edc952d18..5d1f51e3a 100644 --- a/internal/cmd/server/backup/schedule/describe/describe_test.go +++ b/internal/cmd/server/backup/schedule/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/serverbackup" ) @@ -129,54 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go index b3a93e3fa..1c396d0e1 100644 --- a/internal/cmd/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all backup schedules for a server with ID "xxx" in JSON format`, "$ stackit server backup schedule list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -101,7 +101,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/backup/schedule/list/list_test.go b/internal/cmd/server/backup/schedule/list/list_test.go index c88ec459e..2234b0397 100644 --- a/internal/cmd/server/backup/schedule/list/list_test.go +++ b/internal/cmd/server/backup/schedule/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -63,6 +64,7 @@ func fixtureRequest(mods ...func(request *serverbackup.ApiListBackupSchedulesReq func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -117,46 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/volume-backup/delete/delete_test.go b/internal/cmd/server/backup/volume-backup/delete/delete_test.go index 34859934a..0a1da5857 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete_test.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -133,54 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/backup/volume-backup/restore/restore_test.go b/internal/cmd/server/backup/volume-backup/restore/restore_test.go index 21da9b128..f329161db 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore_test.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -139,54 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index 7e1817b50..0f489ee7a 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -49,10 +49,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a server command for server with ID "xxx", template name "RunShellScript" and a script provided on the command line`, `$ stackit server command create --server-id xxx --template-name=RunShellScript --params script='echo hello'`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -108,7 +108,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/server/command/create/create_test.go b/internal/cmd/server/command/create/create_test.go index eed029584..cb2368d6f 100644 --- a/internal/cmd/server/command/create/create_test.go +++ b/internal/cmd/server/command/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -81,6 +82,7 @@ func fixturePayload(mods ...func(payload *runcommand.CreateCommandPayload)) runc func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -127,46 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/command/describe/describe_test.go b/internal/cmd/server/command/describe/describe_test.go index 59363f0e7..89689817d 100644 --- a/internal/cmd/server/command/describe/describe_test.go +++ b/internal/cmd/server/command/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -163,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/command/list/list.go b/internal/cmd/server/command/list/list.go index c3a875043..f917b1689 100644 --- a/internal/cmd/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all commands for a server with ID "xxx" in JSON format`, "$ stackit server command list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -100,7 +100,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/command/list/list_test.go b/internal/cmd/server/command/list/list_test.go index 7d6ce40fb..9af1dfc05 100644 --- a/internal/cmd/server/command/list/list_test.go +++ b/internal/cmd/server/command/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -66,6 +67,7 @@ func fixtureRequest(mods ...func(request *runcommand.ApiListCommandsRequest)) ru func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -120,46 +122,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/command/template/describe/describe_test.go b/internal/cmd/server/command/template/describe/describe_test.go index 9fa7ba208..45cbe627a 100644 --- a/internal/cmd/server/command/template/describe/describe_test.go +++ b/internal/cmd/server/command/template/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -163,54 +164,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/command/template/list/list.go b/internal/cmd/server/command/template/list/list.go index 54ff4fd98..ffd76ac24 100644 --- a/internal/cmd/server/command/template/list/list.go +++ b/internal/cmd/server/command/template/list/list.go @@ -41,9 +41,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all commands templates in JSON format`, "$ stackit server command template list --output-format json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -81,7 +81,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/command/template/list/list_test.go b/internal/cmd/server/command/template/list/list_test.go index 0ff491e5d..9255b13fe 100644 --- a/internal/cmd/server/command/template/list/list_test.go +++ b/internal/cmd/server/command/template/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -57,6 +58,7 @@ func fixtureRequest(mods ...func(request *runcommand.ApiListCommandTemplatesRequ func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -111,46 +113,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/console/console_test.go b/internal/cmd/server/console/console_test.go index 9b6c0413c..ab80a7fc4 100644 --- a/internal/cmd/server/console/console_test.go +++ b/internal/cmd/server/console/console_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -129,54 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index b4f012148..b0142acec 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -108,9 +108,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml")`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -188,7 +188,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/server/create/create_test.go b/internal/cmd/server/create/create_test.go index 1548691d4..192caac02 100644 --- a/internal/cmd/server/create/create_test.go +++ b/internal/cmd/server/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -41,7 +42,6 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st bootVolumeSourceIdFlag: testSourceId, bootVolumeSourceTypeFlag: "test-source-type", bootVolumeDeleteOnTerminationFlag: "false", - imageIdFlag: testImageId, keypairNameFlag: "test-keypair-name", networkIdFlag: testNetworkId, securityGroupsFlag: "test-security-groups", @@ -70,7 +70,6 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { BootVolumeSourceId: utils.Ptr(testSourceId), BootVolumeSourceType: utils.Ptr("test-source-type"), BootVolumeDeleteOnTermination: utils.Ptr(false), - ImageId: utils.Ptr(testImageId), KeypairName: utils.Ptr("test-keypair-name"), NetworkId: utils.Ptr(testNetworkId), SecurityGroups: utils.Ptr([]string{"test-security-groups"}), @@ -117,7 +116,6 @@ func fixturePayload(mods ...func(payload *iaas.CreateServerPayload)) iaas.Create Name: utils.Ptr("test-server-name"), AvailabilityZone: utils.Ptr("eu01-1"), AffinityGroup: utils.Ptr("test-affinity-group"), - ImageId: utils.Ptr(testImageId), KeypairName: utils.Ptr("test-keypair-name"), SecurityGroups: utils.Ptr([]string{"test-security-groups"}), ServiceAccountMails: utils.Ptr([]string{"test-service-account"}), @@ -147,6 +145,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateServerPayload)) iaas.Create func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -175,6 +174,7 @@ func TestParseInput(t *testing.T) { delete(flagValues, serviceAccountEmailsFlag) delete(flagValues, userDataFlag) delete(flagValues, volumesFlag) + flagValues[imageIdFlag] = testImageId }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { @@ -193,6 +193,7 @@ func TestParseInput(t *testing.T) { model.ServiceAccountMails = nil model.UserData = nil model.Volumes = nil + model.ImageId = utils.Ptr(testImageId) }), }, { @@ -292,12 +293,14 @@ func TestParseInput(t *testing.T) { delete(flagValues, bootVolumeSourceIdFlag) delete(flagValues, bootVolumeSourceTypeFlag) delete(flagValues, bootVolumeSizeFlag) + flagValues[imageIdFlag] = testImageId }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { model.BootVolumeSourceId = nil model.BootVolumeSourceType = nil model.BootVolumeSize = nil + model.ImageId = utils.Ptr(testImageId) }), }, { @@ -326,46 +329,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/deallocate/deallocate_test.go b/internal/cmd/server/deallocate/deallocate_test.go index 379fc3a58..5f1c06bea 100644 --- a/internal/cmd/server/deallocate/deallocate_test.go +++ b/internal/cmd/server/deallocate/deallocate_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -128,54 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/delete/delete_test.go b/internal/cmd/server/delete/delete_test.go index 1c04e26cb..3b72baca3 100644 --- a/internal/cmd/server/delete/delete_test.go +++ b/internal/cmd/server/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/describe/describe_test.go b/internal/cmd/server/describe/describe_test.go index 86052e8b7..0d416e464 100644 --- a/internal/cmd/server/describe/describe_test.go +++ b/internal/cmd/server/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -139,54 +140,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/list/list.go b/internal/cmd/server/list/list.go index 13a4be08f..0918e1d91 100644 --- a/internal/cmd/server/list/list.go +++ b/internal/cmd/server/list/list.go @@ -57,9 +57,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit server list --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -105,7 +105,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter by label") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/list/list_test.go b/internal/cmd/server/list/list_test.go index 64fe0ddb4..1507be485 100644 --- a/internal/cmd/server/list/list_test.go +++ b/internal/cmd/server/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -64,6 +65,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListServersRequest)) iaas.ApiL func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -133,46 +135,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/log/log_test.go b/internal/cmd/server/log/log_test.go index 0ebc57bdc..c1768f672 100644 --- a/internal/cmd/server/log/log_test.go +++ b/internal/cmd/server/log/log_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -142,54 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/machine-type/describe/describe_test.go b/internal/cmd/server/machine-type/describe/describe_test.go index 20e47affc..81c992468 100644 --- a/internal/cmd/server/machine-type/describe/describe_test.go +++ b/internal/cmd/server/machine-type/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -126,54 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go index 7d4f228cd..833de684e 100644 --- a/internal/cmd/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit server machine-type list --limit=10`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -96,7 +96,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/machine-type/list/list_test.go b/internal/cmd/server/machine-type/list/list_test.go index 8472b596d..db8906209 100644 --- a/internal/cmd/server/machine-type/list/list_test.go +++ b/internal/cmd/server/machine-type/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -59,6 +60,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListMachineTypesRequest)) iaas func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -118,46 +120,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/network-interface/attach/attach.go b/internal/cmd/server/network-interface/attach/attach.go index 739a9169e..1d774ffea 100644 --- a/internal/cmd/server/network-interface/attach/attach.go +++ b/internal/cmd/server/network-interface/attach/attach.go @@ -52,9 +52,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit server network-interface attach --network-id xxx --server-id yyy --create`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -131,7 +131,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/network-interface/attach/attach_test.go b/internal/cmd/server/network-interface/attach/attach_test.go index 6e5a00011..697562536 100644 --- a/internal/cmd/server/network-interface/attach/attach_test.go +++ b/internal/cmd/server/network-interface/attach/attach_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -73,6 +72,7 @@ func fixtureRequestCreateAndAttach(mods ...func(request *iaas.ApiAddNetworkToSer func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -199,54 +199,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flag groups: %v", err) - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/network-interface/detach/detach.go b/internal/cmd/server/network-interface/detach/detach.go index 7d72df379..b8afad878 100644 --- a/internal/cmd/server/network-interface/detach/detach.go +++ b/internal/cmd/server/network-interface/detach/detach.go @@ -52,9 +52,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit server network-interface detach --network-id xxx --server-id yyy --delete`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -133,7 +133,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/network-interface/detach/detach_test.go b/internal/cmd/server/network-interface/detach/detach_test.go index cc60c9912..1eef8529a 100644 --- a/internal/cmd/server/network-interface/detach/detach_test.go +++ b/internal/cmd/server/network-interface/detach/detach_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -73,6 +72,7 @@ func fixtureRequestDetachAndDelete(mods ...func(request *iaas.ApiRemoveNetworkFr func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -199,54 +199,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flag groups: %v", err) - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/network-interface/list/list.go b/internal/cmd/server/network-interface/list/list.go index 3e895c4b4..ef8f70ca7 100644 --- a/internal/cmd/server/network-interface/list/list.go +++ b/internal/cmd/server/network-interface/list/list.go @@ -50,9 +50,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit server network-interface list --server-id xxx --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -103,7 +103,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/network-interface/list/list_test.go b/internal/cmd/server/network-interface/list/list_test.go index 8d2c90f86..4b91f4742 100644 --- a/internal/cmd/server/network-interface/list/list_test.go +++ b/internal/cmd/server/network-interface/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListServerNicsRequest)) iaas.A func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -137,46 +139,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index 3a2709ded..7af78387a 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -48,10 +48,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a Server os-update with name "myupdate" and maintenance window for 13 o'clock.`, `$ stackit server os-update create --server-id xxx --maintenance-window=13`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -103,7 +103,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64P(maintenanceWindowFlag, "m", defaultMaintenanceWindow, "Maintenance window (in hours, 1-24)") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/server/os-update/create/create_test.go b/internal/cmd/server/os-update/create/create_test.go index 78e914882..073ea1db6 100644 --- a/internal/cmd/server/os-update/create/create_test.go +++ b/internal/cmd/server/os-update/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -78,6 +79,7 @@ func fixturePayload(mods ...func(payload *serverupdate.CreateUpdatePayload)) ser func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -129,46 +131,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/describe/describe_test.go b/internal/cmd/server/os-update/describe/describe_test.go index 0a859c415..32dfa4334 100644 --- a/internal/cmd/server/os-update/describe/describe_test.go +++ b/internal/cmd/server/os-update/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -133,54 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go index dabf2bacf..3c9510b98 100644 --- a/internal/cmd/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -39,9 +39,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Disable os-update functionality for your server.`, "$ stackit server os-update disable --server-id=zzz"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -93,7 +93,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/os-update/disable/disable_test.go b/internal/cmd/server/os-update/disable/disable_test.go index 566300e33..b7d28e23c 100644 --- a/internal/cmd/server/os-update/disable/disable_test.go +++ b/internal/cmd/server/os-update/disable/disable_test.go @@ -5,12 +5,11 @@ import ( "testing" "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) @@ -29,6 +28,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -62,17 +62,23 @@ func fixtureRequest(mods ...func(request *serverupdate.ApiDisableServiceResource func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel }{ { - description: "base", - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.ServerId = "" + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "server id flag is missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" }), + isValid: false, }, { description: "no values", @@ -104,46 +110,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go index 2697de207..c81c27b44 100644 --- a/internal/cmd/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -40,9 +40,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Enable os-update functionality for your server`, "$ stackit server os-update enable --server-id=zzz"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -96,7 +96,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/os-update/enable/enable_test.go b/internal/cmd/server/os-update/enable/enable_test.go index d35251a70..4ebed0b3a 100644 --- a/internal/cmd/server/os-update/enable/enable_test.go +++ b/internal/cmd/server/os-update/enable/enable_test.go @@ -5,12 +5,11 @@ import ( "testing" "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) @@ -29,6 +28,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -62,17 +62,23 @@ func fixtureRequest(mods ...func(request *serverupdate.ApiEnableServiceResourceR func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel }{ { - description: "base", - flagValues: fixtureFlagValues(), - isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.ServerId = "" + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "server id flag is missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[serverIdFlag] = "" }), + isValid: false, }, { description: "no values", @@ -104,46 +110,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go index fbb5d0fa6..5ce2a5c27 100644 --- a/internal/cmd/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all os-updates for a server with ID "xxx" in JSON format`, "$ stackit server os-update list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -101,7 +101,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/os-update/list/list_test.go b/internal/cmd/server/os-update/list/list_test.go index 078f7ca0a..541ad0567 100644 --- a/internal/cmd/server/os-update/list/list_test.go +++ b/internal/cmd/server/os-update/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -66,6 +67,7 @@ func fixtureRequest(mods ...func(request *serverupdate.ApiListUpdatesRequest)) s func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -120,46 +122,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index 63325c4da..76dd76235 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -56,10 +56,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a Server os-update Schedule with name "myschedule" and maintenance window for 14 o'clock`, `$ stackit server os-update schedule create --server-id xxx --name=myschedule --maintenance-window=14`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -117,7 +117,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/server/os-update/schedule/create/create_test.go b/internal/cmd/server/os-update/schedule/create/create_test.go index 2cdb00f75..c944e63e7 100644 --- a/internal/cmd/server/os-update/schedule/create/create_test.go +++ b/internal/cmd/server/os-update/schedule/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -87,6 +88,7 @@ func fixturePayload(mods ...func(payload *serverupdate.CreateUpdateSchedulePaylo func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string aclValues []string isValid bool @@ -136,46 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/schedule/delete/delete_test.go b/internal/cmd/server/os-update/schedule/delete/delete_test.go index eb005e164..99b0aaafb 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete_test.go +++ b/internal/cmd/server/os-update/schedule/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -133,54 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/schedule/describe/describe_test.go b/internal/cmd/server/os-update/schedule/describe/describe_test.go index 178585383..1f938f1de 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe_test.go +++ b/internal/cmd/server/os-update/schedule/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -133,54 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go index c1c0ed606..b9721cca8 100644 --- a/internal/cmd/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -46,9 +46,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all os-update schedules for a server with ID "xxx" in JSON format`, "$ stackit server os-update schedule list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -100,7 +100,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/os-update/schedule/list/list_test.go b/internal/cmd/server/os-update/schedule/list/list_test.go index 57aa1c0dc..f39c88508 100644 --- a/internal/cmd/server/os-update/schedule/list/list_test.go +++ b/internal/cmd/server/os-update/schedule/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -66,6 +67,7 @@ func fixtureRequest(mods ...func(request *serverupdate.ApiListUpdateSchedulesReq func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -120,46 +122,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/reboot/reboot_test.go b/internal/cmd/server/reboot/reboot_test.go index cfcda6783..074ba2a84 100644 --- a/internal/cmd/server/reboot/reboot_test.go +++ b/internal/cmd/server/reboot/reboot_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -130,54 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/rescue/rescue_test.go b/internal/cmd/server/rescue/rescue_test.go index 8a5695fd9..d3e6e3c50 100644 --- a/internal/cmd/server/rescue/rescue_test.go +++ b/internal/cmd/server/rescue/rescue_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -145,54 +144,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/resize/resize_test.go b/internal/cmd/server/resize/resize_test.go index ee94cfe6e..231d7c1c0 100644 --- a/internal/cmd/server/resize/resize_test.go +++ b/internal/cmd/server/resize/resize_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -144,54 +143,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/service-account/list/list.go b/internal/cmd/server/service-account/list/list.go index efb454e8c..5bf727bc7 100644 --- a/internal/cmd/server/service-account/list/list.go +++ b/internal/cmd/server/service-account/list/list.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit server service-account list --server-id xxx --output-format json", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -101,7 +101,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/server/service-account/list/list_test.go b/internal/cmd/server/service-account/list/list_test.go index 9ba1d281a..d2a0c159a 100644 --- a/internal/cmd/server/service-account/list/list_test.go +++ b/internal/cmd/server/service-account/list/list_test.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -64,6 +65,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListServerServiceAccountsReque func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -149,46 +151,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/start/start_test.go b/internal/cmd/server/start/start_test.go index 2776c77e7..f028d85d9 100644 --- a/internal/cmd/server/start/start_test.go +++ b/internal/cmd/server/start/start_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -128,54 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/stop/stop_test.go b/internal/cmd/server/stop/stop_test.go index bbaefddba..7aba2f968 100644 --- a/internal/cmd/server/stop/stop_test.go +++ b/internal/cmd/server/stop/stop_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -128,54 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/unrescue/unrescue_test.go b/internal/cmd/server/unrescue/unrescue_test.go index 1f2d95712..8161f03d4 100644 --- a/internal/cmd/server/unrescue/unrescue_test.go +++ b/internal/cmd/server/unrescue/unrescue_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -128,54 +127,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go index c48eceb5f..6f25321db 100644 --- a/internal/cmd/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -42,9 +42,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all volumes for a server with ID "xxx" in JSON format`, "$ stackit server volumes list --server-id xxx --output-format json"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -100,7 +100,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/server/volume/list/list_test.go b/internal/cmd/server/volume/list/list_test.go index a337fc247..6be36d7d6 100644 --- a/internal/cmd/server/volume/list/list_test.go +++ b/internal/cmd/server/volume/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -60,6 +61,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListAttachedVolumesRequest)) i func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -121,46 +123,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index 98389133c..73618ca1f 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -39,9 +39,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a service account with name "my-service-account"`, "$ stackit service-account create --name my-service-account"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -87,7 +87,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/service-account/create/create_test.go b/internal/cmd/service-account/create/create_test.go index 1c3fac895..2f95584f8 100644 --- a/internal/cmd/service-account/create/create_test.go +++ b/internal/cmd/service-account/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *serviceaccount.ApiCreateServiceAccount func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -117,46 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/delete/delete_test.go b/internal/cmd/service-account/delete/delete_test.go index 9a0dc74ef..7dbcc6dfd 100644 --- a/internal/cmd/service-account/delete/delete_test.go +++ b/internal/cmd/service-account/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -126,54 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/key/create/create.go b/internal/cmd/service-account/key/create/create.go index e25d3fbbc..e23d11cc8 100644 --- a/internal/cmd/service-account/key/create/create.go +++ b/internal/cmd/service-account/key/create/create.go @@ -55,9 +55,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a key for the service account with email "my-service-account-1234567@sa.stackit.cloud" and provide the public key in a .pem file"`, `$ stackit service-account key create --email my-service-account-1234567@sa.stackit.cloud --public-key @./public.pem`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -111,7 +111,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/service-account/key/create/create_test.go b/internal/cmd/service-account/key/create/create_test.go index 8f07ed01f..3ee9c7739 100644 --- a/internal/cmd/service-account/key/create/create_test.go +++ b/internal/cmd/service-account/key/create/create_test.go @@ -5,9 +5,8 @@ import ( "testing" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -65,6 +64,7 @@ func fixtureRequest(mods ...func(request *serviceaccount.ApiCreateServiceAccount func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -142,46 +142,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/key/delete/delete_test.go b/internal/cmd/service-account/key/delete/delete_test.go index 9e811b0a6..7f4ade070 100644 --- a/internal/cmd/service-account/key/delete/delete_test.go +++ b/internal/cmd/service-account/key/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -149,54 +148,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/key/describe/describe_test.go b/internal/cmd/service-account/key/describe/describe_test.go index 7111fa0a6..38a7af958 100644 --- a/internal/cmd/service-account/key/describe/describe_test.go +++ b/internal/cmd/service-account/key/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -149,54 +150,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index e090de0a4..bd7184caa 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -47,9 +47,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 keys belonging to the service account with email "my-service-account-1234567@sa.stackit.cloud"`, "$ stackit service-account key list --email my-service-account-1234567@sa.stackit.cloud --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -93,7 +93,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/service-account/key/list/list_test.go b/internal/cmd/service-account/key/list/list_test.go index ebde67439..845c5cae9 100644 --- a/internal/cmd/service-account/key/list/list_test.go +++ b/internal/cmd/service-account/key/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" ) @@ -63,6 +63,7 @@ func fixtureRequest(mods ...func(request *serviceaccount.ApiListServiceAccountKe func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -124,48 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/key/update/update_test.go b/internal/cmd/service-account/key/update/update_test.go index 84dde9c6d..2d2c66bfa 100644 --- a/internal/cmd/service-account/key/update/update_test.go +++ b/internal/cmd/service-account/key/update/update_test.go @@ -5,9 +5,8 @@ import ( "testing" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -196,54 +195,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index 49ea386cc..7dcd16322 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -39,9 +39,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List all service accounts`, "$ stackit service-account list"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -86,7 +86,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/service-account/list/list_test.go b/internal/cmd/service-account/list/list_test.go index 161f050e2..f6bcc47ec 100644 --- a/internal/cmd/service-account/list/list_test.go +++ b/internal/cmd/service-account/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" ) @@ -60,6 +60,7 @@ func fixtureRequest(mods ...func(request *serviceaccount.ApiListServiceAccountsR func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -114,48 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index 817e1dc27..d01da3a99 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create an access token for the service account with email "my-service-account-1234567@sa.stackit.cloud" with a time to live of 10 days`, "$ stackit service-account token create --email my-service-account-1234567@sa.stackit.cloud --ttl-days 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -93,7 +93,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/service-account/token/create/create_test.go b/internal/cmd/service-account/token/create/create_test.go index ffa760ce5..a7935e1a7 100644 --- a/internal/cmd/service-account/token/create/create_test.go +++ b/internal/cmd/service-account/token/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -67,6 +68,7 @@ func fixtureRequest(mods ...func(request *serviceaccount.ApiCreateAccessTokenReq func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -121,46 +123,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index c302dec8f..7e8f6e12d 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -52,9 +52,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 access tokens of the service account with email "my-service-account-1234567@sa.stackit.cloud"`, "$ stackit service-account token list --email my-service-account-1234567@sa.stackit.cloud --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -98,7 +98,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/service-account/token/list/list_test.go b/internal/cmd/service-account/token/list/list_test.go index e03ee657f..c4cbcf9df 100644 --- a/internal/cmd/service-account/token/list/list_test.go +++ b/internal/cmd/service-account/token/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" ) @@ -63,6 +63,7 @@ func fixtureRequest(mods ...func(request *serviceaccount.ApiListAccessTokensRequ func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -124,48 +125,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/service-account/token/revoke/revoke_test.go b/internal/cmd/service-account/token/revoke/revoke_test.go index 17387aceb..cebb61897 100644 --- a/internal/cmd/service-account/token/revoke/revoke_test.go +++ b/internal/cmd/service-account/token/revoke/revoke_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -149,54 +148,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/cluster/create/create_test.go b/internal/cmd/ske/cluster/create/create_test.go index 8fba70614..b8bb55557 100644 --- a/internal/cmd/ske/cluster/create/create_test.go +++ b/internal/cmd/ske/cluster/create/create_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -233,62 +235,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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) - } - - err = cmd.ValidateFlagGroups() - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/cluster/delete/delete_test.go b/internal/cmd/ske/cluster/delete/delete_test.go index 2835c477b..86cef5d06 100644 --- a/internal/cmd/ske/cluster/delete/delete_test.go +++ b/internal/cmd/ske/cluster/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -130,54 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/cluster/describe/describe_test.go b/internal/cmd/ske/cluster/describe/describe_test.go index a5f7f766e..da85e7af3 100644 --- a/internal/cmd/ske/cluster/describe/describe_test.go +++ b/internal/cmd/ske/cluster/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -131,54 +132,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload.go b/internal/cmd/ske/cluster/generate-payload/generate_payload.go index b03f0d42c..e7fcbe234 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload.go @@ -55,9 +55,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Generate a payload with values of a cluster, and preview it in the terminal`, `$ stackit ske cluster generate-payload --cluster-name my-cluster`), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -102,7 +102,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(filePathFlag, "f", "", "If set, writes the payload to the given file. If unset, writes the payload to the standard output") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) clusterName := flags.FlagToStringPointer(p, cmd, clusterNameFlag) diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go index 856db970d..415f83359 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -70,6 +71,7 @@ func fixtureRequest(mods ...func(request *ske.ApiGetClusterRequest)) ske.ApiGetC func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -133,54 +135,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - err = cmd.ValidateFlagGroups() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index d2a3d4d01..33e93389a 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -48,9 +48,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List up to 10 SKE clusters`, "$ stackit ske cluster list --limit 10"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -109,7 +109,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/ske/cluster/list/list_test.go b/internal/cmd/ske/cluster/list/list_test.go index 4f0543544..a2d8f4d44 100644 --- a/internal/cmd/ske/cluster/list/list_test.go +++ b/internal/cmd/ske/cluster/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) @@ -64,6 +64,7 @@ func fixtureRequest(mods ...func(request *ske.ApiListClustersRequest)) ske.ApiLi func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -118,48 +119,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/cluster/update/update_test.go b/internal/cmd/ske/cluster/update/update_test.go index dcf82f207..8285af7e1 100644 --- a/internal/cmd/ske/cluster/update/update_test.go +++ b/internal/cmd/ske/cluster/update/update_test.go @@ -9,6 +9,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -221,54 +222,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go index b8d40624c..ee40fc120 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -130,54 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go b/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go index 0e2f99fa3..063269174 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -130,54 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index 6becf645a..c1804fc9a 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -33,9 +33,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Get details regarding SKE functionality on your project`, "$ stackit ske describe"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/ske/describe/describe_test.go b/internal/cmd/ske/describe/describe_test.go index 4fb7cbb64..3a0283a6c 100644 --- a/internal/cmd/ske/describe/describe_test.go +++ b/internal/cmd/ske/describe/describe_test.go @@ -8,12 +8,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" serviceEnablementUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" ) type testCtxKey struct{} @@ -59,6 +59,7 @@ func fixtureRequest(mods ...func(request *serviceenablement.ApiGetServiceStatusR func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -99,46 +100,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index 33647becf..f9eb1ac3b 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -35,9 +35,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Disable SKE functionality for your project, deleting all associated clusters`, "$ stackit ske disable"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -91,7 +91,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/ske/disable/disable_test.go b/internal/cmd/ske/disable/disable_test.go index b377dc366..978e383ed 100644 --- a/internal/cmd/ske/disable/disable_test.go +++ b/internal/cmd/ske/disable/disable_test.go @@ -5,13 +5,12 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" + "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" ) @@ -58,6 +57,7 @@ func fixtureRequest(mods ...func(request *serviceenablement.ApiDisableServiceReg func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -98,46 +98,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index 0567a9cab..9d9783dd2 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -35,9 +35,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Enable SKE functionality for your project`, "$ stackit ske enable"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -91,7 +91,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/ske/enable/enable_test.go b/internal/cmd/ske/enable/enable_test.go index d46ec2d07..add7b850b 100644 --- a/internal/cmd/ske/enable/enable_test.go +++ b/internal/cmd/ske/enable/enable_test.go @@ -5,13 +5,12 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" + "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" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" ) @@ -58,6 +57,7 @@ func fixtureRequest(mods ...func(request *serviceenablement.ApiEnableServiceRegi func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -98,46 +98,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/kubeconfig/create/create_test.go b/internal/cmd/ske/kubeconfig/create/create_test.go index 513fae126..5c7b25e58 100644 --- a/internal/cmd/ske/kubeconfig/create/create_test.go +++ b/internal/cmd/ske/kubeconfig/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) @@ -207,54 +208,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index ed8ed322b..5da30e803 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -57,9 +57,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List SKE options regarding Kubernetes versions and machine images`, "$ stackit ske options --kubernetes-versions --machine-images"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -92,7 +92,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(volumeTypesFlag, false, "Lists supported volume types") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) availabilityZones := flags.FlagToBoolValue(p, cmd, availabilityZonesFlag) kubernetesVersions := flags.FlagToBoolValue(p, cmd, kubernetesVersionsFlag) diff --git a/internal/cmd/ske/options/options_test.go b/internal/cmd/ske/options/options_test.go index d2317d1e5..1627f3709 100644 --- a/internal/cmd/ske/options/options_test.go +++ b/internal/cmd/ske/options/options_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -68,6 +69,7 @@ func fixtureInputModelAllTrue(mods ...func(model *inputModel)) *inputModel { func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -127,46 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/backup/create/create.go b/internal/cmd/volume/backup/create/create.go index 789c16585..4245716e9 100644 --- a/internal/cmd/volume/backup/create/create.go +++ b/internal/cmd/volume/backup/create/create.go @@ -56,9 +56,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a backup with labels`, "$ stackit volume backup create --source-id xxx --source-type volume --labels key1=value1,key2=value2"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -137,7 +137,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/volume/backup/create/create_test.go b/internal/cmd/volume/backup/create/create_test.go index 3c4980cc6..2132d89f8 100644 --- a/internal/cmd/volume/backup/create/create_test.go +++ b/internal/cmd/volume/backup/create/create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -84,6 +85,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateBackupRequest)) iaas.Api func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -150,46 +152,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/backup/delete/delete_test.go b/internal/cmd/volume/backup/delete/delete_test.go index 8425e9c98..a0146e406 100644 --- a/internal/cmd/volume/backup/delete/delete_test.go +++ b/internal/cmd/volume/backup/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -110,46 +109,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating args: %v", err) - } - - model, err := parseInput(p, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/backup/describe/describe_test.go b/internal/cmd/volume/backup/describe/describe_test.go index 3dcac1e56..0ff77ca24 100644 --- a/internal/cmd/volume/backup/describe/describe_test.go +++ b/internal/cmd/volume/backup/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -110,46 +111,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating args: %v", err) - } - - model, err := parseInput(p, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/backup/list/list.go b/internal/cmd/volume/backup/list/list.go index af7edc33d..82580a440 100644 --- a/internal/cmd/volume/backup/list/list.go +++ b/internal/cmd/volume/backup/list/list.go @@ -51,9 +51,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List backups with specific labels`, "$ stackit volume backup list --label-selector key1=value1,key2=value2"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -99,7 +99,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter backups by labels") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/volume/backup/list/list_test.go b/internal/cmd/volume/backup/list/list_test.go index 7a24783c2..f3616ef3c 100644 --- a/internal/cmd/volume/backup/list/list_test.go +++ b/internal/cmd/volume/backup/list/list_test.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -63,6 +63,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListBackupsRequest)) iaas.ApiL func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -117,48 +118,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - cmd := &cobra.Command{} - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - configureFlags(cmd) - - 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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - p := print.NewPrinter() - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/backup/restore/restore_test.go b/internal/cmd/volume/backup/restore/restore_test.go index 217300720..8532a05ee 100644 --- a/internal/cmd/volume/backup/restore/restore_test.go +++ b/internal/cmd/volume/backup/restore/restore_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -110,46 +109,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating args: %v", err) - } - - model, err := parseInput(p, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/backup/update/update_test.go b/internal/cmd/volume/backup/update/update_test.go index 21aa21c1e..85faf0764 100644 --- a/internal/cmd/volume/backup/update/update_test.go +++ b/internal/cmd/volume/backup/update/update_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -115,46 +114,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating args: %v", err) - } - - model, err := parseInput(p, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index df781e7c0..f5024261a 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -68,9 +68,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit volume create --availability-zone eu01-1 --performance-class storage_premium_perf1 --size 64`, ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -135,7 +135,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &cliErr.ProjectIdError{} diff --git a/internal/cmd/volume/create/create_test.go b/internal/cmd/volume/create/create_test.go index 716daaad2..35f163e21 100644 --- a/internal/cmd/volume/create/create_test.go +++ b/internal/cmd/volume/create/create_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -109,6 +110,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateVolumePayload)) iaas.Create func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -202,46 +204,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - 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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/delete/delete_test.go b/internal/cmd/volume/delete/delete_test.go index 58d10c79c..db5545312 100644 --- a/internal/cmd/volume/delete/delete_test.go +++ b/internal/cmd/volume/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -138,54 +137,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/describe/describe_test.go b/internal/cmd/volume/describe/describe_test.go index aa0a0754f..1c4e2b907 100644 --- a/internal/cmd/volume/describe/describe_test.go +++ b/internal/cmd/volume/describe/describe_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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-sdk-go/services/iaas" ) @@ -137,54 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/list/list.go b/internal/cmd/volume/list/list.go index 1bf196c95..d1c7b884f 100644 --- a/internal/cmd/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -54,9 +54,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit volume list --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -102,7 +102,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter by label") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/volume/list/list_test.go b/internal/cmd/volume/list/list_test.go index daa736ff1..cb54d2e1f 100644 --- a/internal/cmd/volume/list/list_test.go +++ b/internal/cmd/volume/list/list_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListVolumesRequest)) iaas.ApiL func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -131,46 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/performance-class/describe/describe_test.go b/internal/cmd/volume/performance-class/describe/describe_test.go index b5bf0cf3c..737335164 100644 --- a/internal/cmd/volume/performance-class/describe/describe_test.go +++ b/internal/cmd/volume/performance-class/describe/describe_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "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" @@ -131,54 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - 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 input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/performance-class/list/list.go b/internal/cmd/volume/performance-class/list/list.go index e32ed2c33..0c8a5de64 100644 --- a/internal/cmd/volume/performance-class/list/list.go +++ b/internal/cmd/volume/performance-class/list/list.go @@ -55,9 +55,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { "$ stackit volume performance-class list --limit 10", ), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -103,7 +103,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter by label") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/volume/performance-class/list/list_test.go b/internal/cmd/volume/performance-class/list/list_test.go index 6e877390d..4a36b5333 100644 --- a/internal/cmd/volume/performance-class/list/list_test.go +++ b/internal/cmd/volume/performance-class/list/list_test.go @@ -10,6 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListVolumePerformanceClassesRe func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -131,46 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/snapshot/create/create.go b/internal/cmd/volume/snapshot/create/create.go index 38e92650f..1146ccaba 100644 --- a/internal/cmd/volume/snapshot/create/create.go +++ b/internal/cmd/volume/snapshot/create/create.go @@ -52,9 +52,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `Create a snapshot from a volume with ID "xxx" and labels`, "$ stackit volume snapshot create --volume-id xxx --labels key1=value1,key2=value2"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -126,7 +126,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/volume/snapshot/create/create_test.go b/internal/cmd/volume/snapshot/create/create_test.go index 08c5c0baa..00111c28f 100644 --- a/internal/cmd/volume/snapshot/create/create_test.go +++ b/internal/cmd/volume/snapshot/create/create_test.go @@ -7,9 +7,8 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) @@ -75,6 +74,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateSnapshotRequest)) iaas.A func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -134,46 +134,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/snapshot/delete/delete_test.go b/internal/cmd/volume/snapshot/delete/delete_test.go index bf1f87d15..f97165703 100644 --- a/internal/cmd/volume/snapshot/delete/delete_test.go +++ b/internal/cmd/volume/snapshot/delete/delete_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" @@ -124,46 +123,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating args: %v", err) - } - - model, err := parseInput(p, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/snapshot/describe/describe_test.go b/internal/cmd/volume/snapshot/describe/describe_test.go index 5d501758f..7da9d09a4 100644 --- a/internal/cmd/volume/snapshot/describe/describe_test.go +++ b/internal/cmd/volume/snapshot/describe/describe_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -125,46 +126,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating args: %v", err) - } - - model, err := parseInput(p, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/snapshot/list/list.go b/internal/cmd/volume/snapshot/list/list.go index 2b38252a5..2ef8c9d4d 100644 --- a/internal/cmd/volume/snapshot/list/list.go +++ b/internal/cmd/volume/snapshot/list/list.go @@ -49,9 +49,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `List snapshots filtered by label`, "$ stackit volume snapshot list --label-selector key1=value1"), ), - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(params.Printer, cmd) + model, err := parseInput(params.Printer, cmd, args) if err != nil { return err } @@ -100,7 +100,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(labelSelectorFlag, "", "Filter snapshots by labels") } -func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} diff --git a/internal/cmd/volume/snapshot/list/list_test.go b/internal/cmd/volume/snapshot/list/list_test.go index e1f68f1b1..c9facab11 100644 --- a/internal/cmd/volume/snapshot/list/list_test.go +++ b/internal/cmd/volume/snapshot/list/list_test.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -62,6 +63,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiListSnapshotsRequest)) iaas.Ap func TestParseInput(t *testing.T) { tests := []struct { description string + argValues []string flagValues map[string]string isValid bool expectedModel *inputModel @@ -128,38 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - model, err := parseInput(p, cmd) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/cmd/volume/snapshot/update/update_test.go b/internal/cmd/volume/snapshot/update/update_test.go index cb4af61fc..b96da76f1 100644 --- a/internal/cmd/volume/snapshot/update/update_test.go +++ b/internal/cmd/volume/snapshot/update/update_test.go @@ -4,9 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" "github.com/google/go-cmp/cmp" @@ -167,46 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - p := print.NewPrinter() - cmd := NewCmd(¶ms.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) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating args: %v", err) - } - - model, err := parseInput(p, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing input: %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.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) }) } } diff --git a/internal/pkg/testutils/testutils.go b/internal/pkg/testutils/testutils.go new file mode 100644 index 000000000..8f970fd0a --- /dev/null +++ b/internal/pkg/testutils/testutils.go @@ -0,0 +1,91 @@ +package testutils + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" +) + +// TestParseInput centralizes the logic to test a combination of inputs (arguments, flags) for a cobra command +func TestParseInput[T any](t *testing.T, cmdFactory func(*params.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, isValid bool) { + TestParseInputWithAdditionalFlags(t, cmdFactory, parseInputFunc, expectedModel, argValues, flagValues, map[string][]string{}, isValid) +} + +// TestParseInputWithAdditionalFlags centralizes the logic to test a combination of inputs (arguments, flags) for a cobra command. +// It allows to pass multiple instances of a single flag to the cobra command using the `additionalFlagValues` parameter. +func TestParseInputWithAdditionalFlags[T any](t *testing.T, cmdFactory func(*params.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, additionalFlagValues map[string][]string, isValid bool) { + p := print.NewPrinter() + cmd := cmdFactory(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + // set regular flag values + for flag, value := range flagValues { + err := cmd.Flags().Set(flag, value) + if err != nil { + if !isValid { + return + } + t.Fatalf("setting flag --%s=%s: %v", flag, value, err) + } + } + + // set additional flag values + for flag, values := range additionalFlagValues { + for _, value := range values { + err := cmd.Flags().Set(flag, value) + if err != nil { + if !isValid { + return + } + t.Fatalf("setting flag --%s=%s: %v", flag, value, err) + } + } + } + + err = cmd.ValidateArgs(argValues) + if err != nil { + if !isValid { + return + } + t.Fatalf("error validating args: %v", err) + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + err = cmd.ValidateFlagGroups() + if err != nil { + if !isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + model, err := parseInputFunc(p, cmd, argValues) + if err != nil { + if !isValid { + return + } + t.Fatalf("error parsing input: %v", err) + } + + if !isValid { + t.Fatalf("did not fail on invalid input") + } + diff := cmp.Diff(model, expectedModel) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } +} From 99f4d2d6bf245a3ec1c6f9ab625601a7e64164bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 09:20:02 +0200 Subject: [PATCH 468/619] chore(deps): bump renovatebot/github-action from 43.0.17 to 43.0.18 (#1034) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 211759137..0ebc69e31 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.17 + uses: renovatebot/github-action@v43.0.18 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 8e08cf49895e2e5da339ab9d7b99407dbd7dd261 Mon Sep 17 00:00:00 2001 From: JanStern <65732422+JanStern@users.noreply.github.com> Date: Wed, 22 Oct 2025 17:33:19 +0200 Subject: [PATCH 469/619] feat(kms): Add KMS under beta (#935) --- docs/stackit_beta.md | 1 + docs/stackit_beta_kms.md | 37 ++ docs/stackit_beta_kms_key.md | 39 ++ docs/stackit_beta_kms_key_create.md | 62 +++ docs/stackit_beta_kms_key_delete.md | 41 ++ docs/stackit_beta_kms_key_import.md | 46 +++ docs/stackit_beta_kms_key_list.md | 44 +++ docs/stackit_beta_kms_key_restore.md | 41 ++ docs/stackit_beta_kms_key_rotate.md | 41 ++ docs/stackit_beta_kms_keyring.md | 36 ++ docs/stackit_beta_kms_keyring_create.md | 48 +++ docs/stackit_beta_kms_keyring_delete.md | 40 ++ docs/stackit_beta_kms_keyring_list.md | 43 +++ docs/stackit_beta_kms_version.md | 38 ++ docs/stackit_beta_kms_version_destroy.md | 42 ++ docs/stackit_beta_kms_version_disable.md | 42 ++ docs/stackit_beta_kms_version_enable.md | 42 ++ docs/stackit_beta_kms_version_list.md | 45 +++ docs/stackit_beta_kms_version_restore.md | 42 ++ docs/stackit_beta_kms_wrapping-key.md | 36 ++ docs/stackit_beta_kms_wrapping-key_create.md | 49 +++ docs/stackit_beta_kms_wrapping-key_delete.md | 41 ++ docs/stackit_beta_kms_wrapping-key_list.md | 44 +++ ...ckit_beta_sqlserverflex_instance_create.md | 2 +- docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 2 + internal/cmd/beta/beta.go | 2 + internal/cmd/beta/kms/key/create/create.go | 218 +++++++++++ .../cmd/beta/kms/key/create/create_test.go | 327 ++++++++++++++++ internal/cmd/beta/kms/key/delete/delete.go | 149 +++++++ .../cmd/beta/kms/key/delete/delete_test.go | 292 ++++++++++++++ .../cmd/beta/kms/key/importKey/importKey.go | 181 +++++++++ .../beta/kms/key/importKey/importKey_test.go | 362 ++++++++++++++++++ internal/cmd/beta/kms/key/key.go | 36 ++ internal/cmd/beta/kms/key/list/list.go | 148 +++++++ internal/cmd/beta/kms/key/list/list_test.go | 258 +++++++++++++ internal/cmd/beta/kms/key/restore/restore.go | 148 +++++++ .../cmd/beta/kms/key/restore/restore_test.go | 292 ++++++++++++++ internal/cmd/beta/kms/key/rotate/rotate.go | 144 +++++++ .../cmd/beta/kms/key/rotate/rotate_test.go | 292 ++++++++++++++ .../cmd/beta/kms/keyring/create/create.go | 182 +++++++++ .../beta/kms/keyring/create/create_test.go | 249 ++++++++++++ .../cmd/beta/kms/keyring/delete/delete.go | 105 +++++ .../beta/kms/keyring/delete/delete_test.go | 212 ++++++++++ internal/cmd/beta/kms/keyring/keyring.go | 30 ++ internal/cmd/beta/kms/keyring/list/list.go | 133 +++++++ .../cmd/beta/kms/keyring/list/list_test.go | 229 +++++++++++ internal/cmd/beta/kms/kms.go | 32 ++ .../cmd/beta/kms/version/destroy/destroy.go | 147 +++++++ .../beta/kms/version/destroy/destroy_test.go | 319 +++++++++++++++ .../cmd/beta/kms/version/disable/disable.go | 149 +++++++ .../beta/kms/version/disable/disable_test.go | 320 ++++++++++++++++ .../cmd/beta/kms/version/enable/enable.go | 160 ++++++++ .../beta/kms/version/enable/enable_test.go | 320 ++++++++++++++++ internal/cmd/beta/kms/version/list/list.go | 150 ++++++++ .../cmd/beta/kms/version/list/list_test.go | 282 ++++++++++++++ .../cmd/beta/kms/version/restore/restore.go | 145 +++++++ .../beta/kms/version/restore/restore_test.go | 320 ++++++++++++++++ internal/cmd/beta/kms/version/version.go | 34 ++ .../cmd/beta/kms/wrappingkey/create/create.go | 204 ++++++++++ .../kms/wrappingkey/create/create_test.go | 318 +++++++++++++++ .../cmd/beta/kms/wrappingkey/delete/delete.go | 118 ++++++ .../kms/wrappingkey/delete/delete_test.go | 241 ++++++++++++ .../cmd/beta/kms/wrappingkey/list/list.go | 149 +++++++ .../beta/kms/wrappingkey/list/list_test.go | 250 ++++++++++++ .../cmd/beta/kms/wrappingkey/wrappingkey.go | 30 ++ .../sqlserverflex/instance/create/create.go | 2 +- internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 13 + internal/pkg/config/config.go | 3 + internal/pkg/services/kms/client/client.go | 45 +++ internal/pkg/services/kms/utils/utils.go | 67 ++++ internal/pkg/services/kms/utils/utils_test.go | 257 +++++++++++++ 76 files changed, 9020 insertions(+), 2 deletions(-) create mode 100644 docs/stackit_beta_kms.md create mode 100644 docs/stackit_beta_kms_key.md create mode 100644 docs/stackit_beta_kms_key_create.md create mode 100644 docs/stackit_beta_kms_key_delete.md create mode 100644 docs/stackit_beta_kms_key_import.md create mode 100644 docs/stackit_beta_kms_key_list.md create mode 100644 docs/stackit_beta_kms_key_restore.md create mode 100644 docs/stackit_beta_kms_key_rotate.md create mode 100644 docs/stackit_beta_kms_keyring.md create mode 100644 docs/stackit_beta_kms_keyring_create.md create mode 100644 docs/stackit_beta_kms_keyring_delete.md create mode 100644 docs/stackit_beta_kms_keyring_list.md create mode 100644 docs/stackit_beta_kms_version.md create mode 100644 docs/stackit_beta_kms_version_destroy.md create mode 100644 docs/stackit_beta_kms_version_disable.md create mode 100644 docs/stackit_beta_kms_version_enable.md create mode 100644 docs/stackit_beta_kms_version_list.md create mode 100644 docs/stackit_beta_kms_version_restore.md create mode 100644 docs/stackit_beta_kms_wrapping-key.md create mode 100644 docs/stackit_beta_kms_wrapping-key_create.md create mode 100644 docs/stackit_beta_kms_wrapping-key_delete.md create mode 100644 docs/stackit_beta_kms_wrapping-key_list.md create mode 100644 internal/cmd/beta/kms/key/create/create.go create mode 100644 internal/cmd/beta/kms/key/create/create_test.go create mode 100644 internal/cmd/beta/kms/key/delete/delete.go create mode 100644 internal/cmd/beta/kms/key/delete/delete_test.go create mode 100644 internal/cmd/beta/kms/key/importKey/importKey.go create mode 100644 internal/cmd/beta/kms/key/importKey/importKey_test.go create mode 100644 internal/cmd/beta/kms/key/key.go create mode 100644 internal/cmd/beta/kms/key/list/list.go create mode 100644 internal/cmd/beta/kms/key/list/list_test.go create mode 100644 internal/cmd/beta/kms/key/restore/restore.go create mode 100644 internal/cmd/beta/kms/key/restore/restore_test.go create mode 100644 internal/cmd/beta/kms/key/rotate/rotate.go create mode 100644 internal/cmd/beta/kms/key/rotate/rotate_test.go create mode 100644 internal/cmd/beta/kms/keyring/create/create.go create mode 100644 internal/cmd/beta/kms/keyring/create/create_test.go create mode 100644 internal/cmd/beta/kms/keyring/delete/delete.go create mode 100644 internal/cmd/beta/kms/keyring/delete/delete_test.go create mode 100644 internal/cmd/beta/kms/keyring/keyring.go create mode 100644 internal/cmd/beta/kms/keyring/list/list.go create mode 100644 internal/cmd/beta/kms/keyring/list/list_test.go create mode 100644 internal/cmd/beta/kms/kms.go create mode 100644 internal/cmd/beta/kms/version/destroy/destroy.go create mode 100644 internal/cmd/beta/kms/version/destroy/destroy_test.go create mode 100644 internal/cmd/beta/kms/version/disable/disable.go create mode 100644 internal/cmd/beta/kms/version/disable/disable_test.go create mode 100644 internal/cmd/beta/kms/version/enable/enable.go create mode 100644 internal/cmd/beta/kms/version/enable/enable_test.go create mode 100644 internal/cmd/beta/kms/version/list/list.go create mode 100644 internal/cmd/beta/kms/version/list/list_test.go create mode 100644 internal/cmd/beta/kms/version/restore/restore.go create mode 100644 internal/cmd/beta/kms/version/restore/restore_test.go create mode 100644 internal/cmd/beta/kms/version/version.go create mode 100644 internal/cmd/beta/kms/wrappingkey/create/create.go create mode 100644 internal/cmd/beta/kms/wrappingkey/create/create_test.go create mode 100644 internal/cmd/beta/kms/wrappingkey/delete/delete.go create mode 100644 internal/cmd/beta/kms/wrappingkey/delete/delete_test.go create mode 100644 internal/cmd/beta/kms/wrappingkey/list/list.go create mode 100644 internal/cmd/beta/kms/wrappingkey/list/list_test.go create mode 100644 internal/cmd/beta/kms/wrappingkey/wrappingkey.go create mode 100644 internal/pkg/services/kms/client/client.go create mode 100644 internal/pkg/services/kms/utils/utils.go create mode 100644 internal/pkg/services/kms/utils/utils_test.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index b58eb067a..23097f8ca 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -42,5 +42,6 @@ stackit beta [flags] * [stackit](./stackit.md) - Manage STACKIT resources using the command line * [stackit beta alb](./stackit_beta_alb.md) - Manages application loadbalancers +* [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_kms.md b/docs/stackit_beta_kms.md new file mode 100644 index 000000000..e50cfd05a --- /dev/null +++ b/docs/stackit_beta_kms.md @@ -0,0 +1,37 @@ +## stackit beta kms + +Provides functionality for KMS + +### Synopsis + +Provides functionality for KMS. + +``` +stackit beta kms [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta kms" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta kms key](./stackit_beta_kms_key.md) - Manage KMS keys +* [stackit beta kms keyring](./stackit_beta_kms_keyring.md) - Manage KMS key rings +* [stackit beta kms version](./stackit_beta_kms_version.md) - Manage KMS key versions +* [stackit beta kms wrapping-key](./stackit_beta_kms_wrapping-key.md) - Manage KMS wrapping keys + diff --git a/docs/stackit_beta_kms_key.md b/docs/stackit_beta_kms_key.md new file mode 100644 index 000000000..631808f53 --- /dev/null +++ b/docs/stackit_beta_kms_key.md @@ -0,0 +1,39 @@ +## stackit beta kms key + +Manage KMS keys + +### Synopsis + +Provides functionality for key operations inside the KMS + +``` +stackit beta kms key [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta kms key" +``` + +### 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 beta kms](./stackit_beta_kms.md) - Provides functionality for KMS +* [stackit beta kms key create](./stackit_beta_kms_key_create.md) - Creates a KMS key +* [stackit beta kms key delete](./stackit_beta_kms_key_delete.md) - Deletes a KMS key +* [stackit beta kms key import](./stackit_beta_kms_key_import.md) - Import a KMS key +* [stackit beta kms key list](./stackit_beta_kms_key_list.md) - List all KMS keys +* [stackit beta kms key restore](./stackit_beta_kms_key_restore.md) - Restore a key +* [stackit beta kms key rotate](./stackit_beta_kms_key_rotate.md) - Rotate a key + diff --git a/docs/stackit_beta_kms_key_create.md b/docs/stackit_beta_kms_key_create.md new file mode 100644 index 000000000..0c3114a69 --- /dev/null +++ b/docs/stackit_beta_kms_key_create.md @@ -0,0 +1,62 @@ +## stackit beta kms key create + +Creates a KMS key + +### Synopsis + +Creates a KMS key. + +``` +stackit beta kms key create [flags] +``` + +### Examples + +``` + Create a symmetric AES key (AES-256) with the name "symm-aes-gcm" under the key ring "my-keyring-id" + $ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "aes_256_gcm" --name "symm-aes-gcm" --purpose "symmetric_encrypt_decrypt" --protection "software" + + Create an asymmetric RSA encryption key (RSA-2048) + $ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "rsa_2048_oaep_sha256" --name "prod-orders-rsa" --purpose "asymmetric_encrypt_decrypt" --protection "software" + + Create a message authentication key (HMAC-SHA512) + $ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "hmac_sha512" --name "api-mac-key" --purpose "message_authentication_code" --protection "software" + + Create an ECDSA P-256 key for signing & verification + $ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "ecdsa_p256_sha256" --name "signing-ecdsa-p256" --purpose "asymmetric_sign_verify" --protection "software" + + Create an import-only key (versions must be imported) + $ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "rsa_2048_oaep_sha256" --name "ext-managed-rsa" --purpose "asymmetric_encrypt_decrypt" --protection "software" --import-only + + Create a key and print the result as YAML + $ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "rsa_2048_oaep_sha256" --name "yaml-output-rsa" --purpose "asymmetric_encrypt_decrypt" --protection "software" --output yaml +``` + +### Options + +``` + --algorithm string En-/Decryption / signing algorithm. Possible values: ["aes_256_gcm" "rsa_2048_oaep_sha256" "rsa_3072_oaep_sha256" "rsa_4096_oaep_sha256" "rsa_4096_oaep_sha512" "hmac_sha256" "hmac_sha384" "hmac_sha512" "ecdsa_p256_sha256" "ecdsa_p384_sha384" "ecdsa_p521_sha512"] + --description string Optional description of the key + -h, --help Help for "stackit beta kms key create" + --import-only States whether versions can be created or only imported + --keyring-id string ID of the KMS key ring + --name string The display name to distinguish multiple keys + --protection string The underlying system that is responsible for protecting the key material. Possible values: ["symmetric_encrypt_decrypt" "asymmetric_encrypt_decrypt" "message_authentication_code" "asymmetric_sign_verify"] + --purpose string Purpose of the key. Possible values: ["symmetric_encrypt_decrypt" "asymmetric_encrypt_decrypt" "message_authentication_code" "asymmetric_sign_verify"] +``` + +### 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 beta kms key](./stackit_beta_kms_key.md) - Manage KMS keys + diff --git a/docs/stackit_beta_kms_key_delete.md b/docs/stackit_beta_kms_key_delete.md new file mode 100644 index 000000000..1f67c4ff8 --- /dev/null +++ b/docs/stackit_beta_kms_key_delete.md @@ -0,0 +1,41 @@ +## stackit beta kms key delete + +Deletes a KMS key + +### Synopsis + +Deletes a KMS key inside a specific key ring. + +``` +stackit beta kms key delete KEY_ID [flags] +``` + +### Examples + +``` + Delete a KMS key "MY_KEY_ID" inside the key ring "my-keyring-id" + $ stackit beta kms key delete "MY_KEY_ID" --keyring-id "my-keyring-id" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms key delete" + --keyring-id string ID of the KMS key ring where the key is stored +``` + +### 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 beta kms key](./stackit_beta_kms_key.md) - Manage KMS keys + diff --git a/docs/stackit_beta_kms_key_import.md b/docs/stackit_beta_kms_key_import.md new file mode 100644 index 000000000..efc1ba47a --- /dev/null +++ b/docs/stackit_beta_kms_key_import.md @@ -0,0 +1,46 @@ +## stackit beta kms key import + +Import a KMS key + +### Synopsis + +After encrypting the secret with the wrapping key’s public key and Base64-encoding it, import it as a new version of the specified KMS key. + +``` +stackit beta kms key import KEY_ID [flags] +``` + +### Examples + +``` + Import a new version for the given KMS key "MY_KEY_ID" from literal value + $ stackit beta kms key import "MY_KEY_ID" --keyring-id "my-keyring-id" --wrapped-key "BASE64_VALUE" --wrapping-key-id "MY_WRAPPING_KEY_ID" + + Import from a file + $ stackit beta kms key import "MY_KEY_ID" --keyring-id "my-keyring-id" --wrapped-key "@path/to/wrapped.key.b64" --wrapping-key-id "MY_WRAPPING_KEY_ID" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms key import" + --keyring-id string ID of the KMS key ring + --wrapped-key string The wrapped key material to be imported. Base64-encoded. Pass the value directly or a file path (e.g. @path/to/wrapped.key.b64) + --wrapping-key-id string The unique id of the wrapping key the key material has been wrapped with +``` + +### 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 beta kms key](./stackit_beta_kms_key.md) - Manage KMS keys + diff --git a/docs/stackit_beta_kms_key_list.md b/docs/stackit_beta_kms_key_list.md new file mode 100644 index 000000000..766bb0a5d --- /dev/null +++ b/docs/stackit_beta_kms_key_list.md @@ -0,0 +1,44 @@ +## stackit beta kms key list + +List all KMS keys + +### Synopsis + +List all KMS keys inside a key ring. + +``` +stackit beta kms key list [flags] +``` + +### Examples + +``` + List all KMS keys for the key ring "my-keyring-id" + $ stackit beta kms key list --keyring-id "my-keyring-id" + + List all KMS keys in JSON format + $ stackit beta kms key list --keyring-id "my-keyring-id" --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta kms key list" + --keyring-id string ID of the KMS key ring where the key is stored +``` + +### 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 beta kms key](./stackit_beta_kms_key.md) - Manage KMS keys + diff --git a/docs/stackit_beta_kms_key_restore.md b/docs/stackit_beta_kms_key_restore.md new file mode 100644 index 000000000..9abd9a85e --- /dev/null +++ b/docs/stackit_beta_kms_key_restore.md @@ -0,0 +1,41 @@ +## stackit beta kms key restore + +Restore a key + +### Synopsis + +Restores the given key from deletion. + +``` +stackit beta kms key restore KEY_ID [flags] +``` + +### Examples + +``` + Restore a KMS key "MY_KEY_ID" inside the key ring "my-keyring-id" that was scheduled for deletion. + $ stackit beta kms key restore "MY_KEY_ID" --keyring-id "my-keyring-id" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms key restore" + --keyring-id string ID of the KMS key ring where the key is stored +``` + +### 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 beta kms key](./stackit_beta_kms_key.md) - Manage KMS keys + diff --git a/docs/stackit_beta_kms_key_rotate.md b/docs/stackit_beta_kms_key_rotate.md new file mode 100644 index 000000000..7fdbbe3c5 --- /dev/null +++ b/docs/stackit_beta_kms_key_rotate.md @@ -0,0 +1,41 @@ +## stackit beta kms key rotate + +Rotate a key + +### Synopsis + +Rotates the given key. + +``` +stackit beta kms key rotate KEY_ID [flags] +``` + +### Examples + +``` + Rotate a KMS key "MY_KEY_ID" and increase its version inside the key ring "my-keyring-id". + $ stackit beta kms key rotate "MY_KEY_ID" --keyring-id "my-keyring-id" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms key rotate" + --keyring-id string ID of the KMS key ring where the key is stored +``` + +### 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 beta kms key](./stackit_beta_kms_key.md) - Manage KMS keys + diff --git a/docs/stackit_beta_kms_keyring.md b/docs/stackit_beta_kms_keyring.md new file mode 100644 index 000000000..6e65f3a47 --- /dev/null +++ b/docs/stackit_beta_kms_keyring.md @@ -0,0 +1,36 @@ +## stackit beta kms keyring + +Manage KMS key rings + +### Synopsis + +Provides functionality for key ring operations inside the KMS + +``` +stackit beta kms keyring [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta kms keyring" +``` + +### 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 beta kms](./stackit_beta_kms.md) - Provides functionality for KMS +* [stackit beta kms keyring create](./stackit_beta_kms_keyring_create.md) - Creates a KMS key ring +* [stackit beta kms keyring delete](./stackit_beta_kms_keyring_delete.md) - Deletes a KMS key ring +* [stackit beta kms keyring list](./stackit_beta_kms_keyring_list.md) - Lists all KMS key rings + diff --git a/docs/stackit_beta_kms_keyring_create.md b/docs/stackit_beta_kms_keyring_create.md new file mode 100644 index 000000000..d02e6e13e --- /dev/null +++ b/docs/stackit_beta_kms_keyring_create.md @@ -0,0 +1,48 @@ +## stackit beta kms keyring create + +Creates a KMS key ring + +### Synopsis + +Creates a KMS key ring. + +``` +stackit beta kms keyring create [flags] +``` + +### Examples + +``` + Create a KMS key ring with name "my-keyring" + $ stackit beta kms keyring create --name my-keyring + + Create a KMS key ring with a description + $ stackit beta kms keyring create --name my-keyring --description my-description + + Create a KMS key ring and print the result as YAML + $ stackit beta kms keyring create --name my-keyring -o yaml +``` + +### Options + +``` + --description string Optional description of the key ring + -h, --help Help for "stackit beta kms keyring create" + --name string Name of the KMS key ring +``` + +### 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 beta kms keyring](./stackit_beta_kms_keyring.md) - Manage KMS key rings + diff --git a/docs/stackit_beta_kms_keyring_delete.md b/docs/stackit_beta_kms_keyring_delete.md new file mode 100644 index 000000000..d5230f353 --- /dev/null +++ b/docs/stackit_beta_kms_keyring_delete.md @@ -0,0 +1,40 @@ +## stackit beta kms keyring delete + +Deletes a KMS key ring + +### Synopsis + +Deletes a KMS key ring. + +``` +stackit beta kms keyring delete KEYRING-ID [flags] +``` + +### Examples + +``` + Delete a KMS key ring with ID "MY_KEYRING_ID" + $ stackit beta kms keyring delete "MY_KEYRING_ID" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms keyring delete" +``` + +### 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 beta kms keyring](./stackit_beta_kms_keyring.md) - Manage KMS key rings + diff --git a/docs/stackit_beta_kms_keyring_list.md b/docs/stackit_beta_kms_keyring_list.md new file mode 100644 index 000000000..c82dae950 --- /dev/null +++ b/docs/stackit_beta_kms_keyring_list.md @@ -0,0 +1,43 @@ +## stackit beta kms keyring list + +Lists all KMS key rings + +### Synopsis + +Lists all KMS key rings. + +``` +stackit beta kms keyring list [flags] +``` + +### Examples + +``` + List all KMS key rings + $ stackit beta kms keyring list + + List all KMS key rings in JSON format + $ stackit beta kms keyring list --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta kms keyring list" +``` + +### 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 beta kms keyring](./stackit_beta_kms_keyring.md) - Manage KMS key rings + diff --git a/docs/stackit_beta_kms_version.md b/docs/stackit_beta_kms_version.md new file mode 100644 index 000000000..baf9c5ecb --- /dev/null +++ b/docs/stackit_beta_kms_version.md @@ -0,0 +1,38 @@ +## stackit beta kms version + +Manage KMS key versions + +### Synopsis + +Provides functionality for key version operations inside the KMS + +``` +stackit beta kms version [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta kms version" +``` + +### 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 beta kms](./stackit_beta_kms.md) - Provides functionality for KMS +* [stackit beta kms version destroy](./stackit_beta_kms_version_destroy.md) - Destroy a key version +* [stackit beta kms version disable](./stackit_beta_kms_version_disable.md) - Disable a key version +* [stackit beta kms version enable](./stackit_beta_kms_version_enable.md) - Enable a key version +* [stackit beta kms version list](./stackit_beta_kms_version_list.md) - List all key versions +* [stackit beta kms version restore](./stackit_beta_kms_version_restore.md) - Restore a key version + diff --git a/docs/stackit_beta_kms_version_destroy.md b/docs/stackit_beta_kms_version_destroy.md new file mode 100644 index 000000000..8a189ecf2 --- /dev/null +++ b/docs/stackit_beta_kms_version_destroy.md @@ -0,0 +1,42 @@ +## stackit beta kms version destroy + +Destroy a key version + +### Synopsis + +Removes the key material of a version. + +``` +stackit beta kms version destroy VERSION_NUMBER [flags] +``` + +### Examples + +``` + Destroy key version "42" for the key "my-key-id" inside the key ring "my-keyring-id" + $ stackit beta kms version destroy 42 --key-id "my-key-id" --keyring-id "my-keyring-id" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms version destroy" + --key-id string ID of the key + --keyring-id string ID of the KMS key ring +``` + +### 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 beta kms version](./stackit_beta_kms_version.md) - Manage KMS key versions + diff --git a/docs/stackit_beta_kms_version_disable.md b/docs/stackit_beta_kms_version_disable.md new file mode 100644 index 000000000..c2e13a87e --- /dev/null +++ b/docs/stackit_beta_kms_version_disable.md @@ -0,0 +1,42 @@ +## stackit beta kms version disable + +Disable a key version + +### Synopsis + +Disable the given key version. + +``` +stackit beta kms version disable VERSION_NUMBER [flags] +``` + +### Examples + +``` + Disable key version "42" for the key "my-key-id" inside the key ring "my-keyring-id" + $ stackit beta kms version disable 42 --key-id "my-key-id" --keyring-id "my-keyring-id" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms version disable" + --key-id string ID of the key + --keyring-id string ID of the KMS key ring +``` + +### 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 beta kms version](./stackit_beta_kms_version.md) - Manage KMS key versions + diff --git a/docs/stackit_beta_kms_version_enable.md b/docs/stackit_beta_kms_version_enable.md new file mode 100644 index 000000000..46d23bec0 --- /dev/null +++ b/docs/stackit_beta_kms_version_enable.md @@ -0,0 +1,42 @@ +## stackit beta kms version enable + +Enable a key version + +### Synopsis + +Enable the given key version. + +``` +stackit beta kms version enable VERSION_NUMBER [flags] +``` + +### Examples + +``` + Enable key version "42" for the key "my-key-id" inside the key ring "my-keyring-id" + $ stackit beta kms version enable 42 --key-id "my-key-id" --keyring-id "my-keyring-id" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms version enable" + --key-id string ID of the key + --keyring-id string ID of the KMS key ring +``` + +### 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 beta kms version](./stackit_beta_kms_version.md) - Manage KMS key versions + diff --git a/docs/stackit_beta_kms_version_list.md b/docs/stackit_beta_kms_version_list.md new file mode 100644 index 000000000..bd4a96747 --- /dev/null +++ b/docs/stackit_beta_kms_version_list.md @@ -0,0 +1,45 @@ +## stackit beta kms version list + +List all key versions + +### Synopsis + +List all versions of a given key. + +``` +stackit beta kms version list [flags] +``` + +### Examples + +``` + List all key versions for the key "my-key-id" inside the key ring "my-keyring-id" + $ stackit beta kms version list --key-id "my-key-id" --keyring-id "my-keyring-id" + + List all key versions in JSON format + $ stackit beta kms version list --key-id "my-key-id" --keyring-id "my-keyring-id" -o json +``` + +### Options + +``` + -h, --help Help for "stackit beta kms version list" + --key-id string ID of the key + --keyring-id string ID of the KMS key ring +``` + +### 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 beta kms version](./stackit_beta_kms_version.md) - Manage KMS key versions + diff --git a/docs/stackit_beta_kms_version_restore.md b/docs/stackit_beta_kms_version_restore.md new file mode 100644 index 000000000..1562d5fa2 --- /dev/null +++ b/docs/stackit_beta_kms_version_restore.md @@ -0,0 +1,42 @@ +## stackit beta kms version restore + +Restore a key version + +### Synopsis + +Restores the specified version of a key. + +``` +stackit beta kms version restore VERSION_NUMBER [flags] +``` + +### Examples + +``` + Restore key version "42" for the key "my-key-id" inside the key ring "my-keyring-id" + $ stackit beta kms version restore 42 --key-id "my-key-id" --keyring-id "my-keyring-id" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms version restore" + --key-id string ID of the key + --keyring-id string ID of the KMS key ring +``` + +### 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 beta kms version](./stackit_beta_kms_version.md) - Manage KMS key versions + diff --git a/docs/stackit_beta_kms_wrapping-key.md b/docs/stackit_beta_kms_wrapping-key.md new file mode 100644 index 000000000..c10cb4946 --- /dev/null +++ b/docs/stackit_beta_kms_wrapping-key.md @@ -0,0 +1,36 @@ +## stackit beta kms wrapping-key + +Manage KMS wrapping keys + +### Synopsis + +Provides functionality for wrapping key operations inside the KMS + +``` +stackit beta kms wrapping-key [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta kms wrapping-key" +``` + +### 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 beta kms](./stackit_beta_kms.md) - Provides functionality for KMS +* [stackit beta kms wrapping-key create](./stackit_beta_kms_wrapping-key_create.md) - Creates a KMS wrapping key +* [stackit beta kms wrapping-key delete](./stackit_beta_kms_wrapping-key_delete.md) - Deletes a KMS wrapping key +* [stackit beta kms wrapping-key list](./stackit_beta_kms_wrapping-key_list.md) - Lists all KMS wrapping keys + diff --git a/docs/stackit_beta_kms_wrapping-key_create.md b/docs/stackit_beta_kms_wrapping-key_create.md new file mode 100644 index 000000000..d4087bcbe --- /dev/null +++ b/docs/stackit_beta_kms_wrapping-key_create.md @@ -0,0 +1,49 @@ +## stackit beta kms wrapping-key create + +Creates a KMS wrapping key + +### Synopsis + +Creates a KMS wrapping key. + +``` +stackit beta kms wrapping-key create [flags] +``` + +### Examples + +``` + Create a symmetric (RSA + AES) KMS wrapping key with name "my-wrapping-key-name" in key ring with ID "my-keyring-id" + $ stackit beta kms wrapping-key create --keyring-id "my-keyring-id" --algorithm "rsa_2048_oaep_sha256_aes_256_key_wrap" --name "my-wrapping-key-name" --purpose "wrap_symmetric_key" --protection "software" + + Create an asymmetric (RSA) KMS wrapping key with name "my-wrapping-key-name" in key ring with ID "my-keyring-id" + $ stackit beta kms wrapping-key create --keyring-id "my-keyring-id" --algorithm "rsa_3072_oaep_sha256" --name "my-wrapping-key-name" --purpose "wrap_asymmetric_key" --protection "software" +``` + +### Options + +``` + --algorithm string En-/Decryption / signing algorithm. Possible values: ["rsa_2048_oaep_sha256" "rsa_3072_oaep_sha256" "rsa_4096_oaep_sha256" "rsa_4096_oaep_sha512" "rsa_2048_oaep_sha256_aes_256_key_wrap" "rsa_3072_oaep_sha256_aes_256_key_wrap" "rsa_4096_oaep_sha256_aes_256_key_wrap" "rsa_4096_oaep_sha512_aes_256_key_wrap"] + --description string Optional description of the wrapping key + -h, --help Help for "stackit beta kms wrapping-key create" + --keyring-id string ID of the KMS key ring + --name string The display name to distinguish multiple wrapping keys + --protection string The underlying system that is responsible for protecting the wrapping key material. Possible values: ["wrap_symmetric_key" "wrap_asymmetric_key"] + --purpose string Purpose of the wrapping key. Possible values: ["wrap_symmetric_key" "wrap_asymmetric_key"] +``` + +### 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 beta kms wrapping-key](./stackit_beta_kms_wrapping-key.md) - Manage KMS wrapping keys + diff --git a/docs/stackit_beta_kms_wrapping-key_delete.md b/docs/stackit_beta_kms_wrapping-key_delete.md new file mode 100644 index 000000000..0dfd43a03 --- /dev/null +++ b/docs/stackit_beta_kms_wrapping-key_delete.md @@ -0,0 +1,41 @@ +## stackit beta kms wrapping-key delete + +Deletes a KMS wrapping key + +### Synopsis + +Deletes a KMS wrapping key inside a specific key ring. + +``` +stackit beta kms wrapping-key delete WRAPPING_KEY_ID [flags] +``` + +### Examples + +``` + Delete a KMS wrapping key "MY_WRAPPING_KEY_ID" inside the key ring "my-keyring-id" + $ stackit beta kms wrapping-key delete "MY_WRAPPING_KEY_ID" --keyring-id "my-keyring-id" +``` + +### Options + +``` + -h, --help Help for "stackit beta kms wrapping-key delete" + --keyring-id string ID of the KMS key ring where the wrapping key is stored +``` + +### 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 beta kms wrapping-key](./stackit_beta_kms_wrapping-key.md) - Manage KMS wrapping keys + diff --git a/docs/stackit_beta_kms_wrapping-key_list.md b/docs/stackit_beta_kms_wrapping-key_list.md new file mode 100644 index 000000000..f17c23212 --- /dev/null +++ b/docs/stackit_beta_kms_wrapping-key_list.md @@ -0,0 +1,44 @@ +## stackit beta kms wrapping-key list + +Lists all KMS wrapping keys + +### Synopsis + +Lists all KMS wrapping keys inside a key ring. + +``` +stackit beta kms wrapping-key list [flags] +``` + +### Examples + +``` + List all KMS wrapping keys for the key ring "my-keyring-id" + $ stackit beta kms wrapping-key list --keyring-id "my-keyring-id" + + List all KMS wrapping keys in JSON format + $ stackit beta kms wrapping-key list --keyring-id "my-keyring-id" --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta kms wrapping-key list" + --keyring-id string ID of the KMS key ring where the key is stored +``` + +### 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 beta kms wrapping-key](./stackit_beta_kms_wrapping-key.md) - Manage KMS wrapping keys + diff --git a/docs/stackit_beta_sqlserverflex_instance_create.md b/docs/stackit_beta_sqlserverflex_instance_create.md index 6e8dc16a0..b297bf7b0 100644 --- a/docs/stackit_beta_sqlserverflex_instance_create.md +++ b/docs/stackit_beta_sqlserverflex_instance_create.md @@ -21,7 +21,7 @@ stackit beta sqlserverflex instance create [flags] $ stackit beta sqlserverflex instance create --name my-instance --flavor-id xxx Create a SQLServer Flex instance with name "my-instance", specify flavor by CPU and RAM, set storage size to 20 GB, and restrict access to a specific range of IP addresses. Other parameters are set to default values - $ stackit beta sqlserverflex instance create --name my-instance --cpu 1 --ram 4 --storage-size 20 --acl 1.2.3.0/24 + $ stackit beta sqlserverflex instance create --name my-instance --cpu 1 --ram 4 --storage-size 20 --acl 1.2.3.0/24 ``` ### Options diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index b1abf5662..9b07e46b5 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -36,6 +36,7 @@ stackit config set [flags] --iaas-custom-endpoint string IaaS API base URL, used in calls to this API --identity-provider-custom-client-id string Identity Provider client ID, used for user authentication --identity-provider-custom-well-known-configuration string Identity Provider well-known OpenID configuration URL, used for user authentication + --kms-custom-endpoint string KMS API base URL, used in calls to this API --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API --logme-custom-endpoint string LogMe API base URL, used in calls to this API --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 4a48b759e..9d4c83088 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -34,6 +34,7 @@ stackit config unset [flags] --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL --identity-provider-custom-client-id Identity Provider client ID, used for user authentication --identity-provider-custom-well-known-configuration Identity Provider well-known OpenID configuration URL. If unset, uses the default identity provider + --kms-custom-endpoint KMS API base URL. If unset, uses the default base URL --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL diff --git a/go.mod b/go.mod index d152751e2..fe8258d95 100644 --- a/go.mod +++ b/go.mod @@ -238,6 +238,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 github.com/sagikazarmark/locafero v0.11.0 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect diff --git a/go.sum b/go.sum index a896800c1..64b7cd08f 100644 --- a/go.sum +++ b/go.sum @@ -569,6 +569,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 h1:zxoOv7Fu+FmdsvTKiKkbmLItrMKfL+QoVtz9ReEF30E= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0/go.mod h1:KEPVoO21pC4bjy5l0nyhjUJ0+uVwVWb+k2TYrzJ8xYw= github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0 h1:/weT7P5Uwy1Qlhw0NidqtQBlbbb/dQehweDV/I9ShXg= github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 h1:dnEjyapuv8WwRN5vE2z6+4/+ZqQTBx+bX27x2nOF7Jw= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 5a007b87e..b026da770 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -38,4 +39,5 @@ func NewCmd(params *params.CmdParams) *cobra.Command { func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(sqlserverflex.NewCmd(params)) cmd.AddCommand(alb.NewCmd(params)) + cmd.AddCommand(kms.NewCmd(params)) } diff --git a/internal/cmd/beta/kms/key/create/create.go b/internal/cmd/beta/kms/key/create/create.go new file mode 100644 index 000000000..1d815e638 --- /dev/null +++ b/internal/cmd/beta/kms/key/create/create.go @@ -0,0 +1,218 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" + "github.com/stackitcloud/stackit-sdk-go/services/kms/wait" +) + +const ( + keyRingIdFlag = "keyring-id" + + algorithmFlag = "algorithm" + descriptionFlag = "description" + displayNameFlag = "name" + importOnlyFlag = "import-only" + purposeFlag = "purpose" + protectionFlag = "protection" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string + + Algorithm *string + Description *string + Name *string + ImportOnly bool // Default false + Purpose *string + Protection *string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a KMS key", + Long: "Creates a KMS key.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a symmetric AES key (AES-256) with the name "symm-aes-gcm" under the key ring "my-keyring-id"`, + `$ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "aes_256_gcm" --name "symm-aes-gcm" --purpose "symmetric_encrypt_decrypt" --protection "software"`), + examples.NewExample( + `Create an asymmetric RSA encryption key (RSA-2048)`, + `$ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "rsa_2048_oaep_sha256" --name "prod-orders-rsa" --purpose "asymmetric_encrypt_decrypt" --protection "software"`), + examples.NewExample( + `Create a message authentication key (HMAC-SHA512)`, + `$ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "hmac_sha512" --name "api-mac-key" --purpose "message_authentication_code" --protection "software"`), + examples.NewExample( + `Create an ECDSA P-256 key for signing & verification`, + `$ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "ecdsa_p256_sha256" --name "signing-ecdsa-p256" --purpose "asymmetric_sign_verify" --protection "software"`), + examples.NewExample( + `Create an import-only key (versions must be imported)`, + `$ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "rsa_2048_oaep_sha256" --name "ext-managed-rsa" --purpose "asymmetric_encrypt_decrypt" --protection "software" --import-only`), + examples.NewExample( + `Create a key and print the result as YAML`, + `$ stackit beta kms key create --keyring-id "my-keyring-id" --algorithm "rsa_2048_oaep_sha256" --name "yaml-output-rsa" --purpose "asymmetric_encrypt_decrypt" --protection "software" --output yaml`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + if !model.AssumeYes { + err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS Key?") + if err != nil { + return err + } + } + + // Call API + req, _ := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create KMS key: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for KMS key creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + Algorithm: flags.FlagToStringPointer(p, cmd, algorithmFlag), + Name: flags.FlagToStringPointer(p, cmd, displayNameFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + ImportOnly: flags.FlagToBoolValue(p, cmd, importOnlyFlag), + Purpose: flags.FlagToStringPointer(p, cmd, purposeFlag), + Protection: flags.FlagToStringPointer(p, cmd, protectionFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +type kmsKeyClient interface { + CreateKey(ctx context.Context, projectId string, regionId string, keyRingId string) kms.ApiCreateKeyRequest +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient kmsKeyClient) (kms.ApiCreateKeyRequest, error) { + req := apiClient.CreateKey(ctx, model.ProjectId, model.Region, model.KeyRingId) + + req = req.CreateKeyPayload(kms.CreateKeyPayload{ + DisplayName: model.Name, + Description: model.Description, + Algorithm: kms.CreateKeyPayloadGetAlgorithmAttributeType(model.Algorithm), + Purpose: kms.CreateKeyPayloadGetPurposeAttributeType(model.Purpose), + ImportOnly: &model.ImportOnly, + Protection: kms.CreateKeyPayloadGetProtectionAttributeType(model.Protection), + }) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *kms.Key) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s the KMS key %q. Key ID: %s\n", operationState, utils.PtrString(resp.DisplayName), utils.PtrString(resp.Id)) + } + return nil +} + +func configureFlags(cmd *cobra.Command) { + // Algorithm + var algorithmFlagOptions []string + for _, val := range kms.AllowedAlgorithmEnumValues { + algorithmFlagOptions = append(algorithmFlagOptions, string(val)) + } + cmd.Flags().Var(flags.EnumFlag(false, "", algorithmFlagOptions...), algorithmFlag, fmt.Sprintf("En-/Decryption / signing algorithm. Possible values: %q", algorithmFlagOptions)) + + // Purpose + var purposeFlagOptions []string + for _, val := range kms.AllowedPurposeEnumValues { + purposeFlagOptions = append(purposeFlagOptions, string(val)) + } + cmd.Flags().Var(flags.EnumFlag(false, "", purposeFlagOptions...), purposeFlag, fmt.Sprintf("Purpose of the key. Possible values: %q", purposeFlagOptions)) + + // Protection + var protectionFlagOptions []string + for _, val := range kms.AllowedProtectionEnumValues { + protectionFlagOptions = append(protectionFlagOptions, string(val)) + } + cmd.Flags().Var(flags.EnumFlag(false, "", protectionFlagOptions...), protectionFlag, fmt.Sprintf("The underlying system that is responsible for protecting the key material. Possible values: %q", purposeFlagOptions)) + + // All further non Enum Flags + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring") + cmd.Flags().String(displayNameFlag, "", "The display name to distinguish multiple keys") + cmd.Flags().String(descriptionFlag, "", "Optional description of the key") + cmd.Flags().Bool(importOnlyFlag, false, "States whether versions can be created or only imported") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag, algorithmFlag, purposeFlag, displayNameFlag, protectionFlag) + cobra.CheckErr(err) +} diff --git a/internal/cmd/beta/kms/key/create/create_test.go b/internal/cmd/beta/kms/key/create/create_test.go new file mode 100644 index 000000000..f6c0a024e --- /dev/null +++ b/internal/cmd/beta/kms/key/create/create_test.go @@ -0,0 +1,327 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu01" + testAlgorithm = "rsa_2048_oaep_sha256" + testDisplayName = "my-key" + testPurpose = "asymmetric_encrypt_decrypt" + testDescription = "my key description" + testImportOnly = "true" + testProtection = "software" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() +) + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + algorithmFlag: testAlgorithm, + displayNameFlag: testDisplayName, + purposeFlag: testPurpose, + descriptionFlag: testDescription, + importOnlyFlag: testImportOnly, + protectionFlag: testProtection, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + Algorithm: utils.Ptr(testAlgorithm), + Name: utils.Ptr(testDisplayName), + Purpose: utils.Ptr(testPurpose), + Description: utils.Ptr(testDescription), + ImportOnly: true, // Watch out: ImportOnly is not testImportOnly! + Protection: utils.Ptr(testProtection), + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiCreateKeyRequest)) kms.ApiCreateKeyRequest { + request := testClient.CreateKey(testCtx, testProjectId, testRegion, testKeyRingId) + request = request.CreateKeyPayload(kms.CreateKeyPayload{ + Algorithm: kms.CreateKeyPayloadGetAlgorithmAttributeType(utils.Ptr(testAlgorithm)), + DisplayName: utils.Ptr(testDisplayName), + Purpose: kms.CreateKeyPayloadGetPurposeAttributeType(utils.Ptr(testPurpose)), + Description: utils.Ptr(testDescription), + ImportOnly: utils.Ptr(true), + Protection: kms.CreateKeyPayloadGetProtectionAttributeType(utils.Ptr(testProtection)), + }) + + 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: "optional flags omitted", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, descriptionFlag) + delete(flagValues, importOnlyFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Description = nil + model.ImportOnly = false + }), + }, + { + description: "no values provided", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "key ring id missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "algorithm missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, algorithmFlag) + }), + isValid: false, + }, + { + description: "protection missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, protectionFlag) + }), + isValid: false, + }, + { + description: "name missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, displayNameFlag) + }), + isValid: false, + }, + { + description: "purpose missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, purposeFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + configureFlags(cmd) + + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiCreateKeyRequest + }{ + { + description: "base case", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no optional values", + model: fixtureInputModel(func(model *inputModel) { + model.Description = nil + model.ImportOnly = false + }), + expectedRequest: fixtureRequest().CreateKeyPayload(kms.CreateKeyPayload{ + Algorithm: kms.CreateKeyPayloadGetAlgorithmAttributeType(utils.Ptr(testAlgorithm)), + DisplayName: utils.Ptr(testDisplayName), + Purpose: kms.CreateKeyPayloadGetPurposeAttributeType(utils.Ptr(testPurpose)), + Description: nil, + ImportOnly: utils.Ptr(false), + Protection: kms.CreateKeyPayloadGetProtectionAttributeType(utils.Ptr(testProtection)), + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + model *inputModel + key *kms.Key + wantErr bool + }{ + { + description: "nil response", + key: nil, + wantErr: true, + }, + { + description: "default output", + key: &kms.Key{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, + wantErr: false, + }, + { + description: "json output", + key: &kms.Key{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.JSONOutputFormat}}, + wantErr: false, + }, + { + description: "yaml output", + key: &kms.Key{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.YAMLOutputFormat}}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.model, tt.key) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/key/delete/delete.go b/internal/cmd/beta/kms/key/delete/delete.go new file mode 100644 index 000000000..56ab3059a --- /dev/null +++ b/internal/cmd/beta/kms/key/delete/delete.go @@ -0,0 +1,149 @@ +package delete + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + kmsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + keyIdArg = "KEY_ID" + + keyRingIdFlag = "keyring-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyId string + KeyRingId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", keyIdArg), + Short: "Deletes a KMS key", + Long: "Deletes a KMS key inside a specific key ring.", + Args: args.SingleArg(keyIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a KMS key "MY_KEY_ID" inside the key ring "my-keyring-id"`, + `$ stackit beta kms key delete "MY_KEY_ID" --keyring-id "my-keyring-id"`), + ), + 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 + } + + keyName, err := kmsUtils.GetKeyName(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key name: %v", err) + keyName = model.KeyId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete key %q? (This cannot be undone)", keyName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete KMS key: %w", err) + } + + // Don't wait for a month until the deletion was performed. + // Just print the deletion date. + resp, err := apiClient.GetKeyExecute(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key: %v", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + keyId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + KeyId: keyId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiDeleteKeyRequest { + req := apiClient.DeleteKey(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + return req +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring where the key is stored") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat string, resp *kms.Key) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal output to JSON: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal output to YAML: %w", err) + } + p.Outputln(string(details)) + + default: + p.Outputf("Deletion of KMS key %s scheduled successfully for the deletion date: %s\n", utils.PtrString(resp.DisplayName), utils.PtrString(resp.DeletionDate)) + } + return nil +} diff --git a/internal/cmd/beta/kms/key/delete/delete_test.go b/internal/cmd/beta/kms/key/delete/delete_test.go new file mode 100644 index 000000000..b073b45be --- /dev/null +++ b/internal/cmd/beta/kms/key/delete/delete_test.go @@ -0,0 +1,292 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testKeyId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiDeleteKeyRequest)) kms.ApiDeleteKeyRequest { + request := testClient.DeleteKey(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no args (keyId)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "key id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiDeleteKeyRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + wantErr bool + outputFormat string + resp *kms.Key + }{ + { + description: "nil response", + resp: nil, + wantErr: true, + }, + { + description: "default output", + resp: &kms.Key{}, + wantErr: false, + }, + { + description: "json output", + outputFormat: print.JSONOutputFormat, + resp: &kms.Key{}, + wantErr: false, + }, + { + description: "yaml output", + outputFormat: print.YAMLOutputFormat, + resp: &kms.Key{}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/key/importKey/importKey.go b/internal/cmd/beta/kms/key/importKey/importKey.go new file mode 100644 index 000000000..f491f6eb7 --- /dev/null +++ b/internal/cmd/beta/kms/key/importKey/importKey.go @@ -0,0 +1,181 @@ +package importKey + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + kmsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + keyIdArg = "KEY_ID" + + keyRingIdFlag = "keyring-id" + wrappedKeyFlag = "wrapped-key" + wrappingKeyIdFlag = "wrapping-key-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string + KeyId string + WrappedKey *string + WrappingKeyId *string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("import %s", keyIdArg), + Short: "Import a KMS key", + Long: "After encrypting the secret with the wrapping key’s public key and Base64-encoding it, import it as a new version of the specified KMS key.", + Args: args.SingleArg(keyIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Import a new version for the given KMS key "MY_KEY_ID" from literal value`, + `$ stackit beta kms key import "MY_KEY_ID" --keyring-id "my-keyring-id" --wrapped-key "BASE64_VALUE" --wrapping-key-id "MY_WRAPPING_KEY_ID"`), + examples.NewExample( + `Import from a file`, + `$ stackit beta kms key import "MY_KEY_ID" --keyring-id "my-keyring-id" --wrapped-key "@path/to/wrapped.key.b64" --wrapping-key-id "MY_WRAPPING_KEY_ID"`, + ), + ), + + 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 + } + + keyName, err := kmsUtils.GetKeyName(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key name: %v", err) + keyName = model.KeyId + } + keyRingName, err := kmsUtils.GetKeyRingName(ctx, apiClient, model.ProjectId, model.KeyRingId, model.Region) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key ring name: %v", err) + keyRingName = model.KeyRingId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to import a new version for the KMS Key %q inside the key ring %q?", keyName, keyRingName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, _ := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("import KMS key: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, keyRingName, keyName, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + keyId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // WrappedKey needs to be base64 encoded + var wrappedKey *string = flags.FlagToStringPointer(p, cmd, wrappedKeyFlag) + _, err := base64.StdEncoding.DecodeString(*wrappedKey) + if err != nil || *wrappedKey == "" { + return nil, &cliErr.FlagValidationError{ + Flag: wrappedKeyFlag, + Details: "The 'wrappedKey' argument is required and needs to be base64 encoded (whether provided inline or via file).", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyId: keyId, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + WrappedKey: wrappedKey, + WrappingKeyId: flags.FlagToStringPointer(p, cmd, wrappingKeyIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +type kmsKeyClient interface { + ImportKey(ctx context.Context, projectId string, regionId string, keyRingId string, keyId string) kms.ApiImportKeyRequest +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient kmsKeyClient) (kms.ApiImportKeyRequest, error) { + req := apiClient.ImportKey(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + + req = req.ImportKeyPayload(kms.ImportKeyPayload{ + WrappedKey: model.WrappedKey, + WrappingKeyId: model.WrappingKeyId, + }) + return req, nil +} + +func outputResult(p *print.Printer, outputFormat, keyRingName, keyName string, resp *kms.Version) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + default: + p.Outputf("Imported a new version for the key %q inside the key ring %q\n", keyName, keyRingName) + } + + return nil +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring") + cmd.Flags().Var(flags.ReadFromFileFlag(), wrappedKeyFlag, "The wrapped key material to be imported. Base64-encoded. Pass the value directly or a file path (e.g. @path/to/wrapped.key.b64)") + cmd.Flags().Var(flags.UUIDFlag(), wrappingKeyIdFlag, "The unique id of the wrapping key the key material has been wrapped with") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag, wrappedKeyFlag, wrappingKeyIdFlag) + cobra.CheckErr(err) +} diff --git a/internal/cmd/beta/kms/key/importKey/importKey_test.go b/internal/cmd/beta/kms/key/importKey/importKey_test.go new file mode 100644 index 000000000..37192e9d1 --- /dev/null +++ b/internal/cmd/beta/kms/key/importKey/importKey_test.go @@ -0,0 +1,362 @@ +package importKey + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu01" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() + testWrappingKeyId = uuid.NewString() + testWrappedKey = "SnVzdCBzYXlpbmcgaGV5Oyk=" +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testKeyId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + wrappedKeyFlag: testWrappedKey, + wrappingKeyIdFlag: testWrappingKeyId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + WrappedKey: &testWrappedKey, + WrappingKeyId: &testWrappingKeyId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiImportKeyRequest)) kms.ApiImportKeyRequest { + request := testClient.ImportKey(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId) + request = request.ImportKeyPayload(kms.ImportKeyPayload{ + WrappedKey: &testWrappedKey, + WrappingKeyId: &testWrappingKeyId, + }) + + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no args (keyId)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values provided", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing (required)", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "key id invalid 2", + argValues: []string{"invalid-key"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "wrapping key id missing (required)", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, wrappingKeyIdFlag) + }), + isValid: false, + }, + { + description: "wrapping key id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[wrappingKeyIdFlag] = "" + }), + isValid: false, + }, + { + description: "wrapping key id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[wrappingKeyIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "wrapped key missing (required)", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, wrappedKeyFlag) + }), + isValid: false, + }, + { + description: "wrapped key invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[wrappedKeyFlag] = "" + }), + isValid: false, + }, + { + description: "wrapped key invalid 2 - not base64", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[wrappedKeyFlag] = "Not Base 64" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiImportKeyRequest + }{ + { + description: "base case", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + version *kms.Version + outputFormat string + keyRingName string + keyName string + wantErr bool + }{ + { + description: "nil response", + version: nil, + wantErr: true, + }, + { + description: "default output", + version: &kms.Version{}, + keyRingName: "my-key-ring", + keyName: "my-key", + wantErr: false, + }, + { + description: "json output", + version: &kms.Version{}, + outputFormat: print.JSONOutputFormat, + keyRingName: "my-key-ring", + keyName: "my-key", + wantErr: false, + }, + { + description: "yaml output", + version: &kms.Version{}, + outputFormat: print.YAMLOutputFormat, + keyRingName: "my-key-ring", + keyName: "my-key", + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.keyRingName, tt.keyName, tt.version) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/key/key.go b/internal/cmd/beta/kms/key/key.go new file mode 100644 index 000000000..4b2f7d8fa --- /dev/null +++ b/internal/cmd/beta/kms/key/key.go @@ -0,0 +1,36 @@ +package key + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/importKey" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/restore" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/rotate" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "key", + Short: "Manage KMS keys", + Long: "Provides functionality for key operations inside the KMS", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(importKey.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(restore.NewCmd(params)) + cmd.AddCommand(rotate.NewCmd(params)) +} diff --git a/internal/cmd/beta/kms/key/list/list.go b/internal/cmd/beta/kms/key/list/list.go new file mode 100644 index 000000000..aa337b5b7 --- /dev/null +++ b/internal/cmd/beta/kms/key/list/list.go @@ -0,0 +1,148 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + keyRingIdFlag = "keyring-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List all KMS keys", + Long: "List all KMS keys inside a key ring.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all KMS keys for the key ring "my-keyring-id"`, + `$ stackit beta kms key list --keyring-id "my-keyring-id"`), + examples.NewExample( + `List all KMS keys in JSON format`, + `$ stackit beta kms key list --keyring-id "my-keyring-id" --output-format json`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get KMS Keys: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, model.ProjectId, model.KeyRingId, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiListKeysRequest { + req := apiClient.ListKeys(ctx, model.ProjectId, model.Region, model.KeyRingId) + return req +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring where the key is stored") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat, projectId, keyRingId string, resp *kms.KeyList) error { + if resp == nil || resp.Keys == nil { + return fmt.Errorf("response was nil / empty") + } + + keys := *resp.Keys + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(keys, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS Keys list: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(keys, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS Keys list: %w", err) + } + p.Outputln(string(details)) + + default: + if len(keys) == 0 { + p.Outputf("No keys found for project %q under the key ring %q\n", projectId, keyRingId) + return nil + } + table := tables.NewTable() + table.SetHeader("ID", "NAME", "SCOPE", "ALGORITHM", "DELETION DATE", "STATUS") + + for _, key := range keys { + table.AddRow( + utils.PtrString(key.Id), + utils.PtrString(key.DisplayName), + utils.PtrString(key.Purpose), + utils.PtrString(key.Algorithm), + utils.PtrString(key.DeletionDate), + utils.PtrString(key.State), + ) + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + } + return nil +} diff --git a/internal/cmd/beta/kms/key/list/list_test.go b/internal/cmd/beta/kms/key/list/list_test.go new file mode 100644 index 000000000..17d773bd5 --- /dev/null +++ b/internal/cmd/beta/kms/key/list/list_test.go @@ -0,0 +1,258 @@ +package list + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu01" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() +) + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiListKeysRequest)) kms.ApiListKeysRequest { + request := testClient.ListKeys(testCtx, testProjectId, testRegion, testKeyRingId) + 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: "missing keyRingId", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "invalid keyRingId 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "invalid keyRingId 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "Not a valid uuid" + }), + isValid: false, + }, + { + 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) { + cmd := &cobra.Command{} + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + configureFlags(cmd) + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiListKeysRequest + }{ + { + description: "base case", + 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(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + resp *kms.KeyList + projectId string + keyRingId string + outputFormat string + wantErr bool + }{ + { + description: "nil response", + resp: nil, + projectId: uuid.NewString(), + keyRingId: uuid.NewString(), + wantErr: true, + }, + { + description: "empty response", + resp: &kms.KeyList{}, + projectId: uuid.NewString(), + keyRingId: uuid.NewString(), + wantErr: true, + }, + { + description: "default output", + resp: &kms.KeyList{Keys: &[]kms.Key{}}, + projectId: uuid.NewString(), + keyRingId: uuid.NewString(), + wantErr: false, + }, + { + description: "json output", + resp: &kms.KeyList{Keys: &[]kms.Key{}}, + projectId: uuid.NewString(), + keyRingId: uuid.NewString(), + outputFormat: print.JSONOutputFormat, + wantErr: false, + }, + { + description: "yaml output", + resp: &kms.KeyList{Keys: &[]kms.Key{}}, + projectId: uuid.NewString(), + keyRingId: uuid.NewString(), + outputFormat: print.YAMLOutputFormat, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.projectId, tt.keyRingId, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/key/restore/restore.go b/internal/cmd/beta/kms/key/restore/restore.go new file mode 100644 index 000000000..05494a97a --- /dev/null +++ b/internal/cmd/beta/kms/key/restore/restore.go @@ -0,0 +1,148 @@ +package restore + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + kmsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + keyIdArg = "KEY_ID" + + keyRingIdFlag = "keyring-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyId string + KeyRingId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("restore %s", keyIdArg), + Short: "Restore a key", + Long: "Restores the given key from deletion.", + Args: args.SingleArg(keyIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Restore a KMS key "MY_KEY_ID" inside the key ring "my-keyring-id" that was scheduled for deletion.`, + `$ stackit beta kms key restore "MY_KEY_ID" --keyring-id "my-keyring-id"`), + ), + 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 + } + + keyName, err := kmsUtils.GetKeyName(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key name: %v", err) + keyName = model.KeyId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to restore key %q? (This cannot be undone)", keyName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("restore KMS key: %w", err) + } + + // Grab the key after the restore was applied to display the new state to the user. + resp, err := apiClient.GetKeyExecute(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key: %v", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + keyId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + KeyId: keyId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiRestoreKeyRequest { + req := apiClient.RestoreKey(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + return req +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring where the key is stored") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat string, resp *kms.Key) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal output to JSON: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal output to YAML: %w", err) + } + p.Outputln(string(details)) + + default: + p.Outputf("Successfully restored KMS key %q\n", utils.PtrString(resp.DisplayName)) + } + return nil +} diff --git a/internal/cmd/beta/kms/key/restore/restore_test.go b/internal/cmd/beta/kms/key/restore/restore_test.go new file mode 100644 index 000000000..69860461d --- /dev/null +++ b/internal/cmd/beta/kms/key/restore/restore_test.go @@ -0,0 +1,292 @@ +package restore + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testKeyId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiRestoreKeyRequest)) kms.ApiRestoreKeyRequest { + request := testClient.RestoreKey(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no args (keyId)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "key id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiRestoreKeyRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + wantErr bool + outputFormat string + resp *kms.Key + }{ + { + description: "nil response", + resp: nil, + wantErr: true, + }, + { + description: "default output", + resp: &kms.Key{}, + wantErr: false, + }, + { + description: "json output", + outputFormat: print.JSONOutputFormat, + resp: &kms.Key{}, + wantErr: false, + }, + { + description: "yaml output", + outputFormat: print.YAMLOutputFormat, + resp: &kms.Key{}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/key/rotate/rotate.go b/internal/cmd/beta/kms/key/rotate/rotate.go new file mode 100644 index 000000000..14e4ff15f --- /dev/null +++ b/internal/cmd/beta/kms/key/rotate/rotate.go @@ -0,0 +1,144 @@ +package rotate + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + kmsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + keyIdArg = "KEY_ID" + + keyRingIdFlag = "keyring-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyId string + KeyRingId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("rotate %s", keyIdArg), + Short: "Rotate a key", + Long: "Rotates the given key.", + Args: args.SingleArg(keyIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Rotate a KMS key "MY_KEY_ID" and increase its version inside the key ring "my-keyring-id".`, + `$ stackit beta kms key rotate "MY_KEY_ID" --keyring-id "my-keyring-id"`), + ), + 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 + } + + keyName, err := kmsUtils.GetKeyName(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key name: %v", err) + keyName = model.KeyId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to rotate the key %q? (this cannot be undone)", keyName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("rotate KMS key: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + keyId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + KeyId: keyId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiRotateKeyRequest { + req := apiClient.RotateKey(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) + return req +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring where the key is stored") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS key version: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS key version: %w", err) + } + p.Outputln(string(details)) + + default: + p.Outputf("Rotated key %s\n", utils.PtrString(resp.KeyId)) + } + + return nil +} diff --git a/internal/cmd/beta/kms/key/rotate/rotate_test.go b/internal/cmd/beta/kms/key/rotate/rotate_test.go new file mode 100644 index 000000000..28d84295e --- /dev/null +++ b/internal/cmd/beta/kms/key/rotate/rotate_test.go @@ -0,0 +1,292 @@ +package rotate + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testKeyId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiRotateKeyRequest)) kms.ApiRotateKeyRequest { + request := testClient.RotateKey(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no args (keyId)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "key id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiRotateKeyRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + resp *kms.Version + outputFormat string + wantErr bool + }{ + { + description: "nil response", + resp: nil, + wantErr: true, + }, + { + description: "default output", + resp: &kms.Version{}, + wantErr: false, + }, + { + description: "json output", + resp: &kms.Version{}, + outputFormat: print.JSONOutputFormat, + wantErr: false, + }, + { + description: "yaml output", + resp: &kms.Version{}, + outputFormat: print.YAMLOutputFormat, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/keyring/create/create.go b/internal/cmd/beta/kms/keyring/create/create.go new file mode 100644 index 000000000..b4103e957 --- /dev/null +++ b/internal/cmd/beta/kms/keyring/create/create.go @@ -0,0 +1,182 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" + "github.com/stackitcloud/stackit-sdk-go/services/kms/wait" +) + +const ( + keyRingNameFlag = "name" + descriptionFlag = "description" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyringName string + Description string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a KMS key ring", + Long: "Creates a KMS key ring.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a KMS key ring with name "my-keyring"`, + "$ stackit beta kms keyring create --name my-keyring"), + examples.NewExample( + `Create a KMS key ring with a description`, + "$ stackit beta kms keyring create --name my-keyring --description my-description"), + examples.NewExample( + `Create a KMS key ring and print the result as YAML`, + "$ stackit beta kms keyring create --name my-keyring -o yaml"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + if !model.AssumeYes { + err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS key ring?") + if err != nil { + return err + } + } + + // Call API + req, _ := buildRequest(ctx, model, apiClient) + + keyRing, err := req.Execute() + if err != nil { + return fmt.Errorf("create KMS key ring: %w", err) + } + + // Prevent potential nil pointer dereference + if keyRing == nil || keyRing.Id == nil { + return fmt.Errorf("API call succeeded but returned an invalid response (missing key ring ID)") + } + + keyRingId := *keyRing.Id + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for KMS key ring creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model, keyRing) + }, + } + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + keyringName := flags.FlagToStringValue(p, cmd, keyRingNameFlag) + + if keyringName == "" { + return nil, &cliErr.DSAInputPlanError{ + Cmd: cmd, + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyringName: keyringName, + Description: flags.FlagToStringValue(p, cmd, descriptionFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +type kmsKeyringClient interface { + CreateKeyRing(ctx context.Context, projectId string, regionId string) kms.ApiCreateKeyRingRequest +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient kmsKeyringClient) (kms.ApiCreateKeyRingRequest, error) { + req := apiClient.CreateKeyRing(ctx, model.ProjectId, model.Region) + + req = req.CreateKeyRingPayload(kms.CreateKeyRingPayload{ + DisplayName: &model.KeyringName, + + // Description should be empty by default and only be overwritten with the descriptionFlag if it was passed. + Description: &model.Description, + }) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *kms.KeyRing) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS key ring: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS key ring: %w", err) + } + p.Outputln(string(details)) + + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s key ring. KMS key ring ID: %s\n", operationState, utils.PtrString(resp.Id)) + } + return nil +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(keyRingNameFlag, "", "Name of the KMS key ring") + cmd.Flags().String(descriptionFlag, "", "Optional description of the key ring") + + err := flags.MarkFlagsRequired(cmd, keyRingNameFlag) + cobra.CheckErr(err) +} diff --git a/internal/cmd/beta/kms/keyring/create/create_test.go b/internal/cmd/beta/kms/keyring/create/create_test.go new file mode 100644 index 000000000..8cdf81219 --- /dev/null +++ b/internal/cmd/beta/kms/keyring/create/create_test.go @@ -0,0 +1,249 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu01" + testKeyRingName = "my-key-ring" + testDescription = "my-description" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() +) + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingNameFlag: testKeyRingName, + descriptionFlag: testDescription, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyringName: testKeyRingName, + Description: testDescription, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiCreateKeyRingRequest)) kms.ApiCreateKeyRingRequest { + request := testClient.CreateKeyRing(testCtx, testProjectId, testRegion) + request = request.CreateKeyRingPayload(kms.CreateKeyRingPayload{ + DisplayName: utils.Ptr(testKeyRingName), + Description: utils.Ptr(testDescription), + }) + + 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: "optional flags omitted", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, descriptionFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Description = "" + }), + }, + { + description: "no values provided", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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) { + cmd := &cobra.Command{} + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + configureFlags(cmd) + + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiCreateKeyRingRequest + }{ + { + description: "base case", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + model *inputModel + description string + keyRing *kms.KeyRing + wantErr bool + }{ + { + description: "nil response", + keyRing: nil, + wantErr: true, + }, + { + description: "default output", + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, + keyRing: &kms.KeyRing{}, + wantErr: false, + }, + { + description: "json output", + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.JSONOutputFormat}}, + keyRing: &kms.KeyRing{}, + wantErr: false, + }, + { + description: "yaml output", + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.YAMLOutputFormat}}, + keyRing: &kms.KeyRing{}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.model, tt.keyRing) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/keyring/delete/delete.go b/internal/cmd/beta/kms/keyring/delete/delete.go new file mode 100644 index 000000000..307729745 --- /dev/null +++ b/internal/cmd/beta/kms/keyring/delete/delete.go @@ -0,0 +1,105 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + kmsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + keyRingIdArg = "KEYRING-ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", keyRingIdArg), + Short: "Deletes a KMS key ring", + Long: "Deletes a KMS key ring.", + Args: args.SingleArg(keyRingIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a KMS key ring with ID "MY_KEYRING_ID"`, + `$ stackit beta kms keyring delete "MY_KEYRING_ID"`), + ), + 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 + } + + keyRingLabel, err := kmsUtils.GetKeyRingName(ctx, apiClient, model.ProjectId, model.KeyRingId, model.Region) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key ring name: %v", err) + keyRingLabel = model.KeyRingId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete key ring %q? (this cannot be undone)", keyRingLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete KMS key ring: %w", err) + } + + // No async wait required; key ring deletion is synchronous. + + // Don't output anything. It's a deletion. + params.Printer.Info("Deleted the key ring %q\n", keyRingLabel) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + keyRingId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: keyRingId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiDeleteKeyRingRequest { + req := apiClient.DeleteKeyRing(ctx, model.ProjectId, model.Region, model.KeyRingId) + return req +} diff --git a/internal/cmd/beta/kms/keyring/delete/delete_test.go b/internal/cmd/beta/kms/keyring/delete/delete_test.go new file mode 100644 index 000000000..c53e7d7f0 --- /dev/null +++ b/internal/cmd/beta/kms/keyring/delete/delete_test.go @@ -0,0 +1,212 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu01" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testKeyRingId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +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 +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiDeleteKeyRingRequest)) kms.ApiDeleteKeyRingRequest { + request := testClient.DeleteKeyRing(testCtx, testProjectId, testRegion, testKeyRingId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no args (keyRingId)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "invalid keyRingId", + argValues: fixtureArgValues(func(argValues []string) { + argValues[0] = "Not an uuid" + }), + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + 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) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiDeleteKeyRingRequest + }{ + { + description: "base case", + 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(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/kms/keyring/keyring.go b/internal/cmd/beta/kms/keyring/keyring.go new file mode 100644 index 000000000..7a42ce131 --- /dev/null +++ b/internal/cmd/beta/kms/keyring/keyring.go @@ -0,0 +1,30 @@ +package keyring + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "keyring", + Short: "Manage KMS key rings", + Long: "Provides functionality for key ring operations inside the KMS", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) +} diff --git a/internal/cmd/beta/kms/keyring/list/list.go b/internal/cmd/beta/kms/keyring/list/list.go new file mode 100644 index 000000000..d12b9ae87 --- /dev/null +++ b/internal/cmd/beta/kms/keyring/list/list.go @@ -0,0 +1,133 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +type inputModel struct { + *globalflags.GlobalFlagModel +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all KMS key rings", + Long: "Lists all KMS key rings.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all KMS key rings`, + "$ stackit beta kms keyring list"), + examples.NewExample( + `List all KMS key rings in JSON format`, + "$ stackit beta kms keyring list --output-format json"), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get KMS key rings: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, model.ProjectId, resp) + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*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 *kms.APIClient) kms.ApiListKeyRingsRequest { + req := apiClient.ListKeyRings(ctx, model.ProjectId, model.Region) + return req +} + +func outputResult(p *print.Printer, outputFormat, projectId string, resp *kms.KeyRingList) error { + if resp == nil || resp.KeyRings == nil { + return fmt.Errorf("response was nil / empty") + } + + keyRings := *resp.KeyRings + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(keyRings, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS key rings list: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(keyRings, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS key rings list: %w", err) + } + p.Outputln(string(details)) + + default: + if len(keyRings) == 0 { + p.Outputf("No key rings found for project %q\n", projectId) + return nil + } + + table := tables.NewTable() + table.SetHeader("ID", "NAME", "STATUS") + + for i := range keyRings { + keyRing := keyRings[i] + table.AddRow( + utils.PtrString(keyRing.Id), + utils.PtrString(keyRing.DisplayName), + utils.PtrString(keyRing.State), + ) + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + } + + return nil +} diff --git a/internal/cmd/beta/kms/keyring/list/list_test.go b/internal/cmd/beta/kms/keyring/list/list_test.go new file mode 100644 index 000000000..d85681c99 --- /dev/null +++ b/internal/cmd/beta/kms/keyring/list/list_test.go @@ -0,0 +1,229 @@ +package list + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu01" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() +) + +// Flags +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 +} + +// Input Model +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 +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiListKeyRingsRequest)) kms.ApiListKeyRingsRequest { + request := testClient.ListKeyRings(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: "no values provided", + flagValues: map[string]string{}, + 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) { + cmd := &cobra.Command{} + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiListKeyRingsRequest + }{ + { + description: "base case", + 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(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + projectId string + resp *kms.KeyRingList + outputFormat string + projectLabel string + wantErr bool + }{ + { + description: "nil response", + resp: nil, + projectId: uuid.NewString(), + projectLabel: "my-project", + wantErr: true, + }, + { + description: "empty response", + resp: &kms.KeyRingList{}, + projectId: uuid.NewString(), + projectLabel: "my-project", + wantErr: true, + }, + { + description: "default output", + projectId: uuid.NewString(), + resp: &kms.KeyRingList{KeyRings: &[]kms.KeyRing{}}, + projectLabel: "my-project", + wantErr: false, + }, + { + description: "json output", + projectId: uuid.NewString(), + resp: &kms.KeyRingList{KeyRings: &[]kms.KeyRing{}}, + outputFormat: print.JSONOutputFormat, + wantErr: false, + }, + { + description: "yaml output", + projectId: uuid.NewString(), + resp: &kms.KeyRingList{KeyRings: &[]kms.KeyRing{}}, + outputFormat: print.YAMLOutputFormat, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.projectId, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/kms.go b/internal/cmd/beta/kms/kms.go new file mode 100644 index 000000000..8eeb2b0d2 --- /dev/null +++ b/internal/cmd/beta/kms/kms.go @@ -0,0 +1,32 @@ +package kms + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "kms", + Short: "Provides functionality for KMS", + Long: "Provides functionality for KMS.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(keyring.NewCmd(params)) + cmd.AddCommand(wrappingkey.NewCmd(params)) + cmd.AddCommand(key.NewCmd(params)) + cmd.AddCommand(version.NewCmd(params)) +} diff --git a/internal/cmd/beta/kms/version/destroy/destroy.go b/internal/cmd/beta/kms/version/destroy/destroy.go new file mode 100644 index 000000000..470099c66 --- /dev/null +++ b/internal/cmd/beta/kms/version/destroy/destroy.go @@ -0,0 +1,147 @@ +package destroy + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + versionNumberArg = "VERSION_NUMBER" + + keyRingIdFlag = "keyring-id" + keyIdFlag = "key-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string + KeyId string + VersionNumber int64 +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("destroy %s", versionNumberArg), + Short: "Destroy a key version", + Long: "Removes the key material of a version.", + Args: args.SingleArg(versionNumberArg, nil), + Example: examples.Build( + examples.NewExample( + `Destroy key version "42" for the key "my-key-id" inside the key ring "my-keyring-id"`, + `$ stackit beta kms version destroy 42 --key-id "my-key-id" --keyring-id "my-keyring-id"`), + ), + 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 + } + + // This operation can be undone. Don't ask for confirmation! + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("destroy key Version: %w", err) + } + + // Get the key version in its state afterwards + resp, err := apiClient.GetVersionExecute(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key version: %v", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + versionStr := inputArgs[0] + versionNumber, err := strconv.ParseInt(versionStr, 10, 64) + if err != nil || versionNumber < 0 { + return nil, &errors.ArgValidationError{ + Arg: versionNumberArg, + Details: fmt.Sprintf("invalid value %q: must be a positive integer", versionStr), + } + } + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + KeyId: flags.FlagToStringValue(p, cmd, keyIdFlag), + VersionNumber: versionNumber, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiDestroyVersionRequest { + return apiClient.DestroyVersion(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring") + cmd.Flags().Var(flags.UUIDFlag(), keyIdFlag, "ID of the key") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag, keyIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + default: + p.Outputf("Destroyed version %d of the key %q\n", utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) + } + + return nil +} diff --git a/internal/cmd/beta/kms/version/destroy/destroy_test.go b/internal/cmd/beta/kms/version/destroy/destroy_test.go new file mode 100644 index 000000000..898d1a084 --- /dev/null +++ b/internal/cmd/beta/kms/version/destroy/destroy_test.go @@ -0,0 +1,319 @@ +package destroy + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" + testVersionNumber = int64(1) + testVersionNumberString = "1" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVersionNumberString, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + keyIdFlag: testKeyId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + VersionNumber: testVersionNumber, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiDestroyVersionRequest)) kms.ApiDestroyVersionRequest { + request := testClient.DestroyVersion(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId, testVersionNumber) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no args (versionNumber)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyIdFlag) + }), + isValid: false, + }, + { + description: "key id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "" + }), + isValid: false, + }, + { + description: "key id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "version number invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "version number invalid 2", + argValues: []string{"Not a Number!"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiDestroyVersionRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + wantErr bool + outputFormat string + resp *kms.Version + }{ + { + description: "nil response", + resp: nil, + wantErr: true, + }, + { + description: "default output", + resp: &kms.Version{}, + wantErr: false, + }, + { + description: "json output", + resp: &kms.Version{}, + wantErr: false, + }, + { + description: "yaml output", + resp: &kms.Version{}, + outputFormat: print.YAMLOutputFormat, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/version/disable/disable.go b/internal/cmd/beta/kms/version/disable/disable.go new file mode 100644 index 000000000..095a870e4 --- /dev/null +++ b/internal/cmd/beta/kms/version/disable/disable.go @@ -0,0 +1,149 @@ +package disable + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + versionNumberArg = "VERSION_NUMBER" + + keyRingIdFlag = "keyring-id" + keyIdFlag = "key-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string + KeyId string + VersionNumber int64 +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("disable %s", versionNumberArg), + Short: "Disable a key version", + Long: "Disable the given key version.", + Args: args.SingleArg(versionNumberArg, nil), + Example: examples.Build( + examples.NewExample( + `Disable key version "42" for the key "my-key-id" inside the key ring "my-keyring-id"`, + `$ stackit beta kms version disable 42 --key-id "my-key-id" --keyring-id "my-keyring-id"`), + ), + 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 + } + + // This operation can be undone. Don't ask for confirmation! + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("disable key version: %w", err) + } + + // kms v1.0.0 has a waiter, but it get's stuck even though the disable api call was already successfully completed. + + // Get the key version in its state afterwards + resp, err := apiClient.GetVersionExecute(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key version: %v", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + versionStr := inputArgs[0] + versionNumber, err := strconv.ParseInt(versionStr, 10, 64) + if err != nil || versionNumber < 0 { + return nil, &errors.ArgValidationError{ + Arg: versionNumberArg, + Details: fmt.Sprintf("invalid value %q: must be a positive integer", versionStr), + } + } + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + KeyId: flags.FlagToStringValue(p, cmd, keyIdFlag), + VersionNumber: versionNumber, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiDisableVersionRequest { + return apiClient.DisableVersion(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring") + cmd.Flags().Var(flags.UUIDFlag(), keyIdFlag, "ID of the key") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag, keyIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + default: + p.Outputf("Disabled version %d of the key %q\n", utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) + } + + return nil +} diff --git a/internal/cmd/beta/kms/version/disable/disable_test.go b/internal/cmd/beta/kms/version/disable/disable_test.go new file mode 100644 index 000000000..66ec302b8 --- /dev/null +++ b/internal/cmd/beta/kms/version/disable/disable_test.go @@ -0,0 +1,320 @@ +package disable + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" + testVersionNumber = int64(1) + testVersionNumberString = "1" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVersionNumberString, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + keyIdFlag: testKeyId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + VersionNumber: testVersionNumber, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiDisableVersionRequest)) kms.ApiDisableVersionRequest { + request := testClient.DisableVersion(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId, testVersionNumber) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no args (versionNumber)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyIdFlag) + }), + isValid: false, + }, + { + description: "key id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "" + }), + isValid: false, + }, + { + description: "key id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "version number invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "version number invalid 2", + argValues: []string{"Not a Number!"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiDisableVersionRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + wantErr bool + outputFormat string + resp *kms.Version + }{ + { + description: "nil response", + resp: nil, + wantErr: true, + }, + { + description: "default output", + resp: &kms.Version{}, + wantErr: false, + }, + { + description: "json output", + outputFormat: print.JSONOutputFormat, + resp: &kms.Version{}, + wantErr: false, + }, + { + description: "yaml output", + outputFormat: print.YAMLOutputFormat, + resp: &kms.Version{}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/version/enable/enable.go b/internal/cmd/beta/kms/version/enable/enable.go new file mode 100644 index 000000000..a2530996c --- /dev/null +++ b/internal/cmd/beta/kms/version/enable/enable.go @@ -0,0 +1,160 @@ +package enable + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" + "github.com/stackitcloud/stackit-sdk-go/services/kms/wait" +) + +const ( + versionNumberArg = "VERSION_NUMBER" + + keyRingIdFlag = "keyring-id" + keyIdFlag = "key-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string + KeyId string + VersionNumber int64 +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("enable %s", versionNumberArg), + Short: "Enable a key version", + Long: "Enable the given key version.", + Args: args.SingleArg(versionNumberArg, nil), + Example: examples.Build( + examples.NewExample( + `Enable key version "42" for the key "my-key-id" inside the key ring "my-keyring-id"`, + `$ stackit beta kms version enable 42 --key-id "my-key-id" --keyring-id "my-keyring-id"`), + ), + 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 + } + + // This operation can be undone. Don't ask for confirmation! + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("enable key version: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for key version to be enabled: %w", err) + } + s.Stop() + } + + // Get the key version in its state afterwards + resp, err := apiClient.GetVersionExecute(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key version: %v", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + versionStr := inputArgs[0] + versionNumber, err := strconv.ParseInt(versionStr, 10, 64) + if err != nil || versionNumber < 0 { + return nil, &errors.ArgValidationError{ + Arg: versionNumberArg, + Details: fmt.Sprintf("invalid value %q: must be a positive integer", versionStr), + } + } + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + KeyId: flags.FlagToStringValue(p, cmd, keyIdFlag), + VersionNumber: versionNumber, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiEnableVersionRequest { + return apiClient.EnableVersion(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring") + cmd.Flags().Var(flags.UUIDFlag(), keyIdFlag, "ID of the key") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag, keyIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS key: %w", err) + } + p.Outputln(string(details)) + + default: + p.Outputf("Enabled version %d of the key %q\n", utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) + } + + return nil +} diff --git a/internal/cmd/beta/kms/version/enable/enable_test.go b/internal/cmd/beta/kms/version/enable/enable_test.go new file mode 100644 index 000000000..381f7885a --- /dev/null +++ b/internal/cmd/beta/kms/version/enable/enable_test.go @@ -0,0 +1,320 @@ +package enable + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" + testVersionNumber = int64(1) + testVersionNumberString = "1" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVersionNumberString, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + keyIdFlag: testKeyId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + VersionNumber: testVersionNumber, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiEnableVersionRequest)) kms.ApiEnableVersionRequest { + request := testClient.EnableVersion(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId, testVersionNumber) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no args (versionNumber)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyIdFlag) + }), + isValid: false, + }, + { + description: "key id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "" + }), + isValid: false, + }, + { + description: "key id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "version number invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "version number invalid 2", + argValues: []string{"Not a Number!"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiEnableVersionRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + wantErr bool + outputFormat string + resp *kms.Version + }{ + { + description: "nil response", + resp: nil, + wantErr: true, + }, + { + description: "default output", + resp: &kms.Version{}, + wantErr: false, + }, + { + description: "json output", + resp: &kms.Version{}, + outputFormat: print.JSONOutputFormat, + wantErr: false, + }, + { + description: "yaml output", + resp: &kms.Version{}, + outputFormat: print.YAMLOutputFormat, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/version/list/list.go b/internal/cmd/beta/kms/version/list/list.go new file mode 100644 index 000000000..c73b2a949 --- /dev/null +++ b/internal/cmd/beta/kms/version/list/list.go @@ -0,0 +1,150 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + keyRingIdFlag = "keyring-id" + keyIdFlag = "key-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string + KeyId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List all key versions", + Long: "List all versions of a given key.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all key versions for the key "my-key-id" inside the key ring "my-keyring-id"`, + `$ stackit beta kms version list --key-id "my-key-id" --keyring-id "my-keyring-id"`), + examples.NewExample( + `List all key versions in JSON format`, + `$ stackit beta kms version list --key-id "my-key-id" --keyring-id "my-keyring-id" -o json`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get key version: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, model.ProjectId, model.KeyId, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + KeyId: flags.FlagToStringValue(p, cmd, keyIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiListVersionsRequest { + return apiClient.ListVersions(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId) +} + +func outputResult(p *print.Printer, outputFormat, projectId, keyId string, resp *kms.VersionList) error { + if resp == nil || resp.Versions == nil { + return fmt.Errorf("response is nil / empty") + } + versions := *resp.Versions + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(versions, "", " ") + if err != nil { + return fmt.Errorf("marshal key versions list: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(versions, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal key versions list: %w", err) + } + p.Outputln(string(details)) + + default: + if len(versions) == 0 { + p.Outputf("No key versions found for project %q for the key %q\n", projectId, keyId) + return nil + } + table := tables.NewTable() + table.SetHeader("ID", "NUMBER", "CREATED AT", "DESTROY DATE", "STATUS") + + for _, version := range versions { + table.AddRow( + utils.PtrString(version.KeyId), + utils.PtrString(version.Number), + utils.PtrString(version.CreatedAt), + utils.PtrString(version.DestroyDate), + utils.PtrString(version.State), + ) + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + } + + return nil +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring") + cmd.Flags().Var(flags.UUIDFlag(), keyIdFlag, "ID of the key") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag, keyIdFlag) + cobra.CheckErr(err) +} diff --git a/internal/cmd/beta/kms/version/list/list_test.go b/internal/cmd/beta/kms/version/list/list_test.go new file mode 100644 index 000000000..a1df169ac --- /dev/null +++ b/internal/cmd/beta/kms/version/list/list_test.go @@ -0,0 +1,282 @@ +package list + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() +) + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + keyIdFlag: testKeyId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiListVersionsRequest)) kms.ApiListVersionsRequest { + request := testClient.ListVersions(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId) + 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(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "key ring id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyIdFlag) + }), + isValid: false, + }, + { + description: "key id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "" + }), + isValid: false, + }, + { + description: "key id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + configureFlags(cmd) + + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiListVersionsRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + projectId string + keyId string + resp *kms.VersionList + outputFormat string + projectLabel string + wantErr bool + }{ + { + description: "nil response", + resp: nil, + projectLabel: "my-project", + wantErr: true, + }, + { + description: "empty default", + resp: &kms.VersionList{}, + projectLabel: "my-project", + wantErr: true, + }, + { + description: "default output", + resp: &kms.VersionList{Versions: &[]kms.Version{}}, + projectLabel: "my-project", + wantErr: false, + }, + { + description: "json output", + resp: &kms.VersionList{Versions: &[]kms.Version{}}, + outputFormat: print.JSONOutputFormat, + wantErr: false, + }, + { + description: "yaml output", + resp: &kms.VersionList{Versions: &[]kms.Version{}}, + outputFormat: print.YAMLOutputFormat, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.projectId, tt.keyId, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/version/restore/restore.go b/internal/cmd/beta/kms/version/restore/restore.go new file mode 100644 index 000000000..c5b4e7aec --- /dev/null +++ b/internal/cmd/beta/kms/version/restore/restore.go @@ -0,0 +1,145 @@ +package restore + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + versionNumberArg = "VERSION_NUMBER" + + keyRingIdFlag = "keyring-id" + keyIdFlag = "key-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string + KeyId string + VersionNumber int64 +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("restore %s", versionNumberArg), + Short: "Restore a key version", + Long: "Restores the specified version of a key.", + Args: args.SingleArg(versionNumberArg, nil), + Example: examples.Build( + examples.NewExample( + `Restore key version "42" for the key "my-key-id" inside the key ring "my-keyring-id"`, + `$ stackit beta kms version restore 42 --key-id "my-key-id" --keyring-id "my-keyring-id"`), + ), + 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 + } + + // This operation can be undone. Don't ask for confirmation! + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("restore key Version: %w", err) + } + + // Grab the key after the restore was applied to display the new state to the user. + resp, err := apiClient.GetVersionExecute(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get key version: %v", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + versionStr := inputArgs[0] + versionNumber, err := strconv.ParseInt(versionStr, 10, 64) + if err != nil || versionNumber < 0 { + return nil, &errors.ArgValidationError{ + Arg: versionNumberArg, + Details: fmt.Sprintf("invalid value %q: must be a positive integer", versionStr), + } + } + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + KeyId: flags.FlagToStringValue(p, cmd, keyIdFlag), + VersionNumber: versionNumber, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiRestoreVersionRequest { + return apiClient.RestoreVersion(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring") + cmd.Flags().Var(flags.UUIDFlag(), keyIdFlag, "ID of the key") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag, keyIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) error { + if resp == nil { + return fmt.Errorf("response is nil / empty") + } + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal output to JSON: %w", err) + } + p.Outputln(string(details)) + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal output to YAML: %w", err) + } + p.Outputln(string(details)) + + default: + p.Outputf("Restored version %d of the key %q\n", utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) + } + return nil +} diff --git a/internal/cmd/beta/kms/version/restore/restore_test.go b/internal/cmd/beta/kms/version/restore/restore_test.go new file mode 100644 index 000000000..ad388135e --- /dev/null +++ b/internal/cmd/beta/kms/version/restore/restore_test.go @@ -0,0 +1,320 @@ +package restore + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" + testVersionNumber = int64(1) + testVersionNumberString = "1" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testVersionNumberString, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + keyIdFlag: testKeyId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + KeyId: testKeyId, + VersionNumber: testVersionNumber, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiRestoreVersionRequest)) kms.ApiRestoreVersionRequest { + request := testClient.RestoreVersion(testCtx, testProjectId, testRegion, testKeyRingId, testKeyId, testVersionNumber) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no args (versionNumber)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "key ring id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyIdFlag) + }), + isValid: false, + }, + { + description: "key id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "" + }), + isValid: false, + }, + { + description: "key id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "version number invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "version number invalid 2", + argValues: []string{"Not a Number!"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiRestoreVersionRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + wantErr bool + outputFormat string + resp *kms.Version + }{ + { + description: "nil response", + resp: nil, + wantErr: true, + }, + { + description: "default output", + resp: &kms.Version{}, + wantErr: false, + }, + { + description: "json output", + outputFormat: print.JSONOutputFormat, + resp: &kms.Version{}, + wantErr: false, + }, + { + description: "yaml output", + outputFormat: print.YAMLOutputFormat, + resp: &kms.Version{}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/version/version.go b/internal/cmd/beta/kms/version/version.go new file mode 100644 index 000000000..39c90e5c8 --- /dev/null +++ b/internal/cmd/beta/kms/version/version.go @@ -0,0 +1,34 @@ +package version + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version/destroy" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version/disable" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version/enable" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version/restore" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "version", + Short: "Manage KMS key versions", + Long: "Provides functionality for key version operations inside the KMS", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(destroy.NewCmd(params)) + cmd.AddCommand(disable.NewCmd(params)) + cmd.AddCommand(enable.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(restore.NewCmd(params)) +} diff --git a/internal/cmd/beta/kms/wrappingkey/create/create.go b/internal/cmd/beta/kms/wrappingkey/create/create.go new file mode 100644 index 000000000..76d8be6b5 --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/create/create.go @@ -0,0 +1,204 @@ +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" + "github.com/stackitcloud/stackit-sdk-go/services/kms/wait" +) + +const ( + keyRingIdFlag = "keyring-id" + + algorithmFlag = "algorithm" + descriptionFlag = "description" + displayNameFlag = "name" + purposeFlag = "purpose" + protectionFlag = "protection" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string + + Algorithm *string + Description *string + Name *string + Purpose *string + Protection *string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a KMS wrapping key", + Long: "Creates a KMS wrapping key.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a symmetric (RSA + AES) KMS wrapping key with name "my-wrapping-key-name" in key ring with ID "my-keyring-id"`, + `$ stackit beta kms wrapping-key create --keyring-id "my-keyring-id" --algorithm "rsa_2048_oaep_sha256_aes_256_key_wrap" --name "my-wrapping-key-name" --purpose "wrap_symmetric_key" --protection "software"`), + examples.NewExample( + `Create an asymmetric (RSA) KMS wrapping key with name "my-wrapping-key-name" in key ring with ID "my-keyring-id"`, + `$ stackit beta kms wrapping-key create --keyring-id "my-keyring-id" --algorithm "rsa_3072_oaep_sha256" --name "my-wrapping-key-name" --purpose "wrap_asymmetric_key" --protection "software"`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + if !model.AssumeYes { + err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS wrapping key?") + if err != nil { + return err + } + } + + // Call API + req, _ := buildRequest(ctx, model, apiClient) + wrappingKey, err := req.Execute() + if err != nil { + return fmt.Errorf("create KMS wrapping key: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for KMS wrapping key creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model, wrappingKey) + }, + } + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // All values are mandatory strings. No additional type check required. + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + Algorithm: flags.FlagToStringPointer(p, cmd, algorithmFlag), + Name: flags.FlagToStringPointer(p, cmd, displayNameFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + Purpose: flags.FlagToStringPointer(p, cmd, purposeFlag), + Protection: flags.FlagToStringPointer(p, cmd, protectionFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +type kmsWrappingKeyClient interface { + CreateWrappingKey(ctx context.Context, projectId string, regionId string, keyRingId string) kms.ApiCreateWrappingKeyRequest +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient kmsWrappingKeyClient) (kms.ApiCreateWrappingKeyRequest, error) { + req := apiClient.CreateWrappingKey(ctx, model.ProjectId, model.Region, model.KeyRingId) + + req = req.CreateWrappingKeyPayload(kms.CreateWrappingKeyPayload{ + DisplayName: model.Name, + Description: model.Description, + Algorithm: kms.CreateWrappingKeyPayloadGetAlgorithmAttributeType(model.Algorithm), + Purpose: kms.CreateWrappingKeyPayloadGetPurposeAttributeType(model.Purpose), + Protection: kms.CreateWrappingKeyPayloadGetProtectionAttributeType(model.Protection), + }) + return req, nil +} + +func outputResult(p *print.Printer, model *inputModel, resp *kms.WrappingKey) error { + if resp == nil { + return fmt.Errorf("response is nil") + } + + switch model.OutputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(resp, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS wrapping key: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS wrapping key: %w", err) + } + p.Outputln(string(details)) + + default: + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s wrapping key. Wrapping key ID: %s\n", operationState, utils.PtrString(resp.Id)) + } + + return nil +} + +func configureFlags(cmd *cobra.Command) { + // Algorithm + var algorithmFlagOptions []string + for _, val := range kms.AllowedWrappingAlgorithmEnumValues { + algorithmFlagOptions = append(algorithmFlagOptions, string(val)) + } + cmd.Flags().Var(flags.EnumFlag(false, "", algorithmFlagOptions...), algorithmFlag, fmt.Sprintf("En-/Decryption / signing algorithm. Possible values: %q", algorithmFlagOptions)) + + // Purpose + var purposeFlagOptions []string + for _, val := range kms.AllowedWrappingPurposeEnumValues { + purposeFlagOptions = append(purposeFlagOptions, string(val)) + } + cmd.Flags().Var(flags.EnumFlag(false, "", purposeFlagOptions...), purposeFlag, fmt.Sprintf("Purpose of the wrapping key. Possible values: %q", purposeFlagOptions)) + + // Protection + // backend was deprectaed in /v1beta, but protection is a required attribute with value "software" + var protectionFlagOptions []string + for _, val := range kms.AllowedProtectionEnumValues { + protectionFlagOptions = append(protectionFlagOptions, string(val)) + } + cmd.Flags().Var(flags.EnumFlag(false, "", protectionFlagOptions...), protectionFlag, fmt.Sprintf("The underlying system that is responsible for protecting the wrapping key material. Possible values: %q", purposeFlagOptions)) + + // All further non Enum Flags + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring") + cmd.Flags().String(displayNameFlag, "", "The display name to distinguish multiple wrapping keys") + cmd.Flags().String(descriptionFlag, "", "Optional description of the wrapping key") + + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag, algorithmFlag, purposeFlag, displayNameFlag, protectionFlag) + cobra.CheckErr(err) +} diff --git a/internal/cmd/beta/kms/wrappingkey/create/create_test.go b/internal/cmd/beta/kms/wrappingkey/create/create_test.go new file mode 100644 index 000000000..15616c322 --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/create/create_test.go @@ -0,0 +1,318 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu01" + testAlgorithm = "rsa_2048_oaep_sha256" + testDisplayName = "my-key" + testPurpose = "wrap_asymmetric_key" + testDescription = "my key description" + testProtection = "software" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() +) + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + algorithmFlag: testAlgorithm, + displayNameFlag: testDisplayName, + purposeFlag: testPurpose, + descriptionFlag: testDescription, + protectionFlag: testProtection, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + Algorithm: utils.Ptr(testAlgorithm), + Name: utils.Ptr(testDisplayName), + Purpose: utils.Ptr(testPurpose), + Description: utils.Ptr(testDescription), + Protection: utils.Ptr(testProtection), + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiCreateWrappingKeyRequest)) kms.ApiCreateWrappingKeyRequest { + request := testClient.CreateWrappingKey(testCtx, testProjectId, testRegion, testKeyRingId) + request = request.CreateWrappingKeyPayload(kms.CreateWrappingKeyPayload{ + Algorithm: kms.CreateWrappingKeyPayloadGetAlgorithmAttributeType(utils.Ptr(testAlgorithm)), + DisplayName: utils.Ptr(testDisplayName), + Purpose: kms.CreateWrappingKeyPayloadGetPurposeAttributeType(utils.Ptr(testPurpose)), + Description: utils.Ptr(testDescription), + Protection: kms.CreateWrappingKeyPayloadGetProtectionAttributeType(utils.Ptr(testProtection)), + }) + + 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: "optional flags omitted", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, descriptionFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Description = nil + }), + }, + { + description: "no values provided", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "key ring id missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "algorithm missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, algorithmFlag) + }), + isValid: false, + }, + { + description: "name missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, displayNameFlag) + }), + isValid: false, + }, + { + description: "purpose missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, purposeFlag) + }), + isValid: false, + }, + { + description: "protection missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, protectionFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + configureFlags(cmd) + + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiCreateWrappingKeyRequest + }{ + { + description: "base case", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no optional values", + model: fixtureInputModel(func(model *inputModel) { + model.Description = nil + }), + expectedRequest: fixtureRequest().CreateWrappingKeyPayload(kms.CreateWrappingKeyPayload{ + Algorithm: kms.CreateWrappingKeyPayloadGetAlgorithmAttributeType(utils.Ptr(testAlgorithm)), + DisplayName: utils.Ptr(testDisplayName), + Purpose: kms.CreateWrappingKeyPayloadGetPurposeAttributeType(utils.Ptr(testPurpose)), + Protection: kms.CreateWrappingKeyPayloadGetProtectionAttributeType(utils.Ptr(testProtection)), + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request, err := buildRequest(testCtx, tt.model, testClient) + if err != nil { + t.Fatalf("error building request: %v", err) + } + + diff := cmp.Diff(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + model *inputModel + wrappingKey *kms.WrappingKey + wantErr bool + }{ + { + description: "nil response", + wrappingKey: nil, + wantErr: true, + }, + { + description: "default output", + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, + wrappingKey: &kms.WrappingKey{}, + wantErr: false, + }, + { + description: "json output", + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.JSONOutputFormat}}, + wrappingKey: &kms.WrappingKey{}, + wantErr: false, + }, + { + description: "yaml output", + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.YAMLOutputFormat}}, + wrappingKey: &kms.WrappingKey{}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.model, tt.wrappingKey) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/wrappingkey/delete/delete.go b/internal/cmd/beta/kms/wrappingkey/delete/delete.go new file mode 100644 index 000000000..0ade8822f --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/delete/delete.go @@ -0,0 +1,118 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + kmsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + wrappingKeyIdArg = "WRAPPING_KEY_ID" + + keyRingIdFlag = "keyring-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + WrappingKeyId string + KeyRingId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", wrappingKeyIdArg), + Short: "Deletes a KMS wrapping key", + Long: "Deletes a KMS wrapping key inside a specific key ring.", + Args: args.SingleArg(wrappingKeyIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a KMS wrapping key "MY_WRAPPING_KEY_ID" inside the key ring "my-keyring-id"`, + `$ stackit beta kms wrapping-key delete "MY_WRAPPING_KEY_ID" --keyring-id "my-keyring-id"`), + ), + 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 + } + + wrappingKeyName, err := kmsUtils.GetWrappingKeyName(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.WrappingKeyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get wrapping key name: %v", err) + wrappingKeyName = model.WrappingKeyId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete the wrapping key %q? (this cannot be undone)", wrappingKeyName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete KMS wrapping key: %w", err) + } + + // Wait for async operation not relevant. Wrapping key deletion is synchronous + + // Don't output anything. It's a deletion. + params.Printer.Info("Deleted wrapping key %q\n", wrappingKeyName) + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + wrappingKeyId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + WrappingKeyId: wrappingKeyId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiDeleteWrappingKeyRequest { + req := apiClient.DeleteWrappingKey(ctx, model.ProjectId, model.Region, model.KeyRingId, model.WrappingKeyId) + return req +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring where the wrapping key is stored") + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag) + cobra.CheckErr(err) +} diff --git a/internal/cmd/beta/kms/wrappingkey/delete/delete_test.go b/internal/cmd/beta/kms/wrappingkey/delete/delete_test.go new file mode 100644 index 000000000..57be1cbfa --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/delete/delete_test.go @@ -0,0 +1,241 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu01" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testWrappingKeyId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testWrappingKeyId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + WrappingKeyId: testWrappingKeyId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiDeleteWrappingKeyRequest)) kms.ApiDeleteWrappingKeyRequest { + request := testClient.DeleteWrappingKey(testCtx, testProjectId, testRegion, testKeyRingId, testWrappingKeyId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no args (wrappingKeyId)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values provided", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "key ring id missing (required)", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "key ring id invalid", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "wrapping key id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "wrapping key id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + p := print.NewPrinter() + cmd := NewCmd(¶ms.CmdParams{Printer: p}) + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + err = cmd.ValidateArgs(tt.argValues) + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating args: %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) + } + } + + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiDeleteWrappingKeyRequest + }{ + { + description: "base case", + 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(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/kms/wrappingkey/list/list.go b/internal/cmd/beta/kms/wrappingkey/list/list.go new file mode 100644 index 000000000..a89babc53 --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/list/list.go @@ -0,0 +1,149 @@ +package list + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + keyRingIdFlag = "keyring-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all KMS wrapping keys", + Long: "Lists all KMS wrapping keys inside a key ring.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all KMS wrapping keys for the key ring "my-keyring-id"`, + `$ stackit beta kms wrapping-key list --keyring-id "my-keyring-id"`), + examples.NewExample( + `List all KMS wrapping keys in JSON format`, + `$ stackit beta kms wrapping-key list --keyring-id "my-keyring-id" --output-format json`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get KMS wrapping keys: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, model.KeyRingId, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + KeyRingId: flags.FlagToStringValue(p, cmd, keyRingIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiListWrappingKeysRequest { + req := apiClient.ListWrappingKeys(ctx, model.ProjectId, model.Region, model.KeyRingId) + return req +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), keyRingIdFlag, "ID of the KMS key ring where the key is stored") + err := flags.MarkFlagsRequired(cmd, keyRingIdFlag) + cobra.CheckErr(err) +} + +func outputResult(p *print.Printer, outputFormat, keyRingId string, resp *kms.WrappingKeyList) error { + if resp == nil || resp.WrappingKeys == nil { + return fmt.Errorf("response is nil / empty") + } + + wrappingKeys := *resp.WrappingKeys + + switch outputFormat { + case print.JSONOutputFormat: + details, err := json.MarshalIndent(wrappingKeys, "", " ") + if err != nil { + return fmt.Errorf("marshal KMS wrapping keys list: %w", err) + } + p.Outputln(string(details)) + + case print.YAMLOutputFormat: + details, err := yaml.MarshalWithOptions(wrappingKeys, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return fmt.Errorf("marshal KMS wrapping keys list: %w", err) + } + p.Outputln(string(details)) + + default: + if len(wrappingKeys) == 0 { + p.Outputf("No wrapping keys found under the key ring %q\n", keyRingId) + return nil + } + table := tables.NewTable() + table.SetHeader("ID", "NAME", "SCOPE", "ALGORITHM", "EXPIRES AT", "STATUS") + + for i := range wrappingKeys { + wrappingKey := wrappingKeys[i] + table.AddRow( + utils.PtrString(wrappingKey.Id), + utils.PtrString(wrappingKey.DisplayName), + utils.PtrString(wrappingKey.Purpose), + utils.PtrString(wrappingKey.Algorithm), + utils.PtrString(wrappingKey.ExpiresAt), + utils.PtrString(wrappingKey.State), + ) + } + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + } + + return nil +} diff --git a/internal/cmd/beta/kms/wrappingkey/list/list_test.go b/internal/cmd/beta/kms/wrappingkey/list/list_test.go new file mode 100644 index 000000000..93eb4b88b --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/list/list_test.go @@ -0,0 +1,250 @@ +package list + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + testRegion = "eu02" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &kms.APIClient{} + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() +) + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + keyRingIdFlag: testKeyRingId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + KeyRingId: testKeyRingId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *kms.ApiListWrappingKeysRequest)) kms.ApiListWrappingKeysRequest { + request := testClient.ListWrappingKeys(testCtx, testProjectId, testRegion, testKeyRingId) + 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(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "missing keyRingId", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, keyRingIdFlag) + }), + isValid: false, + }, + { + description: "invalid keyRingId 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "" + }), + isValid: false, + }, + { + description: "invalid keyRingId 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[keyRingIdFlag] = "Not an uuid" + }), + isValid: false, + }, + { + 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) { + cmd := &cobra.Command{} + err := globalflags.Configure(cmd.Flags()) + if err != nil { + t.Fatalf("configure global flags: %v", err) + } + + configureFlags(cmd) + 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) + } + } + + err = cmd.ValidateRequiredFlags() + if err != nil { + if !tt.isValid { + return + } + t.Fatalf("error validating flags: %v", err) + } + + p := print.NewPrinter() + model, err := parseInput(p, cmd) + 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(tt.expectedModel, model) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest kms.ApiListWrappingKeysRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + keyRingId string + resp *kms.WrappingKeyList + outputFormat string + projectLabel string + wantErr bool + }{ + { + description: "nil response", + resp: nil, + projectLabel: "my-project", + wantErr: true, + }, + { + description: "default output", + resp: &kms.WrappingKeyList{WrappingKeys: &[]kms.WrappingKey{}}, + projectLabel: "my-project", + wantErr: false, + }, + { + description: "json output", + resp: &kms.WrappingKeyList{WrappingKeys: &[]kms.WrappingKey{}}, + outputFormat: print.JSONOutputFormat, + wantErr: false, + }, + { + description: "yaml output", + resp: &kms.WrappingKeyList{WrappingKeys: &[]kms.WrappingKey{}}, + outputFormat: print.YAMLOutputFormat, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.outputFormat, tt.keyRingId, tt.resp) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/kms/wrappingkey/wrappingkey.go b/internal/cmd/beta/kms/wrappingkey/wrappingkey.go new file mode 100644 index 000000000..00184a521 --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/wrappingkey.go @@ -0,0 +1,30 @@ +package wrappingkey + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "wrapping-key", + Short: "Manage KMS wrapping keys", + Long: "Provides functionality for wrapping key operations inside the KMS", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) +} diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index cc5f2214d..8e349c6bc 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -80,7 +80,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { `$ stackit beta sqlserverflex instance create --name my-instance --flavor-id xxx`), examples.NewExample( `Create a SQLServer Flex instance with name "my-instance", specify flavor by CPU and RAM, set storage size to 20 GB, and restrict access to a specific range of IP addresses. Other parameters are set to default values`, - `$ stackit beta sqlserverflex instance create --name my-instance --cpu 1 --ram 4 --storage-size 20 --acl 1.2.3.0/24`), + `$ stackit beta sqlserverflex instance create --name my-instance --cpu 1 --ram 4 --storage-size 20 --acl 1.2.3.0/24`), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 5e4dfa540..e694e8901 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -37,6 +37,7 @@ const ( redisCustomEndpointFlag = "redis-custom-endpoint" resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" + kmsCustomEndpointFlag = "kms-custom-endpoint" serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" serverOsUpdateCustomEndpointFlag = "server-osupdate-custom-endpoint" runCommandCustomEndpointFlag = "runcommand-custom-endpoint" @@ -150,6 +151,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(redisCustomEndpointFlag, "", "Redis API base URL, used in calls to this API") cmd.Flags().String(resourceManagerCustomEndpointFlag, "", "Resource Manager API base URL, used in calls to this API") cmd.Flags().String(secretsManagerCustomEndpointFlag, "", "Secrets Manager API base URL, used in calls to this API") + cmd.Flags().String(kmsCustomEndpointFlag, "", "KMS API base URL, used in calls to this API") cmd.Flags().String(serviceAccountCustomEndpointFlag, "", "Service Account API base URL, used in calls to this API") cmd.Flags().String(serviceEnablementCustomEndpointFlag, "", "Service Enablement API base URL, used in calls to this API") cmd.Flags().String(serverBackupCustomEndpointFlag, "", "Server Backup API base URL, used in calls to this API") @@ -197,6 +199,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.SecretsManagerCustomEndpointKey, cmd.Flags().Lookup(secretsManagerCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.KMSCustomEndpointKey, cmd.Flags().Lookup(kmsCustomEndpointFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.ServerBackupCustomEndpointKey, cmd.Flags().Lookup(serverBackupCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.ServerOsUpdateCustomEndpointKey, cmd.Flags().Lookup(serverOsUpdateCustomEndpointFlag)) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index e7b6fd6fa..28ed935b9 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -41,6 +41,7 @@ const ( redisCustomEndpointFlag = "redis-custom-endpoint" resourceManagerCustomEndpointFlag = "resource-manager-custom-endpoint" secretsManagerCustomEndpointFlag = "secrets-manager-custom-endpoint" + kmsCustomEndpointFlag = "kms-custom-endpoint" serviceAccountCustomEndpointFlag = "service-account-custom-endpoint" serviceEnablementCustomEndpointFlag = "service-enablement-custom-endpoint" serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" @@ -78,6 +79,7 @@ type inputModel struct { RedisCustomEndpoint bool ResourceManagerCustomEndpoint bool SecretsManagerCustomEndpoint bool + KMSCustomEndpoint bool ServerBackupCustomEndpoint bool ServerOsUpdateCustomEndpoint bool RunCommandCustomEndpoint bool @@ -180,6 +182,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if model.SecretsManagerCustomEndpoint { viper.Set(config.SecretsManagerCustomEndpointKey, "") } + if model.KMSCustomEndpoint { + viper.Set(config.KMSCustomEndpointKey, "") + } if model.ServiceAccountCustomEndpoint { viper.Set(config.ServiceAccountCustomEndpointKey, "") } @@ -245,6 +250,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(redisCustomEndpointFlag, false, "Redis API base URL. If unset, uses the default base URL") cmd.Flags().Bool(resourceManagerCustomEndpointFlag, false, "Resource Manager API base URL. If unset, uses the default base URL") cmd.Flags().Bool(secretsManagerCustomEndpointFlag, false, "Secrets Manager API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(kmsCustomEndpointFlag, false, "KMS API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serviceAccountCustomEndpointFlag, false, "Service Account API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serviceEnablementCustomEndpointFlag, false, "Service Enablement API base URL. If unset, uses the default base URL") cmd.Flags().Bool(serverBackupCustomEndpointFlag, false, "Server Backup base URL. If unset, uses the default base URL") @@ -283,6 +289,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { RedisCustomEndpoint: flags.FlagToBoolValue(p, cmd, redisCustomEndpointFlag), ResourceManagerCustomEndpoint: flags.FlagToBoolValue(p, cmd, resourceManagerCustomEndpointFlag), SecretsManagerCustomEndpoint: flags.FlagToBoolValue(p, cmd, secretsManagerCustomEndpointFlag), + KMSCustomEndpoint: flags.FlagToBoolValue(p, cmd, kmsCustomEndpointFlag), ServiceAccountCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceAccountCustomEndpointFlag), ServiceEnablementCustomEndpoint: flags.FlagToBoolValue(p, cmd, serviceEnablementCustomEndpointFlag), ServerBackupCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverBackupCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 246696f15..e48dff384 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -35,6 +35,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool redisCustomEndpointFlag: true, resourceManagerCustomEndpointFlag: true, secretsManagerCustomEndpointFlag: true, + kmsCustomEndpointFlag: true, serviceAccountCustomEndpointFlag: true, serverBackupCustomEndpointFlag: true, serverOsUpdateCustomEndpointFlag: true, @@ -74,6 +75,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { RedisCustomEndpoint: true, ResourceManagerCustomEndpoint: true, SecretsManagerCustomEndpoint: true, + KMSCustomEndpoint: true, ServiceAccountCustomEndpoint: true, ServerBackupCustomEndpoint: true, ServerOsUpdateCustomEndpoint: true, @@ -129,6 +131,7 @@ func TestParseInput(t *testing.T) { model.RedisCustomEndpoint = false model.ResourceManagerCustomEndpoint = false model.SecretsManagerCustomEndpoint = false + model.KMSCustomEndpoint = false model.ServiceAccountCustomEndpoint = false model.ServerBackupCustomEndpoint = false model.ServerOsUpdateCustomEndpoint = false @@ -219,6 +222,16 @@ func TestParseInput(t *testing.T) { model.SecretsManagerCustomEndpoint = false }), }, + { + description: "kms custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[kmsCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.KMSCustomEndpoint = false + }), + }, { description: "service account custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 957d7c475..a8c136996 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -36,6 +36,7 @@ const ( RedisCustomEndpointKey = "redis_custom_endpoint" ResourceManagerEndpointKey = "resource_manager_custom_endpoint" SecretsManagerCustomEndpointKey = "secrets_manager_custom_endpoint" + KMSCustomEndpointKey = "kms_custom_endpoint" ServiceAccountCustomEndpointKey = "service_account_custom_endpoint" ServiceEnablementCustomEndpointKey = "service_enablement_custom_endpoint" ServerBackupCustomEndpointKey = "serverbackup_custom_endpoint" @@ -95,6 +96,7 @@ var ConfigKeys = []string{ RedisCustomEndpointKey, ResourceManagerEndpointKey, SecretsManagerCustomEndpointKey, + KMSCustomEndpointKey, ServiceAccountCustomEndpointKey, ServiceEnablementCustomEndpointKey, ServerBackupCustomEndpointKey, @@ -180,6 +182,7 @@ func setConfigDefaults() { viper.SetDefault(PostgresFlexCustomEndpointKey, "") viper.SetDefault(ResourceManagerEndpointKey, "") viper.SetDefault(SecretsManagerCustomEndpointKey, "") + viper.SetDefault(KMSCustomEndpointKey, "") viper.SetDefault(ServiceAccountCustomEndpointKey, "") viper.SetDefault(ServiceEnablementCustomEndpointKey, "") viper.SetDefault(ServerBackupCustomEndpointKey, "") diff --git a/internal/pkg/services/kms/client/client.go b/internal/pkg/services/kms/client/client.go new file mode 100644 index 000000000..b2cbd8250 --- /dev/null +++ b/internal/pkg/services/kms/client/client.go @@ -0,0 +1,45 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/viper" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +func ConfigureClient(p *print.Printer, cliVersion string) (*kms.APIClient, error) { + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return nil, &errors.AuthError{} + } + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } + + customEndpoint := viper.GetString(config.KMSCustomEndpointKey) + + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err := kms.NewAPIClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return nil, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/internal/pkg/services/kms/utils/utils.go b/internal/pkg/services/kms/utils/utils.go new file mode 100644 index 000000000..5630e27d6 --- /dev/null +++ b/internal/pkg/services/kms/utils/utils.go @@ -0,0 +1,67 @@ +package utils + +import ( + "context" + "fmt" + "time" + + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +type KMSClient interface { + GetKeyExecute(ctx context.Context, projectId string, regionId string, keyRingId string, keyId string) (*kms.Key, error) + GetKeyRingExecute(ctx context.Context, projectId string, regionId string, keyRingId string) (*kms.KeyRing, error) + GetWrappingKeyExecute(ctx context.Context, projectId string, regionId string, keyRingId string, wrappingKeyId string) (*kms.WrappingKey, error) +} + +func GetKeyName(ctx context.Context, apiClient KMSClient, projectId, region, keyRingId, keyId string) (string, error) { + resp, err := apiClient.GetKeyExecute(ctx, projectId, region, keyRingId, keyId) + if err != nil { + return "", fmt.Errorf("get KMS Key: %w", err) + } + + if resp == nil || resp.DisplayName == nil { + return "", fmt.Errorf("response is nil / empty") + } + + return *resp.DisplayName, nil +} + +func GetKeyDeletionDate(ctx context.Context, apiClient KMSClient, projectId, region, keyRingId, keyId string) (time.Time, error) { + resp, err := apiClient.GetKeyExecute(ctx, projectId, region, keyRingId, keyId) + if err != nil { + return time.Now(), fmt.Errorf("get KMS Key: %w", err) + } + + if resp == nil || resp.DeletionDate == nil { + return time.Time{}, fmt.Errorf("response is nil / empty") + } + + return *resp.DeletionDate, nil +} + +func GetKeyRingName(ctx context.Context, apiClient KMSClient, projectId, id, region string) (string, error) { + resp, err := apiClient.GetKeyRingExecute(ctx, projectId, region, id) + if err != nil { + return "", fmt.Errorf("get KMS key ring: %w", err) + } + + if resp == nil || resp.DisplayName == nil { + return "", fmt.Errorf("response is nil / empty") + } + + return *resp.DisplayName, nil +} + +func GetWrappingKeyName(ctx context.Context, apiClient KMSClient, projectId, region, keyRingId, wrappingKeyId string) (string, error) { + resp, err := apiClient.GetWrappingKeyExecute(ctx, projectId, region, keyRingId, wrappingKeyId) + if err != nil { + return "", fmt.Errorf("get KMS Wrapping Key: %w", err) + } + + if resp == nil || resp.DisplayName == nil { + return "", fmt.Errorf("response is nil / empty") + } + + return *resp.DisplayName, nil +} diff --git a/internal/pkg/services/kms/utils/utils_test.go b/internal/pkg/services/kms/utils/utils_test.go new file mode 100644 index 000000000..339cb2d3a --- /dev/null +++ b/internal/pkg/services/kms/utils/utils_test.go @@ -0,0 +1,257 @@ +package utils + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +var ( + testProjectId = uuid.NewString() + testKeyRingId = uuid.NewString() + testKeyId = uuid.NewString() + testWrappingKeyId = uuid.NewString() +) + +const ( + testRegion = "eu01" + testKeyName = "my-test-key" + testKeyRingName = "my-key-ring" + testWrappingKeyName = "my-wrapping-key" +) + +type kmsClientMocked struct { + getKeyFails bool + getKeyResp *kms.Key + getKeyRingFails bool + getKeyRingResp *kms.KeyRing + getWrappingKeyFails bool + getWrappingKeyResp *kms.WrappingKey +} + +// Implement the KMSClient interface methods for the mock. +func (m *kmsClientMocked) GetKeyExecute(_ context.Context, _, _, _, _ string) (*kms.Key, error) { + if m.getKeyFails { + return nil, fmt.Errorf("could not get key") + } + return m.getKeyResp, nil +} + +func (m *kmsClientMocked) GetKeyRingExecute(_ context.Context, _, _, _ string) (*kms.KeyRing, error) { + if m.getKeyRingFails { + return nil, fmt.Errorf("could not get key ring") + } + return m.getKeyRingResp, nil +} + +func (m *kmsClientMocked) GetWrappingKeyExecute(_ context.Context, _, _, _, _ string) (*kms.WrappingKey, error) { + if m.getWrappingKeyFails { + return nil, fmt.Errorf("could not get wrapping key") + } + return m.getWrappingKeyResp, nil +} + +func TestGetKeyName(t *testing.T) { + keyName := testKeyName + + tests := []struct { + description string + getKeyFails bool + getKeyResp *kms.Key + isValid bool + expectedOutput string + }{ + { + description: "base", + getKeyResp: &kms.Key{ + DisplayName: &keyName, + }, + isValid: true, + expectedOutput: testKeyName, + }, + { + description: "get key fails", + getKeyFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &kmsClientMocked{ + getKeyFails: tt.getKeyFails, + getKeyResp: tt.getKeyResp, + } + + output, err := GetKeyName(context.Background(), client, testProjectId, testRegion, testKeyRingId, testKeyId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input: %v", err) + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %q, got %q", tt.expectedOutput, output) + } + }) + } +} + +// TestGetKeyDeletionDate tests the GetKeyDeletionDate function. +func TestGetKeyDeletionDate(t *testing.T) { + mockTime := time.Date(2025, 8, 20, 0, 0, 0, 0, time.UTC) + + tests := []struct { + description string + getKeyFails bool + getKeyResp *kms.Key + isValid bool + expectedOutput time.Time + }{ + { + description: "base", + getKeyResp: &kms.Key{ + DeletionDate: &mockTime, + }, + isValid: true, + expectedOutput: mockTime, + }, + { + description: "get key fails", + getKeyFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &kmsClientMocked{ + getKeyFails: tt.getKeyFails, + getKeyResp: tt.getKeyResp, + } + + output, err := GetKeyDeletionDate(context.Background(), client, testProjectId, testRegion, testKeyRingId, testKeyId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input: %v", err) + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if !output.Equal(tt.expectedOutput) { + t.Errorf("expected output to be %v, got %v", tt.expectedOutput, output) + } + }) + } +} + +// TestGetKeyRingName tests the GetKeyRingName function. +func TestGetKeyRingName(t *testing.T) { + keyRingName := testKeyRingName + + tests := []struct { + description string + getKeyRingFails bool + getKeyRingResp *kms.KeyRing + isValid bool + expectedOutput string + }{ + { + description: "base", + getKeyRingResp: &kms.KeyRing{ + DisplayName: &keyRingName, + }, + isValid: true, + expectedOutput: testKeyRingName, + }, + { + description: "get key ring fails", + getKeyRingFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &kmsClientMocked{ + getKeyRingFails: tt.getKeyRingFails, + getKeyRingResp: tt.getKeyRingResp, + } + + output, err := GetKeyRingName(context.Background(), client, testProjectId, testKeyRingId, testRegion) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input: %v", err) + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %q, got %q", tt.expectedOutput, output) + } + }) + } +} + +func TestGetWrappingKeyName(t *testing.T) { + wrappingKeyName := testWrappingKeyName + tests := []struct { + description string + getWrappingKeyFails bool + getWrappingKeyResp *kms.WrappingKey + isValid bool + expectedOutput string + }{ + { + description: "base", + getWrappingKeyResp: &kms.WrappingKey{ + DisplayName: &wrappingKeyName, + }, + isValid: true, + expectedOutput: testWrappingKeyName, + }, + { + description: "get wrapping key fails", + getWrappingKeyFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &kmsClientMocked{ + getWrappingKeyFails: tt.getWrappingKeyFails, + getWrappingKeyResp: tt.getWrappingKeyResp, + } + + output, err := GetWrappingKeyName(context.Background(), client, testProjectId, testRegion, testKeyRingId, testWrappingKeyId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input: %v", err) + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %q, got %q", tt.expectedOutput, output) + } + }) + } +} From 75569dd538e5f2b41ae3a85dd5a4e57c370db831 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:50:13 +0100 Subject: [PATCH 470/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/resourcemanager (#1053) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index fe8258d95..723b49055 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 @@ -238,11 +238,11 @@ require ( github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 github.com/sagikazarmark/locafero v0.11.0 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect + github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 diff --git a/go.sum b/go.sum index 64b7cd08f..a7ee1080a 100644 --- a/go.sum +++ b/go.sum @@ -569,12 +569,12 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 h1:zxoOv7Fu+FmdsvTKiKkbmLItrMKfL+QoVtz9ReEF30E= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0/go.mod h1:KEPVoO21pC4bjy5l0nyhjUJ0+uVwVWb+k2TYrzJ8xYw= github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0 h1:/weT7P5Uwy1Qlhw0NidqtQBlbbb/dQehweDV/I9ShXg= github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 h1:dnEjyapuv8WwRN5vE2z6+4/+ZqQTBx+bX27x2nOF7Jw= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 h1:zxoOv7Fu+FmdsvTKiKkbmLItrMKfL+QoVtz9ReEF30E= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0/go.mod h1:KEPVoO21pC4bjy5l0nyhjUJ0+uVwVWb+k2TYrzJ8xYw= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0/go.mod h1:20QOZ3rBC9wTGgzXzLz9M6YheX0VaxWE0/JI+s8On7k= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= @@ -595,8 +595,8 @@ github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 h1:ALrDCBih8Fu8 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1/go.mod h1:+qGWSehoV0Js3FalgvT/bOgPj+UqW4I7lP5s8uAxP+o= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 h1:8uPt82Ez34OYMOijjEYxB1zUW6kiybkt6veQKl0AL68= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1/go.mod h1:1Y2GEICmZDt+kr8aGnBx/sjYVAIYHmtfC8xYi9oxNEE= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 h1:r7oaINTwLmIG31AaqKTuQHHFF8YNuYGzi+46DOuSjw4= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1/go.mod h1:ipcrPRbwfQXHH18dJVfY7K5ujHF5dTT6isoXgmA7YwQ= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 h1:en8IomJeGqZZgGOyLH53PNDCv2F/x4zURz4mGSlhTKs= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0/go.mod h1:0wVdzrB4PhwhTE6drOVA6rETTmJ+k3eHa0neuxpDM/g= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 h1:CPIuqhQw+oPt08I2WLsxJDoVDsPMW2VkvKW7/SlUv10= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1/go.mod h1:tip0Ob6x06luy3CmRrmnCMtU5cha95fQLdvZlno3J4w= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 h1:WKFzlHllql3JsVcAq+Y1m5pSMkvwp1qH3Vf2N7i8CPg= From f2ed887a1bf48cf04d18c4b542a0894b10032e76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:58:35 +0000 Subject: [PATCH 471/619] chore(deps): bump renovatebot/github-action from 43.0.18 to 43.0.19 (#1052) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 0ebc69e31..8dab86076 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.18 + uses: renovatebot/github-action@v43.0.19 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From af803a3c0293f2550632b5b6f6f361c07dcc102c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 28 Oct 2025 11:39:38 +0100 Subject: [PATCH 472/619] fix(mariadb): print valid JSON/YAML for list commands (#1036) relates to STACKITCLI-263 / #893 --- internal/cmd/mariadb/credentials/list/list.go | 24 ++++++++++--------- .../cmd/mariadb/credentials/list/list_test.go | 21 ++++++++-------- internal/cmd/mariadb/instance/list/list.go | 24 ++++++++++--------- .../cmd/mariadb/instance/list/list_test.go | 15 ++++++------ internal/cmd/mariadb/plans/plans.go | 24 ++++++++++--------- internal/cmd/mariadb/plans/plans_test.go | 15 ++++++------ 6 files changed, 63 insertions(+), 60 deletions(-) diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index b52bf3720..2ba92d3e0 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -66,22 +66,19 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list MariaDB credentials: %w", err) } - credentials := *resp.CredentialsList - if len(credentials) == 0 { - instanceLabel, err := mariadbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) - if err != nil { - params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) - instanceLabel = model.InstanceId - } - params.Printer.Info("No credentials found for instance %q\n", instanceLabel) - return nil + credentials := resp.GetCredentialsList() + + instanceLabel, err := mariadbUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) + instanceLabel = model.InstanceId } // Truncate output if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, credentials) }, } configureFlags(cmd) @@ -125,8 +122,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API return req } -func outputResult(p *print.Printer, outputFormat string, credentials []mariadb.CredentialsListItem) error { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, credentials []mariadb.CredentialsListItem) error { return p.OutputResult(outputFormat, credentials, func() error { + if len(credentials) == 0 { + p.Outputf("No credentials found for instance %q\n", instanceLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID") for i := range credentials { diff --git a/internal/cmd/mariadb/credentials/list/list_test.go b/internal/cmd/mariadb/credentials/list/list_test.go index 1a56a7b6b..7b7b041cb 100644 --- a/internal/cmd/mariadb/credentials/list/list_test.go +++ b/internal/cmd/mariadb/credentials/list/list_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -27,9 +25,9 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -82,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -174,8 +172,9 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - outputFormat string - credentials []mariadb.CredentialsListItem + outputFormat string + instanceLabel string + credentials []mariadb.CredentialsListItem } tests := []struct { name string @@ -207,7 +206,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index 56e1b0e43..6bf70a322 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -64,15 +64,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get MariaDB instances: %w", err) } - instances := *resp.Instances - if len(instances) == 0 { - 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 - } - params.Printer.Info("No instances found for project %q\n", projectLabel) - return nil + instances := resp.GetInstances() + + 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 } // Truncate output @@ -80,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, projectLabel, instances) }, } @@ -120,8 +117,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API return req } -func outputResult(p *print.Printer, outputFormat string, instances []mariadb.Instance) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []mariadb.Instance) error { return p.OutputResult(outputFormat, instances, func() error { + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { diff --git a/internal/cmd/mariadb/instance/list/list_test.go b/internal/cmd/mariadb/instance/list/list_test.go index 14587ff87..092af5002 100644 --- a/internal/cmd/mariadb/instance/list/list_test.go +++ b/internal/cmd/mariadb/instance/list/list_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,8 +24,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -79,21 +77,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -151,6 +149,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string instances []mariadb.Instance } tests := []struct { @@ -183,7 +182,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.instances); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index e66d67052..a09b9cb56 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -64,15 +64,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get MariaDB service plans: %w", err) } - plans := *resp.Offerings - if len(plans) == 0 { - 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 - } - params.Printer.Info("No plans found for project %q\n", projectLabel) - return nil + plans := resp.GetOfferings() + + 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 } // Truncate output @@ -80,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, projectLabel, plans) }, } @@ -120,8 +117,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *mariadb.API return req } -func outputResult(p *print.Printer, outputFormat string, plans []mariadb.Offering) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, plans []mariadb.Offering) error { return p.OutputResult(outputFormat, plans, func() error { + if len(plans) == 0 { + p.Outputf("No plans found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { diff --git a/internal/cmd/mariadb/plans/plans_test.go b/internal/cmd/mariadb/plans/plans_test.go index f63a84125..411579760 100644 --- a/internal/cmd/mariadb/plans/plans_test.go +++ b/internal/cmd/mariadb/plans/plans_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,8 +24,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -79,21 +77,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -151,6 +149,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string plans []mariadb.Offering } tests := []struct { @@ -183,7 +182,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.plans); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From d6772b08181f9396dbcc3711acb242e6b545eb87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 28 Oct 2025 15:13:28 +0100 Subject: [PATCH 473/619] fix(logme): print valid JSON/YAML output for list cmds (#1038) relates to STACKITCLI-264 / #893 --- internal/cmd/logme/credentials/list/list.go | 24 ++++++++++--------- .../cmd/logme/credentials/list/list_test.go | 21 ++++++++-------- internal/cmd/logme/instance/list/list.go | 24 ++++++++++--------- internal/cmd/logme/instance/list/list_test.go | 15 ++++++------ internal/cmd/logme/plans/plans.go | 24 ++++++++++--------- internal/cmd/logme/plans/plans_test.go | 15 ++++++------ 6 files changed, 63 insertions(+), 60 deletions(-) diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index 2d0065a72..eda5d8917 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -67,22 +67,19 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list LogMe credentials: %w", err) } - credentials := *resp.CredentialsList - if len(credentials) == 0 { - instanceLabel, err := logmeUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) - if err != nil { - params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) - instanceLabel = model.InstanceId - } - params.Printer.Info("No credentials found for instance %q\n", instanceLabel) - return nil + credentials := resp.GetCredentialsList() + + instanceLabel, err := logmeUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) + instanceLabel = model.InstanceId } // Truncate output if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, credentials) }, } configureFlags(cmd) @@ -126,8 +123,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl return req } -func outputResult(p *print.Printer, outputFormat string, credentials []logme.CredentialsListItem) error { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, credentials []logme.CredentialsListItem) error { return p.OutputResult(outputFormat, credentials, func() error { + if len(credentials) == 0 { + p.Outputf("No credentials found for instance %q\n", instanceLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID") for i := range credentials { diff --git a/internal/cmd/logme/credentials/list/list_test.go b/internal/cmd/logme/credentials/list/list_test.go index fc6c5069b..73a86bad3 100644 --- a/internal/cmd/logme/credentials/list/list_test.go +++ b/internal/cmd/logme/credentials/list/list_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/logme" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -27,9 +25,9 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -82,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -174,8 +172,9 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - outputFormat string - credentials []logme.CredentialsListItem + outputFormat string + instanceLabel string + credentials []logme.CredentialsListItem } tests := []struct { name string @@ -206,7 +205,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index 201d49d53..ff5c8c55c 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -64,15 +64,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get LogMe instances: %w", err) } - instances := *resp.Instances - if len(instances) == 0 { - 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 - } - params.Printer.Info("No instances found for project %q\n", projectLabel) - return nil + instances := resp.GetInstances() + + 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 } // Truncate output @@ -80,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, projectLabel, instances) }, } @@ -120,8 +117,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl return req } -func outputResult(p *print.Printer, outputFormat string, instances []logme.Instance) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []logme.Instance) error { return p.OutputResult(outputFormat, instances, func() error { + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { diff --git a/internal/cmd/logme/instance/list/list_test.go b/internal/cmd/logme/instance/list/list_test.go index b3a95fc2b..10c36c2ba 100644 --- a/internal/cmd/logme/instance/list/list_test.go +++ b/internal/cmd/logme/instance/list/list_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/logme" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,8 +24,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -79,21 +77,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -151,6 +149,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string instances []logme.Instance } tests := []struct { @@ -182,7 +181,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.instances); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index 72a601109..227900628 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -64,15 +64,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get LogMe service plans: %w", err) } - plans := *resp.Offerings - if len(plans) == 0 { - 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 - } - params.Printer.Info("No plans found for project %q\n", projectLabel) - return nil + plans := resp.GetOfferings() + + 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 } // Truncate output @@ -80,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, projectLabel, plans) }, } @@ -120,8 +117,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *logme.APICl return req } -func outputResult(p *print.Printer, outputFormat string, plans []logme.Offering) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, plans []logme.Offering) error { return p.OutputResult(outputFormat, plans, func() error { + if len(plans) == 0 { + p.Outputf("No plans found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { diff --git a/internal/cmd/logme/plans/plans_test.go b/internal/cmd/logme/plans/plans_test.go index 83980c517..0f93fa3a9 100644 --- a/internal/cmd/logme/plans/plans_test.go +++ b/internal/cmd/logme/plans/plans_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/logme" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,8 +24,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -79,21 +77,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -151,6 +149,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string plans []logme.Offering } tests := []struct { @@ -182,7 +181,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.plans); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From 611d185d2c592a29c61961eb2a80f614a60cb5ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 14:21:52 +0000 Subject: [PATCH 474/619] chore(deps): bump github.com/jedib0t/go-pretty/v6 from 6.6.8 to 6.6.9 (#1059) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 723b49055..f5d9080d3 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.8 + github.com/jedib0t/go-pretty/v6 v6.6.9 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index a7ee1080a..1c421db57 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.8 h1:JnnzQeRz2bACBobIaa/r+nqjvws4yEhcmaZ4n1QzsEc= -github.com/jedib0t/go-pretty/v6 v6.6.8/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.6.9 h1:PQecJLK3L8ODuVyMe2223b61oRJjrKnmXAncbWTv9MY= +github.com/jedib0t/go-pretty/v6 v6.6.9/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From 71b3950e62fcae057e2db0b776d26371ba65fa01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 29 Oct 2025 08:04:17 +0100 Subject: [PATCH 475/619] fix(git): print valid JSON/YAML output for list cmds (#1039) relates to STACKITCLI-265 / #893 --- docs/stackit_git_instance_create.md | 4 +-- internal/cmd/git/flavor/list/list.go | 30 ++++++++++++--------- internal/cmd/git/flavor/list/list_test.go | 3 ++- internal/cmd/git/instance/create/create.go | 4 +-- internal/cmd/git/instance/list/list.go | 30 ++++++++++++--------- internal/cmd/git/instance/list/list_test.go | 3 ++- 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/docs/stackit_git_instance_create.md b/docs/stackit_git_instance_create.md index e5d8bba93..a82c92ec4 100644 --- a/docs/stackit_git_instance_create.md +++ b/docs/stackit_git_instance_create.md @@ -17,10 +17,10 @@ stackit git instance create [flags] $ stackit git instance create --name my-new-instance Create a instance with name 'my-new-instance' and flavor - $ stackit git instance create --name my-new-instance --flavor git-100' + $ stackit git instance create --name my-new-instance --flavor git-100 Create a instance with name 'my-new-instance' and acl - $ stackit git instance create --name my-new-instance --acl 1.1.1.1/1' + $ stackit git instance create --name my-new-instance --acl 1.1.1.1/1 ``` ### Options diff --git a/internal/cmd/git/flavor/list/list.go b/internal/cmd/git/flavor/list/list.go index 68b674830..c8c8fe583 100644 --- a/internal/cmd/git/flavor/list/list.go +++ b/internal/cmd/git/flavor/list/list.go @@ -60,19 +60,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get STACKIT Git flavors: %w", err) } - flavors := *resp.Flavors - if len(flavors) == 0 { - 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 - } - params.Printer.Info("No flavors found for project %q\n", projectLabel) - return nil - } else if model.Limit != nil && len(flavors) > int(*model.Limit) { + flavors := resp.GetFlavors() + + 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 + } + + // Truncate output + if model.Limit != nil && len(flavors) > int(*model.Limit) { flavors = (flavors)[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, flavors) + + return outputResult(params.Printer, model.OutputFormat, projectLabel, flavors) }, } configureFlags(cmd) @@ -110,8 +111,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClie return apiClient.ListFlavors(ctx, model.ProjectId) } -func outputResult(p *print.Printer, outputFormat string, flavors []git.Flavor) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, flavors []git.Flavor) error { return p.OutputResult(outputFormat, flavors, func() error { + if len(flavors) == 0 { + p.Outputf("No flavors found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "DESCRIPTION", "DISPLAY_NAME", "AVAILABLE", "SKU") for i := range flavors { diff --git a/internal/cmd/git/flavor/list/list_test.go b/internal/cmd/git/flavor/list/list_test.go index d5a6e2f54..8c2aca50a 100644 --- a/internal/cmd/git/flavor/list/list_test.go +++ b/internal/cmd/git/flavor/list/list_test.go @@ -161,6 +161,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string flavors []git.Flavor } tests := []struct { @@ -192,7 +193,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.flavors); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.flavors); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index 296a44598..8c6c56ac4 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -46,11 +46,11 @@ func NewCmd(params *params.CmdParams) *cobra.Command { ), examples.NewExample( `Create a instance with name 'my-new-instance' and flavor`, - `$ stackit git instance create --name my-new-instance --flavor git-100'`, + `$ stackit git instance create --name my-new-instance --flavor git-100`, ), examples.NewExample( `Create a instance with name 'my-new-instance' and acl`, - `$ stackit git instance create --name my-new-instance --acl 1.1.1.1/1'`, + `$ stackit git instance create --name my-new-instance --acl 1.1.1.1/1`, ), ), RunE: func(cmd *cobra.Command, args []string) (err error) { diff --git a/internal/cmd/git/instance/list/list.go b/internal/cmd/git/instance/list/list.go index 1499ecfdf..161af2df4 100644 --- a/internal/cmd/git/instance/list/list.go +++ b/internal/cmd/git/instance/list/list.go @@ -61,19 +61,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get STACKIT Git instances: %w", err) } - instances := *resp.Instances - if len(instances) == 0 { - 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 - } - params.Printer.Info("No instances found for project %q\n", projectLabel) - return nil - } else if model.Limit != nil && len(instances) > int(*model.Limit) { + instances := resp.GetInstances() + + 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 + } + + // Truncate output + if model.Limit != nil && len(instances) > int(*model.Limit) { instances = (instances)[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, instances) + + return outputResult(params.Printer, model.OutputFormat, projectLabel, instances) }, } configureFlags(cmd) @@ -111,8 +112,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *git.APIClie return apiClient.ListInstances(ctx, model.ProjectId) } -func outputResult(p *print.Printer, outputFormat string, instances []git.Instance) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []git.Instance) error { return p.OutputResult(outputFormat, instances, func() error { + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "URL", "VERSION", "STATE", "CREATED") for i := range instances { diff --git a/internal/cmd/git/instance/list/list_test.go b/internal/cmd/git/instance/list/list_test.go index 8d6ac21a6..36fa36f10 100644 --- a/internal/cmd/git/instance/list/list_test.go +++ b/internal/cmd/git/instance/list/list_test.go @@ -161,6 +161,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string instances []git.Instance } tests := []struct { @@ -192,7 +193,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.instances); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From 03ca81085069740e49daaf8f738f0880ed770ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 29 Oct 2025 08:28:02 +0100 Subject: [PATCH 476/619] fix(objectstorage): print valid JSON/YAML for list cmds (#1041) relates to STACKITCLI-267 / #893 --- .../bucket/create/create_test.go | 20 +++++++-------- .../bucket/delete/delete_test.go | 20 +++++++-------- .../bucket/describe/describe_test.go | 20 +++++++-------- .../cmd/object-storage/bucket/list/list.go | 24 ++++++++++-------- .../object-storage/bucket/list/list_test.go | 18 ++++++------- .../credentials-group/create/create_test.go | 22 ++++++++-------- .../credentials-group/delete/delete_test.go | 16 ++++++------ .../credentials-group/list/list.go | 11 ++++---- .../credentials-group/list/list_test.go | 18 ++++++------- .../credentials/create/create_test.go | 24 +++++++++--------- .../credentials/delete/delete_test.go | 22 ++++++++-------- .../object-storage/credentials/list/list.go | 25 ++++++++++--------- .../credentials/list/list_test.go | 24 ++++++++---------- .../object-storage/disable/disable_test.go | 16 ++++++------ .../cmd/object-storage/enable/enable_test.go | 16 ++++++------ 15 files changed, 144 insertions(+), 152 deletions(-) diff --git a/internal/cmd/object-storage/bucket/create/create_test.go b/internal/cmd/object-storage/bucket/create/create_test.go index b6e926cd2..976dab8a0 100644 --- a/internal/cmd/object-storage/bucket/create/create_test.go +++ b/internal/cmd/object-storage/bucket/create/create_test.go @@ -15,16 +15,16 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() -var testRegion = "eu01" -var testBucketName = "my-bucket" + +const ( + testRegion = "eu01" + testBucketName = "my-bucket" +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -38,8 +38,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -107,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -115,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -123,7 +123,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/bucket/delete/delete_test.go b/internal/cmd/object-storage/bucket/delete/delete_test.go index 2dfe69ec6..829c374cf 100644 --- a/internal/cmd/object-storage/bucket/delete/delete_test.go +++ b/internal/cmd/object-storage/bucket/delete/delete_test.go @@ -13,16 +13,16 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() -var testRegion = "eu01" -var testBucketName = "my-bucket" + +const ( + testRegion = "eu01" + testBucketName = "my-bucket" +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -36,8 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -105,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/bucket/describe/describe_test.go b/internal/cmd/object-storage/bucket/describe/describe_test.go index df76123d2..a55f90bc1 100644 --- a/internal/cmd/object-storage/bucket/describe/describe_test.go +++ b/internal/cmd/object-storage/bucket/describe/describe_test.go @@ -15,16 +15,16 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() -var testRegion = "eu01" -var testBucketName = "my-bucket" + +const ( + testRegion = "eu01" + testBucketName = "my-bucket" +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -38,8 +38,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -107,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -115,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -123,7 +123,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index fd0ec0552..595b095b9 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -64,23 +64,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get Object Storage buckets: %w", err) } - if resp.Buckets == nil || len(*resp.Buckets) == 0 { - 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 - } - params.Printer.Info("No buckets found for project %s\n", projectLabel) - return nil + buckets := resp.GetBuckets() + + 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 } - buckets := *resp.Buckets // Truncate output if model.Limit != nil && len(buckets) > int(*model.Limit) { buckets = buckets[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, buckets) + return outputResult(params.Printer, model.OutputFormat, projectLabel, buckets) }, } @@ -120,12 +117,17 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora return req } -func outputResult(p *print.Printer, outputFormat string, buckets []objectstorage.Bucket) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, buckets []objectstorage.Bucket) error { if buckets == nil { return fmt.Errorf("buckets is empty") } return p.OutputResult(outputFormat, buckets, func() error { + if len(buckets) == 0 { + p.Outputf("No buckets found for project %s\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("NAME", "REGION", "URL (PATH STYLE)", "URL (VIRTUAL HOSTED STYLE)") for i := range buckets { diff --git a/internal/cmd/object-storage/bucket/list/list_test.go b/internal/cmd/object-storage/bucket/list/list_test.go index 3d70ff50b..93b467433 100644 --- a/internal/cmd/object-storage/bucket/list/list_test.go +++ b/internal/cmd/object-storage/bucket/list/list_test.go @@ -16,9 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -28,9 +25,9 @@ var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -83,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -155,6 +152,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string buckets []objectstorage.Bucket } tests := []struct { @@ -179,7 +177,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.buckets); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.buckets); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/object-storage/credentials-group/create/create_test.go b/internal/cmd/object-storage/credentials-group/create/create_test.go index 23908c876..307876137 100644 --- a/internal/cmd/object-storage/credentials-group/create/create_test.go +++ b/internal/cmd/object-storage/credentials-group/create/create_test.go @@ -16,22 +16,22 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() -var testCredentialsGroupName = "test-name" -var testRegion = "eu01" + +const ( + testCredentialsGroupName = "test-name" + testRegion = "eu01" +) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - credentialsGroupNameFlag: testCredentialsGroupName, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + credentialsGroupNameFlag: testCredentialsGroupName, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -95,21 +95,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/credentials-group/delete/delete_test.go b/internal/cmd/object-storage/credentials-group/delete/delete_test.go index 901fc4304..9be471b32 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete_test.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete_test.go @@ -13,16 +13,14 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() var testCredentialsGroupId = uuid.NewString() -var testRegion = "eu01" + +const testRegion = "eu01" func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -36,8 +34,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -105,7 +103,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +111,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +119,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index 800b0f742..cbad3cba1 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -63,11 +63,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list Object Storage credentials groups: %w", err) } - credentialsGroups := *resp.CredentialsGroups - if len(credentialsGroups) == 0 { - params.Printer.Info("No credentials groups found for your project") - return nil - } + credentialsGroups := resp.GetCredentialsGroups() // Truncate output if model.Limit != nil && len(credentialsGroups) > int(*model.Limit) { @@ -114,6 +110,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora func outputResult(p *print.Printer, outputFormat string, credentialsGroups []objectstorage.CredentialsGroup) error { return p.OutputResult(outputFormat, credentialsGroups, func() error { + if len(credentialsGroups) == 0 { + p.Outputf("No credentials groups found for your project") + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "URN") for i := range credentialsGroups { diff --git a/internal/cmd/object-storage/credentials-group/list/list_test.go b/internal/cmd/object-storage/credentials-group/list/list_test.go index 587e6842a..2415108c4 100644 --- a/internal/cmd/object-storage/credentials-group/list/list_test.go +++ b/internal/cmd/object-storage/credentials-group/list/list_test.go @@ -16,21 +16,19 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() -var testRegion = "eu01" + +const testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", - regionFlag: "eu01", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", + globalflags.RegionFlag: "eu01", } for _, mod := range mods { mod(flagValues) @@ -83,21 +81,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/credentials/create/create_test.go b/internal/cmd/object-storage/credentials/create/create_test.go index f3c0bdd60..f351a4d3e 100644 --- a/internal/cmd/object-storage/credentials/create/create_test.go +++ b/internal/cmd/object-storage/credentials/create/create_test.go @@ -17,24 +17,24 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() var testCredentialsGroupId = uuid.NewString() -var testExpirationDate = "2024-01-01T00:00:00Z" -var testRegion = "eu01" + +const ( + testExpirationDate = "2024-01-01T00:00:00Z" + testRegion = "eu01" +) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - credentialsGroupIdFlag: testCredentialsGroupId, - expireDateFlag: testExpirationDate, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + credentialsGroupIdFlag: testCredentialsGroupId, + expireDateFlag: testExpirationDate, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -109,21 +109,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/credentials/delete/delete_test.go b/internal/cmd/object-storage/credentials/delete/delete_test.go index d5ff9e4e5..699d36bcf 100644 --- a/internal/cmd/object-storage/credentials/delete/delete_test.go +++ b/internal/cmd/object-storage/credentials/delete/delete_test.go @@ -13,17 +13,17 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() var testCredentialsGroupId = uuid.NewString() -var testCredentialsId = "keyID" -var testRegion = "eu01" + +const ( + testCredentialsId = "keyID" + testRegion = "eu01" +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -37,9 +37,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - credentialsGroupIdFlag: testCredentialsGroupId, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + credentialsGroupIdFlag: testCredentialsGroupId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -109,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -117,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -125,7 +125,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index 0ebc5efea..522459440 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -66,23 +66,19 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list Object Storage credentials: %w", err) } - credentials := *resp.AccessKeys - if len(credentials) == 0 { - credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) - if err != nil { - params.Printer.Debug(print.ErrorLevel, "get credentials group name: %v", err) - credentialsGroupLabel = model.CredentialsGroupId - } - - params.Printer.Info("No credentials found for credentials group %q\n", credentialsGroupLabel) - return nil + credentials := resp.GetAccessKeys() + + credentialsGroupLabel, err := objectStorageUtils.GetCredentialsGroupName(ctx, apiClient, model.ProjectId, model.CredentialsGroupId, model.Region) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get credentials group name: %v", err) + credentialsGroupLabel = model.CredentialsGroupId } // Truncate output if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, credentials) + return outputResult(params.Printer, model.OutputFormat, credentialsGroupLabel, credentials) }, } configureFlags(cmd) @@ -127,8 +123,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *objectstora return req } -func outputResult(p *print.Printer, outputFormat string, credentials []objectstorage.AccessKey) error { +func outputResult(p *print.Printer, outputFormat, credentialsGroupLabel string, credentials []objectstorage.AccessKey) error { return p.OutputResult(outputFormat, credentials, func() error { + if len(credentials) == 0 { + p.Outputf("No credentials found for credentials group %q\n", credentialsGroupLabel) + return nil + } + table := tables.NewTable() table.SetHeader("CREDENTIALS ID", "ACCESS KEY ID", "EXPIRES AT") for i := range credentials { diff --git a/internal/cmd/object-storage/credentials/list/list_test.go b/internal/cmd/object-storage/credentials/list/list_test.go index 119f7c7c0..8e6469b18 100644 --- a/internal/cmd/object-storage/credentials/list/list_test.go +++ b/internal/cmd/object-storage/credentials/list/list_test.go @@ -16,9 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -29,10 +26,10 @@ var testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - credentialsGroupIdFlag: testCredentialsGroupId, - limitFlag: "10", - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + credentialsGroupIdFlag: testCredentialsGroupId, + limitFlag: "10", + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -87,21 +84,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -179,8 +176,9 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - outputFormat string - credentials []objectstorage.AccessKey + outputFormat string + credentialsGroupLabel string + credentials []objectstorage.AccessKey } tests := []struct { name string @@ -211,7 +209,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentialsGroupLabel, tt.args.credentials); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/object-storage/disable/disable_test.go b/internal/cmd/object-storage/disable/disable_test.go index 5b5a2ea7f..8820b8cc3 100644 --- a/internal/cmd/object-storage/disable/disable_test.go +++ b/internal/cmd/object-storage/disable/disable_test.go @@ -13,20 +13,18 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() -var testRegion = "eu01" + +const testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -78,21 +76,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/object-storage/enable/enable_test.go b/internal/cmd/object-storage/enable/enable_test.go index 59e88e9e0..db8c35d3f 100644 --- a/internal/cmd/object-storage/enable/enable_test.go +++ b/internal/cmd/object-storage/enable/enable_test.go @@ -13,20 +13,18 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) -var projectIdFlag = globalflags.ProjectIdFlag -var regionFlag = globalflags.RegionFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &objectstorage.APIClient{} var testProjectId = uuid.NewString() -var testRegion = "eu01" + +const testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - regionFlag: testRegion, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -78,21 +76,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, From a14c016918e870d4e9712bb0fe97b7e57d54cc45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Wed, 29 Oct 2025 08:39:15 +0100 Subject: [PATCH 477/619] fix(rabbitmq): print valid JSON/YAML output for list cmds (#1043) relates to STACKITCLI-271 / #893 --- .../credentials/create/create_test.go | 12 ++--- .../credentials/delete/delete_test.go | 12 ++--- .../credentials/describe/describe_test.go | 12 ++--- .../cmd/rabbitmq/credentials/list/list.go | 25 ++++++---- .../rabbitmq/credentials/list/list_test.go | 21 ++++---- .../rabbitmq/instance/create/create_test.go | 50 +++++++++---------- .../rabbitmq/instance/delete/delete_test.go | 10 ++-- .../instance/describe/describe_test.go | 10 ++-- internal/cmd/rabbitmq/instance/list/list.go | 24 +++++---- .../cmd/rabbitmq/instance/list/list_test.go | 15 +++--- .../rabbitmq/instance/update/update_test.go | 42 ++++++++-------- internal/cmd/rabbitmq/plans/plans.go | 24 +++++---- internal/cmd/rabbitmq/plans/plans_test.go | 15 +++--- 13 files changed, 131 insertions(+), 141 deletions(-) diff --git a/internal/cmd/rabbitmq/credentials/create/create_test.go b/internal/cmd/rabbitmq/credentials/create/create_test.go index b4f28de99..b36306cd8 100644 --- a/internal/cmd/rabbitmq/credentials/create/create_test.go +++ b/internal/cmd/rabbitmq/credentials/create/create_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -25,8 +23,8 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -88,21 +86,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/rabbitmq/credentials/delete/delete_test.go b/internal/cmd/rabbitmq/credentials/delete/delete_test.go index 6d6a46340..176138ad9 100644 --- a/internal/cmd/rabbitmq/credentials/delete/delete_test.go +++ b/internal/cmd/rabbitmq/credentials/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -35,8 +33,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -104,7 +102,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +118,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/rabbitmq/credentials/describe/describe_test.go b/internal/cmd/rabbitmq/credentials/describe/describe_test.go index 15bf51687..0a466858c 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe_test.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,8 +34,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -105,7 +103,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +111,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +119,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index efa8fc187..fd6921b8a 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -66,22 +66,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list RabbitMQ credentials: %w", err) } - credentials := *resp.CredentialsList - if len(credentials) == 0 { - instanceLabel, err := rabbitmqUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) - if err != nil { - params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) - instanceLabel = model.InstanceId - } - params.Printer.Info("No credentials found for instance %q\n", instanceLabel) - return nil + credentials := resp.GetCredentialsList() + + instanceLabel, err := rabbitmqUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) + instanceLabel = model.InstanceId } // Truncate output if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, credentials) + + return outputResult(params.Printer, model.OutputFormat, instanceLabel, credentials) }, } configureFlags(cmd) @@ -125,8 +123,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP return req } -func outputResult(p *print.Printer, outputFormat string, credentials []rabbitmq.CredentialsListItem) error { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, credentials []rabbitmq.CredentialsListItem) error { return p.OutputResult(outputFormat, credentials, func() error { + if len(credentials) == 0 { + p.Outputf("No credentials found for instance %q\n", instanceLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID") for i := range credentials { diff --git a/internal/cmd/rabbitmq/credentials/list/list_test.go b/internal/cmd/rabbitmq/credentials/list/list_test.go index ed752b64d..86e36c0aa 100644 --- a/internal/cmd/rabbitmq/credentials/list/list_test.go +++ b/internal/cmd/rabbitmq/credentials/list/list_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,9 +24,9 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -81,21 +79,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -173,8 +171,9 @@ func TestBuildRequest(t *testing.T) { func Test_outputResult(t *testing.T) { type args struct { - outputFormat string - credentials []rabbitmq.CredentialsListItem + outputFormat string + instanceLabel string + credentials []rabbitmq.CredentialsListItem } tests := []struct { name string @@ -201,7 +200,7 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/rabbitmq/instance/create/create_test.go b/internal/cmd/rabbitmq/instance/create/create_test.go index a1b4585c4..c76fa6af3 100644 --- a/internal/cmd/rabbitmq/instance/create/create_test.go +++ b/internal/cmd/rabbitmq/instance/create/create_test.go @@ -17,8 +17,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -46,17 +44,17 @@ var testMonitoringInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceNameFlag: "example-name", - enableMonitoringFlag: "true", - graphiteFlag: "example-graphite", - metricsFrequencyFlag: "100", - metricsPrefixFlag: "example-prefix", - monitoringInstanceIdFlag: testMonitoringInstanceId, - pluginFlag: "example-plugin", - sgwAclFlag: "198.51.100.14/24", - syslogFlag: "example-syslog", - planIdFlag: testPlanId, + globalflags.ProjectIdFlag: testProjectId, + instanceNameFlag: "example-name", + enableMonitoringFlag: "true", + graphiteFlag: "example-graphite", + metricsFrequencyFlag: "100", + metricsPrefixFlag: "example-prefix", + monitoringInstanceIdFlag: testMonitoringInstanceId, + pluginFlag: "example-plugin", + sgwAclFlag: "198.51.100.14/24", + syslogFlag: "example-syslog", + planIdFlag: testPlanId, } for _, mod := range mods { mod(flagValues) @@ -148,9 +146,9 @@ func TestParseInput(t *testing.T) { { description: "required fields only", flagValues: map[string]string{ - projectIdFlag: testProjectId, - instanceNameFlag: "example-name", - planIdFlag: testPlanId, + globalflags.ProjectIdFlag: testProjectId, + instanceNameFlag: "example-name", + planIdFlag: testPlanId, }, isValid: true, expectedModel: &inputModel{ @@ -165,13 +163,13 @@ func TestParseInput(t *testing.T) { { description: "zero values", flagValues: map[string]string{ - projectIdFlag: testProjectId, - planIdFlag: testPlanId, - instanceNameFlag: "", - enableMonitoringFlag: "false", - graphiteFlag: "", - metricsFrequencyFlag: "0", - metricsPrefixFlag: "", + globalflags.ProjectIdFlag: testProjectId, + planIdFlag: testPlanId, + instanceNameFlag: "", + enableMonitoringFlag: "false", + graphiteFlag: "", + metricsFrequencyFlag: "0", + metricsPrefixFlag: "", }, isValid: true, expectedModel: &inputModel{ @@ -190,21 +188,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/rabbitmq/instance/delete/delete_test.go b/internal/cmd/rabbitmq/instance/delete/delete_test.go index 24fbaeac9..4ffdd36a8 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete_test.go +++ b/internal/cmd/rabbitmq/instance/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -34,7 +32,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -101,7 +99,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/rabbitmq/instance/describe/describe_test.go b/internal/cmd/rabbitmq/instance/describe/describe_test.go index 620119e9b..b2e2d2a95 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe_test.go +++ b/internal/cmd/rabbitmq/instance/describe/describe_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -35,7 +33,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -102,7 +100,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -110,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -118,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index 61bc42e5b..2bf032e8c 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -64,15 +64,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get RabbitMQ instances: %w", err) } - instances := *resp.Instances - if len(instances) == 0 { - 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 - } - params.Printer.Info("No instances found for project %q\n", projectLabel) - return nil + instances := resp.GetInstances() + + 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 } // Truncate output @@ -80,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, projectLabel, instances) }, } @@ -120,8 +117,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP return req } -func outputResult(p *print.Printer, outputFormat string, instances []rabbitmq.Instance) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []rabbitmq.Instance) error { return p.OutputResult(outputFormat, instances, func() error { + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { diff --git a/internal/cmd/rabbitmq/instance/list/list_test.go b/internal/cmd/rabbitmq/instance/list/list_test.go index 6160eb6cc..4f9a0ab7d 100644 --- a/internal/cmd/rabbitmq/instance/list/list_test.go +++ b/internal/cmd/rabbitmq/instance/list/list_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -25,8 +23,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -78,21 +76,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -150,6 +148,7 @@ func TestBuildRequest(t *testing.T) { func Test_outputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string instances []rabbitmq.Instance } tests := []struct { @@ -177,7 +176,7 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.instances); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/rabbitmq/instance/update/update_test.go b/internal/cmd/rabbitmq/instance/update/update_test.go index 50642481c..11198d9a6 100644 --- a/internal/cmd/rabbitmq/instance/update/update_test.go +++ b/internal/cmd/rabbitmq/instance/update/update_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -58,16 +56,16 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - enableMonitoringFlag: "true", - graphiteFlag: "example-graphite", - metricsFrequencyFlag: "100", - metricsPrefixFlag: "example-prefix", - monitoringInstanceIdFlag: testMonitoringInstanceId, - pluginFlag: "example-plugin", - sgwAclFlag: "198.51.100.14/24", - syslogFlag: "example-syslog", - planIdFlag: testPlanId, + globalflags.ProjectIdFlag: testProjectId, + enableMonitoringFlag: "true", + graphiteFlag: "example-graphite", + metricsFrequencyFlag: "100", + metricsPrefixFlag: "example-prefix", + monitoringInstanceIdFlag: testMonitoringInstanceId, + pluginFlag: "example-plugin", + sgwAclFlag: "198.51.100.14/24", + syslogFlag: "example-syslog", + planIdFlag: testPlanId, } for _, mod := range mods { mod(flagValues) @@ -159,7 +157,7 @@ func TestParseInput(t *testing.T) { description: "required flags only (no values to update)", argValues: fixtureArgValues(), flagValues: map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, }, isValid: false, expectedModel: &inputModel{ @@ -174,12 +172,12 @@ func TestParseInput(t *testing.T) { description: "zero values", argValues: fixtureArgValues(), flagValues: map[string]string{ - projectIdFlag: testProjectId, - planIdFlag: testPlanId, - enableMonitoringFlag: "false", - graphiteFlag: "", - metricsFrequencyFlag: "0", - metricsPrefixFlag: "", + globalflags.ProjectIdFlag: testProjectId, + planIdFlag: testPlanId, + enableMonitoringFlag: "false", + graphiteFlag: "", + metricsFrequencyFlag: "0", + metricsPrefixFlag: "", }, isValid: true, expectedModel: &inputModel{ @@ -199,7 +197,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -207,7 +205,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -215,7 +213,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index 09f0220ab..d62474125 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -65,15 +65,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get RabbitMQ service plans: %w", err) } - plans := *resp.Offerings - if len(plans) == 0 { - 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 - } - params.Printer.Info("No plans found for project %q\n", projectLabel) - return nil + plans := resp.GetOfferings() + + 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 } // Truncate output @@ -81,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, projectLabel, plans) }, } @@ -121,8 +118,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *rabbitmq.AP return req } -func outputResult(p *print.Printer, outputFormat string, plans []rabbitmq.Offering) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, plans []rabbitmq.Offering) error { return p.OutputResult(outputFormat, plans, func() error { + if len(plans) == 0 { + p.Outputf("No plans found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { diff --git a/internal/cmd/rabbitmq/plans/plans_test.go b/internal/cmd/rabbitmq/plans/plans_test.go index 2089d4414..486369731 100644 --- a/internal/cmd/rabbitmq/plans/plans_test.go +++ b/internal/cmd/rabbitmq/plans/plans_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -25,8 +23,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -78,21 +76,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -150,6 +148,7 @@ func TestBuildRequest(t *testing.T) { func Test_outputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string plans []rabbitmq.Offering } tests := []struct { @@ -177,7 +176,7 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.plans); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From c066de61d51074cf99d3c51bb2f96d8fd8d1d0a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 08:15:17 +0000 Subject: [PATCH 478/619] chore(deps): bump actions/upload-artifact from 4 to 5 (#1054) --- .github/workflows/ci.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6311125ba..1bf4b205f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -36,7 +36,7 @@ jobs: run: make test - name: Archive code coverage results - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} path: ${{ env.CODE_COVERAGE_FILE_NAME }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9e453b7fa..3e67096c4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -90,7 +90,7 @@ jobs: rm -f "$GPG_KEY_PATH" - name: Upload artifacts to workflow - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: goreleaser-dist-temp path: dist From 6972ccde2d345cf88b0a3ac07afe8a3c3d5c22cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 09:24:36 +0100 Subject: [PATCH 479/619] chore(deps): bump actions/download-artifact from 5 to 6 (#1051) --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3e67096c4..8eb074ead 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -110,7 +110,7 @@ jobs: # use the artifacts from the "goreleaser" job - name: Download artifacts from workflow - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: goreleaser-dist-temp path: dist @@ -147,7 +147,7 @@ jobs: uses: actions/checkout@v5 - name: Download artifacts from workflow - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: goreleaser-dist-temp path: dist From 02b922af63105fdf327d5c54d16d88abc41d694a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:32:09 +0100 Subject: [PATCH 480/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/git (#1062) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f5d9080d3..ba1fee414 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 - github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0 + github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 diff --git a/go.sum b/go.sum index 1c421db57..989b9de14 100644 --- a/go.sum +++ b/go.sum @@ -569,8 +569,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= -github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0 h1:/weT7P5Uwy1Qlhw0NidqtQBlbbb/dQehweDV/I9ShXg= -github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= +github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 h1:zuoJnsLnjxdQcQbs7gUXYzrN0Ip5NXj+6LFBp1EO6cg= +github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 h1:dnEjyapuv8WwRN5vE2z6+4/+ZqQTBx+bX27x2nOF7Jw= github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w= github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 h1:zxoOv7Fu+FmdsvTKiKkbmLItrMKfL+QoVtz9ReEF30E= From fc25893f1f940916b803bda036e408e2fc186b6d Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Mon, 3 Nov 2025 11:27:38 +0100 Subject: [PATCH 481/619] chore(client): Refactor ConfigureClient() function to use a generic function instead (#1058) Signed-off-by: Alexander Dahmen --- .github/docs/contribution-guide/client.go | 38 +------------- internal/cmd/git/flavor/list/list.go | 2 +- internal/cmd/git/instance/create/create.go | 2 +- internal/cmd/git/instance/delete/delete.go | 2 +- .../cmd/git/instance/describe/describe.go | 2 +- internal/cmd/git/instance/list/list.go | 2 +- internal/pkg/config/config.go | 3 ++ internal/pkg/generic-client/generic_client.go | 50 +++++++++++++++++++ internal/pkg/services/alb/client/client.go | 34 +------------ .../services/authorization/client/client.go | 35 +------------ internal/pkg/services/dns/client/client.go | 35 +------------ internal/pkg/services/git/client/client.go | 37 ++------------ internal/pkg/services/iaas/client/client.go | 37 +------------- internal/pkg/services/kms/client/client.go | 35 +------------ .../services/load-balancer/client/client.go | 34 +------------ internal/pkg/services/logme/client/client.go | 37 +------------- .../pkg/services/mariadb/client/client.go | 37 +------------- .../pkg/services/mongodbflex/client/client.go | 37 ++------------ .../services/object-storage/client/client.go | 38 +------------- .../services/observability/client/client.go | 37 +------------- .../pkg/services/opensearch/client/client.go | 37 +------------- .../services/postgresflex/client/client.go | 37 +------------- .../pkg/services/rabbitmq/client/client.go | 37 +------------- internal/pkg/services/redis/client/client.go | 37 +------------- .../services/resourcemanager/client/client.go | 35 +------------ .../pkg/services/runcommand/client/client.go | 36 +------------ .../services/secrets-manager/client/client.go | 37 +------------- .../services/serverbackup/client/client.go | 37 +------------- .../services/serverosupdate/client/client.go | 36 +------------ .../services/service-account/client/client.go | 35 +------------ .../service-enablement/client/client.go | 37 +------------- internal/pkg/services/ske/client/client.go | 36 +------------ .../services/sqlserverflex/client/client.go | 35 +------------ 33 files changed, 112 insertions(+), 894 deletions(-) create mode 100644 internal/pkg/generic-client/generic_client.go diff --git a/.github/docs/contribution-guide/client.go b/.github/docs/contribution-guide/client.go index 3fdda371b..df0f74442 100644 --- a/.github/docs/contribution-guide/client.go +++ b/.github/docs/contribution-guide/client.go @@ -2,46 +2,12 @@ package client import ( "github.com/spf13/viper" - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" - "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/foo" // (...) ) func ConfigureClient(p *print.Printer, cliVersion string) (*foo.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - return nil, &errors.AuthError{} - } - - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), // Configuring region is needed if "foo" is a regional API - authCfgOption, - } - - customEndpoint := viper.GetString(config.fooCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := foo.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.fooCustomEndpointKey), false, genericclient.CreateApiClient[*foo.APIClient](foo.NewAPIClient)) } diff --git a/internal/cmd/git/flavor/list/list.go b/internal/cmd/git/flavor/list/list.go index c8c8fe583..fddb9bc26 100644 --- a/internal/cmd/git/flavor/list/list.go +++ b/internal/cmd/git/flavor/list/list.go @@ -49,7 +49,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index 8c6c56ac4..f63e7499d 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -61,7 +61,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/git/instance/delete/delete.go b/internal/cmd/git/instance/delete/delete.go index 01f6f3f19..8b5bb7ba1 100644 --- a/internal/cmd/git/instance/delete/delete.go +++ b/internal/cmd/git/instance/delete/delete.go @@ -46,7 +46,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/git/instance/describe/describe.go b/internal/cmd/git/instance/describe/describe.go index 57bd8e859..2d7948b11 100644 --- a/internal/cmd/git/instance/describe/describe.go +++ b/internal/cmd/git/instance/describe/describe.go @@ -42,7 +42,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/cmd/git/instance/list/list.go b/internal/cmd/git/instance/list/list.go index 161af2df4..83aa2015b 100644 --- a/internal/cmd/git/instance/list/list.go +++ b/internal/cmd/git/instance/list/list.go @@ -50,7 +50,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Configure API client - apiClient, err := client.ConfigureClient(params.Printer) + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) if err != nil { return err } diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index a8c136996..9a03ac3b8 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -23,6 +23,7 @@ const ( AllowedUrlDomainKey = "allowed_url_domain" AuthorizationCustomEndpointKey = "authorization_custom_endpoint" + AlbCustomEndpoint = "alb_custom _endpoint" DNSCustomEndpointKey = "dns_custom_endpoint" LoadBalancerCustomEndpointKey = "load_balancer_custom_endpoint" LogMeCustomEndpointKey = "logme_custom_endpoint" @@ -107,6 +108,7 @@ var ConfigKeys = []string{ IaaSCustomEndpointKey, TokenCustomEndpointKey, GitCustomEndpointKey, + AlbCustomEndpoint, } var defaultConfigFolderPath string @@ -193,6 +195,7 @@ func setConfigDefaults() { viper.SetDefault(IaaSCustomEndpointKey, "") viper.SetDefault(TokenCustomEndpointKey, "") viper.SetDefault(GitCustomEndpointKey, "") + viper.SetDefault(AlbCustomEndpoint, "") } func getConfigFilePath(configFolder string) string { diff --git a/internal/pkg/generic-client/generic_client.go b/internal/pkg/generic-client/generic_client.go new file mode 100644 index 000000000..64ede2600 --- /dev/null +++ b/internal/pkg/generic-client/generic_client.go @@ -0,0 +1,50 @@ +package genericclient + +import ( + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" +) + +type CreateApiClient[T any] func(opts ...sdkConfig.ConfigurationOption) (T, error) + +// ConfigureClientGeneric contains the generic code which needs to be executed in order to configure the api client. +func ConfigureClientGeneric[T any](p *print.Printer, cliVersion, customEndpoint string, useRegion bool, createApiClient CreateApiClient[T]) (T, error) { + // return value if an error happens + var zero T + authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) + if err != nil { + p.Debug(print.ErrorLevel, "configure authentication: %v", err) + return zero, &errors.AuthError{} + } + cfgOptions := []sdkConfig.ConfigurationOption{ + utils.UserAgentConfigOption(cliVersion), + authCfgOption, + } + + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } + + if useRegion { + cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(viper.GetString(config.RegionKey))) + } + + if p.IsVerbosityDebug() { + cfgOptions = append(cfgOptions, + sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), + ) + } + + apiClient, err := createApiClient(cfgOptions...) + if err != nil { + p.Debug(print.ErrorLevel, "create new API client: %v", err) + return zero, &errors.AuthError{} + } + + return apiClient, nil +} diff --git a/internal/pkg/services/alb/client/client.go b/internal/pkg/services/alb/client/client.go index 866a76ad5..1de12c654 100644 --- a/internal/pkg/services/alb/client/client.go +++ b/internal/pkg/services/alb/client/client.go @@ -1,44 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/alb" ) func ConfigureClient(p *print.Printer, cliVersion string) (*alb.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.IaaSCustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := alb.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.AlbCustomEndpoint), true, genericclient.CreateApiClient[*alb.APIClient](alb.NewAPIClient)) } diff --git a/internal/pkg/services/authorization/client/client.go b/internal/pkg/services/authorization/client/client.go index 7deb26b12..8646a8120 100644 --- a/internal/pkg/services/authorization/client/client.go +++ b/internal/pkg/services/authorization/client/client.go @@ -1,45 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/authorization" ) func ConfigureClient(p *print.Printer, cliVersion string) (*authorization.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.AuthorizationCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := authorization.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.AuthorizationCustomEndpointKey), false, genericclient.CreateApiClient[*authorization.APIClient](authorization.NewAPIClient)) } diff --git a/internal/pkg/services/dns/client/client.go b/internal/pkg/services/dns/client/client.go index 15b824da3..478fa0a53 100644 --- a/internal/pkg/services/dns/client/client.go +++ b/internal/pkg/services/dns/client/client.go @@ -1,46 +1,15 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/dns" ) func ConfigureClient(p *print.Printer, cliVersion string) (*dns.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.DNSCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := dns.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.DNSCustomEndpointKey), false, genericclient.CreateApiClient[*dns.APIClient](dns.NewAPIClient)) } diff --git a/internal/pkg/services/git/client/client.go b/internal/pkg/services/git/client/client.go index dde3b7be6..3fc5b21b1 100644 --- a/internal/pkg/services/git/client/client.go +++ b/internal/pkg/services/git/client/client.go @@ -1,45 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/git" ) -func ConfigureClient(p *print.Printer) (*git.APIClient, error) { - var err error - var apiClient *git.APIClient - var cfgOptions []sdkConfig.ConfigurationOption - - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions = append(cfgOptions, authCfgOption) - - customEndpoint := viper.GetString(config.GitCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err = git.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil +func ConfigureClient(p *print.Printer, cliVersion string) (*git.APIClient, error) { + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.GitCustomEndpointKey), false, genericclient.CreateApiClient[*git.APIClient](git.NewAPIClient)) } diff --git a/internal/pkg/services/iaas/client/client.go b/internal/pkg/services/iaas/client/client.go index e32d15b4c..c9401016a 100644 --- a/internal/pkg/services/iaas/client/client.go +++ b/internal/pkg/services/iaas/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) func ConfigureClient(p *print.Printer, cliVersion string) (*iaas.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.IaaSCustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } else { - region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := iaas.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.IaaSCustomEndpointKey), true, genericclient.CreateApiClient[*iaas.APIClient](iaas.NewAPIClient)) } diff --git a/internal/pkg/services/kms/client/client.go b/internal/pkg/services/kms/client/client.go index b2cbd8250..ecb2111a2 100644 --- a/internal/pkg/services/kms/client/client.go +++ b/internal/pkg/services/kms/client/client.go @@ -1,45 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/kms" ) func ConfigureClient(p *print.Printer, cliVersion string) (*kms.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.KMSCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := kms.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.KMSCustomEndpointKey), false, genericclient.CreateApiClient[*kms.APIClient](kms.NewAPIClient)) } diff --git a/internal/pkg/services/load-balancer/client/client.go b/internal/pkg/services/load-balancer/client/client.go index 402498c70..7234c4f88 100644 --- a/internal/pkg/services/load-balancer/client/client.go +++ b/internal/pkg/services/load-balancer/client/client.go @@ -1,44 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" ) func ConfigureClient(p *print.Printer, cliVersion string) (*loadbalancer.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.LoadBalancerCustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := loadbalancer.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.LoadBalancerCustomEndpointKey), false, genericclient.CreateApiClient[*loadbalancer.APIClient](loadbalancer.NewAPIClient)) } diff --git a/internal/pkg/services/logme/client/client.go b/internal/pkg/services/logme/client/client.go index 71a750c7f..f65bcfb6a 100644 --- a/internal/pkg/services/logme/client/client.go +++ b/internal/pkg/services/logme/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/logme" ) func ConfigureClient(p *print.Printer, cliVersion string) (*logme.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.LogMeCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := logme.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.LogMeCustomEndpointKey), true, genericclient.CreateApiClient[*logme.APIClient](logme.NewAPIClient)) } diff --git a/internal/pkg/services/mariadb/client/client.go b/internal/pkg/services/mariadb/client/client.go index 7a7fb9f78..9952a324c 100644 --- a/internal/pkg/services/mariadb/client/client.go +++ b/internal/pkg/services/mariadb/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/mariadb" ) func ConfigureClient(p *print.Printer, cliVersion string) (*mariadb.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.MariaDBCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := mariadb.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.MariaDBCustomEndpointKey), true, genericclient.CreateApiClient[*mariadb.APIClient](mariadb.NewAPIClient)) } diff --git a/internal/pkg/services/mongodbflex/client/client.go b/internal/pkg/services/mongodbflex/client/client.go index 216fbd9d5..58613728b 100644 --- a/internal/pkg/services/mongodbflex/client/client.go +++ b/internal/pkg/services/mongodbflex/client/client.go @@ -1,44 +1,13 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" + "github.com/spf13/viper" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - - "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/mongodbflex" ) func ConfigureClient(p *print.Printer, cliVersion string) (*mongodbflex.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.MongoDBFlexCustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := mongodbflex.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.MongoDBFlexCustomEndpointKey), false, genericclient.CreateApiClient[*mongodbflex.APIClient](mongodbflex.NewAPIClient)) } diff --git a/internal/pkg/services/object-storage/client/client.go b/internal/pkg/services/object-storage/client/client.go index 5eab52238..82b2447f8 100644 --- a/internal/pkg/services/object-storage/client/client.go +++ b/internal/pkg/services/object-storage/client/client.go @@ -1,48 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/objectstorage" ) func ConfigureClient(p *print.Printer, cliVersion string) (*objectstorage.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.ObjectStorageCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := objectstorage.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.ObjectStorageCustomEndpointKey), true, genericclient.CreateApiClient[*objectstorage.APIClient](objectstorage.NewAPIClient)) } diff --git a/internal/pkg/services/observability/client/client.go b/internal/pkg/services/observability/client/client.go index 23698b5ff..83c496121 100644 --- a/internal/pkg/services/observability/client/client.go +++ b/internal/pkg/services/observability/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/observability" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" ) func ConfigureClient(p *print.Printer, cliVersion string) (*observability.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.ObservabilityCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := observability.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.ObservabilityCustomEndpointKey), true, genericclient.CreateApiClient[*observability.APIClient](observability.NewAPIClient)) } diff --git a/internal/pkg/services/opensearch/client/client.go b/internal/pkg/services/opensearch/client/client.go index b1948a389..fb7d218a3 100644 --- a/internal/pkg/services/opensearch/client/client.go +++ b/internal/pkg/services/opensearch/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) func ConfigureClient(p *print.Printer, cliVersion string) (*opensearch.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.OpenSearchCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := opensearch.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.OpenSearchCustomEndpointKey), true, genericclient.CreateApiClient[*opensearch.APIClient](opensearch.NewAPIClient)) } diff --git a/internal/pkg/services/postgresflex/client/client.go b/internal/pkg/services/postgresflex/client/client.go index ad125cd0c..d5b77761f 100644 --- a/internal/pkg/services/postgresflex/client/client.go +++ b/internal/pkg/services/postgresflex/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) func ConfigureClient(p *print.Printer, cliVersion string) (*postgresflex.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.PostgresFlexCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := postgresflex.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.PostgresFlexCustomEndpointKey), true, genericclient.CreateApiClient[*postgresflex.APIClient](postgresflex.NewAPIClient)) } diff --git a/internal/pkg/services/rabbitmq/client/client.go b/internal/pkg/services/rabbitmq/client/client.go index 90c4df9fa..df717b305 100644 --- a/internal/pkg/services/rabbitmq/client/client.go +++ b/internal/pkg/services/rabbitmq/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq" ) func ConfigureClient(p *print.Printer, cliVersion string) (*rabbitmq.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.RabbitMQCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := rabbitmq.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.RabbitMQCustomEndpointKey), true, genericclient.CreateApiClient[*rabbitmq.APIClient](rabbitmq.NewAPIClient)) } diff --git a/internal/pkg/services/redis/client/client.go b/internal/pkg/services/redis/client/client.go index 1966b0ad2..72c023398 100644 --- a/internal/pkg/services/redis/client/client.go +++ b/internal/pkg/services/redis/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/redis" ) func ConfigureClient(p *print.Printer, cliVersion string) (*redis.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.RedisCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := redis.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.RedisCustomEndpointKey), true, genericclient.CreateApiClient[*redis.APIClient](redis.NewAPIClient)) } diff --git a/internal/pkg/services/resourcemanager/client/client.go b/internal/pkg/services/resourcemanager/client/client.go index 5cca3a34b..199b2a2e1 100644 --- a/internal/pkg/services/resourcemanager/client/client.go +++ b/internal/pkg/services/resourcemanager/client/client.go @@ -1,45 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" ) func ConfigureClient(p *print.Printer, cliVersion string) (*resourcemanager.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.ResourceManagerEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := resourcemanager.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.ResourceManagerEndpointKey), false, genericclient.CreateApiClient[*resourcemanager.APIClient](resourcemanager.NewAPIClient)) } diff --git a/internal/pkg/services/runcommand/client/client.go b/internal/pkg/services/runcommand/client/client.go index 86f6d3d5d..1ecb49f4f 100644 --- a/internal/pkg/services/runcommand/client/client.go +++ b/internal/pkg/services/runcommand/client/client.go @@ -1,46 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/runcommand" ) func ConfigureClient(p *print.Printer, cliVersion string) (*runcommand.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.RunCommandCustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } else { - cfgOptions = append(cfgOptions, authCfgOption) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := runcommand.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.RunCommandCustomEndpointKey), false, genericclient.CreateApiClient[*runcommand.APIClient](runcommand.NewAPIClient)) } diff --git a/internal/pkg/services/secrets-manager/client/client.go b/internal/pkg/services/secrets-manager/client/client.go index 3ef6e1402..dfedcb0e3 100644 --- a/internal/pkg/services/secrets-manager/client/client.go +++ b/internal/pkg/services/secrets-manager/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/secretsmanager" ) func ConfigureClient(p *print.Printer, cliVersion string) (*secretsmanager.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - region := viper.GetString(config.RegionKey) - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - sdkConfig.WithRegion(region), - authCfgOption, - } - - customEndpoint := viper.GetString(config.SecretsManagerCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := secretsmanager.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.SecretsManagerCustomEndpointKey), true, genericclient.CreateApiClient[*secretsmanager.APIClient](secretsmanager.NewAPIClient)) } diff --git a/internal/pkg/services/serverbackup/client/client.go b/internal/pkg/services/serverbackup/client/client.go index 1184ce684..c8726b392 100644 --- a/internal/pkg/services/serverbackup/client/client.go +++ b/internal/pkg/services/serverbackup/client/client.go @@ -1,47 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/serverbackup" ) func ConfigureClient(p *print.Printer, cliVersion string) (*serverbackup.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.ServerBackupCustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } else { - region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion(region)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := serverbackup.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.ServerBackupCustomEndpointKey), true, genericclient.CreateApiClient[*serverbackup.APIClient](serverbackup.NewAPIClient)) } diff --git a/internal/pkg/services/serverosupdate/client/client.go b/internal/pkg/services/serverosupdate/client/client.go index ec39a5477..a3d324d90 100644 --- a/internal/pkg/services/serverosupdate/client/client.go +++ b/internal/pkg/services/serverosupdate/client/client.go @@ -1,46 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/serverupdate" ) func ConfigureClient(p *print.Printer, cliVersion string) (*serverupdate.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.ServerOsUpdateCustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } else { - cfgOptions = append(cfgOptions, authCfgOption) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := serverupdate.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.ServerOsUpdateCustomEndpointKey), false, genericclient.CreateApiClient[*serverupdate.APIClient](serverupdate.NewAPIClient)) } diff --git a/internal/pkg/services/service-account/client/client.go b/internal/pkg/services/service-account/client/client.go index cb35d2c4d..f7150c892 100644 --- a/internal/pkg/services/service-account/client/client.go +++ b/internal/pkg/services/service-account/client/client.go @@ -1,45 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/serviceaccount" ) func ConfigureClient(p *print.Printer, cliVersion string) (*serviceaccount.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.ServiceAccountCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := serviceaccount.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.ServiceAccountCustomEndpointKey), false, genericclient.CreateApiClient[*serviceaccount.APIClient](serviceaccount.NewAPIClient)) } diff --git a/internal/pkg/services/service-enablement/client/client.go b/internal/pkg/services/service-enablement/client/client.go index 66b952376..e0bced744 100644 --- a/internal/pkg/services/service-enablement/client/client.go +++ b/internal/pkg/services/service-enablement/client/client.go @@ -2,46 +2,13 @@ package client import ( "github.com/spf13/viper" - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" ) func ConfigureClient(p *print.Printer, cliVersion string) (*serviceenablement.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.ServiceEnablementCustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } else { - region := viper.GetString(config.RegionKey) - cfgOptions = append(cfgOptions, sdkConfig.WithRegion(region)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := serviceenablement.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.ServiceEnablementCustomEndpointKey), true, genericclient.CreateApiClient[*serviceenablement.APIClient](serviceenablement.NewAPIClient)) } diff --git a/internal/pkg/services/ske/client/client.go b/internal/pkg/services/ske/client/client.go index 1495ba7bf..5b4b69f38 100644 --- a/internal/pkg/services/ske/client/client.go +++ b/internal/pkg/services/ske/client/client.go @@ -1,46 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/ske" ) func ConfigureClient(p *print.Printer, cliVersion string) (*ske.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.SKECustomEndpointKey) - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } else { - cfgOptions = append(cfgOptions, authCfgOption) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := ske.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.SKECustomEndpointKey), false, genericclient.CreateApiClient[*ske.APIClient](ske.NewAPIClient)) } diff --git a/internal/pkg/services/sqlserverflex/client/client.go b/internal/pkg/services/sqlserverflex/client/client.go index 30e937f59..25bbb4ec3 100644 --- a/internal/pkg/services/sqlserverflex/client/client.go +++ b/internal/pkg/services/sqlserverflex/client/client.go @@ -1,45 +1,14 @@ package client import ( - "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/viper" - sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex" ) func ConfigureClient(p *print.Printer, cliVersion string) (*sqlserverflex.APIClient, error) { - authCfgOption, err := auth.AuthenticationConfig(p, auth.AuthorizeUser) - if err != nil { - p.Debug(print.ErrorLevel, "configure authentication: %v", err) - return nil, &errors.AuthError{} - } - cfgOptions := []sdkConfig.ConfigurationOption{ - utils.UserAgentConfigOption(cliVersion), - authCfgOption, - } - - customEndpoint := viper.GetString(config.SQLServerFlexCustomEndpointKey) - - if customEndpoint != "" { - cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) - } - - if p.IsVerbosityDebug() { - cfgOptions = append(cfgOptions, - sdkConfig.WithMiddleware(print.RequestResponseCapturer(p, nil)), - ) - } - - apiClient, err := sqlserverflex.NewAPIClient(cfgOptions...) - if err != nil { - p.Debug(print.ErrorLevel, "create new API client: %v", err) - return nil, &errors.AuthError{} - } - - return apiClient, nil + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.SQLServerFlexCustomEndpointKey), false, genericclient.CreateApiClient[*sqlserverflex.APIClient](sqlserverflex.NewAPIClient)) } From b11890db516454e394f0ec88cbe70b24b731ca53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 11:35:33 +0100 Subject: [PATCH 482/619] chore(deps): bump renovatebot/github-action from 43.0.19 to 43.0.20 (#1067) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 8dab86076..fc34b9b41 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.19 + uses: renovatebot/github-action@v43.0.20 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 3fdc40650aa5be01701c6774eac2d2d5ce8047ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 10:42:17 +0000 Subject: [PATCH 483/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/core (#1066) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ba1fee414..6eff66cae 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/spf13/cobra v1.10.1 github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 - github.com/stackitcloud/stackit-sdk-go/core v0.17.3 + github.com/stackitcloud/stackit-sdk-go/core v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 diff --git a/go.sum b/go.sum index 989b9de14..b9e0a5002 100644 --- a/go.sum +++ b/go.sum @@ -561,8 +561,8 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stackitcloud/stackit-sdk-go/core v0.17.3 h1:GsZGmRRc/3GJLmCUnsZswirr5wfLRrwavbnL/renOqg= -github.com/stackitcloud/stackit-sdk-go/core v0.17.3/go.mod h1:HBCXJGPgdRulplDzhrmwC+Dak9B/x0nzNtmOpu+1Ahg= +github.com/stackitcloud/stackit-sdk-go/core v0.18.0 h1:+4v8sjQpQXPihO3crgTp0Kz/XRIi5p7oKV28dw6jsEQ= +github.com/stackitcloud/stackit-sdk-go/core v0.18.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 h1:UM/HvewAgELEvZ4zk++Ykd6jUTSL+asRqtK+DszDOzE= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0/go.mod h1:mOmGoNLPXLJ5tKLnhOnhKW7wL9Giy/4DowiDZNLlQCY= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo= From 52ad9528bc64415431d4845147803194f424e30f Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:39:33 +0100 Subject: [PATCH 484/619] feat(iaas): Region adjustments and migration to v2 API (#1056) relates to STACKITCLI-227 --- docs/stackit_network-area.md | 1 + docs/stackit_network-area_create.md | 28 +- docs/stackit_network-area_region.md | 38 ++ docs/stackit_network-area_region_create.md | 58 +++ docs/stackit_network-area_region_delete.md | 46 ++ docs/stackit_network-area_region_describe.md | 46 ++ docs/stackit_network-area_region_list.md | 42 ++ docs/stackit_network-area_region_update.md | 56 ++ docs/stackit_network-area_route_create.md | 15 +- docs/stackit_network-area_update.md | 12 +- docs/stackit_network_create.md | 2 +- go.mod | 2 +- go.sum | 4 +- internal/cmd/affinity-groups/create/create.go | 2 +- .../cmd/affinity-groups/create/create_test.go | 17 +- internal/cmd/affinity-groups/delete/delete.go | 4 +- .../cmd/affinity-groups/delete/delete_test.go | 10 +- .../cmd/affinity-groups/describe/describe.go | 2 +- .../affinity-groups/describe/describe_test.go | 12 +- internal/cmd/affinity-groups/list/list.go | 2 +- .../cmd/affinity-groups/list/list_test.go | 15 +- internal/cmd/image/create/create.go | 2 +- internal/cmd/image/create/create_test.go | 114 +++-- internal/cmd/image/delete/delete.go | 4 +- internal/cmd/image/delete/delete_test.go | 21 +- internal/cmd/image/describe/describe.go | 2 +- internal/cmd/image/describe/describe_test.go | 23 +- internal/cmd/image/list/list.go | 2 +- internal/cmd/image/list/list_test.go | 26 +- internal/cmd/image/update/update.go | 4 +- internal/cmd/image/update/update_test.go | 35 +- internal/cmd/network-area/create/create.go | 230 ++++++--- .../cmd/network-area/create/create_test.go | 361 +++++++++++-- internal/cmd/network-area/delete/delete.go | 43 +- .../cmd/network-area/describe/describe.go | 55 +- internal/cmd/network-area/list/list.go | 13 +- .../network-range/create/create.go | 4 +- .../network-range/create/create_test.go | 9 +- .../network-range/delete/delete.go | 4 +- .../network-range/delete/delete_test.go | 9 +- .../network-range/describe/describe.go | 4 +- .../network-range/describe/describe_test.go | 10 +- .../network-area/network-range/list/list.go | 4 +- .../network-range/list/list_test.go | 9 +- internal/cmd/network-area/network_area.go | 2 + .../cmd/network-area/region/create/create.go | 195 +++++++ .../network-area/region/create/create_test.go | 307 +++++++++++ .../cmd/network-area/region/delete/delete.go | 129 +++++ .../network-area/region/delete/delete_test.go | 168 ++++++ .../network-area/region/describe/describe.go | 169 ++++++ .../region/describe/describe_test.go | 214 ++++++++ internal/cmd/network-area/region/list/list.go | 153 ++++++ .../cmd/network-area/region/list/list_test.go | 221 ++++++++ internal/cmd/network-area/region/region.go | 34 ++ .../cmd/network-area/region/update/update.go | 165 ++++++ .../network-area/region/update/update_test.go | 265 ++++++++++ .../cmd/network-area/route/create/create.go | 205 +++++++- .../network-area/route/create/create_test.go | 68 ++- .../cmd/network-area/route/delete/delete.go | 2 +- .../network-area/route/delete/delete_test.go | 9 +- .../network-area/route/describe/describe.go | 39 +- .../route/describe/describe_test.go | 9 +- internal/cmd/network-area/route/list/list.go | 36 +- .../cmd/network-area/route/list/list_test.go | 27 +- .../cmd/network-area/route/update/update.go | 4 +- .../network-area/route/update/update_test.go | 9 +- internal/cmd/network-area/update/update.go | 138 ++++- .../cmd/network-area/update/update_test.go | 256 ++++++++-- .../cmd/network-interface/create/create.go | 6 +- .../network-interface/create/create_test.go | 14 +- .../cmd/network-interface/delete/delete.go | 6 +- .../network-interface/delete/delete_test.go | 16 +- .../network-interface/describe/describe.go | 6 +- .../describe/describe_test.go | 16 +- internal/cmd/network-interface/list/list.go | 12 +- .../cmd/network-interface/list/list_test.go | 19 +- .../cmd/network-interface/update/update.go | 6 +- .../network-interface/update/update_test.go | 13 +- internal/cmd/network/create/create.go | 117 ++++- internal/cmd/network/create/create_test.go | 483 +++++++++++++----- internal/cmd/network/delete/delete.go | 6 +- internal/cmd/network/delete/delete_test.go | 16 +- internal/cmd/network/describe/describe.go | 83 +-- .../cmd/network/describe/describe_test.go | 34 +- internal/cmd/network/list/list.go | 13 +- internal/cmd/network/list/list_test.go | 19 +- internal/cmd/network/update/update.go | 27 +- internal/cmd/network/update/update_test.go | 33 +- internal/cmd/public-ip/associate/associate.go | 4 +- .../cmd/public-ip/associate/associate_test.go | 17 +- internal/cmd/public-ip/create/create.go | 2 +- internal/cmd/public-ip/create/create_test.go | 17 +- internal/cmd/public-ip/delete/delete.go | 4 +- internal/cmd/public-ip/delete/delete_test.go | 16 +- internal/cmd/public-ip/describe/describe.go | 2 +- .../cmd/public-ip/describe/describe_test.go | 16 +- .../public-ip/disassociate/disassociate.go | 4 +- .../disassociate/disassociate_test.go | 16 +- internal/cmd/public-ip/list/list.go | 2 +- internal/cmd/public-ip/list/list_test.go | 17 +- internal/cmd/public-ip/update/update.go | 4 +- internal/cmd/public-ip/update/update_test.go | 19 +- internal/cmd/quota/list/list.go | 2 +- internal/cmd/quota/list/list_test.go | 21 +- internal/cmd/security-group/create/create.go | 2 +- .../cmd/security-group/create/create_test.go | 30 +- internal/cmd/security-group/delete/delete.go | 4 +- .../cmd/security-group/delete/delete_test.go | 19 +- .../cmd/security-group/describe/describe.go | 2 +- .../security-group/describe/describe_test.go | 21 +- internal/cmd/security-group/list/list.go | 2 +- internal/cmd/security-group/list/list_test.go | 24 +- .../cmd/security-group/rule/create/create.go | 4 +- .../security-group/rule/create/create_test.go | 20 +- .../cmd/security-group/rule/delete/delete.go | 12 +- .../security-group/rule/delete/delete_test.go | 27 +- .../security-group/rule/describe/describe.go | 6 +- .../rule/describe/describe_test.go | 20 +- internal/cmd/security-group/rule/list/list.go | 10 +- .../cmd/security-group/rule/list/list_test.go | 19 +- internal/cmd/security-group/update/update.go | 4 +- .../cmd/security-group/update/update_test.go | 24 +- internal/cmd/server/backup/create/create.go | 2 +- internal/cmd/server/backup/disable/disable.go | 2 +- internal/cmd/server/backup/enable/enable.go | 2 +- internal/cmd/server/backup/list/list.go | 2 +- .../server/backup/schedule/create/create.go | 2 +- .../server/backup/schedule/delete/delete.go | 2 +- .../cmd/server/backup/schedule/list/list.go | 2 +- internal/cmd/server/command/create/create.go | 2 +- internal/cmd/server/command/list/list.go | 2 +- internal/cmd/server/console/console.go | 4 +- internal/cmd/server/console/console_test.go | 14 +- internal/cmd/server/create/create.go | 9 +- internal/cmd/server/create/create_test.go | 26 +- internal/cmd/server/deallocate/deallocate.go | 6 +- .../cmd/server/deallocate/deallocate_test.go | 14 +- internal/cmd/server/delete/delete.go | 6 +- internal/cmd/server/delete/delete_test.go | 16 +- internal/cmd/server/describe/describe.go | 2 +- internal/cmd/server/describe/describe_test.go | 16 +- internal/cmd/server/list/list.go | 2 +- internal/cmd/server/list/list_test.go | 17 +- internal/cmd/server/log/log.go | 4 +- internal/cmd/server/log/log_test.go | 15 +- .../server/machine-type/describe/describe.go | 2 +- .../machine-type/describe/describe_test.go | 16 +- internal/cmd/server/machine-type/list/list.go | 2 +- .../cmd/server/machine-type/list/list_test.go | 19 +- .../server/network-interface/attach/attach.go | 8 +- .../network-interface/attach/attach_test.go | 19 +- .../server/network-interface/detach/detach.go | 8 +- .../network-interface/detach/detach_test.go | 19 +- .../cmd/server/network-interface/list/list.go | 16 +- .../network-interface/list/list_test.go | 27 +- .../cmd/server/os-update/create/create.go | 2 +- .../cmd/server/os-update/disable/disable.go | 2 +- .../cmd/server/os-update/enable/enable.go | 2 +- internal/cmd/server/os-update/list/list.go | 2 +- .../os-update/schedule/create/create.go | 2 +- .../server/os-update/schedule/list/list.go | 2 +- .../cmd/server/public-ip/attach/attach.go | 14 +- .../server/public-ip/attach/attach_test.go | 29 +- .../cmd/server/public-ip/detach/detach.go | 14 +- .../server/public-ip/detach/detach_test.go | 21 +- internal/cmd/server/reboot/reboot.go | 4 +- internal/cmd/server/reboot/reboot_test.go | 15 +- internal/cmd/server/rescue/rescue.go | 6 +- internal/cmd/server/rescue/rescue_test.go | 19 +- internal/cmd/server/resize/resize.go | 6 +- internal/cmd/server/resize/resize_test.go | 17 +- .../server/service-account/attach/attach.go | 12 +- .../service-account/attach/attach_test.go | 22 +- .../server/service-account/detach/detach.go | 12 +- .../service-account/detach/detach_test.go | 22 +- .../cmd/server/service-account/list/list.go | 14 +- .../server/service-account/list/list_test.go | 23 +- internal/cmd/server/start/start.go | 6 +- internal/cmd/server/start/start_test.go | 14 +- internal/cmd/server/stop/stop.go | 6 +- internal/cmd/server/stop/stop_test.go | 14 +- internal/cmd/server/unrescue/unrescue.go | 6 +- internal/cmd/server/unrescue/unrescue_test.go | 14 +- internal/cmd/server/update/update.go | 4 +- internal/cmd/server/update/update_test.go | 21 +- internal/cmd/server/volume/attach/attach.go | 14 +- .../cmd/server/volume/attach/attach_test.go | 19 +- .../cmd/server/volume/describe/describe.go | 14 +- .../server/volume/describe/describe_test.go | 29 +- internal/cmd/server/volume/detach/detach.go | 14 +- .../cmd/server/volume/detach/detach_test.go | 29 +- internal/cmd/server/volume/list/list.go | 14 +- internal/cmd/server/volume/list/list_test.go | 29 +- internal/cmd/server/volume/update/update.go | 14 +- .../cmd/server/volume/update/update_test.go | 19 +- internal/cmd/volume/backup/create/create.go | 12 +- .../cmd/volume/backup/create/create_test.go | 18 +- internal/cmd/volume/backup/delete/delete.go | 6 +- .../cmd/volume/backup/delete/delete_test.go | 8 +- .../cmd/volume/backup/describe/describe.go | 2 +- .../volume/backup/describe/describe_test.go | 8 +- internal/cmd/volume/backup/list/list.go | 2 +- internal/cmd/volume/backup/list/list_test.go | 13 +- internal/cmd/volume/backup/restore/restore.go | 10 +- .../cmd/volume/backup/restore/restore_test.go | 8 +- internal/cmd/volume/backup/update/update.go | 4 +- .../cmd/volume/backup/update/update_test.go | 19 +- internal/cmd/volume/create/create.go | 4 +- internal/cmd/volume/create/create_test.go | 20 +- internal/cmd/volume/delete/delete.go | 6 +- internal/cmd/volume/delete/delete_test.go | 16 +- internal/cmd/volume/describe/describe.go | 2 +- internal/cmd/volume/describe/describe_test.go | 16 +- internal/cmd/volume/list/list.go | 2 +- internal/cmd/volume/list/list_test.go | 17 +- .../performance-class/describe/describe.go | 2 +- .../describe/describe_test.go | 16 +- .../cmd/volume/performance-class/list/list.go | 2 +- .../performance-class/list/list_test.go | 17 +- internal/cmd/volume/resize/resize.go | 4 +- internal/cmd/volume/resize/resize_test.go | 19 +- internal/cmd/volume/snapshot/create/create.go | 6 +- .../cmd/volume/snapshot/create/create_test.go | 14 +- internal/cmd/volume/snapshot/delete/delete.go | 6 +- .../cmd/volume/snapshot/delete/delete_test.go | 8 +- .../cmd/volume/snapshot/describe/describe.go | 2 +- .../volume/snapshot/describe/describe_test.go | 8 +- internal/cmd/volume/snapshot/list/list.go | 4 +- .../cmd/volume/snapshot/list/list_test.go | 21 +- internal/cmd/volume/snapshot/update/update.go | 4 +- .../cmd/volume/snapshot/update/update_test.go | 19 +- internal/cmd/volume/update/update.go | 4 +- internal/cmd/volume/update/update_test.go | 17 +- internal/pkg/errors/errors.go | 49 ++ internal/pkg/services/iaas/client/client.go | 2 +- internal/pkg/services/iaas/utils/utils.go | 109 ++-- .../pkg/services/iaas/utils/utils_test.go | 270 ++++++++-- internal/pkg/utils/utils.go | 46 +- 238 files changed, 5740 insertions(+), 1533 deletions(-) create mode 100644 docs/stackit_network-area_region.md create mode 100644 docs/stackit_network-area_region_create.md create mode 100644 docs/stackit_network-area_region_delete.md create mode 100644 docs/stackit_network-area_region_describe.md create mode 100644 docs/stackit_network-area_region_list.md create mode 100644 docs/stackit_network-area_region_update.md create mode 100644 internal/cmd/network-area/region/create/create.go create mode 100644 internal/cmd/network-area/region/create/create_test.go create mode 100644 internal/cmd/network-area/region/delete/delete.go create mode 100644 internal/cmd/network-area/region/delete/delete_test.go create mode 100644 internal/cmd/network-area/region/describe/describe.go create mode 100644 internal/cmd/network-area/region/describe/describe_test.go create mode 100644 internal/cmd/network-area/region/list/list.go create mode 100644 internal/cmd/network-area/region/list/list_test.go create mode 100644 internal/cmd/network-area/region/region.go create mode 100644 internal/cmd/network-area/region/update/update.go create mode 100644 internal/cmd/network-area/region/update/update_test.go diff --git a/docs/stackit_network-area.md b/docs/stackit_network-area.md index d9ba1ecda..6f2d751f8 100644 --- a/docs/stackit_network-area.md +++ b/docs/stackit_network-area.md @@ -35,6 +35,7 @@ stackit network-area [flags] * [stackit network-area describe](./stackit_network-area_describe.md) - Shows details of a STACKIT Network Area * [stackit network-area list](./stackit_network-area_list.md) - Lists all STACKIT Network Areas (SNA) of an organization * [stackit network-area network-range](./stackit_network-area_network-range.md) - Provides functionality for network ranges in STACKIT Network Areas +* [stackit network-area region](./stackit_network-area_region.md) - Provides functionality for regional configuration of STACKIT Network Area (SNA) * [stackit network-area route](./stackit_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas * [stackit network-area update](./stackit_network-area_update.md) - Updates a STACKIT Network Area (SNA) diff --git a/docs/stackit_network-area_create.md b/docs/stackit_network-area_create.md index 7dc278927..e9a28231d 100644 --- a/docs/stackit_network-area_create.md +++ b/docs/stackit_network-area_create.md @@ -13,32 +13,20 @@ stackit network-area create [flags] ### Examples ``` - Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network - $ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" + Create a network area with name "network-area-1" in organization with ID "xxx" + $ stackit network-area create --name network-area-1 --organization-id xxx" - Create a network area with name "network-area-2" in organization with ID "xxx" with network ranges, transfer network and DNS name server - $ stackit network-area create --name network-area-2 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --dns-name-servers "1.1.1.1" - - Create a network area with name "network-area-3" in organization with ID "xxx" with network ranges, transfer network and additional options - $ stackit network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24 - - Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network and labels "key=value,key1=value1" - $ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1 + Create a network area with name "network-area-1" in organization with ID "xxx" with labels "key=value,key1=value1" + $ stackit network-area create --name network-area-1 --organization-id xxx --labels key=value,key1=value1 ``` ### Options ``` - --default-prefix-length int The default prefix length for networks in the network area - --dns-name-servers strings List of DNS name server IPs - -h, --help Help for "stackit network-area create" - --labels stringToString Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...' (default []) - --max-prefix-length int The maximum prefix length for networks in the network area - --min-prefix-length int The minimum prefix length for networks in the network area - -n, --name string Network area name - --network-ranges strings List of network ranges (default []) - --organization-id string Organization ID - --transfer-network string Transfer network in CIDR notation + -h, --help Help for "stackit network-area create" + --labels stringToString Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...' (default []) + -n, --name string Network area name + --organization-id string Organization ID ``` ### Options inherited from parent commands diff --git a/docs/stackit_network-area_region.md b/docs/stackit_network-area_region.md new file mode 100644 index 000000000..07fd820eb --- /dev/null +++ b/docs/stackit_network-area_region.md @@ -0,0 +1,38 @@ +## stackit network-area region + +Provides functionality for regional configuration of STACKIT Network Area (SNA) + +### Synopsis + +Provides functionality for regional configuration of STACKIT Network Area (SNA). + +``` +stackit network-area region [flags] +``` + +### Options + +``` + -h, --help Help for "stackit network-area region" +``` + +### 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 network-area](./stackit_network-area.md) - Provides functionality for STACKIT Network Area (SNA) +* [stackit network-area region create](./stackit_network-area_region_create.md) - Creates a new regional configuration for a STACKIT Network Area (SNA) +* [stackit network-area region delete](./stackit_network-area_region_delete.md) - Deletes a regional configuration for a STACKIT Network Area (SNA) +* [stackit network-area region describe](./stackit_network-area_region_describe.md) - Describes a regional configuration for a STACKIT Network Area (SNA) +* [stackit network-area region list](./stackit_network-area_region_list.md) - Lists all configured regions for a STACKIT Network Area (SNA) +* [stackit network-area region update](./stackit_network-area_region_update.md) - Updates a existing regional configuration for a STACKIT Network Area (SNA) + diff --git a/docs/stackit_network-area_region_create.md b/docs/stackit_network-area_region_create.md new file mode 100644 index 000000000..55632632f --- /dev/null +++ b/docs/stackit_network-area_region_create.md @@ -0,0 +1,58 @@ +## stackit network-area region create + +Creates a new regional configuration for a STACKIT Network Area (SNA) + +### Synopsis + +Creates a new regional configuration for a STACKIT Network Area (SNA). + +``` +stackit network-area region create [flags] +``` + +### Examples + +``` + Create a new regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24" and ipv4 transfer network "192.168.1.0/24" + $ stackit network-area region create --network-area-id xxx --region eu02 --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 + + Create a new regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", using the set region config + $ stackit config set --region eu02 + $ stackit network-area region create --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 + + Create a new regional configuration for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24", ipv4 transfer network "192.168.1.0/24", default prefix length "24", max prefix length "25" and min prefix length "20" + $ stackit network-area region create --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 --region "eu02" --ipv4-default-prefix-length 24 --ipv4-max-prefix-length 25 --ipv4-min-prefix-length 20 + + Create a new regional configuration for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24", ipv4 transfer network "192.168.1.0/24", default prefix length "24", max prefix length "25" and min prefix length "20" + $ stackit network-area region create --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 --region "eu02" --ipv4-default-prefix-length 24 --ipv4-max-prefix-length 25 --ipv4-min-prefix-length 20 +``` + +### Options + +``` + -h, --help Help for "stackit network-area region create" + --ipv4-default-nameservers strings List of default DNS name server IPs + --ipv4-default-prefix-length int The default prefix length for networks in the network area + --ipv4-max-prefix-length int The maximum prefix length for networks in the network area + --ipv4-min-prefix-length int The minimum prefix length for networks in the network area + --ipv4-network-ranges strings Network range to create in CIDR notation (default []) + --ipv4-transfer-network string Transfer network in CIDR notation + --network-area-id string STACKIT Network Area (SNA) ID + --organization-id string Organization ID +``` + +### 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 network-area region](./stackit_network-area_region.md) - Provides functionality for regional configuration of STACKIT Network Area (SNA) + diff --git a/docs/stackit_network-area_region_delete.md b/docs/stackit_network-area_region_delete.md new file mode 100644 index 000000000..6f2193e5e --- /dev/null +++ b/docs/stackit_network-area_region_delete.md @@ -0,0 +1,46 @@ +## stackit network-area region delete + +Deletes a regional configuration for a STACKIT Network Area (SNA) + +### Synopsis + +Deletes a regional configuration for a STACKIT Network Area (SNA). + +``` +stackit network-area region delete [flags] +``` + +### Examples + +``` + Delete a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit network-area region delete --network-area-id xxx --region eu02 --organization-id yyy + + Delete a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", using the set region config + $ stackit config set --region eu02 + $ stackit network-area region delete --network-area-id xxx --organization-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit network-area region delete" + --network-area-id string STACKIT Network Area (SNA) ID + --organization-id string Organization ID +``` + +### 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 network-area region](./stackit_network-area_region.md) - Provides functionality for regional configuration of STACKIT Network Area (SNA) + diff --git a/docs/stackit_network-area_region_describe.md b/docs/stackit_network-area_region_describe.md new file mode 100644 index 000000000..e97ee813a --- /dev/null +++ b/docs/stackit_network-area_region_describe.md @@ -0,0 +1,46 @@ +## stackit network-area region describe + +Describes a regional configuration for a STACKIT Network Area (SNA) + +### Synopsis + +Describes a regional configuration for a STACKIT Network Area (SNA). + +``` +stackit network-area region describe [flags] +``` + +### Examples + +``` + Describe a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit network-area region describe --network-area-id xxx --region eu02 --organization-id yyy + + Describe a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", using the set region config + $ stackit config set --region eu02 + $ stackit network-area region describe --network-area-id xxx --organization-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit network-area region describe" + --network-area-id string STACKIT Network Area (SNA) ID + --organization-id string Organization ID +``` + +### 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 network-area region](./stackit_network-area_region.md) - Provides functionality for regional configuration of STACKIT Network Area (SNA) + diff --git a/docs/stackit_network-area_region_list.md b/docs/stackit_network-area_region_list.md new file mode 100644 index 000000000..2b6eaf673 --- /dev/null +++ b/docs/stackit_network-area_region_list.md @@ -0,0 +1,42 @@ +## stackit network-area region list + +Lists all configured regions for a STACKIT Network Area (SNA) + +### Synopsis + +Lists all configured regions for a STACKIT Network Area (SNA). + +``` +stackit network-area region list [flags] +``` + +### Examples + +``` + List all configured region for a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit network-area region list --network-area-id xxx --organization-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit network-area region list" + --network-area-id string STACKIT Network Area (SNA) ID + --organization-id string Organization ID +``` + +### 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 network-area region](./stackit_network-area_region.md) - Provides functionality for regional configuration of STACKIT Network Area (SNA) + diff --git a/docs/stackit_network-area_region_update.md b/docs/stackit_network-area_region_update.md new file mode 100644 index 000000000..400d85bc7 --- /dev/null +++ b/docs/stackit_network-area_region_update.md @@ -0,0 +1,56 @@ +## stackit network-area region update + +Updates a existing regional configuration for a STACKIT Network Area (SNA) + +### Synopsis + +Updates a existing regional configuration for a STACKIT Network Area (SNA). + +``` +stackit network-area region update [flags] +``` + +### Examples + +``` + Update a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy" with new ipv4-default-nameservers "8.8.8.8" + $ stackit network-area region update --network-area-id xxx --region eu02 --organization-id yyy --ipv4-default-nameservers 8.8.8.8 + + Update a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy" with new ipv4-default-nameservers "8.8.8.8", using the set region config + $ stackit config set --region eu02 + $ stackit network-area region update --network-area-id xxx --organization-id yyy --ipv4-default-nameservers 8.8.8.8 + + Update a new regional configuration for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24", ipv4 transfer network "192.168.1.0/24", default prefix length "24", max prefix length "25" and min prefix length "20" + $ stackit network-area region update --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 --region "eu02" --ipv4-default-prefix-length 24 --ipv4-max-prefix-length 25 --ipv4-min-prefix-length 20 + + Update a new regional configuration for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24", ipv4 transfer network "192.168.1.0/24", default prefix length "24", max prefix length "25" and min prefix length "20" + $ stackit network-area region update --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 --region "eu02" --ipv4-default-prefix-length 24 --ipv4-max-prefix-length 25 --ipv4-min-prefix-length 20 +``` + +### Options + +``` + -h, --help Help for "stackit network-area region update" + --ipv4-default-nameservers strings List of default DNS name server IPs + --ipv4-default-prefix-length int The default prefix length for networks in the network area + --ipv4-max-prefix-length int The maximum prefix length for networks in the network area + --ipv4-min-prefix-length int The minimum prefix length for networks in the network area + --network-area-id string STACKIT Network Area (SNA) ID + --organization-id string Organization ID +``` + +### 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 network-area region](./stackit_network-area_region.md) - Provides functionality for regional configuration of STACKIT Network Area (SNA) + diff --git a/docs/stackit_network-area_route_create.md b/docs/stackit_network-area_route_create.md index 79d239fee..ff697f896 100644 --- a/docs/stackit_network-area_route_create.md +++ b/docs/stackit_network-area_route_create.md @@ -15,22 +15,25 @@ stackit network-area route create [flags] ### Examples ``` - Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 + Create a static route with destination "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit network-area route create --organization-id yyy --network-area-id xxx --destination 1.1.1.0/24 --next-hop 1.1.1.1 - Create a static route with labels "key:value" and "foo:bar" with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" - $ stackit network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1 + Create a static route with labels "key:value" and "foo:bar" with destination "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy" + $ stackit network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --destination 1.1.1.0/24 --next-hop 1.1.1.1 ``` ### Options ``` + --destination string Destination route. Must be a valid IPv4 or IPv6 CIDR -h, --help Help for "stackit network-area route create" --labels stringToString Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default []) --network-area-id string STACKIT Network Area ID - --next-hop string Next hop IP address. Must be a valid IPv4 + --next-hop-ipv4 string Next hop IPv4 address + --next-hop-ipv6 string Next hop IPv6 address + --nexthop-blackhole Sets next hop to black hole + --nexthop-internet Sets next hop to internet --organization-id string Organization ID - --prefix string Static route prefix ``` ### Options inherited from parent commands diff --git a/docs/stackit_network-area_update.md b/docs/stackit_network-area_update.md index 57b32a662..77665f0e8 100644 --- a/docs/stackit_network-area_update.md +++ b/docs/stackit_network-area_update.md @@ -20,14 +20,10 @@ stackit network-area update AREA_ID [flags] ### Options ``` - --default-prefix-length int The default prefix length for networks in the network area - --dns-name-servers strings List of DNS name server IPs - -h, --help Help for "stackit network-area update" - --labels stringToString Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...' (default []) - --max-prefix-length int The maximum prefix length for networks in the network area - --min-prefix-length int The minimum prefix length for networks in the network area - -n, --name string Network area name - --organization-id string Organization ID + -h, --help Help for "stackit network-area update" + --labels stringToString Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...' (default []) + -n, --name string Network area name + --organization-id string Organization ID ``` ### Options inherited from parent commands diff --git a/docs/stackit_network_create.md b/docs/stackit_network_create.md index 21d9e863c..146264977 100644 --- a/docs/stackit_network_create.md +++ b/docs/stackit_network_create.md @@ -26,7 +26,7 @@ stackit network create [flags] $ stackit network create --name network-1 --labels key=value,key1=value1 Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway - $ stackit network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3" + $ stackit network create --name network-1 --non-routed --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3" Create an IPv6 network with name "network-1" with DNS name servers, a prefix and a gateway $ stackit network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888" diff --git a/go.mod b/go.mod index 6eff66cae..1d4e8ac4f 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 diff --git a/go.sum b/go.sum index b9e0a5002..850d60dfe 100644 --- a/go.sum +++ b/go.sum @@ -571,8 +571,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4r github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 h1:zuoJnsLnjxdQcQbs7gUXYzrN0Ip5NXj+6LFBp1EO6cg= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0 h1:dnEjyapuv8WwRN5vE2z6+4/+ZqQTBx+bX27x2nOF7Jw= -github.com/stackitcloud/stackit-sdk-go/services/iaas v0.31.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0 h1:qLMpd5whPMLnaLEdFQjK51q/o9V6eMFMORBDSsyGyNI= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w= github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 h1:zxoOv7Fu+FmdsvTKiKkbmLItrMKfL+QoVtz9ReEF30E= github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0/go.mod h1:KEPVoO21pC4bjy5l0nyhjUJ0+uVwVWb+k2TYrzJ8xYw= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= diff --git a/internal/cmd/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go index 89e7659bb..311115644 100644 --- a/internal/cmd/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -88,7 +88,7 @@ func configureFlags(cmd *cobra.Command) { } func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClient) iaas.ApiCreateAffinityGroupRequest { - req := apiClient.CreateAffinityGroup(ctx, model.ProjectId) + req := apiClient.CreateAffinityGroup(ctx, model.ProjectId, model.Region) req = req.CreateAffinityGroupPayload( iaas.CreateAffinityGroupPayload{ Name: utils.Ptr(model.Name), diff --git a/internal/cmd/affinity-groups/create/create_test.go b/internal/cmd/affinity-groups/create/create_test.go index ba70232d0..6876da538 100644 --- a/internal/cmd/affinity-groups/create/create_test.go +++ b/internal/cmd/affinity-groups/create/create_test.go @@ -15,7 +15,11 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -const projectIdFlag = globalflags.ProjectIdFlag +const ( + testName = "test-name" + testPolicy = "test-policy" + testRegion = "eu01" +) type testCtxKey struct{} @@ -25,14 +29,10 @@ var ( testProjectId = uuid.NewString() ) -const ( - testName = "test-name" - testPolicy = "test-policy" -) - func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, nameFlag: testName, policyFlag: testPolicy, @@ -48,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Name: testName, Policy: testPolicy, @@ -59,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateAffinityGroupRequest)) iaas.ApiCreateAffinityGroupRequest { - request := testClient.CreateAffinityGroup(testCtx, testProjectId) + request := testClient.CreateAffinityGroup(testCtx, testProjectId, testRegion) request = request.CreateAffinityGroupPayload(fixturePayload()) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/affinity-groups/delete/delete.go b/internal/cmd/affinity-groups/delete/delete.go index 59532f96d..fdfb68c1a 100644 --- a/internal/cmd/affinity-groups/delete/delete.go +++ b/internal/cmd/affinity-groups/delete/delete.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - affinityGroupLabel, err := iaasUtils.GetAffinityGroupName(ctx, apiClient, model.ProjectId, model.AffinityGroupId) + affinityGroupLabel, err := iaasUtils.GetAffinityGroupName(ctx, apiClient, model.ProjectId, model.Region, model.AffinityGroupId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get affinity group name: %v", err) affinityGroupLabel = model.AffinityGroupId @@ -87,7 +87,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteAffinityGroupRequest { - return apiClient.DeleteAffinityGroup(ctx, model.ProjectId, model.AffinityGroupId) + return apiClient.DeleteAffinityGroup(ctx, model.ProjectId, model.Region, model.AffinityGroupId) } func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { diff --git a/internal/cmd/affinity-groups/delete/delete_test.go b/internal/cmd/affinity-groups/delete/delete_test.go index e3df49cbb..d66437d2f 100644 --- a/internal/cmd/affinity-groups/delete/delete_test.go +++ b/internal/cmd/affinity-groups/delete/delete_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -const projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,7 +39,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -50,6 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, AffinityGroupId: testAffinityGroupId, } @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteAffinityGroupRequest)) iaas.ApiDeleteAffinityGroupRequest { - request := testClient.DeleteAffinityGroup(testCtx, testProjectId, testAffinityGroupId) + request := testClient.DeleteAffinityGroup(testCtx, testProjectId, testRegion, testAffinityGroupId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/affinity-groups/describe/describe.go b/internal/cmd/affinity-groups/describe/describe.go index 7af292d74..5510a439d 100644 --- a/internal/cmd/affinity-groups/describe/describe.go +++ b/internal/cmd/affinity-groups/describe/describe.go @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClient) iaas.ApiGetAffinityGroupRequest { - return apiClient.GetAffinityGroup(ctx, model.ProjectId, model.AffinityGroupId) + return apiClient.GetAffinityGroup(ctx, model.ProjectId, model.Region, model.AffinityGroupId) } func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputModel, error) { diff --git a/internal/cmd/affinity-groups/describe/describe_test.go b/internal/cmd/affinity-groups/describe/describe_test.go index 530319c96..01c0d3eac 100644 --- a/internal/cmd/affinity-groups/describe/describe_test.go +++ b/internal/cmd/affinity-groups/describe/describe_test.go @@ -13,12 +13,14 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -const projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} var ( - testCtx = context.WithValue(context.Background(), &testCtxKey{}, projectIdFlag) + testCtx = context.WithValue(context.Background(), &testCtxKey{}, "test") testClient = &iaas.APIClient{} testProjectId = uuid.NewString() @@ -37,7 +39,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -50,6 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, AffinityGroupId: testAffinityGroupId, } @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetAffinityGroupRequest)) iaas.ApiGetAffinityGroupRequest { - request := testClient.GetAffinityGroup(testCtx, testProjectId, testAffinityGroupId) + request := testClient.GetAffinityGroup(testCtx, testProjectId, testRegion, testAffinityGroupId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/affinity-groups/list/list.go b/internal/cmd/affinity-groups/list/list.go index 75d0e667e..3752106e0 100644 --- a/internal/cmd/affinity-groups/list/list.go +++ b/internal/cmd/affinity-groups/list/list.go @@ -82,7 +82,7 @@ func configureFlags(cmd *cobra.Command) { } func buildRequest(ctx context.Context, model inputModel, apiClient *iaas.APIClient) iaas.ApiListAffinityGroupsRequest { - return apiClient.ListAffinityGroups(ctx, model.ProjectId) + return apiClient.ListAffinityGroups(ctx, model.ProjectId, model.Region) } func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { diff --git a/internal/cmd/affinity-groups/list/list_test.go b/internal/cmd/affinity-groups/list/list_test.go index 23c643f1b..5c792a299 100644 --- a/internal/cmd/affinity-groups/list/list_test.go +++ b/internal/cmd/affinity-groups/list/list_test.go @@ -16,7 +16,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -const projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" + testLimit = 10 +) type testCtxKey struct{} @@ -26,13 +29,10 @@ var ( testProjectId = uuid.NewString() ) -const ( - testLimit = 10 -) - func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -45,6 +45,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, } for _, mod := range mods { @@ -54,7 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListAffinityGroupsRequest)) iaas.ApiListAffinityGroupsRequest { - request := testClient.ListAffinityGroups(testCtx, testProjectId) + request := testClient.ListAffinityGroups(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 9ad653d18..06a270b11 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -332,7 +332,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateImageRequest { - request := apiClient.CreateImage(ctx, model.ProjectId). + request := apiClient.CreateImage(ctx, model.ProjectId, model.Region). CreateImagePayload(createPayload(ctx, model)) return request } diff --git a/internal/cmd/image/create/create_test.go b/internal/cmd/image/create/create_test.go index 545586502..2b28c7676 100644 --- a/internal/cmd/image/create/create_test.go +++ b/internal/cmd/image/create/create_test.go @@ -17,15 +17,8 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag - -type testCtxKey struct{} - -var ( - testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") - testClient = &iaas.APIClient{} - testProjectId = uuid.NewString() - +const ( + testRegion = "eu01" testLocalImagePath = "/does/not/exist" testDiskFormat = "raw" testDiskSize int64 = 16 * 1024 * 1024 * 1024 @@ -49,9 +42,18 @@ var ( testLabels = "foo=FOO,bar=BAR,baz=BAZ" ) +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() +) + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, nameFlag: testName, diskFormatFlag: testDiskFormat, @@ -93,30 +95,34 @@ func parseLabels(labelstring string) map[string]string { func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, - Name: testName, - DiskFormat: testDiskFormat, - LocalFilePath: testLocalImagePath, - Labels: utils.Ptr(parseLabels(testLabels)), + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Name: testName, + DiskFormat: testDiskFormat, + LocalFilePath: testLocalImagePath, + Labels: utils.Ptr(parseLabels(testLabels)), Config: &imageConfig{ - Architecture: &testArchitecture, - BootMenu: &testBootmenu, - CdromBus: &testCdRomBus, - DiskBus: &testDiskBus, - NicModel: &testNicModel, - OperatingSystem: &testOperatingSystem, - OperatingSystemDistro: &testOperatingSystemDistro, - OperatingSystemVersion: &testOperatingSystemVersion, - RescueBus: &testRescueBus, - RescueDevice: &testRescueDevice, - SecureBoot: &testSecureBoot, + Architecture: utils.Ptr(testArchitecture), + BootMenu: utils.Ptr(testBootmenu), + CdromBus: utils.Ptr(testCdRomBus), + DiskBus: utils.Ptr(testDiskBus), + NicModel: utils.Ptr(testNicModel), + OperatingSystem: utils.Ptr(testOperatingSystem), + OperatingSystemDistro: utils.Ptr(testOperatingSystemDistro), + OperatingSystemVersion: utils.Ptr(testOperatingSystemVersion), + RescueBus: utils.Ptr(testRescueBus), + RescueDevice: utils.Ptr(testRescueDevice), + SecureBoot: utils.Ptr(testSecureBoot), Uefi: testUefi, - VideoModel: &testVideoModel, - VirtioScsi: &testVirtioScsi, + VideoModel: utils.Ptr(testVideoModel), + VirtioScsi: utils.Ptr(testVirtioScsi), }, - MinDiskSize: &testDiskSize, - MinRam: &testRamSize, - Protected: &testProtected, + MinDiskSize: utils.Ptr(testDiskSize), + MinRam: utils.Ptr(testRamSize), + Protected: utils.Ptr(testProtected), } for _, mod := range mods { mod(model) @@ -127,31 +133,31 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func fixtureCreatePayload(mods ...func(payload *iaas.CreateImagePayload)) (payload iaas.CreateImagePayload) { payload = iaas.CreateImagePayload{ Config: &iaas.ImageConfig{ - Architecture: &testArchitecture, - BootMenu: &testBootmenu, - CdromBus: iaas.NewNullableString(&testCdRomBus), - DiskBus: iaas.NewNullableString(&testDiskBus), - NicModel: iaas.NewNullableString(&testNicModel), - OperatingSystem: &testOperatingSystem, - OperatingSystemDistro: iaas.NewNullableString(&testOperatingSystemDistro), - OperatingSystemVersion: iaas.NewNullableString(&testOperatingSystemVersion), - RescueBus: iaas.NewNullableString(&testRescueBus), - RescueDevice: iaas.NewNullableString(&testRescueDevice), - SecureBoot: &testSecureBoot, - Uefi: &testUefi, - VideoModel: iaas.NewNullableString(&testVideoModel), - VirtioScsi: &testVirtioScsi, + Architecture: utils.Ptr(testArchitecture), + BootMenu: utils.Ptr(testBootmenu), + CdromBus: iaas.NewNullableString(utils.Ptr(testCdRomBus)), + DiskBus: iaas.NewNullableString(utils.Ptr(testDiskBus)), + NicModel: iaas.NewNullableString(utils.Ptr(testNicModel)), + OperatingSystem: utils.Ptr(testOperatingSystem), + OperatingSystemDistro: iaas.NewNullableString(utils.Ptr(testOperatingSystemDistro)), + OperatingSystemVersion: iaas.NewNullableString(utils.Ptr(testOperatingSystemVersion)), + RescueBus: iaas.NewNullableString(utils.Ptr(testRescueBus)), + RescueDevice: iaas.NewNullableString(utils.Ptr(testRescueDevice)), + SecureBoot: utils.Ptr(testSecureBoot), + Uefi: utils.Ptr(testUefi), + VideoModel: iaas.NewNullableString(utils.Ptr(testVideoModel)), + VirtioScsi: utils.Ptr(testVirtioScsi), }, - DiskFormat: &testDiskFormat, + DiskFormat: utils.Ptr(testDiskFormat), Labels: &map[string]interface{}{ "foo": "FOO", "bar": "BAR", "baz": "BAZ", }, - MinDiskSize: &testDiskSize, - MinRam: &testRamSize, - Name: &testName, - Protected: &testProtected, + MinDiskSize: utils.Ptr(testDiskSize), + MinRam: utils.Ptr(testRamSize), + Name: utils.Ptr(testName), + Protected: utils.Ptr(testProtected), } for _, mod := range mods { mod(&payload) @@ -160,7 +166,7 @@ func fixtureCreatePayload(mods ...func(payload *iaas.CreateImagePayload)) (paylo } func fixtureRequest(mods ...func(request *iaas.ApiCreateImageRequest)) iaas.ApiCreateImageRequest { - request := testClient.CreateImage(testCtx, testProjectId) + request := testClient.CreateImage(testCtx, testProjectId, testRegion) request = request.CreateImagePayload(fixtureCreatePayload()) @@ -192,21 +198,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/image/delete/delete.go b/internal/cmd/image/delete/delete.go index 80f7f2dc8..d394c0bfd 100644 --- a/internal/cmd/image/delete/delete.go +++ b/internal/cmd/image/delete/delete.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - imageName, err := iaasUtils.GetImageName(ctx, apiClient, model.ProjectId, model.ImageId) + imageName, err := iaasUtils.GetImageName(ctx, apiClient, model.ProjectId, model.Region, model.ImageId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get image name: %v", err) imageName = model.ImageId @@ -98,6 +98,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteImageRequest { - request := apiClient.DeleteImage(ctx, model.ProjectId, model.ImageId) + request := apiClient.DeleteImage(ctx, model.ProjectId, model.Region, model.ImageId) return request } diff --git a/internal/cmd/image/delete/delete_test.go b/internal/cmd/image/delete/delete_test.go index 2b4f74c1e..cd1179f41 100644 --- a/internal/cmd/image/delete/delete_test.go +++ b/internal/cmd/image/delete/delete_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,7 +29,8 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,8 +40,12 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, - ImageId: testImageId, + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ImageId: testImageId, } for _, mod := range mods { mod(model) @@ -47,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteImageRequest)) iaas.ApiDeleteImageRequest { - request := testClient.DeleteImage(testCtx, testProjectId, testImageId) + request := testClient.DeleteImage(testCtx, testProjectId, testRegion, testImageId) for _, mod := range mods { mod(&request) } @@ -73,14 +80,14 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/image/describe/describe.go b/internal/cmd/image/describe/describe.go index b6d81e06d..516fa9c99 100644 --- a/internal/cmd/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -67,7 +67,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetImageRequest { - request := apiClient.GetImage(ctx, model.ProjectId, model.ImageId) + request := apiClient.GetImage(ctx, model.ProjectId, model.Region, model.ImageId) return request } diff --git a/internal/cmd/image/describe/describe_test.go b/internal/cmd/image/describe/describe_test.go index 076010d69..6a76a3200 100644 --- a/internal/cmd/image/describe/describe_test.go +++ b/internal/cmd/image/describe/describe_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,7 +29,8 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,8 +40,12 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, - ImageId: testImageId[0], + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ImageId: testImageId[0], } for _, mod := range mods { mod(model) @@ -47,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetImageRequest)) iaas.ApiGetImageRequest { - request := testClient.GetImage(testCtx, testProjectId, testImageId[0]) + request := testClient.GetImage(testCtx, testProjectId, testRegion, testImageId[0]) for _, mod := range mods { mod(&request) } @@ -79,7 +86,7 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), args: testImageId, isValid: false, @@ -87,7 +94,7 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), args: testImageId, isValid: false, @@ -95,7 +102,7 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), args: testImageId, isValid: false, diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index a0949187f..0ebdf9e95 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -128,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListImagesRequest { - request := apiClient.ListImages(ctx, model.ProjectId) + request := apiClient.ListImages(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { request = request.LabelSelector(*model.LabelSelector) } diff --git a/internal/cmd/image/list/list_test.go b/internal/cmd/image/list/list_test.go index bdfc4c6ed..6dbdb119f 100644 --- a/internal/cmd/image/list/list_test.go +++ b/internal/cmd/image/list/list_test.go @@ -17,7 +17,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -31,7 +33,9 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + labelSelectorFlag: testLabels, limitFlag: strconv.Itoa(int(testLimit)), } @@ -43,9 +47,13 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, - LabelSelector: utils.Ptr(testLabels), - Limit: &testLimit, + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + LabelSelector: utils.Ptr(testLabels), + Limit: &testLimit, } for _, mod := range mods { mod(model) @@ -54,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListImagesRequest)) iaas.ApiListImagesRequest { - request := testClient.ListImages(testCtx, testProjectId) + request := testClient.ListImages(testCtx, testProjectId, testRegion) request = request.LabelSelector(testLabels) for _, mod := range mods { mod(&request) @@ -84,21 +92,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index 434fc0ea8..799b594b6 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -132,7 +132,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - imageLabel, err := iaasUtils.GetImageName(ctx, apiClient, model.ProjectId, model.Id) + imageLabel, err := iaasUtils.GetImageName(ctx, apiClient, model.ProjectId, model.Region, model.Id) if err != nil { params.Printer.Debug(print.WarningLevel, "cannot retrieve image name: %v", err) imageLabel = model.Id @@ -238,7 +238,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateImageRequest { - request := apiClient.UpdateImage(ctx, model.ProjectId, model.Id) + request := apiClient.UpdateImage(ctx, model.ProjectId, model.Region, model.Id) payload := iaas.NewUpdateImagePayload() // Config *ImageConfig `json:"config,omitempty"` diff --git a/internal/cmd/image/update/update_test.go b/internal/cmd/image/update/update_test.go index a40748f3b..9df1cf99e 100644 --- a/internal/cmd/image/update/update_test.go +++ b/internal/cmd/image/update/update_test.go @@ -17,7 +17,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -50,7 +52,8 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, nameFlag: testName, diskFormatFlag: testDiskFormat, @@ -90,11 +93,15 @@ func parseLabels(labelstring string) map[string]string { func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, - Id: testImageId[0], - Name: &testName, - DiskFormat: &testDiskFormat, - Labels: utils.Ptr(parseLabels(testLabels)), + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Id: testImageId[0], + Name: &testName, + DiskFormat: &testDiskFormat, + Labels: utils.Ptr(parseLabels(testLabels)), Config: &imageConfig{ BootMenu: &testBootmenu, CdromBus: &testCdRomBus, @@ -155,7 +162,7 @@ func fixtureCreatePayload(mods ...func(payload *iaas.UpdateImagePayload)) (paylo } func fixtureRequest(mods ...func(*iaas.ApiUpdateImageRequest)) iaas.ApiUpdateImageRequest { - request := testClient.UpdateImage(testCtx, testProjectId, testImageId[0]) + request := testClient.UpdateImage(testCtx, testProjectId, testRegion, testImageId[0]) request = request.UpdateImagePayload(fixtureCreatePayload()) @@ -184,7 +191,7 @@ func TestParseInput(t *testing.T) { { description: "no values but valid image id", flagValues: map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, }, args: testImageId, isValid: false, @@ -196,7 +203,7 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), args: testImageId, isValid: false, @@ -204,7 +211,7 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), args: testImageId, isValid: false, @@ -212,7 +219,7 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), args: testImageId, isValid: false, @@ -302,8 +309,8 @@ func TestParseInput(t *testing.T) { { description: "update only name", flagValues: map[string]string{ - projectIdFlag: testProjectId, - nameFlag: "foo", + globalflags.ProjectIdFlag: testProjectId, + nameFlag: "foo", }, args: testImageId, isValid: true, diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index fa97908d9..7268d0a2d 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -3,9 +3,12 @@ package create import ( "context" "fmt" + "os" + "strings" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -13,35 +16,58 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" rmUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" "github.com/spf13/cobra" ) const ( - nameFlag = "name" - organizationIdFlag = "organization-id" - dnsNameServersFlag = "dns-name-servers" - networkRangesFlag = "network-ranges" - transferNetworkFlag = "transfer-network" + nameFlag = "name" + organizationIdFlag = "organization-id" + // Deprecated: dnsNameServersFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + dnsNameServersFlag = "dns-name-servers" + // Deprecated: networkRangesFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + networkRangesFlag = "network-ranges" + // Deprecated: transferNetworkFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + transferNetworkFlag = "transfer-network" + // Deprecated: defaultPrefixLengthFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. defaultPrefixLengthFlag = "default-prefix-length" - maxPrefixLengthFlag = "max-prefix-length" - minPrefixLengthFlag = "min-prefix-length" - labelFlag = "labels" + // Deprecated: maxPrefixLengthFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + maxPrefixLengthFlag = "max-prefix-length" + // Deprecated: minPrefixLengthFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + minPrefixLengthFlag = "min-prefix-length" + labelFlag = "labels" + + deprecationMessage = "Deprecated and will be removed after April 2026. Use instead the new command `$ stackit network-area region` to configure these options for a network area." ) type inputModel struct { *globalflags.GlobalFlagModel - Name *string - OrganizationId *string - DnsNameServers *[]string - NetworkRanges *[]string - TransferNetwork *string + Name *string + OrganizationId string + // Deprecated: DnsNameServers is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + DnsNameServers *[]string + // Deprecated: NetworkRanges is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + NetworkRanges *[]string + // Deprecated: TransferNetwork is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + TransferNetwork *string + // Deprecated: DefaultPrefixLength is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. DefaultPrefixLength *int64 - MaxPrefixLength *int64 - MinPrefixLength *int64 - Labels *map[string]string + // Deprecated: MaxPrefixLength is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + MaxPrefixLength *int64 + // Deprecated: MinPrefixLength is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + MinPrefixLength *int64 + Labels *map[string]string +} + +// NetworkAreaResponses is a workaround, to keep the two responses of the iaas v2 api together for the json and yaml output +// Should be removed when the deprecated flags are removed +type NetworkAreaResponses struct { + NetworkArea iaas.NetworkArea `json:"network_area"` + RegionalArea *iaas.RegionalArea `json:"regional_area"` } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -52,20 +78,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network`, - `$ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24"`, - ), - examples.NewExample( - `Create a network area with name "network-area-2" in organization with ID "xxx" with network ranges, transfer network and DNS name server`, - `$ stackit network-area create --name network-area-2 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --dns-name-servers "1.1.1.1"`, - ), - examples.NewExample( - `Create a network area with name "network-area-3" in organization with ID "xxx" with network ranges, transfer network and additional options`, - `$ stackit network-area create --name network-area-3 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --default-prefix-length 25 --max-prefix-length 29 --min-prefix-length 24`, + `Create a network area with name "network-area-1" in organization with ID "xxx"`, + `$ stackit network-area create --name network-area-1 --organization-id xxx"`, ), examples.NewExample( - `Create a network area with name "network-area-1" in organization with ID "xxx" with network ranges and a transfer network and labels "key=value,key1=value1"`, - `$ stackit network-area create --name network-area-1 --organization-id xxx --network-ranges "1.1.1.0/24,192.123.1.0/24" --transfer-network "192.160.0.0/24" --labels key=value,key1=value1`, + `Create a network area with name "network-area-1" in organization with ID "xxx" with labels "key=value,key1=value1"`, + `$ stackit network-area create --name network-area-1 --organization-id xxx --labels key=value,key1=value1`, ), ), RunE: func(cmd *cobra.Command, args []string) error { @@ -84,12 +102,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { var orgLabel string rmApiClient, err := rmClient.ConfigureClient(params.Printer, params.CliVersion) if err == nil { - orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, *model.OrganizationId) + orgLabel, err = rmUtils.GetOrganizationName(ctx, rmApiClient, model.OrganizationId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get organization name: %v", err) - orgLabel = *model.OrganizationId + orgLabel = model.OrganizationId } else if orgLabel == "" { - orgLabel = *model.OrganizationId + orgLabel = model.OrganizationId } } else { params.Printer.Debug(print.ErrorLevel, "configure resource manager client: %v", err) @@ -109,8 +127,38 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("create network area: %w", err) } + if resp == nil || resp.Id == nil { + return fmt.Errorf("create network area: empty response") + } + + responses := &NetworkAreaResponses{ + NetworkArea: *resp, + } - return outputResult(params.Printer, model.OutputFormat, orgLabel, resp) + if hasDeprecatedFlagsSet(model) { + deprecatedFlags := getConfiguredDeprecatedFlags(model) + params.Printer.Warn("the flags %q are deprecated and will be removed after April 2026. Use `$ stackit network-area region` to configure these options for a network area.\n", strings.Join(deprecatedFlags, ",")) + if resp == nil || resp.Id == nil { + return fmt.Errorf("create network area: empty response") + } + reqNetworkArea := buildRequestNetworkAreaRegion(ctx, model, *resp.Id, apiClient) + respNetworkArea, err := reqNetworkArea.Execute() + if err != nil { + return fmt.Errorf("create network area region: %w", err) + } + if !model.AssumeYes { + s := spinner.New(params.Printer) + s.Start("Create network area region") + _, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, *resp.Id, model.Region).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for creating network area region %w", err) + } + s.Stop() + } + responses.RegionalArea = respNetworkArea + } + + return outputResult(params.Printer, model.OutputFormat, orgLabel, responses) }, } configureFlags(cmd) @@ -120,25 +168,64 @@ func NewCmd(params *params.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(nameFlag, "n", "", "Network area name") cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...'") cmd.Flags().StringSlice(dnsNameServersFlag, nil, "List of DNS name server IPs") cmd.Flags().Var(flags.CIDRSliceFlag(), networkRangesFlag, "List of network ranges") cmd.Flags().Var(flags.CIDRFlag(), transferNetworkFlag, "Transfer network in CIDR notation") cmd.Flags().Int64(defaultPrefixLengthFlag, 0, "The default prefix length for networks in the network area") cmd.Flags().Int64(maxPrefixLengthFlag, 0, "The maximum prefix length for networks in the network area") cmd.Flags().Int64(minPrefixLengthFlag, 0, "The minimum prefix length for networks in the network area") - cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...'") - err := flags.MarkFlagsRequired(cmd, nameFlag, organizationIdFlag, networkRangesFlag, transferNetworkFlag) + cobra.CheckErr(cmd.Flags().MarkDeprecated(dnsNameServersFlag, deprecationMessage)) + cobra.CheckErr(cmd.Flags().MarkDeprecated(networkRangesFlag, deprecationMessage)) + cobra.CheckErr(cmd.Flags().MarkDeprecated(transferNetworkFlag, deprecationMessage)) + cobra.CheckErr(cmd.Flags().MarkDeprecated(defaultPrefixLengthFlag, deprecationMessage)) + cobra.CheckErr(cmd.Flags().MarkDeprecated(maxPrefixLengthFlag, deprecationMessage)) + cobra.CheckErr(cmd.Flags().MarkDeprecated(minPrefixLengthFlag, deprecationMessage)) + // Set the output for deprecation warnings to stderr + cmd.Flags().SetOutput(os.Stderr) + + cmd.MarkFlagsRequiredTogether(networkRangesFlag, transferNetworkFlag) + + err := flags.MarkFlagsRequired(cmd, nameFlag, organizationIdFlag) cobra.CheckErr(err) } +func hasDeprecatedFlagsSet(model *inputModel) bool { + deprecatedFlags := getConfiguredDeprecatedFlags(model) + return len(deprecatedFlags) > 0 +} + +func getConfiguredDeprecatedFlags(model *inputModel) []string { + var result []string + if model.DnsNameServers != nil { + result = append(result, dnsNameServersFlag) + } + if model.NetworkRanges != nil { + result = append(result, networkRangesFlag) + } + if model.TransferNetwork != nil { + result = append(result, transferNetworkFlag) + } + if model.DefaultPrefixLength != nil { + result = append(result, defaultPrefixLengthFlag) + } + if model.MaxPrefixLength != nil { + result = append(result, maxPrefixLengthFlag) + } + if model.MinPrefixLength != nil { + result = append(result, minPrefixLengthFlag) + } + return result +} + func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) model := inputModel{ GlobalFlagModel: globalFlags, Name: flags.FlagToStringPointer(p, cmd, nameFlag), - OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + OrganizationId: flags.FlagToStringValue(p, cmd, organizationIdFlag), DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, dnsNameServersFlag), NetworkRanges: flags.FlagToStringSlicePointer(p, cmd, networkRangesFlag), TransferNetwork: flags.FlagToStringPointer(p, cmd, transferNetworkFlag), @@ -148,44 +235,71 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } + // Check if any of the deprecated **optional** fields are set and if no of the associated deprecated **required** fields is set. + hasAllRequiredRegionalAreaFieldsSet := model.NetworkRanges != nil && model.TransferNetwork != nil + hasOptionalRegionalAreaFieldsSet := model.DnsNameServers != nil || model.DefaultPrefixLength != nil || model.MaxPrefixLength != nil || model.MinPrefixLength != nil + if hasOptionalRegionalAreaFieldsSet && !hasAllRequiredRegionalAreaFieldsSet { + return nil, &cliErr.MultipleFlagsAreMissing{ + MissingFlags: []string{networkRangesFlag, transferNetworkFlag}, + SetFlags: []string{dnsNameServersFlag, defaultPrefixLengthFlag, minPrefixLengthFlag, maxPrefixLengthFlag}, + } + } + p.DebugInputModel(model) return &model, nil } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRequest { - req := apiClient.CreateNetworkArea(ctx, *model.OrganizationId) - - networkRanges := make([]iaas.NetworkRange, len(*model.NetworkRanges)) - for i, networkRange := range *model.NetworkRanges { - networkRanges[i] = iaas.NetworkRange{ - Prefix: utils.Ptr(networkRange), - } - } + req := apiClient.CreateNetworkArea(ctx, model.OrganizationId) payload := iaas.CreateNetworkAreaPayload{ Name: model.Name, Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), - AddressFamily: &iaas.CreateAreaAddressFamily{ - Ipv4: &iaas.CreateAreaIPv4{ - DefaultNameservers: model.DnsNameServers, - NetworkRanges: utils.Ptr(networkRanges), - TransferNetwork: model.TransferNetwork, - DefaultPrefixLen: model.DefaultPrefixLength, - MaxPrefixLen: model.MaxPrefixLength, - MinPrefixLen: model.MinPrefixLength, - }, - }, } return req.CreateNetworkAreaPayload(payload) } -func outputResult(p *print.Printer, outputFormat, orgLabel string, networkArea *iaas.NetworkArea) error { - if networkArea == nil { +func buildRequestNetworkAreaRegion(ctx context.Context, model *inputModel, networkAreaId string, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRegionRequest { + req := apiClient.CreateNetworkAreaRegion(ctx, model.OrganizationId, networkAreaId, model.Region) + + var networkRanges []iaas.NetworkRange + if model.NetworkRanges != nil { + networkRanges = make([]iaas.NetworkRange, len(*model.NetworkRanges)) + for i, networkRange := range *model.NetworkRanges { + networkRanges[i] = iaas.NetworkRange{ + Prefix: utils.Ptr(networkRange), + } + } + } + + payload := iaas.CreateNetworkAreaRegionPayload{ + Ipv4: &iaas.RegionalAreaIPv4{ + DefaultNameservers: model.DnsNameServers, + NetworkRanges: utils.Ptr(networkRanges), + TransferNetwork: model.TransferNetwork, + DefaultPrefixLen: model.DefaultPrefixLength, + MaxPrefixLen: model.MaxPrefixLength, + MinPrefixLen: model.MinPrefixLength, + }, + } + + return req.CreateNetworkAreaRegionPayload(payload) +} + +func outputResult(p *print.Printer, outputFormat, orgLabel string, responses *NetworkAreaResponses) error { + if responses == nil { return fmt.Errorf("network area is nil") } - return p.OutputResult(outputFormat, networkArea, func() error { - p.Outputf("Created STACKIT Network Area for organization %q.\nNetwork area ID: %s\n", orgLabel, utils.PtrString(networkArea.AreaId)) + + prettyOutputFunc := func() error { + p.Outputf("Created STACKIT Network Area for organization %q.\nNetwork area ID: %s\n", orgLabel, utils.PtrString(responses.NetworkArea.Id)) return nil - }) + } + // If RegionalArea is NOT set in the response, then no deprecated Flags were set. + // In this case, only the response of NetworkArea should be printed in JSON and yaml output, to avoid breaking changes after the deprecated fields are removed + if responses.RegionalArea == nil { + return p.OutputResult(outputFormat, responses.NetworkArea, prettyOutputFunc) + } + return p.OutputResult(outputFormat, responses, prettyOutputFunc) } diff --git a/internal/cmd/network-area/create/create_test.go b/internal/cmd/network-area/create/create_test.go index a731541fd..9bfadd260 100644 --- a/internal/cmd/network-area/create/create_test.go +++ b/internal/cmd/network-area/create/create_test.go @@ -2,6 +2,8 @@ package create import ( "context" + "strconv" + "strings" "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -16,24 +18,34 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" + testName = "example-network-area-name" + testTransferNetwork = "100.0.0.0/24" + testDefaultPrefixLength int64 = 25 + testMaxPrefixLength int64 = 26 + testMinPrefixLength int64 = 24 +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &iaas.APIClient{} -var testOrgId = uuid.NewString() +var ( + testOrgId = uuid.NewString() + testAreaId = uuid.NewString() + testDnsNameservers = []string{"1.1.1.0", "1.1.2.0"} + testNetworkRanges = []string{"192.0.0.0/24", "102.0.0.0/24"} +) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - nameFlag: "example-network-area-name", - organizationIdFlag: testOrgId, - dnsNameServersFlag: "1.1.1.0,1.1.2.0", - networkRangesFlag: "192.0.0.0/24,102.0.0.0/24", - transferNetworkFlag: "100.0.0.0/24", - defaultPrefixLengthFlag: "24", - maxPrefixLengthFlag: "24", - minPrefixLengthFlag: "24", - labelFlag: "key=value", + globalflags.RegionFlag: testRegion, + + nameFlag: testName, + organizationIdFlag: testOrgId, + labelFlag: "key=value", } for _, mod := range mods { mod(flagValues) @@ -45,15 +57,10 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, - Name: utils.Ptr("example-network-area-name"), - OrganizationId: utils.Ptr(testOrgId), - DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), - NetworkRanges: utils.Ptr([]string{"192.0.0.0/24", "102.0.0.0/24"}), - TransferNetwork: utils.Ptr("100.0.0.0/24"), - DefaultPrefixLength: utils.Ptr(int64(24)), - MaxPrefixLength: utils.Ptr(int64(24)), - MinPrefixLength: utils.Ptr(int64(24)), + Name: utils.Ptr("example-network-area-name"), + OrganizationId: testOrgId, Labels: utils.Ptr(map[string]string{ "key": "value", }), @@ -79,23 +86,40 @@ func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaPayload)) iaas.C Labels: utils.Ptr(map[string]interface{}{ "key": "value", }), - AddressFamily: &iaas.CreateAreaAddressFamily{ - Ipv4: &iaas.CreateAreaIPv4{ - DefaultNameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), - NetworkRanges: &[]iaas.NetworkRange{ - { - Prefix: utils.Ptr("192.0.0.0/24"), - }, - { - Prefix: utils.Ptr("102.0.0.0/24"), - }, - }, - TransferNetwork: utils.Ptr("100.0.0.0/24"), - DefaultPrefixLen: utils.Ptr(int64(24)), - MaxPrefixLen: utils.Ptr(int64(24)), - MinPrefixLen: utils.Ptr(int64(24)), - }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequestRegionalArea(mods ...func(request *iaas.ApiCreateNetworkAreaRegionRequest)) iaas.ApiCreateNetworkAreaRegionRequest { + req := testClient.CreateNetworkAreaRegion(testCtx, testOrgId, testAreaId, testRegion) + req = req.CreateNetworkAreaRegionPayload(fixtureRegionalAreaPayload()) + for _, mod := range mods { + mod(&req) + } + return req +} + +func fixtureRegionalAreaPayload(mods ...func(request *iaas.CreateNetworkAreaRegionPayload)) iaas.CreateNetworkAreaRegionPayload { + var networkRanges []iaas.NetworkRange + for _, networkRange := range testNetworkRanges { + networkRanges = append(networkRanges, iaas.NetworkRange{ + Prefix: utils.Ptr(networkRange), + }) + } + + payload := iaas.CreateNetworkAreaRegionPayload{ + Ipv4: &iaas.RegionalAreaIPv4{ + DefaultNameservers: utils.Ptr(testDnsNameservers), + DefaultPrefixLen: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLen: utils.Ptr(testMaxPrefixLength), + MinPrefixLen: utils.Ptr(testMinPrefixLength), + NetworkRanges: utils.Ptr(networkRanges), + TransferNetwork: utils.Ptr(testTransferNetwork), }, + Status: nil, } for _, mod := range mods { mod(&payload) @@ -119,20 +143,35 @@ func TestParseInput(t *testing.T) { expectedModel: fixtureInputModel(), }, { - description: "required only", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, dnsNameServersFlag) - delete(flagValues, defaultPrefixLengthFlag) - delete(flagValues, maxPrefixLengthFlag) - delete(flagValues, minPrefixLengthFlag) - }), + description: "with deprecated flags", + flagValues: map[string]string{ + nameFlag: testName, + organizationIdFlag: testOrgId, + + // Deprecated flags + dnsNameServersFlag: strings.Join(testDnsNameservers, ","), + networkRangesFlag: strings.Join(testNetworkRanges, ","), + transferNetworkFlag: testTransferNetwork, + defaultPrefixLengthFlag: strconv.FormatInt(testDefaultPrefixLength, 10), + maxPrefixLengthFlag: strconv.FormatInt(testMaxPrefixLength, 10), + minPrefixLengthFlag: strconv.FormatInt(testMinPrefixLength, 10), + }, isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.DnsNameServers = nil - model.DefaultPrefixLength = nil - model.MaxPrefixLength = nil - model.MinPrefixLength = nil - }), + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: testOrgId, + + // Deprecated fields + DnsNameServers: utils.Ptr(testDnsNameservers), + NetworkRanges: utils.Ptr(testNetworkRanges), + TransferNetwork: utils.Ptr(testTransferNetwork), + DefaultPrefixLength: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLength: utils.Ptr(testMaxPrefixLength), + MinPrefixLength: utils.Ptr(testMinPrefixLength), + }, }, { description: "name missing", @@ -142,16 +181,38 @@ func TestParseInput(t *testing.T) { isValid: false, }, { - description: "network ranges missing", + description: "set deprecated network ranges - missing transfer network", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, networkRangesFlag) + flagValues[networkRangesFlag] = strings.Join(testNetworkRanges, ",") }), isValid: false, }, { - description: "transfer network missing", + description: "set deprecated transfer network - missing network ranges", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, transferNetworkFlag) + flagValues[transferNetworkFlag] = testTransferNetwork + }), + isValid: false, + }, + { + description: "set deprecated transfer network and network ranges", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkRangesFlag] = strings.Join(testNetworkRanges, ",") + flagValues[transferNetworkFlag] = testTransferNetwork + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.NetworkRanges = utils.Ptr(testNetworkRanges) + model.TransferNetwork = utils.Ptr(testTransferNetwork) + }), + }, + { + description: "set deprecated optional flags", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[dnsNameServersFlag] = strings.Join(testDnsNameservers, ",") + flagValues[defaultPrefixLengthFlag] = strconv.FormatInt(testDefaultPrefixLength, 10) + flagValues[maxPrefixLengthFlag] = strconv.FormatInt(testMaxPrefixLength, 10) + flagValues[minPrefixLengthFlag] = strconv.FormatInt(testMinPrefixLength, 10) }), isValid: false, }, @@ -228,11 +289,63 @@ func TestBuildRequest(t *testing.T) { } } +func TestBuildRequestNetworkAreaRegion(t *testing.T) { + tests := []struct { + description string + model *inputModel + areaId string + expectedRequest iaas.ApiCreateNetworkAreaRegionRequest + }{ + { + description: "base", + model: fixtureInputModel(func(model *inputModel) { + // Deprecated fields + model.DnsNameServers = utils.Ptr(testDnsNameservers) + model.NetworkRanges = utils.Ptr(testNetworkRanges) + model.TransferNetwork = utils.Ptr(testTransferNetwork) + model.DefaultPrefixLength = utils.Ptr(testDefaultPrefixLength) + model.MaxPrefixLength = utils.Ptr(testMaxPrefixLength) + model.MinPrefixLength = utils.Ptr(testMinPrefixLength) + }), + areaId: testAreaId, + expectedRequest: fixtureRequestRegionalArea(), + }, + { + description: "base without network ranges", + model: fixtureInputModel(func(model *inputModel) { + // Deprecated fields + model.DnsNameServers = utils.Ptr(testDnsNameservers) + model.NetworkRanges = utils.Ptr(testNetworkRanges) + model.TransferNetwork = utils.Ptr(testTransferNetwork) + model.DefaultPrefixLength = utils.Ptr(testDefaultPrefixLength) + model.MaxPrefixLength = utils.Ptr(testMaxPrefixLength) + model.MinPrefixLength = utils.Ptr(testMinPrefixLength) + }), + areaId: testAreaId, + expectedRequest: fixtureRequestRegionalArea(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequestNetworkAreaRegion(testCtx, tt.model, testAreaId, testClient) + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + func Test_outputResult(t *testing.T) { type args struct { outputFormat string orgLabel string - networkArea *iaas.NetworkArea + responses *NetworkAreaResponses } tests := []struct { name string @@ -244,10 +357,19 @@ func Test_outputResult(t *testing.T) { args: args{}, wantErr: true, }, + { + name: "set empty response", + args: args{ + responses: &NetworkAreaResponses{}, + }, + wantErr: false, + }, { name: "set empty network area", args: args{ - networkArea: &iaas.NetworkArea{}, + responses: &NetworkAreaResponses{ + NetworkArea: iaas.NetworkArea{}, + }, }, wantErr: false, }, @@ -256,9 +378,140 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.orgLabel, tt.args.networkArea); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.orgLabel, tt.args.responses); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) } } + +func TestGetConfiguredDeprecatedFlags(t *testing.T) { + type args struct { + model *inputModel + } + tests := []struct { + name string + args args + want []string + }{ + { + name: "no deprecated flags", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: testOrgId, + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + DnsNameServers: nil, + NetworkRanges: nil, + TransferNetwork: nil, + DefaultPrefixLength: nil, + MaxPrefixLength: nil, + MinPrefixLength: nil, + }, + }, + want: nil, + }, + { + name: "deprecated flags", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: testOrgId, + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + DnsNameServers: utils.Ptr(testDnsNameservers), + NetworkRanges: utils.Ptr(testNetworkRanges), + TransferNetwork: utils.Ptr(testTransferNetwork), + DefaultPrefixLength: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLength: utils.Ptr(testMaxPrefixLength), + MinPrefixLength: utils.Ptr(testMinPrefixLength), + }, + }, + want: []string{dnsNameServersFlag, networkRangesFlag, transferNetworkFlag, defaultPrefixLengthFlag, minPrefixLengthFlag, maxPrefixLengthFlag}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := getConfiguredDeprecatedFlags(tt.args.model) + + less := func(a, b string) bool { + return a < b + } + if diff := cmp.Diff(tt.want, got, cmpopts.SortSlices(less)); diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestHasDeprecatedFlagsSet(t *testing.T) { + type args struct { + model *inputModel + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "no deprecated flags", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: testOrgId, + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + DnsNameServers: nil, + NetworkRanges: nil, + TransferNetwork: nil, + DefaultPrefixLength: nil, + MaxPrefixLength: nil, + MinPrefixLength: nil, + }, + }, + want: false, + }, + { + name: "deprecated flags", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: testOrgId, + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + DnsNameServers: utils.Ptr(testDnsNameservers), + NetworkRanges: utils.Ptr(testNetworkRanges), + TransferNetwork: utils.Ptr(testTransferNetwork), + DefaultPrefixLength: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLength: utils.Ptr(testMaxPrefixLength), + MinPrefixLength: utils.Ptr(testMinPrefixLength), + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := hasDeprecatedFlagsSet(tt.args.model); got != tt.want { + t.Errorf("hasDeprecatedFlagsSet() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/cmd/network-area/delete/delete.go b/internal/cmd/network-area/delete/delete.go index d16a9e656..0e42d5883 100644 --- a/internal/cmd/network-area/delete/delete.go +++ b/internal/cmd/network-area/delete/delete.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -12,17 +13,19 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" - "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" - - "github.com/spf13/cobra" ) const ( areaIdArg = "AREA_ID" organizationIdFlag = "organization-id" + + deprecationMessage = "The regional network area configuration %q for the area %q still exists.\n" + + "The regional configuration of the network area was moved to the new command group `$ stackit network-area region`.\n" + + "The regional area will be automatically deleted. This behavior is deprecated and will be removed after April 2026.\n" + + "Use in the future the command `$ stackit network-area region delete` to delete the regional network area and afterwards delete the network-area with the command `$ stackit network-area delete`.\n" ) type inputModel struct { @@ -73,29 +76,31 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } } - // Call API - req := buildRequest(ctx, model, apiClient) - err = req.Execute() + // Check if the network area has a regional configuration + regionalArea, err := apiClient.GetNetworkAreaRegion(ctx, *model.OrganizationId, model.AreaId, model.Region).Execute() if err != nil { - return fmt.Errorf("delete network area: %w", err) + params.Printer.Debug(print.ErrorLevel, "get regional area: %v", err) } - - // Wait for async operation, if async mode not enabled - if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting network area") - _, err = wait.DeleteNetworkAreaWaitHandler(ctx, apiClient, *model.OrganizationId, model.AreaId).WaitWithContext(ctx) + if regionalArea != nil { + params.Printer.Warn(deprecationMessage, model.Region, networkAreaLabel) + err = apiClient.DeleteNetworkAreaRegion(ctx, *model.OrganizationId, model.AreaId, model.Region).Execute() if err != nil { - return fmt.Errorf("wait for network area deletion: %w", err) + return fmt.Errorf("delete network area region: %w", err) + } + _, err := wait.DeleteNetworkAreaRegionWaitHandler(ctx, apiClient, *model.OrganizationId, model.AreaId, model.Region).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait delete network area region: %w", err) } - s.Stop() } - operationState := "Deleted" - if model.Async { - operationState = "Triggered deletion of" + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete network area: %w", err) } - params.Printer.Info("%s STACKIT Network Area %q\n", operationState, networkAreaLabel) + + params.Printer.Outputf("Deleted STACKIT Network Area %q\n", networkAreaLabel) return nil }, } diff --git a/internal/cmd/network-area/describe/describe.go b/internal/cmd/network-area/describe/describe.go index b6c086a4b..4fdf257c5 100644 --- a/internal/cmd/network-area/describe/describe.go +++ b/internal/cmd/network-area/describe/describe.go @@ -126,60 +126,11 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo } return p.OutputResult(outputFormat, networkArea, func() error { - var routes []string - var networkRanges []string - - if networkArea.Ipv4 != nil { - if networkArea.Ipv4.Routes != nil { - for _, route := range *networkArea.Ipv4.Routes { - routes = append(routes, fmt.Sprintf("next hop: %s\nprefix: %s", *route.Nexthop, *route.Prefix)) - } - } - - if networkArea.Ipv4.NetworkRanges != nil { - for _, networkRange := range *networkArea.Ipv4.NetworkRanges { - networkRanges = append(networkRanges, *networkRange.Prefix) - } - } - } - table := tables.NewTable() - table.AddRow("ID", utils.PtrString(networkArea.AreaId)) + table.AddRow("ID", utils.PtrString(networkArea.Id)) table.AddSeparator() table.AddRow("NAME", utils.PtrString(networkArea.Name)) table.AddSeparator() - table.AddRow("STATE", utils.PtrString(networkArea.State)) - table.AddSeparator() - if len(networkRanges) > 0 { - table.AddRow("NETWORK RANGES", strings.Join(networkRanges, ",")) - } - table.AddSeparator() - for i, route := range routes { - table.AddRow(fmt.Sprintf("STATIC ROUTE %d", i+1), route) - table.AddSeparator() - } - if networkArea.Ipv4 != nil { - if networkArea.Ipv4.TransferNetwork != nil { - table.AddRow("TRANSFER RANGE", *networkArea.Ipv4.TransferNetwork) - table.AddSeparator() - } - if networkArea.Ipv4.DefaultNameservers != nil && len(*networkArea.Ipv4.DefaultNameservers) > 0 { - table.AddRow("DNS NAME SERVERS", strings.Join(*networkArea.Ipv4.DefaultNameservers, ",")) - table.AddSeparator() - } - if networkArea.Ipv4.DefaultPrefixLen != nil { - table.AddRow("DEFAULT PREFIX LENGTH", *networkArea.Ipv4.DefaultPrefixLen) - table.AddSeparator() - } - if networkArea.Ipv4.MaxPrefixLen != nil { - table.AddRow("MAX PREFIX LENGTH", *networkArea.Ipv4.MaxPrefixLen) - table.AddSeparator() - } - if networkArea.Ipv4.MinPrefixLen != nil { - table.AddRow("MIN PREFIX LENGTH", *networkArea.Ipv4.MinPrefixLen) - table.AddSeparator() - } - } if networkArea.Labels != nil && len(*networkArea.Labels) > 0 { var labels []string for key, value := range *networkArea.Labels { @@ -195,6 +146,10 @@ func outputResult(p *print.Printer, outputFormat string, networkArea *iaas.Netwo table.AddRow("# ATTACHED PROJECTS", utils.PtrString(networkArea.ProjectCount)) table.AddSeparator() } + table.AddRow("CREATED AT", utils.PtrString(networkArea.CreatedAt)) + table.AddSeparator() + table.AddRow("UPDATED AT", utils.PtrString(networkArea.UpdatedAt)) + table.AddSeparator() err := table.Display(p) if err != nil { diff --git a/internal/cmd/network-area/list/list.go b/internal/cmd/network-area/list/list.go index 6184148aa..e37822602 100644 --- a/internal/cmd/network-area/list/list.go +++ b/internal/cmd/network-area/list/list.go @@ -150,21 +150,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli func outputResult(p *print.Printer, outputFormat string, networkAreas []iaas.NetworkArea) error { return p.OutputResult(outputFormat, networkAreas, func() error { table := tables.NewTable() - table.SetHeader("ID", "Name", "Status", "Network Ranges", "# Attached Projects") + table.SetHeader("ID", "Name", "# Attached Projects") for _, networkArea := range networkAreas { - networkRanges := "n/a" - if ipv4 := networkArea.Ipv4; ipv4 != nil { - if netRange := ipv4.NetworkRanges; netRange != nil { - networkRanges = fmt.Sprint(len(*netRange)) - } - } - table.AddRow( - utils.PtrString(networkArea.AreaId), + utils.PtrString(networkArea.Id), utils.PtrString(networkArea.Name), - utils.PtrString(networkArea.State), - networkRanges, utils.PtrString(networkArea.ProjectCount), ) table.AddSeparator() diff --git a/internal/cmd/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go index ec7f1dbcf..33610c045 100644 --- a/internal/cmd/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -118,7 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRangeRequest { - req := apiClient.CreateNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId) + req := apiClient.CreateNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region) payload := iaas.CreateNetworkAreaRangePayload{ Ipv4: &[]iaas.NetworkRange{ { @@ -131,7 +131,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, networkRange iaas.NetworkRange) error { return p.OutputResult(outputFormat, networkRange, func() error { - p.Outputf("Created network range for SNA %q.\nNetwork range ID: %s\n", networkAreaLabel, utils.PtrString(networkRange.NetworkRangeId)) + p.Outputf("Created network range for SNA %q.\nNetwork range ID: %s\n", networkAreaLabel, utils.PtrString(networkRange.Id)) return nil }) } diff --git a/internal/cmd/network-area/network-range/create/create_test.go b/internal/cmd/network-area/network-range/create/create_test.go index 6edc6b23b..e5b01e224 100644 --- a/internal/cmd/network-area/network-range/create/create_test.go +++ b/internal/cmd/network-area/network-range/create/create_test.go @@ -16,6 +16,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,6 +30,8 @@ var testNetworkAreaId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrgId, networkAreaIdFlag: testNetworkAreaId, networkRangeFlag: "1.1.1.0/24", @@ -40,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, OrganizationId: utils.Ptr(testOrgId), NetworkAreaId: utils.Ptr(testNetworkAreaId), @@ -52,7 +59,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkAreaRangeRequest)) iaas.ApiCreateNetworkAreaRangeRequest { - request := testClient.CreateNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId) + request := testClient.CreateNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId, testRegion) request = request.CreateNetworkAreaRangePayload(fixturePayload()) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/network-area/network-range/delete/delete.go b/internal/cmd/network-area/network-range/delete/delete.go index 12126917e..4d3a94c5d 100644 --- a/internal/cmd/network-area/network-range/delete/delete.go +++ b/internal/cmd/network-area/network-range/delete/delete.go @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) networkAreaLabel = *model.NetworkAreaId } - networkRangeLabel, err := iaasUtils.GetNetworkRangePrefix(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) + networkRangeLabel, err := iaasUtils.GetNetworkRangePrefix(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId, model.Region, model.NetworkRangeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get network range prefix: %v", err) networkRangeLabel = model.NetworkRangeId @@ -118,6 +118,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNetworkAreaRangeRequest { - req := apiClient.DeleteNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) + req := apiClient.DeleteNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region, model.NetworkRangeId) return req } diff --git a/internal/cmd/network-area/network-range/delete/delete_test.go b/internal/cmd/network-area/network-range/delete/delete_test.go index 5fb112ef6..79c1ad52c 100644 --- a/internal/cmd/network-area/network-range/delete/delete_test.go +++ b/internal/cmd/network-area/network-range/delete/delete_test.go @@ -15,6 +15,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,6 +40,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrgId, networkAreaIdFlag: testNetworkAreaId, } @@ -49,6 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, OrganizationId: utils.Ptr(testOrgId), NetworkAreaId: utils.Ptr(testNetworkAreaId), @@ -61,7 +68,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteNetworkAreaRangeRequest)) iaas.ApiDeleteNetworkAreaRangeRequest { - request := testClient.DeleteNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId, testNetworkRangeId) + request := testClient.DeleteNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId, testRegion, testNetworkRangeId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/network-area/network-range/describe/describe.go b/internal/cmd/network-area/network-range/describe/describe.go index dcc695246..ee13560b9 100644 --- a/internal/cmd/network-area/network-range/describe/describe.go +++ b/internal/cmd/network-area/network-range/describe/describe.go @@ -95,7 +95,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNetworkAreaRangeRequest { - req := apiClient.GetNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId, model.NetworkRangeId) + req := apiClient.GetNetworkAreaRange(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region, model.NetworkRangeId) return req } @@ -106,7 +106,7 @@ func outputResult(p *print.Printer, outputFormat string, networkRange *iaas.Netw return p.OutputResult(outputFormat, networkRange, func() error { table := tables.NewTable() - table.AddRow("ID", utils.PtrString(networkRange.NetworkRangeId)) + table.AddRow("ID", utils.PtrString(networkRange.Id)) table.AddSeparator() table.AddRow("Network range", utils.PtrString(networkRange.Prefix)) diff --git a/internal/cmd/network-area/network-range/describe/describe_test.go b/internal/cmd/network-area/network-range/describe/describe_test.go index a314d11ee..6e519fef8 100644 --- a/internal/cmd/network-area/network-range/describe/describe_test.go +++ b/internal/cmd/network-area/network-range/describe/describe_test.go @@ -15,6 +15,11 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + projectIdFlag = globalflags.ProjectIdFlag + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,6 +41,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrgId, networkAreaIdFlag: testNetworkAreaId, } @@ -48,6 +55,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, OrganizationId: utils.Ptr(testOrgId), @@ -61,7 +69,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetNetworkAreaRangeRequest)) iaas.ApiGetNetworkAreaRangeRequest { - request := testClient.GetNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId, testNetworkRangeId) + request := testClient.GetNetworkAreaRange(testCtx, testOrgId, testNetworkAreaId, testRegion, testNetworkRangeId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go index 967ffbb9c..2fec7b330 100644 --- a/internal/cmd/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -128,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworkAreaRangesRequest { - return apiClient.ListNetworkAreaRanges(ctx, *model.OrganizationId, *model.NetworkAreaId) + return apiClient.ListNetworkAreaRanges(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region) } func outputResult(p *print.Printer, outputFormat string, networkRanges []iaas.NetworkRange) error { @@ -137,7 +137,7 @@ func outputResult(p *print.Printer, outputFormat string, networkRanges []iaas.Ne table.SetHeader("ID", "Network Range") for _, networkRange := range networkRanges { - table.AddRow(utils.PtrString(networkRange.NetworkRangeId), utils.PtrString(networkRange.Prefix)) + table.AddRow(utils.PtrString(networkRange.Id), utils.PtrString(networkRange.Prefix)) } p.Outputln(table.Render()) diff --git a/internal/cmd/network-area/network-range/list/list_test.go b/internal/cmd/network-area/network-range/list/list_test.go index f8525e39b..67044ee06 100644 --- a/internal/cmd/network-area/network-range/list/list_test.go +++ b/internal/cmd/network-area/network-range/list/list_test.go @@ -16,6 +16,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -25,6 +29,8 @@ var testNetworkAreaId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrganizationId, networkAreaIdFlag: testNetworkAreaId, limitFlag: "10", @@ -38,6 +44,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, OrganizationId: &testOrganizationId, @@ -51,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreaRangesRequest)) iaas.ApiListNetworkAreaRangesRequest { - request := testClient.ListNetworkAreaRanges(testCtx, testOrganizationId, testNetworkAreaId) + request := testClient.ListNetworkAreaRanges(testCtx, testOrganizationId, testNetworkAreaId, testRegion) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/network-area/network_area.go b/internal/cmd/network-area/network_area.go index 0b67ea3ea..637a7af0e 100644 --- a/internal/cmd/network-area/network_area.go +++ b/internal/cmd/network-area/network_area.go @@ -6,6 +6,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/list" networkrange "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/update" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -33,6 +34,7 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(networkrange.NewCmd(params)) + cmd.AddCommand(region.NewCmd(params)) cmd.AddCommand(route.NewCmd(params)) cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/network-area/region/create/create.go b/internal/cmd/network-area/region/create/create.go new file mode 100644 index 000000000..a4cda53d6 --- /dev/null +++ b/internal/cmd/network-area/region/create/create.go @@ -0,0 +1,195 @@ +package create + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" +) + +const ( + networkAreaIdFlag = "network-area-id" + organizationIdFlag = "organization-id" + ipv4DefaultNameservers = "ipv4-default-nameservers" + ipv4DefaultPrefixLengthFlag = "ipv4-default-prefix-length" + ipv4MaxPrefixLengthFlag = "ipv4-max-prefix-length" + ipv4MinPrefixLengthFlag = "ipv4-min-prefix-length" + ipv4NetworkRangesFlag = "ipv4-network-ranges" + ipv4TransferNetworkFlag = "ipv4-transfer-network" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId string + NetworkAreaId string + + IPv4DefaultNameservers *[]string + IPv4DefaultPrefixLength *int64 + IPv4MaxPrefixLength *int64 + IPv4MinPrefixLength *int64 + IPv4NetworkRanges []string + IPv4TransferNetwork string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a new regional configuration for a STACKIT Network Area (SNA)", + Long: "Creates a new regional configuration for a STACKIT Network Area (SNA).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a new regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24" and ipv4 transfer network "192.168.1.0/24"`, + `$ stackit network-area region create --network-area-id xxx --region eu02 --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24`, + ), + examples.NewExample( + `Create a new regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", using the set region config`, + `$ stackit config set --region eu02`, + `$ stackit network-area region create --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24`, + ), + examples.NewExample( + `Create a new regional configuration for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24", ipv4 transfer network "192.168.1.0/24", default prefix length "24", max prefix length "25" and min prefix length "20"`, + `$ stackit network-area region create --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 --region "eu02" --ipv4-default-prefix-length 24 --ipv4-max-prefix-length 25 --ipv4-min-prefix-length 20`, + ), + examples.NewExample( + `Create a new regional configuration for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24", ipv4 transfer network "192.168.1.0/24", default prefix length "24", max prefix length "25" and min prefix length "20"`, + `$ stackit network-area region create --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 --region "eu02" --ipv4-default-prefix-length 24 --ipv4-max-prefix-length 25 --ipv4-min-prefix-length 20`, + ), + ), + 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 + } + + // Get network area label + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, model.OrganizationId, model.NetworkAreaId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = model.NetworkAreaId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create network area region: %w", err) + } + + if resp == nil || resp.Ipv4 == nil { + return fmt.Errorf("empty response from API") + } + + 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) + if err != nil { + return fmt.Errorf("wait for network area region creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model.OutputFormat, model.Region, networkAreaLabel, *resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().Var(flags.CIDRSliceFlag(), ipv4NetworkRangesFlag, "Network range to create in CIDR notation") + cmd.Flags().Var(flags.CIDRFlag(), ipv4TransferNetworkFlag, "Transfer network in CIDR notation") + cmd.Flags().StringSlice(ipv4DefaultNameservers, nil, "List of default DNS name server IPs") + cmd.Flags().Int64(ipv4DefaultPrefixLengthFlag, 0, "The default prefix length for networks in the network area") + cmd.Flags().Int64(ipv4MaxPrefixLengthFlag, 0, "The maximum prefix length for networks in the network area") + cmd.Flags().Int64(ipv4MinPrefixLengthFlag, 0, "The minimum prefix length for networks in the network area") + + err := flags.MarkFlagsRequired(cmd, networkAreaIdFlag, organizationIdFlag, ipv4NetworkRangesFlag, ipv4TransferNetworkFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.Region == "" { + return nil, &errors.RegionError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkAreaId: flags.FlagToStringValue(p, cmd, networkAreaIdFlag), + OrganizationId: flags.FlagToStringValue(p, cmd, organizationIdFlag), + IPv4DefaultNameservers: flags.FlagToStringSlicePointer(p, cmd, ipv4DefaultNameservers), + IPv4DefaultPrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4DefaultPrefixLengthFlag), + IPv4MaxPrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4MaxPrefixLengthFlag), + IPv4MinPrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4MinPrefixLengthFlag), + IPv4NetworkRanges: flags.FlagToStringSliceValue(p, cmd, ipv4NetworkRangesFlag), + IPv4TransferNetwork: flags.FlagToStringValue(p, cmd, ipv4TransferNetworkFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRegionRequest { + req := apiClient.CreateNetworkAreaRegion(ctx, model.OrganizationId, model.NetworkAreaId, model.Region) + + var networkRange []iaas.NetworkRange + if len(model.IPv4NetworkRanges) > 0 { + networkRange = make([]iaas.NetworkRange, len(model.IPv4NetworkRanges)) + for i := range model.IPv4NetworkRanges { + networkRange[i] = iaas.NetworkRange{ + Prefix: utils.Ptr(model.IPv4NetworkRanges[i]), + } + } + } + + payload := iaas.CreateNetworkAreaRegionPayload{ + Ipv4: &iaas.RegionalAreaIPv4{ + DefaultNameservers: model.IPv4DefaultNameservers, + DefaultPrefixLen: model.IPv4DefaultPrefixLength, + MaxPrefixLen: model.IPv4MaxPrefixLength, + MinPrefixLen: model.IPv4MinPrefixLength, + NetworkRanges: utils.Ptr(networkRange), + TransferNetwork: utils.Ptr(model.IPv4TransferNetwork), + }, + } + return req.CreateNetworkAreaRegionPayload(payload) +} + +func outputResult(p *print.Printer, outputFormat, region, networkAreaLabel string, regionalArea iaas.RegionalArea) error { + return p.OutputResult(outputFormat, regionalArea, func() error { + p.Outputf("Create region configuration for SNA %q.\nRegion: %s\n", networkAreaLabel, region) + return nil + }) +} diff --git a/internal/cmd/network-area/region/create/create_test.go b/internal/cmd/network-area/region/create/create_test.go new file mode 100644 index 000000000..1f8cacef2 --- /dev/null +++ b/internal/cmd/network-area/region/create/create_test.go @@ -0,0 +1,307 @@ +package create + +import ( + "context" + "strconv" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + testRegion = "eu01" + testDefaultPrefixLength int64 = 25 + testMaxPrefixLength int64 = 29 + testMinPrefixLength int64 = 24 + testTransferNetwork = "192.168.2.0/24" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var ( + testAreaId = uuid.NewString() + testOrgId = uuid.NewString() + testDefaultNameservers = []string{"8.8.8.8", "8.8.4.4"} + testNetworkRanges = []string{"192.168.0.0/24", "10.0.0.0/24"} +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + + networkAreaIdFlag: testAreaId, + organizationIdFlag: testOrgId, + ipv4DefaultNameservers: strings.Join(testDefaultNameservers, ","), + ipv4DefaultPrefixLengthFlag: strconv.FormatInt(testDefaultPrefixLength, 10), + ipv4MaxPrefixLengthFlag: strconv.FormatInt(testMaxPrefixLength, 10), + ipv4MinPrefixLengthFlag: strconv.FormatInt(testMinPrefixLength, 10), + ipv4NetworkRangesFlag: strings.Join(testNetworkRanges, ","), + ipv4TransferNetworkFlag: testTransferNetwork, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: testOrgId, + NetworkAreaId: testAreaId, + IPv4DefaultNameservers: utils.Ptr(testDefaultNameservers), + IPv4DefaultPrefixLength: utils.Ptr(testDefaultPrefixLength), + IPv4MaxPrefixLength: utils.Ptr(testMaxPrefixLength), + IPv4MinPrefixLength: utils.Ptr(testMinPrefixLength), + IPv4NetworkRanges: testNetworkRanges, + IPv4TransferNetwork: testTransferNetwork, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkAreaRegionRequest)) iaas.ApiCreateNetworkAreaRegionRequest { + request := testClient.CreateNetworkAreaRegion(testCtx, testOrgId, testAreaId, testRegion) + request = request.CreateNetworkAreaRegionPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaRegionPayload)) iaas.CreateNetworkAreaRegionPayload { + var networkRange []iaas.NetworkRange + if len(testNetworkRanges) > 0 { + networkRange = make([]iaas.NetworkRange, len(testNetworkRanges)) + for i := range testNetworkRanges { + networkRange[i] = iaas.NetworkRange{ + Prefix: utils.Ptr(testNetworkRanges[i]), + } + } + } + + payload := iaas.CreateNetworkAreaRegionPayload{ + Ipv4: &iaas.RegionalAreaIPv4{ + DefaultNameservers: utils.Ptr(testDefaultNameservers), + DefaultPrefixLen: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLen: utils.Ptr(testMaxPrefixLength), + MinPrefixLen: utils.Ptr(testMinPrefixLength), + NetworkRanges: utils.Ptr(networkRange), + TransferNetwork: utils.Ptr(testTransferNetwork), + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "network range missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipv4NetworkRangesFlag) + }), + isValid: false, + }, + { + description: "multiple network ranges", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4NetworkRangesFlag] = "192.168.2.0/24,10.0.0.0/24" + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IPv4NetworkRanges = []string{"192.168.2.0/24", "10.0.0.0/24"} + }), + isValid: true, + }, + { + description: "network range invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4NetworkRangesFlag] = "invalid-cidr" + }), + isValid: false, + }, + { + description: "transfer network missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipv4TransferNetworkFlag) + }), + isValid: false, + }, + { + description: "transfer network invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4TransferNetworkFlag] = "" + }), + isValid: false, + }, + { + description: "transfer network invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4TransferNetworkFlag] = "invalid-cidr" + }), + isValid: false, + }, + { + description: "region empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.RegionFlag] = "" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiCreateNetworkAreaRegionRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + region string + networkAreaLabel string + regionalArea iaas.RegionalArea + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty regional area", + args: args{ + regionalArea: iaas.RegionalArea{}, + }, + wantErr: false, + }, + { + name: "output json", + args: args{ + outputFormat: print.JSONOutputFormat, + regionalArea: iaas.RegionalArea{}, + }, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.region, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/network-area/region/delete/delete.go b/internal/cmd/network-area/region/delete/delete.go new file mode 100644 index 000000000..37f1f8bb0 --- /dev/null +++ b/internal/cmd/network-area/region/delete/delete.go @@ -0,0 +1,129 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" +) + +const ( + networkAreaIdFlag = "network-area-id" + organizationIdFlag = "organization-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId string + NetworkAreaId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a regional configuration for a STACKIT Network Area (SNA)", + Long: "Deletes a regional configuration for a STACKIT Network Area (SNA).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Delete a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + `$ stackit network-area region delete --network-area-id xxx --region eu02 --organization-id yyy`, + ), + examples.NewExample( + `Delete a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", using the set region config`, + `$ stackit config set --region eu02`, + `$ stackit network-area region delete --network-area-id xxx --organization-id yyy`, + ), + ), + 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 + } + + // Get network area label + networkAreaName, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, model.OrganizationId, model.NetworkAreaId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaName = model.NetworkAreaId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete network area region: %w", err) + } + + 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) + if err != nil { + return fmt.Errorf("wait for network area region deletion: %w", err) + } + s.Stop() + } + + params.Printer.Outputf("Delete regional network area %q for %q\n", model.Region, networkAreaName) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + + err := flags.MarkFlagsRequired(cmd, networkAreaIdFlag, organizationIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.Region == "" { + return nil, &errors.RegionError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkAreaId: flags.FlagToStringValue(p, cmd, networkAreaIdFlag), + OrganizationId: flags.FlagToStringValue(p, cmd, organizationIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNetworkAreaRegionRequest { + return apiClient.DeleteNetworkAreaRegion(ctx, model.OrganizationId, model.NetworkAreaId, model.Region) +} diff --git a/internal/cmd/network-area/region/delete/delete_test.go b/internal/cmd/network-area/region/delete/delete_test.go new file mode 100644 index 000000000..919e86cb8 --- /dev/null +++ b/internal/cmd/network-area/region/delete/delete_test.go @@ -0,0 +1,168 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + testRegion = "eu01" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var ( + testAreaId = uuid.NewString() + testOrgId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + + networkAreaIdFlag: testAreaId, + organizationIdFlag: testOrgId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: testOrgId, + NetworkAreaId: testAreaId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiDeleteNetworkAreaRegionRequest)) iaas.ApiDeleteNetworkAreaRegionRequest { + request := testClient.DeleteNetworkAreaRegion(testCtx, testOrgId, testAreaId, testRegion) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "region empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.RegionFlag] = "" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiDeleteNetworkAreaRegionRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/network-area/region/describe/describe.go b/internal/cmd/network-area/region/describe/describe.go new file mode 100644 index 000000000..71e4f5c31 --- /dev/null +++ b/internal/cmd/network-area/region/describe/describe.go @@ -0,0 +1,169 @@ +package describe + +import ( + "context" + "fmt" + "strings" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + networkAreaIdFlag = "network-area-id" + organizationIdFlag = "organization-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId string + NetworkAreaId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Describes a regional configuration for a STACKIT Network Area (SNA)", + Long: "Describes a regional configuration for a STACKIT Network Area (SNA).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Describe a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + `$ stackit network-area region describe --network-area-id xxx --region eu02 --organization-id yyy`, + ), + examples.NewExample( + `Describe a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", using the set region config`, + `$ stackit config set --region eu02`, + `$ stackit network-area region describe --network-area-id xxx --organization-id yyy`, + ), + ), + 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 + } + + // Get network area label + networkAreaName, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, model.OrganizationId, model.NetworkAreaId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) + // Set explicit the networkAreaName to empty string and not to the ID, because this is used for the table output + networkAreaName = "" + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("describe network area region: %w", err) + } + + if resp == nil || resp.Ipv4 == nil { + return fmt.Errorf("empty response from API") + } + + return outputResult(params.Printer, model.OutputFormat, model.Region, model.NetworkAreaId, networkAreaName, *resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + + err := flags.MarkFlagsRequired(cmd, networkAreaIdFlag, organizationIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.Region == "" { + return nil, &errors.RegionError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkAreaId: flags.FlagToStringValue(p, cmd, networkAreaIdFlag), + OrganizationId: flags.FlagToStringValue(p, cmd, organizationIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNetworkAreaRegionRequest { + return apiClient.GetNetworkAreaRegion(ctx, model.OrganizationId, model.NetworkAreaId, model.Region) +} + +func outputResult(p *print.Printer, outputFormat, region, areaId, areaName string, regionalArea iaas.RegionalArea) error { + return p.OutputResult(outputFormat, regionalArea, func() error { + table := tables.NewTable() + table.AddRow("ID", areaId) + table.AddSeparator() + if areaName != "" { + table.AddRow("NAME", areaName) + table.AddSeparator() + } + table.AddRow("REGION", region) + table.AddSeparator() + table.AddRow("STATUS", utils.PtrString(regionalArea.Status)) + table.AddSeparator() + if ipv4 := regionalArea.Ipv4; ipv4 != nil { + if ipv4.NetworkRanges != nil { + var networkRanges []string + for _, networkRange := range *ipv4.NetworkRanges { + if networkRange.Prefix != nil { + networkRanges = append(networkRanges, *networkRange.Prefix) + } + } + table.AddRow("NETWORK RANGES", strings.Join(networkRanges, ",")) + table.AddSeparator() + } + if transferNetwork := ipv4.TransferNetwork; transferNetwork != nil { + table.AddRow("TRANSFER RANGE", utils.PtrString(transferNetwork)) + table.AddSeparator() + } + if defaultNameserver := ipv4.DefaultNameservers; defaultNameserver != nil && len(*defaultNameserver) > 0 { + table.AddRow("DNS NAME SERVERS", strings.Join(*defaultNameserver, ",")) + table.AddSeparator() + } + if defaultPrefixLength := ipv4.DefaultPrefixLen; defaultPrefixLength != nil { + table.AddRow("DEFAULT PREFIX LENGTH", utils.PtrString(defaultPrefixLength)) + table.AddSeparator() + } + if maxPrefixLength := ipv4.MaxPrefixLen; maxPrefixLength != nil { + table.AddRow("MAX PREFIX LENGTH", utils.PtrString(maxPrefixLength)) + table.AddSeparator() + } + if minPrefixLen := ipv4.MinPrefixLen; minPrefixLen != nil { + table.AddRow("MIN PREFIX LENGTH", utils.PtrString(minPrefixLen)) + table.AddSeparator() + } + } + + if err := table.Display(p); err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/network-area/region/describe/describe_test.go b/internal/cmd/network-area/region/describe/describe_test.go new file mode 100644 index 000000000..7d06c1794 --- /dev/null +++ b/internal/cmd/network-area/region/describe/describe_test.go @@ -0,0 +1,214 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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-sdk-go/services/iaas" +) + +const ( + testRegion = "eu01" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var ( + testAreaId = uuid.NewString() + testOrgId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + + networkAreaIdFlag: testAreaId, + organizationIdFlag: testOrgId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: testOrgId, + NetworkAreaId: testAreaId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiGetNetworkAreaRegionRequest)) iaas.ApiGetNetworkAreaRegionRequest { + request := testClient.GetNetworkAreaRegion(testCtx, testOrgId, testAreaId, testRegion) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "region empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.RegionFlag] = "" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiGetNetworkAreaRegionRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + areaId string + region string + networkAreaLabel string + regionalArea iaas.RegionalArea + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty regional area", + args: args{ + regionalArea: iaas.RegionalArea{}, + }, + wantErr: false, + }, + { + name: "output json", + args: args{ + outputFormat: print.JSONOutputFormat, + regionalArea: iaas.RegionalArea{}, + }, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.region, tt.args.areaId, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/network-area/region/list/list.go b/internal/cmd/network-area/region/list/list.go new file mode 100644 index 000000000..44149c9af --- /dev/null +++ b/internal/cmd/network-area/region/list/list.go @@ -0,0 +1,153 @@ +package list + +import ( + "context" + "fmt" + "strings" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + networkAreaIdFlag = "network-area-id" + organizationIdFlag = "organization-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId string + NetworkAreaId string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all configured regions for a STACKIT Network Area (SNA)", + Long: "Lists all configured regions for a STACKIT Network Area (SNA).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all configured region for a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + `$ stackit network-area region list --network-area-id xxx --organization-id yyy`, + ), + ), + 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 + } + + // Get network area label + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, model.OrganizationId, model.NetworkAreaId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = model.NetworkAreaId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list network area region: %w", err) + } + + if resp == nil { + return fmt.Errorf("empty response from API") + } + + return outputResult(params.Printer, model.OutputFormat, networkAreaLabel, *resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + + err := flags.MarkFlagsRequired(cmd, networkAreaIdFlag, organizationIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkAreaId: flags.FlagToStringValue(p, cmd, networkAreaIdFlag), + OrganizationId: flags.FlagToStringValue(p, cmd, organizationIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworkAreaRegionsRequest { + return apiClient.ListNetworkAreaRegions(ctx, model.OrganizationId, model.NetworkAreaId) +} + +func outputResult(p *print.Printer, outputFormat, areaLabel string, regionalArea iaas.RegionalAreaListResponse) error { + return p.OutputResult(outputFormat, regionalArea, func() error { + if regionalArea.Regions == nil || len(*regionalArea.Regions) == 0 { + p.Outputf("No regions found for network area %q\n", areaLabel) + return nil + } + + table := tables.NewTable() + table.SetHeader("REGION", "STATUS", "DNS NAME SERVERS", "NETWORK RANGES", "TRANSFER NETWORK") + for region, regionConfig := range *regionalArea.Regions { + var dnsNames string + var networkRanges []string + var transferNetwork string + + if ipv4 := regionConfig.Ipv4; ipv4 != nil { + // Set dnsNames + dnsNames = utils.JoinStringPtr(ipv4.DefaultNameservers, ",") + + // Set networkRanges + if ipv4.NetworkRanges != nil && len(*ipv4.NetworkRanges) > 0 { + for _, networkRange := range *ipv4.NetworkRanges { + if networkRange.Prefix != nil { + networkRanges = append(networkRanges, *networkRange.Prefix) + } + } + } + + // Set transferNetwork + transferNetwork = utils.PtrString(ipv4.TransferNetwork) + } + + table.AddRow( + region, + utils.PtrString(regionConfig.Status), + dnsNames, + strings.Join(networkRanges, ","), + transferNetwork, + ) + } + + if err := table.Display(p); err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/network-area/region/list/list_test.go b/internal/cmd/network-area/region/list/list_test.go new file mode 100644 index 000000000..bb7b3f15b --- /dev/null +++ b/internal/cmd/network-area/region/list/list_test.go @@ -0,0 +1,221 @@ +package list + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var ( + testAreaId = uuid.NewString() + testOrgId = uuid.NewString() +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + networkAreaIdFlag: testAreaId, + organizationIdFlag: testOrgId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: testOrgId, + NetworkAreaId: testAreaId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreaRegionsRequest)) iaas.ApiListNetworkAreaRegionsRequest { + request := testClient.ListNetworkAreaRegions(testCtx, testOrgId, testAreaId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiListNetworkAreaRegionsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + networkAreaLabel string + regionalArea iaas.RegionalAreaListResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + regionalArea: iaas.RegionalAreaListResponse{}, + }, + wantErr: false, + }, + { + name: "set nil for regions map in response", + args: args{ + regionalArea: iaas.RegionalAreaListResponse{ + Regions: nil, + }, + }, + wantErr: false, + }, + { + name: "set empty map for regions map in response", + args: args{ + regionalArea: iaas.RegionalAreaListResponse{ + Regions: utils.Ptr(map[string]iaas.RegionalArea{}), + }, + }, + wantErr: false, + }, + { + name: "set empty region in response", + args: args{ + regionalArea: iaas.RegionalAreaListResponse{ + Regions: utils.Ptr(map[string]iaas.RegionalArea{ + "eu01": {}, + }), + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/network-area/region/region.go b/internal/cmd/network-area/region/region.go new file mode 100644 index 000000000..99edcace2 --- /dev/null +++ b/internal/cmd/network-area/region/region.go @@ -0,0 +1,34 @@ +package region + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "region", + Short: "Provides functionality for regional configuration of STACKIT Network Area (SNA)", + Long: "Provides functionality for regional configuration of STACKIT Network Area (SNA).", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) +} diff --git a/internal/cmd/network-area/region/update/update.go b/internal/cmd/network-area/region/update/update.go new file mode 100644 index 000000000..9018cb175 --- /dev/null +++ b/internal/cmd/network-area/region/update/update.go @@ -0,0 +1,165 @@ +package update + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + networkAreaIdFlag = "network-area-id" + organizationIdFlag = "organization-id" + ipv4DefaultNameservers = "ipv4-default-nameservers" + ipv4DefaultPrefixLengthFlag = "ipv4-default-prefix-length" + ipv4MaxPrefixLengthFlag = "ipv4-max-prefix-length" + ipv4MinPrefixLengthFlag = "ipv4-min-prefix-length" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + OrganizationId string + NetworkAreaId string + + IPv4DefaultNameservers *[]string + IPv4DefaultPrefixLength *int64 + IPv4MaxPrefixLength *int64 + IPv4MinPrefixLength *int64 +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a existing regional configuration for a STACKIT Network Area (SNA)", + Long: "Updates a existing regional configuration for a STACKIT Network Area (SNA).", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Update a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy" with new ipv4-default-nameservers "8.8.8.8"`, + `$ stackit network-area region update --network-area-id xxx --region eu02 --organization-id yyy --ipv4-default-nameservers 8.8.8.8`, + ), + examples.NewExample( + `Update a regional configuration "eu02" for a STACKIT Network Area with ID "xxx" in organization with ID "yyy" with new ipv4-default-nameservers "8.8.8.8", using the set region config`, + `$ stackit config set --region eu02`, + `$ stackit network-area region update --network-area-id xxx --organization-id yyy --ipv4-default-nameservers 8.8.8.8`, + ), + examples.NewExample( + `Update a new regional configuration for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24", ipv4 transfer network "192.168.1.0/24", default prefix length "24", max prefix length "25" and min prefix length "20"`, + `$ stackit network-area region update --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 --region "eu02" --ipv4-default-prefix-length 24 --ipv4-max-prefix-length 25 --ipv4-min-prefix-length 20`, + ), + examples.NewExample( + `Update a new regional configuration for a STACKIT Network Area with ID "xxx" in organization with ID "yyy", ipv4 network range "192.168.0.0/24", ipv4 transfer network "192.168.1.0/24", default prefix length "24", max prefix length "25" and min prefix length "20"`, + `$ stackit network-area region update --network-area-id xxx --organization-id yyy --ipv4-network-ranges 192.168.0.0/24 --ipv4-transfer-network 192.168.1.0/24 --region "eu02" --ipv4-default-prefix-length 24 --ipv4-max-prefix-length 25 --ipv4-min-prefix-length 20`, + ), + ), + 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 + } + + // Get network area label + networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, model.OrganizationId, model.NetworkAreaId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get network area name: %v", err) + networkAreaLabel = model.NetworkAreaId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update network area region: %w", err) + } + + if resp == nil || resp.Ipv4 == nil { + return fmt.Errorf("empty response from API") + } + + return outputResult(params.Printer, model.OutputFormat, model.Region, networkAreaLabel, *resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area (SNA) ID") + cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") + cmd.Flags().StringSlice(ipv4DefaultNameservers, nil, "List of default DNS name server IPs") + cmd.Flags().Int64(ipv4DefaultPrefixLengthFlag, 0, "The default prefix length for networks in the network area") + cmd.Flags().Int64(ipv4MaxPrefixLengthFlag, 0, "The maximum prefix length for networks in the network area") + cmd.Flags().Int64(ipv4MinPrefixLengthFlag, 0, "The minimum prefix length for networks in the network area") + + // At least one of the flags is required, otherwise there is nothing to update + cmd.MarkFlagsOneRequired(ipv4DefaultNameservers, ipv4MaxPrefixLengthFlag, ipv4MinPrefixLengthFlag, ipv4DefaultPrefixLengthFlag) + + err := flags.MarkFlagsRequired(cmd, networkAreaIdFlag, organizationIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.Region == "" { + return nil, &errors.RegionError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + NetworkAreaId: flags.FlagToStringValue(p, cmd, networkAreaIdFlag), + OrganizationId: flags.FlagToStringValue(p, cmd, organizationIdFlag), + IPv4DefaultNameservers: flags.FlagToStringSlicePointer(p, cmd, ipv4DefaultNameservers), + IPv4DefaultPrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4DefaultPrefixLengthFlag), + IPv4MaxPrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4MaxPrefixLengthFlag), + IPv4MinPrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4MinPrefixLengthFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNetworkAreaRegionRequest { + req := apiClient.UpdateNetworkAreaRegion(ctx, model.OrganizationId, model.NetworkAreaId, model.Region) + + payload := iaas.UpdateNetworkAreaRegionPayload{ + Ipv4: &iaas.UpdateRegionalAreaIPv4{ + DefaultNameservers: model.IPv4DefaultNameservers, + DefaultPrefixLen: model.IPv4DefaultPrefixLength, + MaxPrefixLen: model.IPv4MaxPrefixLength, + MinPrefixLen: model.IPv4MinPrefixLength, + }, + } + return req.UpdateNetworkAreaRegionPayload(payload) +} + +func outputResult(p *print.Printer, outputFormat, region, networkAreaLabel string, regionalArea iaas.RegionalArea) error { + return p.OutputResult(outputFormat, regionalArea, func() error { + p.Outputf("Updated region configuration for SNA %q.\nRegion: %s\n", networkAreaLabel, region) + return nil + }) +} diff --git a/internal/cmd/network-area/region/update/update_test.go b/internal/cmd/network-area/region/update/update_test.go new file mode 100644 index 000000000..73482555d --- /dev/null +++ b/internal/cmd/network-area/region/update/update_test.go @@ -0,0 +1,265 @@ +package update + +import ( + "context" + "strconv" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/iaas" +) + +const ( + testRegion = "eu01" + testDefaultPrefixLength int64 = 25 + testMaxPrefixLength int64 = 29 + testMinPrefixLength int64 = 24 +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &iaas.APIClient{} + +var ( + testAreaId = uuid.NewString() + testOrgId = uuid.NewString() + testDefaultNameservers = []string{"8.8.8.8", "8.8.4.4"} + testNetworkRanges = []string{"192.168.0.0/24", "10.0.0.0/24"} +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + + networkAreaIdFlag: testAreaId, + organizationIdFlag: testOrgId, + ipv4DefaultNameservers: strings.Join(testDefaultNameservers, ","), + ipv4DefaultPrefixLengthFlag: strconv.FormatInt(testDefaultPrefixLength, 10), + ipv4MaxPrefixLengthFlag: strconv.FormatInt(testMaxPrefixLength, 10), + ipv4MinPrefixLengthFlag: strconv.FormatInt(testMinPrefixLength, 10), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + OrganizationId: testOrgId, + NetworkAreaId: testAreaId, + IPv4DefaultNameservers: utils.Ptr(testDefaultNameservers), + IPv4DefaultPrefixLength: utils.Ptr(testDefaultPrefixLength), + IPv4MaxPrefixLength: utils.Ptr(testMaxPrefixLength), + IPv4MinPrefixLength: utils.Ptr(testMinPrefixLength), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *iaas.ApiUpdateNetworkAreaRegionRequest)) iaas.ApiUpdateNetworkAreaRegionRequest { + request := testClient.UpdateNetworkAreaRegion(testCtx, testOrgId, testAreaId, testRegion) + request = request.UpdateNetworkAreaRegionPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *iaas.UpdateNetworkAreaRegionPayload)) iaas.UpdateNetworkAreaRegionPayload { + var networkRange []iaas.NetworkRange + if len(testNetworkRanges) > 0 { + networkRange = make([]iaas.NetworkRange, len(testNetworkRanges)) + for i := range testNetworkRanges { + networkRange[i] = iaas.NetworkRange{ + Prefix: utils.Ptr(testNetworkRanges[i]), + } + } + } + + payload := iaas.UpdateNetworkAreaRegionPayload{ + Ipv4: &iaas.UpdateRegionalAreaIPv4{ + DefaultNameservers: utils.Ptr(testDefaultNameservers), + DefaultPrefixLen: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLen: utils.Ptr(testMaxPrefixLength), + MinPrefixLen: utils.Ptr(testMinPrefixLength), + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "org id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, organizationIdFlag) + }), + isValid: false, + }, + { + description: "org id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "" + }), + isValid: false, + }, + { + description: "org id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[organizationIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "area id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, networkAreaIdFlag) + }), + isValid: false, + }, + { + description: "area id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "" + }), + isValid: false, + }, + { + description: "area id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[networkAreaIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "no update data is set", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipv4DefaultPrefixLengthFlag) + delete(flagValues, ipv4MaxPrefixLengthFlag) + delete(flagValues, ipv4MinPrefixLengthFlag) + delete(flagValues, ipv4DefaultNameservers) + }), + isValid: false, + }, + { + description: "region empty", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.RegionFlag] = "" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateNetworkAreaRegionRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + region string + networkAreaLabel string + regionalArea iaas.RegionalArea + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty regional area", + args: args{ + regionalArea: iaas.RegionalArea{}, + }, + wantErr: false, + }, + { + name: "output json", + args: args{ + outputFormat: print.JSONOutputFormat, + regionalArea: iaas.RegionalArea{}, + }, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.region, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index f8548316c..c8950144e 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -3,6 +3,8 @@ package create import ( "context" "fmt" + "net" + "os" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -21,18 +23,39 @@ import ( const ( organizationIdFlag = "organization-id" networkAreaIdFlag = "network-area-id" - prefixFlag = "prefix" - nexthopFlag = "next-hop" - labelFlag = "labels" + // Deprecated: prefixFlag is deprecated and will be removed after April 2026. Use instead destinationFlag + prefixFlag = "prefix" + destinationFlag = "destination" + // Deprecated: nexthopFlag is deprecated and will be removed after April 2026. Use instead nexthopIPv4Flag or nexthopIPv6Flag + nexthopFlag = "next-hop" + nexthopIPv4Flag = "next-hop-ipv4" + nexthopIPv6Flag = "next-hop-ipv6" + nexthopBlackholeFlag = "nexthop-blackhole" + nexthopInternetFlag = "nexthop-internet" + labelFlag = "labels" +) + +const ( + destinationCIDRv4Type = "cidrv4" + destinationCIDRv6Type = "cidrv6" + + nexthopBlackholeType = "blackhole" + nexthopInternetType = "internet" + nexthopIPv4Type = "ipv4" + nexthopIPv6Type = "ipv6" ) type inputModel struct { *globalflags.GlobalFlagModel - OrganizationId *string - NetworkAreaId *string - Prefix *string - Nexthop *string - Labels *map[string]string + OrganizationId *string + NetworkAreaId *string + DestinationV4 *string + DestinationV6 *string + NexthopV4 *string + NexthopV6 *string + NexthopBlackhole *bool + NexthopInternet *bool + Labels *map[string]string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -46,12 +69,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { Args: args.NoArgs, Example: examples.Build( examples.NewExample( - `Create a static route with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit network-area route create --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", + `Create a static route with destination "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + "$ stackit network-area route create --organization-id yyy --network-area-id xxx --destination 1.1.1.0/24 --next-hop 1.1.1.1", ), examples.NewExample( - `Create a static route with labels "key:value" and "foo:bar" with prefix "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, - "$ stackit network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --prefix 1.1.1.0/24 --next-hop 1.1.1.1", + `Create a static route with labels "key:value" and "foo:bar" with destination "1.1.1.0/24" and next hop "1.1.1.1" in a STACKIT Network Area with ID "xxx" in organization with ID "yyy"`, + "$ stackit network-area route create --labels key=value,foo=bar --organization-id yyy --network-area-id xxx --destination 1.1.1.0/24 --next-hop 1.1.1.1", ), ), RunE: func(cmd *cobra.Command, args []string) error { @@ -93,7 +116,27 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("empty response from API") } - route, err := iaasUtils.GetRouteFromAPIResponse(*model.Prefix, *model.Nexthop, resp.Items) + var destination string + var nexthop string + if model.DestinationV4 != nil { + destination = *model.DestinationV4 + } else if model.DestinationV6 != nil { + destination = *model.DestinationV6 + } + + if model.NexthopV4 != nil { + nexthop = *model.NexthopV4 + } else if model.NexthopV6 != nil { + nexthop = *model.NexthopV6 + } else if model.NexthopBlackhole != nil { + // For nexthopBlackhole the type is assigned to nexthop, because it doesn't have any value + nexthop = nexthopBlackholeType + } else if model.NexthopInternet != nil { + // For nexthopInternet the type is assigned to nexthop, because it doesn't have any value + nexthop = nexthopInternetType + } + + route, err := iaasUtils.GetRouteFromAPIResponse(destination, nexthop, resp.Items) if err != nil { return err } @@ -109,23 +152,83 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID") cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area ID") cmd.Flags().Var(flags.CIDRFlag(), prefixFlag, "Static route prefix") - cmd.Flags().String(nexthopFlag, "", "Next hop IP address. Must be a valid IPv4") + cmd.Flags().Var(flags.CIDRFlag(), destinationFlag, "Destination route. Must be a valid IPv4 or IPv6 CIDR") + cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels") + cmd.Flags().String(nexthopFlag, "", "Next hop IP address. Must be a valid IPv4") + cmd.Flags().String(nexthopIPv4Flag, "", "Next hop IPv4 address") + cmd.Flags().String(nexthopIPv6Flag, "", "Next hop IPv6 address") + cmd.Flags().Bool(nexthopBlackholeFlag, false, "Sets next hop to black hole") + cmd.Flags().Bool(nexthopInternetFlag, false, "Sets next hop to internet") - err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag, prefixFlag, nexthopFlag) + cobra.CheckErr(cmd.Flags().MarkDeprecated(nexthopFlag, fmt.Sprintf("The flag %q is deprecated and will be removed after April 2026. Use instead %q to configure a IPv4 next hop.", nexthopFlag, nexthopBlackholeFlag))) + cobra.CheckErr(cmd.Flags().MarkDeprecated(prefixFlag, fmt.Sprintf("The flag %q is deprecated and will be removed after April 2026. Use instead %q to configure a destination.", prefixFlag, destinationFlag))) + // Set the output for deprecation warnings to stderr + cmd.Flags().SetOutput(os.Stderr) + + destinationFlags := []string{prefixFlag, destinationFlag} + nexthopFlags := []string{nexthopFlag, nexthopIPv4Flag, nexthopIPv6Flag, nexthopBlackholeFlag, nexthopInternetFlag} + cmd.MarkFlagsMutuallyExclusive(destinationFlags...) + cmd.MarkFlagsMutuallyExclusive(nexthopFlags...) + + cmd.MarkFlagsOneRequired(destinationFlags...) + cmd.MarkFlagsOneRequired(nexthopFlags...) + err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag) cobra.CheckErr(err) } +func parseDestination(input string) (destinationV4, destinationV6 *string, err error) { + ip, _, err := net.ParseCIDR(input) + if err != nil { + return nil, nil, fmt.Errorf("parse CIDR: %w", err) + } + if ip.To4() != nil { // CIDR is IPv4 + destinationV4 = utils.Ptr(input) + return destinationV4, nil, nil + } + // CIDR is IPv6 + destinationV6 = utils.Ptr(input) + return nil, destinationV6, nil +} + func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) + var destinationV4, destinationV6 *string + if destination := flags.FlagToStringPointer(p, cmd, destinationFlag); destination != nil { + var err error + destinationV4, destinationV6, err = parseDestination(*destination) + if err != nil { + return nil, err + } + } + if prefix := flags.FlagToStringPointer(p, cmd, prefixFlag); prefix != nil { + var err error + destinationV4, destinationV6, err = parseDestination(*prefix) + if err != nil { + return nil, err + } + } + + nexthopIPv4 := flags.FlagToStringPointer(p, cmd, nexthopIPv4Flag) + nexthopIPv6 := flags.FlagToStringPointer(p, cmd, nexthopIPv6Flag) + nexthopInternet := flags.FlagToBoolPointer(p, cmd, nexthopInternetFlag) + nexthopBlackhole := flags.FlagToBoolPointer(p, cmd, nexthopBlackholeFlag) + if nexthop := flags.FlagToStringPointer(p, cmd, nexthopFlag); nexthop != nil { + nexthopIPv4 = nexthop + } + model := inputModel{ - GlobalFlagModel: globalFlags, - OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), - NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), - Prefix: flags.FlagToStringPointer(p, cmd, prefixFlag), - Nexthop: flags.FlagToStringPointer(p, cmd, nexthopFlag), - Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + GlobalFlagModel: globalFlags, + OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag), + NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag), + DestinationV4: destinationV4, + DestinationV6: destinationV6, + NexthopV4: nexthopIPv4, + NexthopV6: nexthopIPv6, + NexthopBlackhole: nexthopBlackhole, + NexthopInternet: nexthopInternet, + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } p.DebugInputModel(model) @@ -133,14 +236,62 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkAreaRouteRequest { - req := apiClient.CreateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId) + req := apiClient.CreateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region) + + var destinationV4 *iaas.DestinationCIDRv4 + var destinationV6 *iaas.DestinationCIDRv6 + if model.DestinationV4 != nil { + destinationV4 = &iaas.DestinationCIDRv4{ + Type: utils.Ptr(destinationCIDRv4Type), + Value: model.DestinationV4, + } + } + if model.DestinationV6 != nil { + destinationV6 = &iaas.DestinationCIDRv6{ + Type: utils.Ptr(destinationCIDRv6Type), + Value: model.DestinationV6, + } + } + + var nexthopIPv4 *iaas.NexthopIPv4 + var nexthopIPv6 *iaas.NexthopIPv6 + var nexthopBlackhole *iaas.NexthopBlackhole + var nexthopInternet *iaas.NexthopInternet + + if model.NexthopV4 != nil { + nexthopIPv4 = &iaas.NexthopIPv4{ + Type: utils.Ptr(nexthopIPv4Type), + Value: model.NexthopV4, + } + } else if model.NexthopV6 != nil { + nexthopIPv6 = &iaas.NexthopIPv6{ + Type: utils.Ptr(nexthopIPv6Type), + Value: model.NexthopV6, + } + } else if model.NexthopBlackhole != nil { + nexthopBlackhole = &iaas.NexthopBlackhole{ + Type: utils.Ptr(nexthopBlackholeType), + } + } else if model.NexthopInternet != nil { + nexthopInternet = &iaas.NexthopInternet{ + Type: utils.Ptr(nexthopInternetType), + } + } payload := iaas.CreateNetworkAreaRoutePayload{ - Ipv4: &[]iaas.Route{ + Items: &[]iaas.Route{ { - Prefix: model.Prefix, - Nexthop: model.Nexthop, - Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: destinationV4, + DestinationCIDRv6: destinationV6, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: nexthopIPv4, + NexthopIPv6: nexthopIPv6, + NexthopBlackhole: nexthopBlackhole, + NexthopInternet: nexthopInternet, + }, + Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), }, }, } @@ -149,7 +300,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, route iaas.Route) error { return p.OutputResult(outputFormat, route, func() error { - p.Outputf("Created static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, utils.PtrString(route.RouteId)) + p.Outputf("Created static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, utils.PtrString(route.Id)) return nil }) } diff --git a/internal/cmd/network-area/route/create/create_test.go b/internal/cmd/network-area/route/create/create_test.go index 1bc7cb161..b3d577b80 100644 --- a/internal/cmd/network-area/route/create/create_test.go +++ b/internal/cmd/network-area/route/create/create_test.go @@ -16,6 +16,12 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" + testDestinationCIDRv4 = "1.1.1.0/24" + testNexthopIPv4 = "1.1.1.1" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,10 +32,12 @@ var testNetworkAreaId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrgId, networkAreaIdFlag: testNetworkAreaId, - prefixFlag: "1.1.1.0/24", - nexthopFlag: "1.1.1.1", + destinationFlag: testDestinationCIDRv4, + nexthopIPv4Flag: testNexthopIPv4, } for _, mod := range mods { mod(flagValues) @@ -41,11 +49,12 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, OrganizationId: utils.Ptr(testOrgId), NetworkAreaId: utils.Ptr(testNetworkAreaId), - Prefix: utils.Ptr("1.1.1.0/24"), - Nexthop: utils.Ptr("1.1.1.1"), + DestinationV4: utils.Ptr(testDestinationCIDRv4), + NexthopV4: utils.Ptr(testNexthopIPv4), } for _, mod := range mods { mod(model) @@ -54,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkAreaRouteRequest)) iaas.ApiCreateNetworkAreaRouteRequest { - request := testClient.CreateNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId) + request := testClient.CreateNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRegion) request = request.CreateNetworkAreaRoutePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -64,10 +73,20 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkAreaRouteRequest) func fixturePayload(mods ...func(payload *iaas.CreateNetworkAreaRoutePayload)) iaas.CreateNetworkAreaRoutePayload { payload := iaas.CreateNetworkAreaRoutePayload{ - Ipv4: &[]iaas.Route{ + Items: &[]iaas.Route{ { - Prefix: utils.Ptr("1.1.1.0/24"), - Nexthop: utils.Ptr("1.1.1.1"), + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Type: utils.Ptr(destinationCIDRv4Type), + Value: utils.Ptr(testDestinationCIDRv4), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Type: utils.Ptr(nexthopIPv4Type), + Value: utils.Ptr(testNexthopIPv4), + }, + }, }, }, } @@ -96,7 +115,7 @@ func TestParseInput(t *testing.T) { { description: "next hop missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, nexthopFlag) + delete(flagValues, nexthopIPv4Flag) }), isValid: false, }, @@ -148,23 +167,23 @@ func TestParseInput(t *testing.T) { isValid: false, }, { - description: "prefix missing", + description: "destination missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, prefixFlag) + delete(flagValues, destinationFlag) }), isValid: false, }, { - description: "prefix invalid 1", + description: "destinationFlag invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[prefixFlag] = "" + flagValues[destinationFlag] = "" }), isValid: false, }, { - description: "prefix invalid 2", + description: "destinationFlag invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[prefixFlag] = "invalid-prefix" + flagValues[destinationFlag] = "invalid-destinationFlag" }), isValid: false, }, @@ -178,6 +197,23 @@ func TestParseInput(t *testing.T) { }), isValid: true, }, + { + description: "conflicting destination and prefix set", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[prefixFlag] = testDestinationCIDRv4 + }), + isValid: false, + }, + { + description: "conflicting nexthop and nexthop-ipv4 set", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[nexthopFlag] = testNexthopIPv4 + }), + isValid: false, + }, + { + description: "conflicting nexthop and nexthop-ipv4 set", + }, } for _, tt := range tests { @@ -205,7 +241,7 @@ func TestBuildRequest(t *testing.T) { }), expectedRequest: fixtureRequest(func(request *iaas.ApiCreateNetworkAreaRouteRequest) { *request = (*request).CreateNetworkAreaRoutePayload(fixturePayload(func(payload *iaas.CreateNetworkAreaRoutePayload) { - (*payload.Ipv4)[0].Labels = utils.Ptr(map[string]interface{}{"key": "value"}) + (*payload.Items)[0].Labels = utils.Ptr(map[string]interface{}{"key": "value"}) })) }), }, diff --git a/internal/cmd/network-area/route/delete/delete.go b/internal/cmd/network-area/route/delete/delete.go index 254e7fb7a..b888fb6d5 100644 --- a/internal/cmd/network-area/route/delete/delete.go +++ b/internal/cmd/network-area/route/delete/delete.go @@ -110,6 +110,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNetworkAreaRouteRequest { - req := apiClient.DeleteNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.RouteId) + req := apiClient.DeleteNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region, model.RouteId) return req } diff --git a/internal/cmd/network-area/route/delete/delete_test.go b/internal/cmd/network-area/route/delete/delete_test.go index 0358eba8c..d34c268a7 100644 --- a/internal/cmd/network-area/route/delete/delete_test.go +++ b/internal/cmd/network-area/route/delete/delete_test.go @@ -15,6 +15,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,6 +40,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrgId, networkAreaIdFlag: testNetworkAreaId, } @@ -49,6 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, OrganizationId: utils.Ptr(testOrgId), NetworkAreaId: utils.Ptr(testNetworkAreaId), @@ -61,7 +68,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteNetworkAreaRouteRequest)) iaas.ApiDeleteNetworkAreaRouteRequest { - request := testClient.DeleteNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRouteId) + request := testClient.DeleteNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRegion, testRouteId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/network-area/route/describe/describe.go b/internal/cmd/network-area/route/describe/describe.go index 2e54ac4c8..b650e5964 100644 --- a/internal/cmd/network-area/route/describe/describe.go +++ b/internal/cmd/network-area/route/describe/describe.go @@ -100,18 +100,47 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNetworkAreaRouteRequest { - req := apiClient.GetNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.RouteId) + req := apiClient.GetNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region, model.RouteId) return req } func outputResult(p *print.Printer, outputFormat string, route iaas.Route) error { return p.OutputResult(outputFormat, route, func() error { table := tables.NewTable() - table.AddRow("ID", utils.PtrString(route.RouteId)) + table.AddRow("ID", utils.PtrString(route.Id)) table.AddSeparator() - table.AddRow("PREFIX", utils.PtrString(route.Prefix)) - table.AddSeparator() - table.AddRow("NEXTHOP", utils.PtrString(route.Nexthop)) + if destination := route.Destination; destination != nil { + if destination.DestinationCIDRv4 != nil { + table.AddRow("DESTINATION TYPE", utils.PtrString(destination.DestinationCIDRv4.Type)) + table.AddSeparator() + table.AddRow("DESTINATION", utils.PtrString(destination.DestinationCIDRv4.Value)) + table.AddSeparator() + } else if destination.DestinationCIDRv6 != nil { + table.AddRow("DESTINATION TYPE", utils.PtrString(destination.DestinationCIDRv6.Type)) + table.AddSeparator() + table.AddRow("DESTINATION", utils.PtrString(destination.DestinationCIDRv6.Value)) + table.AddSeparator() + } + } + if nexthop := route.Nexthop; nexthop != nil { + if nexthop.NexthopIPv4 != nil { + table.AddRow("NEXTHOP", utils.PtrString(nexthop.NexthopIPv4.Value)) + table.AddSeparator() + table.AddRow("NEXTHOP TYPE", utils.PtrString(nexthop.NexthopIPv4.Type)) + table.AddSeparator() + } else if nexthop.NexthopIPv6 != nil { + table.AddRow("NEXTHOP", utils.PtrString(nexthop.NexthopIPv6.Value)) + table.AddSeparator() + table.AddRow("NEXTHOP TYPE", utils.PtrString(nexthop.NexthopIPv6.Type)) + table.AddSeparator() + } else if nexthop.NexthopBlackhole != nil { + table.AddRow("NEXTHOP TYPE", utils.PtrString(nexthop.NexthopBlackhole.Type)) + table.AddSeparator() + } else if nexthop.NexthopInternet != nil { + table.AddRow("NEXTHOP TYPE", utils.PtrString(nexthop.NexthopInternet.Type)) + table.AddSeparator() + } + } if route.Labels != nil && len(*route.Labels) > 0 { labels := []string{} for key, value := range *route.Labels { diff --git a/internal/cmd/network-area/route/describe/describe_test.go b/internal/cmd/network-area/route/describe/describe_test.go index 0c674de81..67345ccae 100644 --- a/internal/cmd/network-area/route/describe/describe_test.go +++ b/internal/cmd/network-area/route/describe/describe_test.go @@ -15,6 +15,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,6 +40,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrgId, networkAreaIdFlag: testNetworkAreaId, } @@ -49,6 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, OrganizationId: utils.Ptr(testOrgId), NetworkAreaId: utils.Ptr(testNetworkAreaId), @@ -61,7 +68,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetNetworkAreaRouteRequest)) iaas.ApiGetNetworkAreaRouteRequest { - request := testClient.GetNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRouteId) + request := testClient.GetNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRegion, testRouteId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go index 2af24763a..9ea4f6159 100644 --- a/internal/cmd/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -127,19 +127,45 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworkAreaRoutesRequest { - return apiClient.ListNetworkAreaRoutes(ctx, *model.OrganizationId, *model.NetworkAreaId) + return apiClient.ListNetworkAreaRoutes(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region) } func outputResult(p *print.Printer, outputFormat string, routes []iaas.Route) error { return p.OutputResult(outputFormat, routes, func() error { table := tables.NewTable() - table.SetHeader("Static Route ID", "Next Hop", "Prefix") + table.SetHeader("Static Route ID", "Next Hop", "Next Hop Type", "Destination") for _, route := range routes { + var nextHop string + var nextHopType string + var destination string + if routeDest := route.Destination; routeDest != nil { + if routeDest.DestinationCIDRv4 != nil { + destination = *routeDest.DestinationCIDRv4.Value + } + if routeDest.DestinationCIDRv6 != nil { + destination = *routeDest.DestinationCIDRv6.Value + } + } + if routeNexthop := route.Nexthop; routeNexthop != nil { + if routeNexthop.NexthopIPv4 != nil { + nextHop = *routeNexthop.NexthopIPv4.Value + nextHopType = *routeNexthop.NexthopIPv4.Type + } else if routeNexthop.NexthopIPv6 != nil { + nextHop = *routeNexthop.NexthopIPv6.Value + nextHopType = *routeNexthop.NexthopIPv6.Type + } else if routeNexthop.NexthopBlackhole != nil { + nextHopType = *routeNexthop.NexthopBlackhole.Type + } else if routeNexthop.NexthopInternet != nil { + nextHopType = *routeNexthop.NexthopInternet.Type + } + } + table.AddRow( - utils.PtrString(route.RouteId), - utils.PtrString(route.Nexthop), - utils.PtrString(route.Prefix), + utils.PtrString(route.Id), + nextHop, + nextHopType, + destination, ) } diff --git a/internal/cmd/network-area/route/list/list_test.go b/internal/cmd/network-area/route/list/list_test.go index 8681aa87d..365249370 100644 --- a/internal/cmd/network-area/route/list/list_test.go +++ b/internal/cmd/network-area/route/list/list_test.go @@ -16,6 +16,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -25,6 +29,8 @@ var testNetworkAreaId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrganizationId, networkAreaIdFlag: testNetworkAreaId, limitFlag: "10", @@ -39,6 +45,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, OrganizationId: &testOrganizationId, NetworkAreaId: &testNetworkAreaId, @@ -51,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListNetworkAreaRoutesRequest)) iaas.ApiListNetworkAreaRoutesRequest { - request := testClient.ListNetworkAreaRoutes(testCtx, testOrganizationId, testNetworkAreaId) + request := testClient.ListNetworkAreaRoutes(testCtx, testOrganizationId, testNetworkAreaId, testRegion) for _, mod := range mods { mod(&request) } @@ -204,6 +211,24 @@ func TestOutputResult(t *testing.T) { }, wantErr: false, }, + { + name: "empty destination in route", + args: args{ + routes: []iaas.Route{{ + Destination: &iaas.RouteDestination{}, + }}, + }, + wantErr: false, + }, + { + name: "empty nexthop in route", + args: args{ + routes: []iaas.Route{{ + Nexthop: &iaas.RouteNexthop{}, + }}, + }, + wantErr: false, + }, } p := print.NewPrinter() p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) diff --git a/internal/cmd/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go index 23e6391ff..92ca244a9 100644 --- a/internal/cmd/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -116,7 +116,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNetworkAreaRouteRequest { - req := apiClient.UpdateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.RouteId) + req := apiClient.UpdateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.Region, model.RouteId) payload := iaas.UpdateNetworkAreaRoutePayload{ Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), @@ -128,7 +128,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli func outputResult(p *print.Printer, outputFormat, networkAreaLabel string, route iaas.Route) error { return p.OutputResult(outputFormat, route, func() error { - p.Outputf("Updated static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, utils.PtrString(route.RouteId)) + p.Outputf("Updated static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, utils.PtrString(route.Id)) return nil }) } diff --git a/internal/cmd/network-area/route/update/update_test.go b/internal/cmd/network-area/route/update/update_test.go index 03bdf6da2..da6c6e03a 100644 --- a/internal/cmd/network-area/route/update/update_test.go +++ b/internal/cmd/network-area/route/update/update_test.go @@ -14,6 +14,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -35,6 +39,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.RegionFlag: testRegion, + organizationIdFlag: testOrgId, networkAreaIdFlag: testNetworkAreaId, labelFlag: "value=key", @@ -74,6 +80,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, OrganizationId: utils.Ptr(testOrgId), NetworkAreaId: utils.Ptr(testNetworkAreaId), @@ -87,7 +94,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdateNetworkAreaRouteRequest)) iaas.ApiUpdateNetworkAreaRouteRequest { - request := testClient.UpdateNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRouteId) + request := testClient.UpdateNetworkAreaRoute(testCtx, testOrgId, testNetworkAreaId, testRegion, testRouteId) request = request.UpdateNetworkAreaRoutePayload(fixturePayload()) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/network-area/update/update.go b/internal/cmd/network-area/update/update.go index 855da9f10..20f426d89 100644 --- a/internal/cmd/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -3,8 +3,8 @@ package update import ( "context" "fmt" - - rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" + "os" + "strings" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -13,6 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" + rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" rmUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -23,26 +24,43 @@ import ( const ( areaIdArg = "AREA_ID" - nameFlag = "name" - organizationIdFlag = "organization-id" - areaIdFlag = "area-id" - dnsNameServersFlag = "dns-name-servers" + nameFlag = "name" + organizationIdFlag = "organization-id" + areaIdFlag = "area-id" + // Deprecated: dnsNameServersFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + dnsNameServersFlag = "dns-name-servers" + // Deprecated: defaultPrefixLengthFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. defaultPrefixLengthFlag = "default-prefix-length" - maxPrefixLengthFlag = "max-prefix-length" - minPrefixLengthFlag = "min-prefix-length" - labelFlag = "labels" + // Deprecated: maxPrefixLengthFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + maxPrefixLengthFlag = "max-prefix-length" + // Deprecated: minPrefixLengthFlag is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + minPrefixLengthFlag = "min-prefix-length" + labelFlag = "labels" + + deprecationMessage = "Deprecated and will be removed after April 2026. Use instead the new command `$ stackit network-area region` to configure these options for a network area." ) +// NetworkAreaResponses is a workaround, to keep the two responses of the iaas v2 api together for the json and yaml output +// Should be removed when the deprecated flags are removed +type NetworkAreaResponses struct { + NetworkArea iaas.NetworkArea `json:"network_area"` + RegionalArea *iaas.RegionalArea `json:"regional_area"` +} + type inputModel struct { *globalflags.GlobalFlagModel - AreaId string - Name *string - OrganizationId *string - DnsNameServers *[]string + AreaId string + Name *string + OrganizationId *string + // Deprecated: DnsNameServers is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + DnsNameServers *[]string + // Deprecated: DefaultPrefixLength is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. DefaultPrefixLength *int64 - MaxPrefixLength *int64 - MinPrefixLength *int64 - Labels *map[string]string + // Deprecated: MaxPrefixLength is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + MaxPrefixLength *int64 + // Deprecated: MinPrefixLength is deprecated, because with iaas v2 the create endpoint for network area was separated, remove this after April 2026. + MinPrefixLength *int64 + Labels *map[string]string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -99,7 +117,26 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("update network area: %w", err) } - return outputResult(params.Printer, model.OutputFormat, orgLabel, *resp) + if resp == nil || resp.Id == nil { + return fmt.Errorf("update network area: empty response") + } + + responses := NetworkAreaResponses{ + NetworkArea: *resp, + } + + if hasDeprecatedFlagsSet(model) { + deprecatedFlags := getConfiguredDeprecatedFlags(model) + params.Printer.Warn("the flags %q are deprecated and will be removed after April 2026. Use `$ stackit network-area region` to configure these options for a network area.\n", strings.Join(deprecatedFlags, ",")) + reqNetworkArea := buildRequestNetworkAreaRegion(ctx, model, apiClient) + respNetworkArea, err := reqNetworkArea.Execute() + if err != nil { + return fmt.Errorf("create network area region: %w", err) + } + responses.RegionalArea = respNetworkArea + } + + return outputResult(params.Printer, model.OutputFormat, orgLabel, responses) }, } configureFlags(cmd) @@ -115,6 +152,13 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Int64(minPrefixLengthFlag, 0, "The minimum prefix length for networks in the network area") cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network-area. E.g. '--labels key1=value1,key2=value2,...'") + cobra.CheckErr(cmd.Flags().MarkDeprecated(dnsNameServersFlag, deprecationMessage)) + cobra.CheckErr(cmd.Flags().MarkDeprecated(defaultPrefixLengthFlag, deprecationMessage)) + cobra.CheckErr(cmd.Flags().MarkDeprecated(maxPrefixLengthFlag, deprecationMessage)) + cobra.CheckErr(cmd.Flags().MarkDeprecated(minPrefixLengthFlag, deprecationMessage)) + // Set the output for deprecation warnings to stderr + cmd.Flags().SetOutput(os.Stderr) + err := flags.MarkFlagsRequired(cmd, organizationIdFlag) cobra.CheckErr(err) } @@ -140,27 +184,67 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } +func hasDeprecatedFlagsSet(model *inputModel) bool { + deprecatedFlags := getConfiguredDeprecatedFlags(model) + return len(deprecatedFlags) > 0 +} + +func getConfiguredDeprecatedFlags(model *inputModel) []string { + var result []string + if model.DnsNameServers != nil { + result = append(result, dnsNameServersFlag) + } + if model.DefaultPrefixLength != nil { + result = append(result, defaultPrefixLengthFlag) + } + if model.MaxPrefixLength != nil { + result = append(result, maxPrefixLengthFlag) + } + if model.MinPrefixLength != nil { + result = append(result, minPrefixLengthFlag) + } + return result +} + func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiPartialUpdateNetworkAreaRequest { req := apiClient.PartialUpdateNetworkArea(ctx, *model.OrganizationId, model.AreaId) payload := iaas.PartialUpdateNetworkAreaPayload{ Name: model.Name, Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), - AddressFamily: &iaas.UpdateAreaAddressFamily{ - Ipv4: &iaas.UpdateAreaIPv4{ - DefaultNameservers: model.DnsNameServers, - DefaultPrefixLen: model.DefaultPrefixLength, - MaxPrefixLen: model.MaxPrefixLength, - MinPrefixLen: model.MinPrefixLength, - }, - }, } return req.PartialUpdateNetworkAreaPayload(payload) } -func outputResult(p *print.Printer, outputFormat, projectLabel string, networkArea iaas.NetworkArea) error { - return p.OutputResult(outputFormat, networkArea, func() error { +func buildRequestNetworkAreaRegion(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNetworkAreaRegionRequest { + req := apiClient.UpdateNetworkAreaRegion(ctx, *model.OrganizationId, model.AreaId, model.Region) + + payload := iaas.UpdateNetworkAreaRegionPayload{ + Ipv4: &iaas.UpdateRegionalAreaIPv4{ + DefaultNameservers: model.DnsNameServers, + DefaultPrefixLen: model.DefaultPrefixLength, + MaxPrefixLen: model.MaxPrefixLength, + MinPrefixLen: model.MinPrefixLength, + }, + } + + return req.UpdateNetworkAreaRegionPayload(payload) +} + +func outputResult(p *print.Printer, outputFormat, projectLabel string, responses NetworkAreaResponses) error { + prettyOutputFunc := func() error { + p.Outputf("Updated STACKIT Network Area for project %q.\n", projectLabel) + return nil + } + + // If RegionalArea is NOT set in the reponses, then no deprecated Flags were set. + // In this case, only the response of NetworkArea should be printed in JSON and yaml output, to avoid breaking changes after the deprecated fields are removed + if responses.RegionalArea == nil { + return p.OutputResult(outputFormat, responses.NetworkArea, prettyOutputFunc) + } + + return p.OutputResult(outputFormat, responses, func() error { p.Outputf("Updated STACKIT Network Area for project %q.\n", projectLabel) return nil }) diff --git a/internal/cmd/network-area/update/update_test.go b/internal/cmd/network-area/update/update_test.go index f25018286..b46b66aab 100644 --- a/internal/cmd/network-area/update/update_test.go +++ b/internal/cmd/network-area/update/update_test.go @@ -2,6 +2,8 @@ package update import ( "context" + "strconv" + "strings" "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -15,13 +17,25 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" + testName = "example-network-area-name" + testDefaultPrefixLength int64 = 25 + testMinPrefixLength int64 = 24 + testMaxPrefixLength int64 = 26 +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &iaas.APIClient{} -var testOrgId = uuid.NewString() -var testAreaId = uuid.NewString() +var ( + testOrgId = uuid.NewString() + testAreaId = uuid.NewString() + + testDnsNameservers = []string{"1.1.1.0", "1.1.2.0"} +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -35,13 +49,11 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - nameFlag: "example-network-area-name", - organizationIdFlag: testOrgId, - dnsNameServersFlag: "1.1.1.0,1.1.2.0", - defaultPrefixLengthFlag: "24", - maxPrefixLengthFlag: "24", - minPrefixLengthFlag: "24", - labelFlag: "key=value", + globalflags.RegionFlag: testRegion, + + nameFlag: testName, + organizationIdFlag: testOrgId, + labelFlag: "key=value", } for _, mod := range mods { mod(flagValues) @@ -53,14 +65,11 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, - Name: utils.Ptr("example-network-area-name"), - OrganizationId: utils.Ptr(testOrgId), - AreaId: testAreaId, - DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), - DefaultPrefixLength: utils.Ptr(int64(24)), - MaxPrefixLength: utils.Ptr(int64(24)), - MinPrefixLength: utils.Ptr(int64(24)), + Name: utils.Ptr(testName), + OrganizationId: utils.Ptr(testOrgId), + AreaId: testAreaId, Labels: utils.Ptr(map[string]string{ "key": "value", }), @@ -82,17 +91,33 @@ func fixtureRequest(mods ...func(request *iaas.ApiPartialUpdateNetworkAreaReques func fixturePayload(mods ...func(payload *iaas.PartialUpdateNetworkAreaPayload)) iaas.PartialUpdateNetworkAreaPayload { payload := iaas.PartialUpdateNetworkAreaPayload{ - Name: utils.Ptr("example-network-area-name"), + Name: utils.Ptr(testName), Labels: utils.Ptr(map[string]interface{}{ "key": "value", }), - AddressFamily: &iaas.UpdateAreaAddressFamily{ - Ipv4: &iaas.UpdateAreaIPv4{ - DefaultNameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), - DefaultPrefixLen: utils.Ptr(int64(24)), - MaxPrefixLen: utils.Ptr(int64(24)), - MinPrefixLen: utils.Ptr(int64(24)), - }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixtureRequestRegionalArea(mods ...func(request *iaas.ApiUpdateNetworkAreaRegionRequest)) iaas.ApiUpdateNetworkAreaRegionRequest { + request := testClient.UpdateNetworkAreaRegion(testCtx, testOrgId, testAreaId, testRegion) + request = request.UpdateNetworkAreaRegionPayload(fixturePayloadRegionalArea()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayloadRegionalArea(mods ...func(payload *iaas.UpdateNetworkAreaRegionPayload)) iaas.UpdateNetworkAreaRegionPayload { + payload := iaas.UpdateNetworkAreaRegionPayload{ + Ipv4: &iaas.UpdateRegionalAreaIPv4{ + DefaultNameservers: utils.Ptr(testDnsNameservers), + DefaultPrefixLen: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLen: utils.Ptr(testMaxPrefixLength), + MinPrefixLen: utils.Ptr(testMinPrefixLength), }, } for _, mod := range mods { @@ -118,20 +143,20 @@ func TestParseInput(t *testing.T) { expectedModel: fixtureInputModel(), }, { - description: "required only", + description: "with deprecated flags", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, dnsNameServersFlag) - delete(flagValues, defaultPrefixLengthFlag) - delete(flagValues, maxPrefixLengthFlag) - delete(flagValues, minPrefixLengthFlag) + flagValues[dnsNameServersFlag] = strings.Join(testDnsNameservers, ",") + flagValues[defaultPrefixLengthFlag] = strconv.FormatInt(testDefaultPrefixLength, 10) + flagValues[maxPrefixLengthFlag] = strconv.FormatInt(testMaxPrefixLength, 10) + flagValues[minPrefixLengthFlag] = strconv.FormatInt(testMinPrefixLength, 10) }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.DnsNameServers = nil - model.DefaultPrefixLength = nil - model.MaxPrefixLength = nil - model.MinPrefixLength = nil + model.DnsNameServers = utils.Ptr(testDnsNameservers) + model.DefaultPrefixLength = utils.Ptr(testDefaultPrefixLength) + model.MaxPrefixLength = utils.Ptr(testMaxPrefixLength) + model.MinPrefixLength = utils.Ptr(testMinPrefixLength) }), }, @@ -286,11 +311,44 @@ func TestBuildRequest(t *testing.T) { } } +func TestBuildRequestNetworkAreaRegion(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest iaas.ApiUpdateNetworkAreaRegionRequest + }{ + { + description: "base", + model: fixtureInputModel(func(model *inputModel) { + model.DnsNameServers = utils.Ptr(testDnsNameservers) + model.DefaultPrefixLength = utils.Ptr(testDefaultPrefixLength) + model.MaxPrefixLength = utils.Ptr(testMaxPrefixLength) + model.MinPrefixLength = utils.Ptr(testMinPrefixLength) + }), + expectedRequest: fixtureRequestRegionalArea(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequestNetworkAreaRegion(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) + } + }) + } +} + func TestOutputResult(t *testing.T) { type args struct { outputFormat string projectLabel string - networkArea iaas.NetworkArea + responses NetworkAreaResponses } tests := []struct { name string @@ -305,7 +363,10 @@ func TestOutputResult(t *testing.T) { { name: "empty network area", args: args{ - networkArea: iaas.NetworkArea{}, + responses: NetworkAreaResponses{ + NetworkArea: iaas.NetworkArea{}, + RegionalArea: nil, + }, }, wantErr: false, }, @@ -314,9 +375,132 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.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.networkArea); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.responses); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) } } + +func TestGetConfiguredDeprecatedFlags(t *testing.T) { + type args struct { + model *inputModel + } + tests := []struct { + name string + args args + want []string + }{ + { + name: "no deprecated flags", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: utils.Ptr(testOrgId), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + DnsNameServers: nil, + DefaultPrefixLength: nil, + MaxPrefixLength: nil, + MinPrefixLength: nil, + }, + }, + want: nil, + }, + { + name: "deprecated flags", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: utils.Ptr(testOrgId), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + DnsNameServers: utils.Ptr(testDnsNameservers), + DefaultPrefixLength: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLength: utils.Ptr(testMaxPrefixLength), + MinPrefixLength: utils.Ptr(testMinPrefixLength), + }, + }, + want: []string{dnsNameServersFlag, defaultPrefixLengthFlag, minPrefixLengthFlag, maxPrefixLengthFlag}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := getConfiguredDeprecatedFlags(tt.args.model) + + less := func(a, b string) bool { + return a < b + } + if diff := cmp.Diff(tt.want, got, cmpopts.SortSlices(less)); diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestHasDeprecatedFlagsSet(t *testing.T) { + type args struct { + model *inputModel + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "no deprecated flags", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: utils.Ptr(testOrgId), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + DnsNameServers: nil, + DefaultPrefixLength: nil, + MaxPrefixLength: nil, + MinPrefixLength: nil, + }, + }, + want: false, + }, + { + name: "deprecated flags", + args: args{ + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + }, + Name: utils.Ptr(testName), + OrganizationId: utils.Ptr(testOrgId), + Labels: utils.Ptr(map[string]string{ + "key": "value", + }), + DnsNameServers: utils.Ptr(testDnsNameservers), + DefaultPrefixLength: utils.Ptr(testDefaultPrefixLength), + MaxPrefixLength: utils.Ptr(testMaxPrefixLength), + MinPrefixLength: utils.Ptr(testMinPrefixLength), + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := hasDeprecatedFlagsSet(tt.args.model); got != tt.want { + t.Errorf("hasDeprecatedFlagsSet() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index 1fc368ffa..ad945e81d 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -38,7 +38,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - NetworkId *string + NetworkId string AllowedAddresses *[]iaas.AllowedAddressesInner Ipv4 *string Ipv6 *string @@ -177,7 +177,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, model := inputModel{ GlobalFlagModel: globalFlags, - NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NetworkId: flags.FlagToStringValue(p, cmd, networkIdFlag), Ipv4: flags.FlagToStringPointer(p, cmd, ipv4Flag), Ipv6: flags.FlagToStringPointer(p, cmd, ipv6Flag), Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), @@ -195,7 +195,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNicRequest { - req := apiClient.CreateNic(ctx, model.ProjectId, *model.NetworkId) + req := apiClient.CreateNic(ctx, model.ProjectId, model.Region, model.NetworkId) payload := iaas.CreateNicPayload{ AllowedAddresses: model.AllowedAddresses, diff --git a/internal/cmd/network-interface/create/create_test.go b/internal/cmd/network-interface/create/create_test.go index 82e5b628a..fd584b84e 100644 --- a/internal/cmd/network-interface/create/create_test.go +++ b/internal/cmd/network-interface/create/create_test.go @@ -15,19 +15,24 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &iaas.APIClient{} -var projectIdFlag = globalflags.ProjectIdFlag var testProjectId = uuid.NewString() var testNetworkId = uuid.NewString() var testSecurityGroup = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + networkIdFlag: testNetworkId, allowedAddressesFlag: "1.1.1.1,8.8.8.8,9.9.9.9", ipv4Flag: "1.2.3.4", @@ -52,9 +57,10 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, - NetworkId: utils.Ptr(testNetworkId), + NetworkId: testNetworkId, AllowedAddresses: utils.Ptr(allowedAddresses), Ipv4: utils.Ptr("1.2.3.4"), Ipv6: utils.Ptr("2001:0db8:85a3:08d3::0370:7344"), @@ -72,7 +78,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateNicRequest)) iaas.ApiCreateNicRequest { - request := testClient.CreateNic(testCtx, testProjectId, testNetworkId) + request := testClient.CreateNic(testCtx, testProjectId, testRegion, testNetworkId) request = request.CreateNicPayload(fixturePayload()) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/network-interface/delete/delete.go b/internal/cmd/network-interface/delete/delete.go index 043e41217..c5d9d61e0 100644 --- a/internal/cmd/network-interface/delete/delete.go +++ b/internal/cmd/network-interface/delete/delete.go @@ -24,7 +24,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - NetworkId *string + NetworkId string NicId string } @@ -90,7 +90,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NetworkId: flags.FlagToStringValue(p, cmd, networkIdFlag), NicId: nicId, } @@ -99,6 +99,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNicRequest { - req := apiClient.DeleteNic(ctx, model.ProjectId, *model.NetworkId, model.NicId) + req := apiClient.DeleteNic(ctx, model.ProjectId, model.Region, model.NetworkId, model.NicId) return req } diff --git a/internal/cmd/network-interface/delete/delete_test.go b/internal/cmd/network-interface/delete/delete_test.go index ac03d45f6..c0170eab1 100644 --- a/internal/cmd/network-interface/delete/delete_test.go +++ b/internal/cmd/network-interface/delete/delete_test.go @@ -10,16 +10,18 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &iaas.APIClient{} -var projectIdFlag = globalflags.ProjectIdFlag var testProjectId = uuid.NewString() var testNetworkId = uuid.NewString() var testNicId = uuid.NewString() @@ -36,8 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - networkIdFlag: testNetworkId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + networkIdFlag: testNetworkId, } for _, mod := range mods { mod(flagValues) @@ -50,8 +53,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, - NetworkId: utils.Ptr(testNetworkId), + NetworkId: testNetworkId, NicId: testNicId, } for _, mod := range mods { @@ -61,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteNicRequest)) iaas.ApiDeleteNicRequest { - request := testClient.DeleteNic(testCtx, testProjectId, testNetworkId, testNicId) + request := testClient.DeleteNic(testCtx, testProjectId, testRegion, testNetworkId, testNicId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/network-interface/describe/describe.go b/internal/cmd/network-interface/describe/describe.go index 4c1fc6d7d..128c333fa 100644 --- a/internal/cmd/network-interface/describe/describe.go +++ b/internal/cmd/network-interface/describe/describe.go @@ -27,7 +27,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - NetworkId *string + NetworkId string NicId string } @@ -94,7 +94,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NetworkId: flags.FlagToStringValue(p, cmd, networkIdFlag), NicId: nicId, } @@ -103,7 +103,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNicRequest { - req := apiClient.GetNic(ctx, model.ProjectId, *model.NetworkId, model.NicId) + req := apiClient.GetNic(ctx, model.ProjectId, model.Region, model.NetworkId, model.NicId) return req } diff --git a/internal/cmd/network-interface/describe/describe_test.go b/internal/cmd/network-interface/describe/describe_test.go index 24163ac87..2f802bf0e 100644 --- a/internal/cmd/network-interface/describe/describe_test.go +++ b/internal/cmd/network-interface/describe/describe_test.go @@ -10,16 +10,18 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &iaas.APIClient{} -var projectIdFlag = globalflags.ProjectIdFlag var testProjectId = uuid.NewString() var testNetworkId = uuid.NewString() var testNicId = uuid.NewString() @@ -36,8 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - networkIdFlag: testNetworkId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + networkIdFlag: testNetworkId, } for _, mod := range mods { mod(flagValues) @@ -50,8 +53,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, - NetworkId: utils.Ptr(testNetworkId), + NetworkId: testNetworkId, NicId: testNicId, } for _, mod := range mods { @@ -61,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetNicRequest)) iaas.ApiGetNicRequest { - request := testClient.GetNic(testCtx, testProjectId, testNetworkId, testNicId) + request := testClient.GetNic(testCtx, testProjectId, testRegion, testNetworkId, testNicId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go index cd683883a..23fe3aa4d 100644 --- a/internal/cmd/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -29,7 +29,7 @@ type inputModel struct { *globalflags.GlobalFlagModel Limit *int64 LabelSelector *string - NetworkId *string + NetworkId string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -77,12 +77,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) - networkLabel = *model.NetworkId + networkLabel = model.NetworkId } else if networkLabel == "" { - networkLabel = *model.NetworkId + networkLabel = model.NetworkId } params.Printer.Info("No network interfaces found for network %q\n", networkLabel) return nil @@ -128,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, GlobalFlagModel: globalFlags, Limit: limit, LabelSelector: flags.FlagToStringPointer(p, cmd, labelSelectorFlag), - NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NetworkId: flags.FlagToStringValue(p, cmd, networkIdFlag), } p.DebugInputModel(model) @@ -136,7 +136,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNicsRequest { - req := apiClient.ListNics(ctx, model.ProjectId, *model.NetworkId) + req := apiClient.ListNics(ctx, model.ProjectId, model.Region, model.NetworkId) if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) } diff --git a/internal/cmd/network-interface/list/list_test.go b/internal/cmd/network-interface/list/list_test.go index 68df78a25..56eb5435d 100644 --- a/internal/cmd/network-interface/list/list_test.go +++ b/internal/cmd/network-interface/list/list_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -28,7 +30,9 @@ var testLabelSelector = "label" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + networkIdFlag: testNetworkId, limitFlag: "10", labelSelectorFlag: testLabelSelector, @@ -44,10 +48,11 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), LabelSelector: utils.Ptr(testLabelSelector), - NetworkId: utils.Ptr(testNetworkId), + NetworkId: testNetworkId, } for _, mod := range mods { mod(model) @@ -56,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListNicsRequest)) iaas.ApiListNicsRequest { - request := testClient.ListNics(testCtx, testProjectId, testNetworkId) + request := testClient.ListNics(testCtx, testProjectId, testRegion, testNetworkId) request = request.LabelSelector(testLabelSelector) for _, mod := range mods { mod(&request) @@ -91,21 +96,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go index 190946bd7..3b1902bb4 100644 --- a/internal/cmd/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -38,7 +38,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel NicId string - NetworkId *string + NetworkId string AllowedAddresses *[]iaas.AllowedAddressesInner Labels *map[string]string Name *string // <= 63 characters + regex ^[A-Za-z0-9]+((-|_|\s|\.)[A-Za-z0-9]+)*$ @@ -171,7 +171,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, NicId: nicId, - NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag), + NetworkId: flags.FlagToStringValue(p, cmd, networkIdFlag), Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), Name: name, NicSecurity: flags.FlagToBoolPointer(p, cmd, nicSecurityFlag), @@ -187,7 +187,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNicRequest { - req := apiClient.UpdateNic(ctx, model.ProjectId, *model.NetworkId, model.NicId) + req := apiClient.UpdateNic(ctx, model.ProjectId, model.Region, model.NetworkId, model.NicId) payload := iaas.UpdateNicPayload{ AllowedAddresses: model.AllowedAddresses, diff --git a/internal/cmd/network-interface/update/update_test.go b/internal/cmd/network-interface/update/update_test.go index 03faa73ad..3f1382dab 100644 --- a/internal/cmd/network-interface/update/update_test.go +++ b/internal/cmd/network-interface/update/update_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -38,7 +40,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + networkIdFlag: testNetworkId, allowedAddressesFlag: "1.1.1.1,8.8.8.8,9.9.9.9", labelFlag: "key=value", @@ -62,8 +66,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, - NetworkId: utils.Ptr(testNetworkId), + NetworkId: testNetworkId, AllowedAddresses: utils.Ptr(allowedAddresses), Labels: utils.Ptr(map[string]string{ "key": "value", @@ -80,7 +85,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdateNicRequest)) iaas.ApiUpdateNicRequest { - request := testClient.UpdateNic(testCtx, testProjectId, testNetworkId, testNicId) + request := testClient.UpdateNic(testCtx, testProjectId, testRegion, testNetworkId, testNicId) request = request.UpdateNicPayload(fixturePayload()) for _, mod := range mods { mod(&request) diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index acb1bc7e1..9877e4477 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -79,7 +79,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { ), examples.NewExample( `Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway`, - `$ stackit network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3"`, + `$ stackit network create --name network-1 --non-routed --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3"`, ), examples.NewExample( `Create an IPv6 network with name "network-1" with DNS name servers, a prefix and a gateway`, @@ -121,13 +121,17 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("create network : %w", err) } - networkId := *resp.NetworkId + + if resp == nil || resp.Id == nil { + return fmt.Errorf("create network : empty response") + } + networkId := *resp.Id // Wait for async operation, if async mode not enabled if !model.Async { s := spinner.New(params.Printer) s.Start("Creating network") - _, err = wait.CreateNetworkWaitHandler(ctx, apiClient, model.ProjectId, networkId).WaitWithContext(ctx) + _, err = wait.CreateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for network creation: %w", err) } @@ -156,6 +160,17 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(noIpv6GatewayFlag, false, "If set to true, the network doesn't have an IPv6 gateway") cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a network. E.g. '--labels key1=value1,key2=value2,...'") + // IPv4 checks + cmd.MarkFlagsMutuallyExclusive(ipv4PrefixFlag, ipv4PrefixLengthFlag) + cmd.MarkFlagsMutuallyExclusive(ipv4GatewayFlag, ipv4PrefixLengthFlag) + cmd.MarkFlagsMutuallyExclusive(ipv4GatewayFlag, noIpv4GatewayFlag) + cmd.MarkFlagsMutuallyExclusive(noIpv4GatewayFlag, ipv4PrefixLengthFlag) + + // IPv6 checks + cmd.MarkFlagsMutuallyExclusive(ipv6PrefixFlag, ipv6PrefixLengthFlag) + cmd.MarkFlagsMutuallyExclusive(ipv6GatewayFlag, ipv6PrefixLengthFlag) + cmd.MarkFlagsMutuallyExclusive(ipv6GatewayFlag, noIpv6GatewayFlag) + err := flags.MarkFlagsRequired(cmd, nameFlag) cobra.CheckErr(err) } @@ -173,6 +188,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, IPv4PrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4PrefixLengthFlag), IPv4Prefix: flags.FlagToStringPointer(p, cmd, ipv4PrefixFlag), IPv4Gateway: flags.FlagToStringPointer(p, cmd, ipv4GatewayFlag), + IPv6DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv6DnsNameServersFlag), IPv6PrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv6PrefixLengthFlag), IPv6Prefix: flags.FlagToStringPointer(p, cmd, ipv6PrefixFlag), @@ -183,39 +199,92 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), } + // IPv4 nameserver can not be set alone. IPv4 Prefix || IPv4 Prefix length must be set as well + isIPv4NameserverSet := model.IPv4DnsNameServers != nil && len(*model.IPv4DnsNameServers) > 0 + isIPv4PrefixOrPrefixLengthSet := model.IPv4Prefix != nil || model.IPv4PrefixLength != nil + if isIPv4NameserverSet && !isIPv4PrefixOrPrefixLengthSet { + return nil, &cliErr.OneOfFlagsIsMissing{ + MissingFlags: []string{ipv4PrefixLengthFlag, ipv4PrefixFlag}, + SetFlag: ipv4DnsNameServersFlag, + } + } + isIPv4GatewaySet := model.IPv4Gateway != nil + isIPv4PrefixSet := model.IPv4Prefix != nil + if isIPv4GatewaySet && !isIPv4PrefixSet { + return nil, &cliErr.DependingFlagIsMissing{ + MissingFlag: ipv4PrefixFlag, + SetFlag: ipv4GatewayFlag, + } + } + + // IPv6 nameserver can not be set alone. IPv6 Prefix || IPv6 Prefix length must be set as well + isIPv6NameserverSet := model.IPv6DnsNameServers != nil && len(*model.IPv6DnsNameServers) > 0 + isIPv6PrefixOrPrefixLengthSet := model.IPv6Prefix != nil || model.IPv6PrefixLength != nil + if isIPv6NameserverSet && !isIPv6PrefixOrPrefixLengthSet { + return nil, &cliErr.OneOfFlagsIsMissing{ + MissingFlags: []string{ipv6PrefixLengthFlag, ipv6PrefixFlag}, + SetFlag: ipv6DnsNameServersFlag, + } + } + isIPv6GatewaySet := model.IPv6Gateway != nil + isIPv6PrefixSet := model.IPv6Prefix != nil + if isIPv6GatewaySet && !isIPv6PrefixSet { + return nil, &cliErr.DependingFlagIsMissing{ + MissingFlag: ipv6PrefixFlag, + SetFlag: ipv6GatewayFlag, + } + } + p.DebugInputModel(model) return &model, nil } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateNetworkRequest { - req := apiClient.CreateNetwork(ctx, model.ProjectId) - addressFamily := &iaas.CreateNetworkAddressFamily{} - - if model.IPv6DnsNameServers != nil || model.IPv6PrefixLength != nil || model.IPv6Prefix != nil || model.NoIPv6Gateway || model.IPv6Gateway != nil { - addressFamily.Ipv6 = &iaas.CreateNetworkIPv6Body{ - Nameservers: model.IPv6DnsNameServers, - PrefixLength: model.IPv6PrefixLength, - Prefix: model.IPv6Prefix, + req := apiClient.CreateNetwork(ctx, model.ProjectId, model.Region) + var ipv4Network *iaas.CreateNetworkIPv4 + var ipv6Network *iaas.CreateNetworkIPv6 + + if model.IPv6Prefix != nil { + ipv6Network = &iaas.CreateNetworkIPv6{ + CreateNetworkIPv6WithPrefix: &iaas.CreateNetworkIPv6WithPrefix{ + Prefix: model.IPv6Prefix, + Nameservers: model.IPv6DnsNameServers, + }, } if model.NoIPv6Gateway { - addressFamily.Ipv6.Gateway = iaas.NewNullableString(nil) + ipv6Network.CreateNetworkIPv6WithPrefix.Gateway = iaas.NewNullableString(nil) } else if model.IPv6Gateway != nil { - addressFamily.Ipv6.Gateway = iaas.NewNullableString(model.IPv6Gateway) + ipv6Network.CreateNetworkIPv6WithPrefix.Gateway = iaas.NewNullableString(model.IPv6Gateway) + } + } else if model.IPv6PrefixLength != nil { + ipv6Network = &iaas.CreateNetworkIPv6{ + CreateNetworkIPv6WithPrefixLength: &iaas.CreateNetworkIPv6WithPrefixLength{ + PrefixLength: model.IPv6PrefixLength, + Nameservers: model.IPv6DnsNameServers, + }, } } - if model.IPv4DnsNameServers != nil || model.IPv4PrefixLength != nil || model.IPv4Prefix != nil || model.NoIPv4Gateway || model.IPv4Gateway != nil { - addressFamily.Ipv4 = &iaas.CreateNetworkIPv4Body{ - Nameservers: model.IPv4DnsNameServers, - PrefixLength: model.IPv4PrefixLength, - Prefix: model.IPv4Prefix, + if model.IPv4Prefix != nil { + ipv4Network = &iaas.CreateNetworkIPv4{ + CreateNetworkIPv4WithPrefix: &iaas.CreateNetworkIPv4WithPrefix{ + Prefix: model.IPv4Prefix, + Nameservers: model.IPv4DnsNameServers, + }, } if model.NoIPv4Gateway { - addressFamily.Ipv4.Gateway = iaas.NewNullableString(nil) + ipv4Network.CreateNetworkIPv4WithPrefix.Gateway = iaas.NewNullableString(nil) } else if model.IPv4Gateway != nil { - addressFamily.Ipv4.Gateway = iaas.NewNullableString(model.IPv4Gateway) + ipv4Network.CreateNetworkIPv4WithPrefix.Gateway = iaas.NewNullableString(model.IPv4Gateway) + } + } else if model.IPv4PrefixLength != nil { + ipv4Network = &iaas.CreateNetworkIPv4{ + CreateNetworkIPv4WithPrefixLength: &iaas.CreateNetworkIPv4WithPrefixLength{ + PrefixLength: model.IPv4PrefixLength, + Nameservers: model.IPv4DnsNameServers, + }, } } @@ -228,10 +297,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli Name: model.Name, Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), Routed: &routed, - } - - if addressFamily.Ipv4 != nil || addressFamily.Ipv6 != nil { - payload.AddressFamily = addressFamily + Ipv4: ipv4Network, + Ipv6: ipv6Network, } return req.CreateNetworkPayload(payload) @@ -246,7 +313,7 @@ func outputResult(p *print.Printer, outputFormat string, async bool, projectLabe if async { operationState = "Triggered creation of" } - p.Outputf("%s network for project %q.\nNetwork ID: %s\n", operationState, projectLabel, utils.PtrString(network.NetworkId)) + p.Outputf("%s network for project %q.\nNetwork ID: %s\n", operationState, projectLabel, utils.PtrString(network.Id)) return nil }) } diff --git a/internal/cmd/network/create/create_test.go b/internal/cmd/network/create/create_test.go index 6fd5c6a9a..a73f7d07a 100644 --- a/internal/cmd/network/create/create_test.go +++ b/internal/cmd/network/create/create_test.go @@ -2,6 +2,8 @@ package create import ( "context" + "strconv" + "strings" "testing" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -16,30 +18,71 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" -type testCtxKey struct{} + testNetworkName = "example-network-name" + testIPv4PrefixLength int64 = 24 + testIPv4Prefix = "10.1.2.0/24" + testIPv4Gateway = "10.1.2.3" + testIPv6PrefixLength int64 = 24 + testIPv6Prefix = "2001:4860:4860::/64" + testIPv6Gateway = "2001:db8:0:8d3:0:8a2e:70:1" + testNonRouted = false +) + +var ( + testIPv4NameServers = []string{"1.1.1.0", "1.1.2.0"} + testIPv6NameServers = []string{"2001:4860:4860::8888", "2001:4860:4860::8844"} +) -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &iaas.APIClient{} +type testCtxKey struct{} -var testProjectId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &iaas.APIClient{} + testProjectId = uuid.NewString() +) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - nameFlag: "example-network-name", - ipv4DnsNameServersFlag: "1.1.1.0,1.1.2.0", - ipv4PrefixLengthFlag: "24", - ipv4PrefixFlag: "10.1.2.0/24", - ipv4GatewayFlag: "10.1.2.3", - ipv6DnsNameServersFlag: "2001:4860:4860::8888,2001:4860:4860::8844", - ipv6PrefixLengthFlag: "24", - ipv6PrefixFlag: "2001:4860:4860::8888", - ipv6GatewayFlag: "2001:4860:4860::8888", - nonRoutedFlag: "false", - labelFlag: "key=value", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + nameFlag: testNetworkName, + nonRoutedFlag: strconv.FormatBool(testNonRouted), + labelFlag: "key=value", + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureFlagValuesWithPrefix(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4DnsNameServersFlag] = strings.Join(testIPv4NameServers, ",") + flagValues[ipv4PrefixFlag] = testIPv4Prefix + flagValues[ipv4GatewayFlag] = testIPv4Gateway + + flagValues[ipv6DnsNameServersFlag] = strings.Join(testIPv6NameServers, ",") + flagValues[ipv6PrefixFlag] = testIPv6Prefix + flagValues[ipv6GatewayFlag] = testIPv6Gateway + }) + for _, mod := range mods { + mod(flagValues) } + return flagValues +} + +func fixtureFlagValuesWithPrefixLength(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4PrefixLengthFlag] = strconv.FormatInt(testIPv4PrefixLength, 10) + flagValues[ipv4DnsNameServersFlag] = strings.Join(testIPv4NameServers, ",") + + flagValues[ipv6PrefixLengthFlag] = strconv.FormatInt(testIPv6PrefixLength, 10) + flagValues[ipv6DnsNameServersFlag] = strings.Join(testIPv6NameServers, ",") + }) for _, mod := range mods { mod(flagValues) } @@ -51,17 +94,10 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, - Name: utils.Ptr("example-network-name"), - IPv4DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), - IPv4PrefixLength: utils.Ptr(int64(24)), - IPv4Prefix: utils.Ptr("10.1.2.0/24"), - IPv4Gateway: utils.Ptr("10.1.2.3"), - IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), - IPv6PrefixLength: utils.Ptr(int64(24)), - IPv6Prefix: utils.Ptr("2001:4860:4860::8888"), - IPv6Gateway: utils.Ptr("2001:4860:4860::8888"), - NonRouted: false, + Name: utils.Ptr(testNetworkName), + NonRouted: testNonRouted, Labels: utils.Ptr(map[string]string{ "key": "value", }), @@ -72,8 +108,40 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } +func fixtureInputModelWithPrefix(mods ...func(model *inputModel)) *inputModel { + model := fixtureInputModel() + + model.IPv4DnsNameServers = utils.Ptr(testIPv4NameServers) + model.IPv4Prefix = utils.Ptr(testIPv4Prefix) + model.IPv4Gateway = utils.Ptr(testIPv4Gateway) + + model.IPv6DnsNameServers = utils.Ptr(testIPv6NameServers) + model.IPv6Prefix = utils.Ptr(testIPv6Prefix) + model.IPv6Gateway = utils.Ptr(testIPv6Gateway) + + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureInputModelWithPrefixLength(mods ...func(model *inputModel)) *inputModel { + model := fixtureInputModel() + + model.IPv4DnsNameServers = utils.Ptr(testIPv4NameServers) + model.IPv4PrefixLength = utils.Ptr(testIPv4PrefixLength) + + model.IPv6DnsNameServers = utils.Ptr(testIPv6NameServers) + model.IPv6PrefixLength = utils.Ptr(testIPv6PrefixLength) + + for _, mod := range mods { + mod(model) + } + return model +} + func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.ApiCreateNetworkRequest { - request := testClient.CreateNetwork(testCtx, testProjectId) + request := testClient.CreateNetwork(testCtx, testProjectId, testRegion) request = request.CreateNetworkPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -82,9 +150,9 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.Ap } func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.ApiCreateNetworkRequest { - request := testClient.CreateNetwork(testCtx, testProjectId) + request := testClient.CreateNetwork(testCtx, testProjectId, testRegion) request = request.CreateNetworkPayload(iaas.CreateNetworkPayload{ - Name: utils.Ptr("example-network-name"), + Name: utils.Ptr(testNetworkName), Routed: utils.Ptr(true), }) for _, mod := range mods { @@ -100,19 +168,47 @@ func fixturePayload(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.Creat Labels: utils.Ptr(map[string]interface{}{ "key": "value", }), - AddressFamily: &iaas.CreateNetworkAddressFamily{ - Ipv4: &iaas.CreateNetworkIPv4Body{ - Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), - PrefixLength: utils.Ptr(int64(24)), - Prefix: utils.Ptr("10.1.2.0/24"), - Gateway: iaas.NewNullableString(utils.Ptr("10.1.2.3")), - }, - Ipv6: &iaas.CreateNetworkIPv6Body{ - Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), - PrefixLength: utils.Ptr(int64(24)), - Prefix: utils.Ptr("2001:4860:4860::8888"), - Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")), - }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixturePayloadWithPrefix(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.CreateNetworkPayload { + payload := fixturePayload() + payload.Ipv4 = &iaas.CreateNetworkIPv4{ + CreateNetworkIPv4WithPrefix: &iaas.CreateNetworkIPv4WithPrefix{ + Gateway: iaas.NewNullableString(utils.Ptr(testIPv4Gateway)), + Nameservers: utils.Ptr(testIPv4NameServers), + Prefix: utils.Ptr(testIPv4Prefix), + }, + } + payload.Ipv6 = &iaas.CreateNetworkIPv6{ + CreateNetworkIPv6WithPrefix: &iaas.CreateNetworkIPv6WithPrefix{ + Nameservers: utils.Ptr(testIPv6NameServers), + Prefix: utils.Ptr(testIPv6Prefix), + Gateway: iaas.NewNullableString(utils.Ptr(testIPv6Gateway)), + }, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func fixturePayloadWithPrefixLength(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.CreateNetworkPayload { + payload := fixturePayload() + payload.Ipv4 = &iaas.CreateNetworkIPv4{ + CreateNetworkIPv4WithPrefixLength: &iaas.CreateNetworkIPv4WithPrefixLength{ + PrefixLength: utils.Ptr(testIPv4PrefixLength), + Nameservers: utils.Ptr(testIPv4NameServers), + }, + } + payload.Ipv6 = &iaas.CreateNetworkIPv6{ + CreateNetworkIPv6WithPrefixLength: &iaas.CreateNetworkIPv6WithPrefixLength{ + PrefixLength: utils.Ptr(testIPv6PrefixLength), + Nameservers: utils.Ptr(testIPv6NameServers), }, } for _, mod := range mods { @@ -137,15 +233,21 @@ func TestParseInput(t *testing.T) { }, { description: "required only", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, ipv4DnsNameServersFlag) - delete(flagValues, ipv4PrefixLengthFlag) - }), + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + nameFlag: testNetworkName, + }, isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.IPv4DnsNameServers = nil - model.IPv4PrefixLength = nil - }), + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Name: utils.Ptr(testNetworkName), + }, }, { description: "name missing", @@ -162,66 +264,110 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, { - description: "use dns servers, prefix, gateway and prefix length", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[ipv4DnsNameServersFlag] = "1.1.1.1" - flagValues[ipv4PrefixLengthFlag] = "25" - flagValues[ipv4PrefixFlag] = "10.1.2.0/24" - flagValues[ipv4GatewayFlag] = "10.1.2.3" + description: "use with prefix", + flagValues: fixtureFlagValuesWithPrefix(), + isValid: true, + expectedModel: fixtureInputModelWithPrefix(), + }, + { + description: "use with prefix only ipv4", + flagValues: fixtureFlagValuesWithPrefix(func(flagValues map[string]string) { + delete(flagValues, ipv6GatewayFlag) + delete(flagValues, ipv6PrefixFlag) + delete(flagValues, ipv6PrefixLengthFlag) + delete(flagValues, ipv6DnsNameServersFlag) }), isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.IPv4DnsNameServers = utils.Ptr([]string{"1.1.1.1"}) - model.IPv4PrefixLength = utils.Ptr(int64(25)) - model.IPv4Prefix = utils.Ptr("10.1.2.0/24") - model.IPv4Gateway = utils.Ptr("10.1.2.3") + expectedModel: fixtureInputModelWithPrefix(func(model *inputModel) { + model.IPv6PrefixLength = nil + model.IPv6Prefix = nil + model.IPv6DnsNameServers = nil + model.IPv6Gateway = nil }), }, { - description: "use ipv4 gateway nil", - flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[noIpv4GatewayFlag] = "true" + description: "use with prefix only ipv6", + flagValues: fixtureFlagValuesWithPrefix(func(flagValues map[string]string) { delete(flagValues, ipv4GatewayFlag) + delete(flagValues, ipv4PrefixFlag) + delete(flagValues, ipv4PrefixLengthFlag) + delete(flagValues, ipv4DnsNameServersFlag) }), isValid: true, - expectedModel: fixtureInputModel(func(model *inputModel) { - model.NoIPv4Gateway = true + expectedModel: fixtureInputModelWithPrefix(func(model *inputModel) { + model.IPv4PrefixLength = nil + model.IPv4Prefix = nil + model.IPv4DnsNameServers = nil + model.IPv4Gateway = nil + }), + }, + { + description: "use with prefixLength", + flagValues: fixtureFlagValuesWithPrefixLength(), + isValid: true, + expectedModel: fixtureInputModelWithPrefixLength(), + }, + { + description: "use with prefixLength only ipv4", + flagValues: fixtureFlagValuesWithPrefixLength(func(flagValues map[string]string) { + delete(flagValues, ipv6GatewayFlag) + delete(flagValues, ipv6PrefixFlag) + delete(flagValues, ipv6PrefixLengthFlag) + delete(flagValues, ipv6DnsNameServersFlag) + }), + isValid: true, + expectedModel: fixtureInputModelWithPrefixLength(func(model *inputModel) { + model.IPv6PrefixLength = nil + model.IPv6Prefix = nil + model.IPv6DnsNameServers = nil + model.IPv6Gateway = nil + }), + }, + { + description: "use with prefixLength only ipv6", + flagValues: fixtureFlagValuesWithPrefixLength(func(flagValues map[string]string) { + delete(flagValues, ipv4GatewayFlag) + delete(flagValues, ipv4PrefixFlag) + delete(flagValues, ipv4PrefixLengthFlag) + delete(flagValues, ipv4DnsNameServersFlag) + }), + isValid: true, + expectedModel: fixtureInputModelWithPrefixLength(func(model *inputModel) { + model.IPv4PrefixLength = nil + model.IPv4Prefix = nil + model.IPv4DnsNameServers = nil model.IPv4Gateway = nil }), }, { - description: "use ipv6 dns servers, prefix, gateway and prefix length", + description: "use ipv4 gateway nil", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[ipv6DnsNameServersFlag] = "2001:4860:4860::8888" - flagValues[ipv6PrefixLengthFlag] = "25" - flagValues[ipv6PrefixFlag] = "2001:4860:4860::8888" - flagValues[ipv6GatewayFlag] = "2001:4860:4860::8888" + flagValues[noIpv4GatewayFlag] = "true" + delete(flagValues, ipv4GatewayFlag) }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.IPv6DnsNameServers = utils.Ptr([]string{"2001:4860:4860::8888"}) - model.IPv6PrefixLength = utils.Ptr(int64(25)) - model.IPv6Prefix = utils.Ptr("2001:4860:4860::8888") - model.IPv6Gateway = utils.Ptr("2001:4860:4860::8888") + model.NoIPv4Gateway = true + model.IPv4Gateway = nil }), }, { @@ -236,6 +382,72 @@ func TestParseInput(t *testing.T) { model.IPv6Gateway = nil }), }, + { + description: "ipv4 prefix length and prefix conflict", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4PrefixFlag] = testIPv4Prefix + flagValues[ipv4PrefixLengthFlag] = strconv.FormatInt(testIPv4PrefixLength, 10) + }), + isValid: false, + expectedModel: nil, + }, + { + description: "ipv6 prefix length and prefix conflict", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv6PrefixFlag] = testIPv6Prefix + flagValues[ipv6PrefixLengthFlag] = strconv.FormatInt(testIPv6PrefixLength, 10) + }), + isValid: false, + expectedModel: nil, + }, + { + description: "ipv4 nameserver with missing prefix or prefix length", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4DnsNameServersFlag] = strings.Join(testIPv4NameServers, ",") + }), + isValid: false, + expectedModel: nil, + }, + { + description: "ipv6 nameserver with missing prefix or prefix length", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv6DnsNameServersFlag] = strings.Join(testIPv6NameServers, ",") + }), + isValid: false, + expectedModel: nil, + }, + { + description: "ipv4 gateway and no-gateway flag conflict", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4GatewayFlag] = testIPv4Gateway + flagValues[noIpv4GatewayFlag] = "true" + }), + isValid: false, + }, + { + description: "ipv6 gateway and no-gateway flag conflict", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv6GatewayFlag] = testIPv4Gateway + flagValues[noIpv6GatewayFlag] = "true" + }), + isValid: false, + }, + { + description: "ipv4 gateway and prefixLength flag conflict", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv4GatewayFlag] = testIPv4Gateway + flagValues[ipv4PrefixLengthFlag] = strconv.FormatInt(testIPv4PrefixLength, 10) + }), + isValid: false, + }, + { + description: "ipv6 gateway and prefixLength flag conflict", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipv6GatewayFlag] = testIPv6Gateway + flagValues[ipv6PrefixLengthFlag] = strconv.FormatInt(testIPv6PrefixLength, 10) + }), + isValid: false, + }, { description: "non-routed network", flagValues: fixtureFlagValues(func(flagValues map[string]string) { @@ -282,107 +494,98 @@ func TestBuildRequest(t *testing.T) { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, - Name: utils.Ptr("example-network-name"), + Name: utils.Ptr(testNetworkName), }, expectedRequest: fixtureRequiredRequest(), }, + { + description: "use prefix length", + model: fixtureInputModelWithPrefixLength(), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateNetworkRequest) { + *request = (*request).CreateNetworkPayload(fixturePayloadWithPrefixLength()) + }), + }, + { + description: "use prefix", + model: fixtureInputModelWithPrefix(), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateNetworkRequest) { + *request = (*request).CreateNetworkPayload(fixturePayloadWithPrefix()) + }), + }, { description: "non-routed network", model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, - Name: utils.Ptr("example-network-name"), + Name: utils.Ptr(testNetworkName), NonRouted: true, }, - expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ - Name: utils.Ptr("example-network-name"), + expectedRequest: testClient.CreateNetwork(testCtx, testProjectId, testRegion).CreateNetworkPayload(iaas.CreateNetworkPayload{ + Name: utils.Ptr(testNetworkName), Routed: utils.Ptr(false), }), }, { - description: "use dns servers, prefix, gateway and prefix length", + description: "use ipv4 dns servers and prefix length", model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, IPv4DnsNameServers: utils.Ptr([]string{"1.1.1.1"}), IPv4PrefixLength: utils.Ptr(int64(25)), - IPv4Prefix: utils.Ptr("10.1.2.0/24"), - IPv4Gateway: utils.Ptr("10.1.2.3"), }, - expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ - AddressFamily: &iaas.CreateNetworkAddressFamily{ - Ipv4: &iaas.CreateNetworkIPv4Body{ - Nameservers: utils.Ptr([]string{"1.1.1.1"}), - PrefixLength: utils.Ptr(int64(25)), - Prefix: utils.Ptr("10.1.2.0/24"), - Gateway: iaas.NewNullableString(utils.Ptr("10.1.2.3")), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateNetworkRequest) { + *request = (*request).CreateNetworkPayload(iaas.CreateNetworkPayload{ + Ipv4: &iaas.CreateNetworkIPv4{ + CreateNetworkIPv4WithPrefixLength: &iaas.CreateNetworkIPv4WithPrefixLength{ + Nameservers: utils.Ptr([]string{"1.1.1.1"}), + PrefixLength: utils.Ptr(int64(25)), + }, }, - }, - Routed: utils.Ptr(true), + Routed: utils.Ptr(true), + }) }), }, { - description: "use ipv4 gateway nil", - model: &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ - ProjectId: testProjectId, - Verbosity: globalflags.VerbosityDefault, - }, - NoIPv4Gateway: true, - IPv4Gateway: nil, - }, - expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ - AddressFamily: &iaas.CreateNetworkAddressFamily{ - Ipv4: &iaas.CreateNetworkIPv4Body{ - Gateway: iaas.NewNullableString(nil), - }, - }, - Routed: utils.Ptr(true), + description: "use prefix with no gateway", + model: fixtureInputModelWithPrefix(func(model *inputModel) { + model.NoIPv4Gateway = true + model.NoIPv6Gateway = true + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiCreateNetworkRequest) { + *request = (*request).CreateNetworkPayload( + fixturePayloadWithPrefix(func(payload *iaas.CreateNetworkPayload) { + payload.Ipv4.CreateNetworkIPv4WithPrefix.Gateway = iaas.NewNullableString(nil) + payload.Ipv6.CreateNetworkIPv6WithPrefix.Gateway = iaas.NewNullableString(nil) + }), + ) }), }, { - description: "use ipv6 dns servers, prefix, gateway and prefix length", + description: "use ipv6 dns servers, prefix and gateway", model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888"}), - IPv6PrefixLength: utils.Ptr(int64(25)), IPv6Prefix: utils.Ptr("2001:4860:4860::8888"), IPv6Gateway: utils.Ptr("2001:4860:4860::8888"), }, - expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ - AddressFamily: &iaas.CreateNetworkAddressFamily{ - Ipv6: &iaas.CreateNetworkIPv6Body{ - Nameservers: utils.Ptr([]string{"2001:4860:4860::8888"}), - PrefixLength: utils.Ptr(int64(25)), - Prefix: utils.Ptr("2001:4860:4860::8888"), - Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")), - }, - }, - Routed: utils.Ptr(true), - }), - }, - { - description: "use ipv6 gateway nil", - model: &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ - ProjectId: testProjectId, - Verbosity: globalflags.VerbosityDefault, - }, - NoIPv6Gateway: true, - IPv6Gateway: nil, - }, - expectedRequest: testClient.CreateNetwork(testCtx, testProjectId).CreateNetworkPayload(iaas.CreateNetworkPayload{ - AddressFamily: &iaas.CreateNetworkAddressFamily{ - Ipv6: &iaas.CreateNetworkIPv6Body{ - Gateway: iaas.NewNullableString(nil), + expectedRequest: testClient.CreateNetwork(testCtx, testProjectId, testRegion).CreateNetworkPayload(iaas.CreateNetworkPayload{ + Ipv6: &iaas.CreateNetworkIPv6{ + CreateNetworkIPv6WithPrefix: &iaas.CreateNetworkIPv6WithPrefix{ + Nameservers: utils.Ptr([]string{"2001:4860:4860::8888"}), + Prefix: utils.Ptr("2001:4860:4860::8888"), + Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")), }, }, Routed: utils.Ptr(true), @@ -393,7 +596,7 @@ func TestBuildRequest(t *testing.T) { t.Run(tt.description, func(t *testing.T) { request := buildRequest(testCtx, tt.model, testClient) - diff := cmp.Diff(request, tt.expectedRequest, + diff := cmp.Diff(tt.expectedRequest, request, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), cmp.AllowUnexported(iaas.NullableString{}), diff --git a/internal/cmd/network/delete/delete.go b/internal/cmd/network/delete/delete.go index 473edf34b..e101edf0a 100644 --- a/internal/cmd/network/delete/delete.go +++ b/internal/cmd/network/delete/delete.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.NetworkId) + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = model.NetworkId @@ -84,7 +84,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Deleting network") - _, err = wait.DeleteNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.NetworkId).WaitWithContext(ctx) + _, err = wait.DeleteNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for network deletion: %w", err) } @@ -120,5 +120,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteNetworkRequest { - return apiClient.DeleteNetwork(ctx, model.ProjectId, model.NetworkId) + return apiClient.DeleteNetwork(ctx, model.ProjectId, model.Region, model.NetworkId) } diff --git a/internal/cmd/network/delete/delete_test.go b/internal/cmd/network/delete/delete_test.go index 20c5eed47..76627b697 100644 --- a/internal/cmd/network/delete/delete_test.go +++ b/internal/cmd/network/delete/delete_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, NetworkId: testNetworkId, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteNetworkRequest)) iaas.ApiDeleteNetworkRequest { - request := testClient.DeleteNetwork(testCtx, testProjectId, testNetworkId) + request := testClient.DeleteNetwork(testCtx, testProjectId, testRegion, testNetworkId) for _, mod := range mods { mod(&request) } @@ -101,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/network/describe/describe.go b/internal/cmd/network/describe/describe.go index e7315519a..c7f0d08bc 100644 --- a/internal/cmd/network/describe/describe.go +++ b/internal/cmd/network/describe/describe.go @@ -88,7 +88,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetNetworkRequest { - return apiClient.GetNetwork(ctx, model.ProjectId, model.NetworkId) + return apiClient.GetNetwork(ctx, model.ProjectId, model.Region, model.NetworkId) } func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) error { @@ -96,36 +96,49 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) return fmt.Errorf("network cannot be nil") } return p.OutputResult(outputFormat, network, func() error { - var ipv4nameservers []string - if network.Nameservers != nil { - ipv4nameservers = append(ipv4nameservers, *network.Nameservers...) - } - - var ipv4prefixes []string - if network.Prefixes != nil { - ipv4prefixes = append(ipv4prefixes, *network.Prefixes...) - } - - var ipv6nameservers []string - if network.NameserversV6 != nil { - ipv6nameservers = append(ipv6nameservers, *network.NameserversV6...) + // IPv4 + var ipv4Nameservers, ipv4Prefixes []string + var publicIp, ipv4Gateway *string + if ipv4 := network.Ipv4; ipv4 != nil { + if ipv4.Nameservers != nil { + ipv4Nameservers = append(ipv4Nameservers, *ipv4.Nameservers...) + } + if ipv4.Prefixes != nil { + ipv4Prefixes = append(ipv4Prefixes, *ipv4.Prefixes...) + } + if ipv4.PublicIp != nil { + publicIp = ipv4.PublicIp + } + if ipv4.Gateway != nil && ipv4.Gateway.IsSet() { + ipv4Gateway = ipv4.Gateway.Get() + } } - var ipv6prefixes []string - if network.PrefixesV6 != nil { - ipv6prefixes = append(ipv6prefixes, *network.PrefixesV6...) + // IPv6 + var ipv6Nameservers, ipv6Prefixes []string + var ipv6Gateway *string + if ipv6 := network.Ipv6; ipv6 != nil { + if ipv6.Nameservers != nil { + ipv6Nameservers = append(ipv6Nameservers, *ipv6.Nameservers...) + } + if ipv6.Prefixes != nil { + ipv6Prefixes = append(ipv6Prefixes, *ipv6.Prefixes...) + } + if ipv6.Gateway != nil && ipv6.Gateway.IsSet() { + ipv6Gateway = ipv6.Gateway.Get() + } } table := tables.NewTable() - table.AddRow("ID", utils.PtrString(network.NetworkId)) + table.AddRow("ID", utils.PtrString(network.Id)) table.AddSeparator() table.AddRow("NAME", utils.PtrString(network.Name)) table.AddSeparator() - table.AddRow("STATE", utils.PtrString(network.State)) + table.AddRow("STATE", utils.PtrString(network.Status)) table.AddSeparator() - if network.PublicIp != nil { - table.AddRow("PUBLIC IP", *network.PublicIp) + if publicIp != nil { + table.AddRow("PUBLIC IP", *publicIp) table.AddSeparator() } @@ -137,33 +150,33 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network) table.AddRow("ROUTED", routed) table.AddSeparator() - if network.Gateway != nil { - table.AddRow("IPv4 GATEWAY", *network.Gateway.Get()) + if ipv4Gateway != nil { + table.AddRow("IPv4 GATEWAY", *ipv4Gateway) table.AddSeparator() } - if len(ipv4nameservers) > 0 { - table.AddRow("IPv4 NAME SERVERS", strings.Join(ipv4nameservers, ", ")) + if len(ipv4Nameservers) > 0 { + table.AddRow("IPv4 NAME SERVERS", strings.Join(ipv4Nameservers, ", ")) } table.AddSeparator() - if len(ipv4prefixes) > 0 { - table.AddRow("IPv4 PREFIXES", strings.Join(ipv4prefixes, ", ")) + if len(ipv4Prefixes) > 0 { + table.AddRow("IPv4 PREFIXES", strings.Join(ipv4Prefixes, ", ")) } table.AddSeparator() - if network.Gatewayv6 != nil { - table.AddRow("IPv6 GATEWAY", *network.Gatewayv6.Get()) + if ipv6Gateway != nil { + table.AddRow("IPv6 GATEWAY", *ipv6Gateway) table.AddSeparator() } - if len(ipv6nameservers) > 0 { - table.AddRow("IPv6 NAME SERVERS", strings.Join(ipv6nameservers, ", ")) + if len(ipv6Nameservers) > 0 { + table.AddRow("IPv6 NAME SERVERS", strings.Join(ipv6Nameservers, ", ")) + table.AddSeparator() } - table.AddSeparator() - if len(ipv6prefixes) > 0 { - table.AddRow("IPv6 PREFIXES", strings.Join(ipv6prefixes, ", ")) + if len(ipv6Prefixes) > 0 { + table.AddRow("IPv6 PREFIXES", strings.Join(ipv6Prefixes, ", ")) + table.AddSeparator() } - table.AddSeparator() if network.Labels != nil && len(*network.Labels) > 0 { var labels []string for key, value := range *network.Labels { diff --git a/internal/cmd/network/describe/describe_test.go b/internal/cmd/network/describe/describe_test.go index 098baa905..5a9015489 100644 --- a/internal/cmd/network/describe/describe_test.go +++ b/internal/cmd/network/describe/describe_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -36,7 +38,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, NetworkId: testNetworkId, } @@ -59,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetNetworkRequest)) iaas.ApiGetNetworkRequest { - request := testClient.GetNetwork(testCtx, testProjectId, testNetworkId) + request := testClient.GetNetwork(testCtx, testProjectId, testRegion, testNetworkId) for _, mod := range mods { mod(&request) } @@ -103,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +123,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -194,6 +198,24 @@ func TestOutputResult(t *testing.T) { }, wantErr: false, }, + { + name: "set empty ipv4", + args: args{ + network: &iaas.Network{ + Ipv4: &iaas.NetworkIPv4{}, + }, + }, + wantErr: false, + }, + { + name: "set empty ipv6", + args: args{ + network: &iaas.Network{ + Ipv6: &iaas.NetworkIPv6{}, + }, + }, + wantErr: false, + }, } p := print.NewPrinter() p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) diff --git a/internal/cmd/network/list/list.go b/internal/cmd/network/list/list.go index a0c871466..e92ab31cc 100644 --- a/internal/cmd/network/list/list.go +++ b/internal/cmd/network/list/list.go @@ -130,7 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNetworksRequest { - req := apiClient.ListNetworks(ctx, model.ProjectId) + req := apiClient.ListNetworks(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) } @@ -143,18 +143,21 @@ func outputResult(p *print.Printer, outputFormat string, networks []iaas.Network table.SetHeader("ID", "NAME", "STATUS", "PUBLIC IP", "PREFIXES", "ROUTED") for _, network := range networks { - publicIp := utils.PtrString(network.PublicIp) + var publicIp, prefixes string + if ipv4 := network.Ipv4; ipv4 != nil { + publicIp = utils.PtrString(ipv4.PublicIp) + prefixes = utils.JoinStringPtr(ipv4.Prefixes, ", ") + } routed := false if network.Routed != nil { routed = *network.Routed } - prefixes := utils.JoinStringPtr(network.Prefixes, ", ") table.AddRow( - utils.PtrString(network.NetworkId), + utils.PtrString(network.Id), utils.PtrString(network.Name), - utils.PtrString(network.State), + utils.PtrString(network.Status), publicIp, prefixes, routed, diff --git a/internal/cmd/network/list/list_test.go b/internal/cmd/network/list/list_test.go index f408eeb78..d753ab11d 100644 --- a/internal/cmd/network/list/list_test.go +++ b/internal/cmd/network/list/list_test.go @@ -16,18 +16,22 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" + testLabelSelector = "foo=bar" +) type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &iaas.APIClient{} var testProjectId = uuid.NewString() -var testLabelSelector = "foo=bar" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", labelSelectorFlag: testLabelSelector, } @@ -42,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), LabelSelector: utils.Ptr(testLabelSelector), @@ -53,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListNetworksRequest)) iaas.ApiListNetworksRequest { - request := testClient.ListNetworks(testCtx, testProjectId) + request := testClient.ListNetworks(testCtx, testProjectId, testRegion) request = request.LabelSelector(testLabelSelector) for _, mod := range mods { mod(&request) @@ -88,21 +93,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/network/update/update.go b/internal/cmd/network/update/update.go index 8527a901f..b1891fd34 100644 --- a/internal/cmd/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -84,7 +84,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.NetworkId) + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = model.NetworkId @@ -112,7 +112,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Updating network") - _, err = wait.UpdateNetworkWaitHandler(ctx, apiClient, model.ProjectId, networkId).WaitWithContext(ctx) + _, err = wait.UpdateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for network update: %w", err) } @@ -168,41 +168,40 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiPartialUpdateNetworkRequest { - req := apiClient.PartialUpdateNetwork(ctx, model.ProjectId, model.NetworkId) - addressFamily := &iaas.UpdateNetworkAddressFamily{} + req := apiClient.PartialUpdateNetwork(ctx, model.ProjectId, model.Region, model.NetworkId) + var payloadIPv4 *iaas.UpdateNetworkIPv4Body + var payloadIPv6 *iaas.UpdateNetworkIPv6Body if model.IPv6DnsNameServers != nil || model.NoIPv6Gateway || model.IPv6Gateway != nil { - addressFamily.Ipv6 = &iaas.UpdateNetworkIPv6Body{ + payloadIPv6 = &iaas.UpdateNetworkIPv6Body{ Nameservers: model.IPv6DnsNameServers, } if model.NoIPv6Gateway { - addressFamily.Ipv6.Gateway = iaas.NewNullableString(nil) + payloadIPv6.Gateway = iaas.NewNullableString(nil) } else if model.IPv6Gateway != nil { - addressFamily.Ipv6.Gateway = iaas.NewNullableString(model.IPv6Gateway) + payloadIPv6.Gateway = iaas.NewNullableString(model.IPv6Gateway) } } if model.IPv4DnsNameServers != nil || model.NoIPv4Gateway || model.IPv4Gateway != nil { - addressFamily.Ipv4 = &iaas.UpdateNetworkIPv4Body{ + payloadIPv4 = &iaas.UpdateNetworkIPv4Body{ Nameservers: model.IPv4DnsNameServers, } if model.NoIPv4Gateway { - addressFamily.Ipv4.Gateway = iaas.NewNullableString(nil) + payloadIPv4.Gateway = iaas.NewNullableString(nil) } else if model.IPv4Gateway != nil { - addressFamily.Ipv4.Gateway = iaas.NewNullableString(model.IPv4Gateway) + payloadIPv4.Gateway = iaas.NewNullableString(model.IPv4Gateway) } } payload := iaas.PartialUpdateNetworkPayload{ Name: model.Name, + Ipv4: payloadIPv4, + Ipv6: payloadIPv6, Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } - if addressFamily.Ipv4 != nil || addressFamily.Ipv6 != nil { - payload.AddressFamily = addressFamily - } - return req.PartialUpdateNetworkPayload(payload) } diff --git a/internal/cmd/network/update/update_test.go b/internal/cmd/network/update/update_test.go index d05624840..236fbcd8b 100644 --- a/internal/cmd/network/update/update_test.go +++ b/internal/cmd/network/update/update_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +39,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + nameFlag: "example-network-name", - projectIdFlag: testProjectId, ipv4DnsNameServersFlag: "1.1.1.0,1.1.2.0", ipv4GatewayFlag: "10.1.2.3", ipv6DnsNameServersFlag: "2001:4860:4860::8888,2001:4860:4860::8844", @@ -56,6 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, Name: utils.Ptr("example-network-name"), NetworkId: testNetworkId, @@ -74,7 +79,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiPartialUpdateNetworkRequest)) iaas.ApiPartialUpdateNetworkRequest { - request := testClient.PartialUpdateNetwork(testCtx, testProjectId, testNetworkId) + request := testClient.PartialUpdateNetwork(testCtx, testProjectId, testRegion, testNetworkId) request = request.PartialUpdateNetworkPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -88,15 +93,13 @@ func fixturePayload(mods ...func(payload *iaas.PartialUpdateNetworkPayload)) iaa Labels: utils.Ptr(map[string]interface{}{ "key": "value", }), - AddressFamily: &iaas.UpdateNetworkAddressFamily{ - Ipv4: &iaas.UpdateNetworkIPv4Body{ - Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), - Gateway: iaas.NewNullableString(utils.Ptr("10.1.2.3")), - }, - Ipv6: &iaas.UpdateNetworkIPv6Body{ - Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), - Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")), - }, + Ipv4: &iaas.UpdateNetworkIPv4Body{ + Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}), + Gateway: iaas.NewNullableString(utils.Ptr("10.1.2.3")), + }, + Ipv6: &iaas.UpdateNetworkIPv6Body{ + Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}), + Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")), }, } for _, mod := range mods { @@ -142,7 +145,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -150,7 +153,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -158,7 +161,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/public-ip/associate/associate.go b/internal/cmd/public-ip/associate/associate.go index e2398fe08..ec2ac72c3 100644 --- a/internal/cmd/public-ip/associate/associate.go +++ b/internal/cmd/public-ip/associate/associate.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.Region, model.PublicIpId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId @@ -113,7 +113,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdatePublicIPRequest { - req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.PublicIpId) + req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.Region, model.PublicIpId) payload := iaas.UpdatePublicIPPayload{ NetworkInterface: iaas.NewNullableString(model.AssociatedResourceId), diff --git a/internal/cmd/public-ip/associate/associate_test.go b/internal/cmd/public-ip/associate/associate_test.go index bc2b890e7..18084731d 100644 --- a/internal/cmd/public-ip/associate/associate_test.go +++ b/internal/cmd/public-ip/associate/associate_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,7 +39,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + associatedResourceIdFlag: testAssociatedResourceId, } for _, mod := range mods { @@ -51,6 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, PublicIpId: testPublicIpId, AssociatedResourceId: utils.Ptr(testAssociatedResourceId), @@ -62,7 +67,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdatePublicIPRequest)) iaas.ApiUpdatePublicIPRequest { - request := testClient.UpdatePublicIP(testCtx, testProjectId, testPublicIpId) + request := testClient.UpdatePublicIP(testCtx, testProjectId, testRegion, testPublicIpId) request = request.UpdatePublicIPPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -105,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +118,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +126,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index 1929e81e6..872a95057 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -114,7 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreatePublicIPRequest { - req := apiClient.CreatePublicIP(ctx, model.ProjectId) + req := apiClient.CreatePublicIP(ctx, model.ProjectId, model.Region) payload := iaas.CreatePublicIPPayload{ NetworkInterface: iaas.NewNullableString(model.AssociatedResourceId), diff --git a/internal/cmd/public-ip/create/create_test.go b/internal/cmd/public-ip/create/create_test.go index 5e946f386..3602a422b 100644 --- a/internal/cmd/public-ip/create/create_test.go +++ b/internal/cmd/public-ip/create/create_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -28,7 +30,9 @@ var testAssociatedResourceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + associatedResourceIdFlag: testAssociatedResourceId, labelFlag: "key=value", } @@ -43,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, AssociatedResourceId: utils.Ptr(testAssociatedResourceId), Labels: utils.Ptr(map[string]string{ @@ -56,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreatePublicIPRequest)) iaas.ApiCreatePublicIPRequest { - request := testClient.CreatePublicIP(testCtx, testProjectId) + request := testClient.CreatePublicIP(testCtx, testProjectId, testRegion) request = request.CreatePublicIPPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -122,21 +127,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/public-ip/delete/delete.go b/internal/cmd/public-ip/delete/delete.go index 525318184..f5f8e340a 100644 --- a/internal/cmd/public-ip/delete/delete.go +++ b/internal/cmd/public-ip/delete/delete.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.Region, model.PublicIpId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId @@ -102,5 +102,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeletePublicIPRequest { - return apiClient.DeletePublicIP(ctx, model.ProjectId, model.PublicIpId) + return apiClient.DeletePublicIP(ctx, model.ProjectId, model.Region, model.PublicIpId) } diff --git a/internal/cmd/public-ip/delete/delete_test.go b/internal/cmd/public-ip/delete/delete_test.go index 115c9d2e7..25290233e 100644 --- a/internal/cmd/public-ip/delete/delete_test.go +++ b/internal/cmd/public-ip/delete/delete_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, PublicIpId: testPublicIpId, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeletePublicIPRequest)) iaas.ApiDeletePublicIPRequest { - request := testClient.DeletePublicIP(testCtx, testProjectId, testPublicIpId) + request := testClient.DeletePublicIP(testCtx, testProjectId, testRegion, testPublicIpId) for _, mod := range mods { mod(&request) } @@ -101,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/public-ip/describe/describe.go b/internal/cmd/public-ip/describe/describe.go index 4ec7836f2..94ff1a5c9 100644 --- a/internal/cmd/public-ip/describe/describe.go +++ b/internal/cmd/public-ip/describe/describe.go @@ -88,7 +88,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetPublicIPRequest { - return apiClient.GetPublicIP(ctx, model.ProjectId, model.PublicIpId) + return apiClient.GetPublicIP(ctx, model.ProjectId, model.Region, model.PublicIpId) } func outputResult(p *print.Printer, outputFormat string, publicIp iaas.PublicIp) error { diff --git a/internal/cmd/public-ip/describe/describe_test.go b/internal/cmd/public-ip/describe/describe_test.go index 05ceefe6e..581eb0496 100644 --- a/internal/cmd/public-ip/describe/describe_test.go +++ b/internal/cmd/public-ip/describe/describe_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -36,7 +38,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, PublicIpId: testPublicIpId, } @@ -59,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetPublicIPRequest)) iaas.ApiGetPublicIPRequest { - request := testClient.GetPublicIP(testCtx, testProjectId, testPublicIpId) + request := testClient.GetPublicIP(testCtx, testProjectId, testRegion, testPublicIpId) for _, mod := range mods { mod(&request) } @@ -103,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +123,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/public-ip/disassociate/disassociate.go b/internal/cmd/public-ip/disassociate/disassociate.go index 7af16991d..3a54d40cb 100644 --- a/internal/cmd/public-ip/disassociate/disassociate.go +++ b/internal/cmd/public-ip/disassociate/disassociate.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - publicIpLabel, associatedResourceId, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + publicIpLabel, associatedResourceId, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.Region, model.PublicIpId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId @@ -100,7 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdatePublicIPRequest { - req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.PublicIpId) + req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.Region, model.PublicIpId) payload := iaas.UpdatePublicIPPayload{ NetworkInterface: iaas.NewNullableString(nil), diff --git a/internal/cmd/public-ip/disassociate/disassociate_test.go b/internal/cmd/public-ip/disassociate/disassociate_test.go index 956be6b23..1edc96014 100644 --- a/internal/cmd/public-ip/disassociate/disassociate_test.go +++ b/internal/cmd/public-ip/disassociate/disassociate_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -36,7 +38,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, PublicIpId: testPublicIpId, } @@ -59,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdatePublicIPRequest)) iaas.ApiUpdatePublicIPRequest { - request := testClient.UpdatePublicIP(testCtx, testProjectId, testPublicIpId) + request := testClient.UpdatePublicIP(testCtx, testProjectId, testRegion, testPublicIpId) request = request.UpdatePublicIPPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -102,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -110,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -118,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/public-ip/list/list.go b/internal/cmd/public-ip/list/list.go index 4501c1cab..ec95cb0c6 100644 --- a/internal/cmd/public-ip/list/list.go +++ b/internal/cmd/public-ip/list/list.go @@ -130,7 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListPublicIPsRequest { - req := apiClient.ListPublicIPs(ctx, model.ProjectId) + req := apiClient.ListPublicIPs(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) } diff --git a/internal/cmd/public-ip/list/list_test.go b/internal/cmd/public-ip/list/list_test.go index 1d6f7b20d..2256ed99c 100644 --- a/internal/cmd/public-ip/list/list_test.go +++ b/internal/cmd/public-ip/list/list_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,7 +29,9 @@ var testLabelSelector = "label" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", labelSelectorFlag: testLabelSelector, } @@ -42,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), LabelSelector: utils.Ptr(testLabelSelector), @@ -53,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListPublicIPsRequest)) iaas.ApiListPublicIPsRequest { - request := testClient.ListPublicIPs(testCtx, testProjectId) + request := testClient.ListPublicIPs(testCtx, testProjectId, testRegion) request = request.LabelSelector(testLabelSelector) for _, mod := range mods { mod(&request) @@ -88,21 +93,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go index 4146fb6ee..c4498a032 100644 --- a/internal/cmd/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.Region, model.PublicIpId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get public IP: %v", err) publicIpLabel = model.PublicIpId @@ -117,7 +117,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdatePublicIPRequest { - req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.PublicIpId) + req := apiClient.UpdatePublicIP(ctx, model.ProjectId, model.Region, model.PublicIpId) payload := iaas.UpdatePublicIPPayload{ Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), diff --git a/internal/cmd/public-ip/update/update_test.go b/internal/cmd/public-ip/update/update_test.go index 87c598665..bf987a524 100644 --- a/internal/cmd/public-ip/update/update_test.go +++ b/internal/cmd/public-ip/update/update_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +39,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - labelFlag: "key=value", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + labelFlag: "key=value", } for _, mod := range mods { mod(flagValues) @@ -51,6 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, PublicIpId: testPublicIpId, Labels: utils.Ptr(map[string]string{ @@ -64,7 +69,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdatePublicIPRequest)) iaas.ApiUpdatePublicIPRequest { - request := testClient.UpdatePublicIP(testCtx, testProjectId, testPublicIpId) + request := testClient.UpdatePublicIP(testCtx, testProjectId, testRegion, testPublicIpId) request = request.UpdatePublicIPPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -109,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -117,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -125,7 +130,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/quota/list/list.go b/internal/cmd/quota/list/list.go index 84835b555..f61151f24 100644 --- a/internal/cmd/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -93,7 +93,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListQuotasRequest { - request := apiClient.ListQuotas(ctx, model.ProjectId) + request := apiClient.ListQuotas(ctx, model.ProjectId, model.Region) return request } diff --git a/internal/cmd/quota/list/list_test.go b/internal/cmd/quota/list/list_test.go index 973f28abb..358749384 100644 --- a/internal/cmd/quota/list/list_test.go +++ b/internal/cmd/quota/list/list_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,7 +29,8 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,7 +40,11 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, } for _, mod := range mods { mod(model) @@ -46,7 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListQuotasRequest)) iaas.ApiListQuotasRequest { - request := testClient.ListQuotas(testCtx, testProjectId) + request := testClient.ListQuotas(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -75,21 +82,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index 9598ef794..fd10a585d 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -115,7 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateSecurityGroupRequest { - request := apiClient.CreateSecurityGroup(ctx, model.ProjectId) + request := apiClient.CreateSecurityGroup(ctx, model.ProjectId, model.Region) payload := iaas.CreateSecurityGroupPayload{ Description: model.Description, diff --git a/internal/cmd/security-group/create/create_test.go b/internal/cmd/security-group/create/create_test.go index 3f936f5ab..9b6d8f92c 100644 --- a/internal/cmd/security-group/create/create_test.go +++ b/internal/cmd/security-group/create/create_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -35,7 +37,9 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + descriptionFlag: testDescription, labelsFlag: "fooKey=fooValue,barKey=barValue,bazKey=bazValue", statefulFlag: "true", @@ -49,11 +53,15 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, - Labels: &testLabels, - Description: &testDescription, - Name: &testName, - Stateful: &testStateful, + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + Labels: &testLabels, + Description: &testDescription, + Name: &testName, + Stateful: &testStateful, } for _, mod := range mods { mod(model) @@ -72,7 +80,7 @@ func toStringAnyMapPtr(m map[string]string) map[string]any { return result } func fixtureRequest(mods ...func(request *iaas.ApiCreateSecurityGroupRequest)) iaas.ApiCreateSecurityGroupRequest { - request := testClient.CreateSecurityGroup(testCtx, testProjectId) + request := testClient.CreateSecurityGroup(testCtx, testProjectId, testRegion) request = request.CreateSecurityGroupPayload(iaas.CreateSecurityGroupPayload{ Description: &testDescription, @@ -109,21 +117,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/security-group/delete/delete.go b/internal/cmd/security-group/delete/delete.go index 376435432..506dce800 100644 --- a/internal/cmd/security-group/delete/delete.go +++ b/internal/cmd/security-group/delete/delete.go @@ -53,7 +53,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - groupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) + groupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.Region, model.SecurityGroupId) if err != nil { params.Printer.Warn("get security group name: %v", err) groupLabel = model.SecurityGroupId @@ -98,6 +98,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteSecurityGroupRequest { - request := apiClient.DeleteSecurityGroup(ctx, model.ProjectId, model.SecurityGroupId) + request := apiClient.DeleteSecurityGroup(ctx, model.ProjectId, model.Region, model.SecurityGroupId) return request } diff --git a/internal/cmd/security-group/delete/delete_test.go b/internal/cmd/security-group/delete/delete_test.go index 5a4787576..e29d614e6 100644 --- a/internal/cmd/security-group/delete/delete_test.go +++ b/internal/cmd/security-group/delete/delete_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,7 +29,8 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -37,7 +40,11 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, SecurityGroupId: testGroupId, } for _, mod := range mods { @@ -47,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteSecurityGroupRequest)) iaas.ApiDeleteSecurityGroupRequest { - request := testClient.DeleteSecurityGroup(testCtx, testProjectId, testGroupId) + request := testClient.DeleteSecurityGroup(testCtx, testProjectId, testRegion, testGroupId) for _, mod := range mods { mod(&request) } @@ -73,14 +80,14 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/security-group/describe/describe.go b/internal/cmd/security-group/describe/describe.go index 80fd5cb0c..6d8d615b0 100644 --- a/internal/cmd/security-group/describe/describe.go +++ b/internal/cmd/security-group/describe/describe.go @@ -68,7 +68,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetSecurityGroupRequest { - request := apiClient.GetSecurityGroup(ctx, model.ProjectId, model.SecurityGroupId) + request := apiClient.GetSecurityGroup(ctx, model.ProjectId, model.Region, model.SecurityGroupId) return request } diff --git a/internal/cmd/security-group/describe/describe_test.go b/internal/cmd/security-group/describe/describe_test.go index 62bf425be..1c6f15431 100644 --- a/internal/cmd/security-group/describe/describe_test.go +++ b/internal/cmd/security-group/describe/describe_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -26,7 +28,8 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -36,7 +39,11 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, SecurityGroupId: testSecurityGroupId[0], } for _, mod := range mods { @@ -46,7 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetSecurityGroupRequest)) iaas.ApiGetSecurityGroupRequest { - request := testClient.GetSecurityGroup(testCtx, testProjectId, testSecurityGroupId[0]) + request := testClient.GetSecurityGroup(testCtx, testProjectId, testRegion, testSecurityGroupId[0]) for _, mod := range mods { mod(&request) } @@ -78,7 +85,7 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), args: testSecurityGroupId, isValid: false, @@ -86,7 +93,7 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), args: testSecurityGroupId, isValid: false, @@ -94,7 +101,7 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), args: testSecurityGroupId, isValid: false, diff --git a/internal/cmd/security-group/list/list.go b/internal/cmd/security-group/list/list.go index ae9ecdd10..159995162 100644 --- a/internal/cmd/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -102,7 +102,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListSecurityGroupsRequest { - request := apiClient.ListSecurityGroups(ctx, model.ProjectId) + request := apiClient.ListSecurityGroups(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { request = request.LabelSelector(*model.LabelSelector) } diff --git a/internal/cmd/security-group/list/list_test.go b/internal/cmd/security-group/list/list_test.go index 806ab98e3..7e5515059 100644 --- a/internal/cmd/security-group/list/list_test.go +++ b/internal/cmd/security-group/list/list_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -28,7 +30,9 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + labelSelectorFlag: testLabels, } for _, mod := range mods { @@ -39,8 +43,12 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, - LabelSelector: utils.Ptr(testLabels), + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + LabelSelector: utils.Ptr(testLabels), } for _, mod := range mods { mod(model) @@ -49,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListSecurityGroupsRequest)) iaas.ApiListSecurityGroupsRequest { - request := testClient.ListSecurityGroups(testCtx, testProjectId) + request := testClient.ListSecurityGroups(testCtx, testProjectId, testRegion) request = request.LabelSelector(testLabels) for _, mod := range mods { mod(&request) @@ -79,21 +87,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go index cee025e98..9c87570f3 100644 --- a/internal/cmd/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -94,7 +94,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) + securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.Region, model.SecurityGroupId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get security group name: %v", err) securityGroupLabel = model.SecurityGroupId @@ -168,7 +168,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateSecurityGroupRuleRequest { - req := apiClient.CreateSecurityGroupRule(ctx, model.ProjectId, model.SecurityGroupId) + req := apiClient.CreateSecurityGroupRule(ctx, model.ProjectId, model.Region, model.SecurityGroupId) icmpParameters := &iaas.ICMPParameters{} portRange := &iaas.PortRange{} protocol := &iaas.CreateProtocol{} diff --git a/internal/cmd/security-group/rule/create/create_test.go b/internal/cmd/security-group/rule/create/create_test.go index 2432c55ae..4088823e4 100644 --- a/internal/cmd/security-group/rule/create/create_test.go +++ b/internal/cmd/security-group/rule/create/create_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -29,7 +31,9 @@ var testRemoteSecurityGroupId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + securityGroupIdFlag: testSecurityGroupId, directionFlag: "ingress", descriptionFlag: "example-description", @@ -53,6 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, SecurityGroupId: testSecurityGroupId, @@ -75,7 +80,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateSecurityGroupRuleRequest)) iaas.ApiCreateSecurityGroupRuleRequest { - request := testClient.CreateSecurityGroupRule(testCtx, testProjectId, testSecurityGroupId) + request := testClient.CreateSecurityGroupRule(testCtx, testProjectId, testRegion, testSecurityGroupId) request = request.CreateSecurityGroupRulePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -84,7 +89,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateSecurityGroupRuleRequest } func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateSecurityGroupRuleRequest)) iaas.ApiCreateSecurityGroupRuleRequest { - request := testClient.CreateSecurityGroupRule(testCtx, testProjectId, testSecurityGroupId) + request := testClient.CreateSecurityGroupRule(testCtx, testProjectId, testRegion, testSecurityGroupId) request = request.CreateSecurityGroupRulePayload(iaas.CreateSecurityGroupRulePayload{ Direction: utils.Ptr("ingress"), }) @@ -203,21 +208,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -267,6 +272,7 @@ func TestBuildRequest(t *testing.T) { model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Direction: utils.Ptr("ingress"), diff --git a/internal/cmd/security-group/rule/delete/delete.go b/internal/cmd/security-group/rule/delete/delete.go index 9248663cf..f0426854b 100644 --- a/internal/cmd/security-group/rule/delete/delete.go +++ b/internal/cmd/security-group/rule/delete/delete.go @@ -27,7 +27,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel SecurityGroupRuleId string - SecurityGroupId *string + SecurityGroupId string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -58,13 +58,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, *model.SecurityGroupId) + securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.Region, model.SecurityGroupId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get security group name: %v", err) - securityGroupLabel = *model.SecurityGroupId + securityGroupLabel = model.SecurityGroupId } - securityGroupRuleLabel, err := iaasUtils.GetSecurityGroupRuleName(ctx, apiClient, model.ProjectId, model.SecurityGroupRuleId, *model.SecurityGroupId) + securityGroupRuleLabel, err := iaasUtils.GetSecurityGroupRuleName(ctx, apiClient, model.ProjectId, model.Region, model.SecurityGroupRuleId, model.SecurityGroupId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get security group rule name: %v", err) securityGroupRuleLabel = model.SecurityGroupRuleId @@ -111,7 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, SecurityGroupRuleId: securityGroupRuleId, - SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), + SecurityGroupId: flags.FlagToStringValue(p, cmd, securityGroupIdFlag), } p.DebugInputModel(model) @@ -119,5 +119,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteSecurityGroupRuleRequest { - return apiClient.DeleteSecurityGroupRule(ctx, model.ProjectId, *model.SecurityGroupId, model.SecurityGroupRuleId) + return apiClient.DeleteSecurityGroupRule(ctx, model.ProjectId, model.Region, model.SecurityGroupId, model.SecurityGroupRuleId) } diff --git a/internal/cmd/security-group/rule/delete/delete_test.go b/internal/cmd/security-group/rule/delete/delete_test.go index ebf83035c..9f78a7e1a 100644 --- a/internal/cmd/security-group/rule/delete/delete_test.go +++ b/internal/cmd/security-group/rule/delete/delete_test.go @@ -4,18 +4,18 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -38,7 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + securityGroupIdFlag: testSecurityGroupId, } for _, mod := range mods { @@ -51,9 +53,10 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, - SecurityGroupId: utils.Ptr(testSecurityGroupId), + SecurityGroupId: testSecurityGroupId, SecurityGroupRuleId: testSecurityGroupRuleId, } for _, mod := range mods { @@ -63,7 +66,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteSecurityGroupRuleRequest)) iaas.ApiDeleteSecurityGroupRuleRequest { - request := testClient.DeleteSecurityGroupRule(testCtx, testProjectId, testSecurityGroupId, testSecurityGroupRuleId) + request := testClient.DeleteSecurityGroupRule(testCtx, testProjectId, testRegion, testSecurityGroupId, testSecurityGroupRuleId) for _, mod := range mods { mod(&request) } @@ -95,7 +98,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -103,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -111,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/security-group/rule/describe/describe.go b/internal/cmd/security-group/rule/describe/describe.go index 23407466d..12d6edece 100644 --- a/internal/cmd/security-group/rule/describe/describe.go +++ b/internal/cmd/security-group/rule/describe/describe.go @@ -28,7 +28,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel SecurityGroupRuleId string - SecurityGroupId *string + SecurityGroupId string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -92,7 +92,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, SecurityGroupRuleId: securityGroupRuleId, - SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), + SecurityGroupId: flags.FlagToStringValue(p, cmd, securityGroupIdFlag), } p.DebugInputModel(model) @@ -100,7 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetSecurityGroupRuleRequest { - return apiClient.GetSecurityGroupRule(ctx, model.ProjectId, *model.SecurityGroupId, model.SecurityGroupRuleId) + return apiClient.GetSecurityGroupRule(ctx, model.ProjectId, model.Region, model.SecurityGroupId, model.SecurityGroupRuleId) } func outputResult(p *print.Printer, outputFormat string, securityGroupRule *iaas.SecurityGroupRule) error { diff --git a/internal/cmd/security-group/rule/describe/describe_test.go b/internal/cmd/security-group/rule/describe/describe_test.go index 68c84b395..357457705 100644 --- a/internal/cmd/security-group/rule/describe/describe_test.go +++ b/internal/cmd/security-group/rule/describe/describe_test.go @@ -11,11 +11,12 @@ import ( "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" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,7 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + securityGroupIdFlag: testSecurityGroupId, } for _, mod := range mods { @@ -50,9 +53,10 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, - SecurityGroupId: utils.Ptr(testSecurityGroupId), + SecurityGroupId: testSecurityGroupId, SecurityGroupRuleId: testSecurityGroupRuleId, } for _, mod := range mods { @@ -62,7 +66,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetSecurityGroupRuleRequest)) iaas.ApiGetSecurityGroupRuleRequest { - request := testClient.GetSecurityGroupRule(testCtx, testProjectId, testSecurityGroupId, testSecurityGroupRuleId) + request := testClient.GetSecurityGroupRule(testCtx, testProjectId, testRegion, testSecurityGroupId, testSecurityGroupRuleId) for _, mod := range mods { mod(&request) } @@ -106,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -114,7 +118,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -122,7 +126,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/security-group/rule/list/list.go b/internal/cmd/security-group/rule/list/list.go index 4984d6b17..7ddb33c7a 100644 --- a/internal/cmd/security-group/rule/list/list.go +++ b/internal/cmd/security-group/rule/list/list.go @@ -30,7 +30,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel Limit *int64 - SecurityGroupId *string + SecurityGroupId string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -74,10 +74,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, *model.SecurityGroupId) + securityGroupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.Region, model.SecurityGroupId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get security group name: %v", err) - securityGroupLabel = *model.SecurityGroupId + securityGroupLabel = model.SecurityGroupId } projectLabel, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd) @@ -127,7 +127,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, model := inputModel{ GlobalFlagModel: globalFlags, Limit: limit, - SecurityGroupId: flags.FlagToStringPointer(p, cmd, securityGroupIdFlag), + SecurityGroupId: flags.FlagToStringValue(p, cmd, securityGroupIdFlag), } p.DebugInputModel(model) @@ -135,7 +135,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListSecurityGroupRulesRequest { - return apiClient.ListSecurityGroupRules(ctx, model.ProjectId, *model.SecurityGroupId) + return apiClient.ListSecurityGroupRules(ctx, model.ProjectId, model.Region, model.SecurityGroupId) } func outputResult(p *print.Printer, outputFormat string, securityGroupRules []iaas.SecurityGroupRule) error { diff --git a/internal/cmd/security-group/rule/list/list_test.go b/internal/cmd/security-group/rule/list/list_test.go index ab41b1d87..92ba77801 100644 --- a/internal/cmd/security-group/rule/list/list_test.go +++ b/internal/cmd/security-group/rule/list/list_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -26,7 +28,9 @@ var testSecurityGroupId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", securityGroupIdFlag: testSecurityGroupId, } @@ -41,9 +45,10 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), - SecurityGroupId: utils.Ptr(testSecurityGroupId), + SecurityGroupId: testSecurityGroupId, } for _, mod := range mods { mod(model) @@ -52,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListSecurityGroupRulesRequest)) iaas.ApiListSecurityGroupRulesRequest { - request := testClient.ListSecurityGroupRules(testCtx, testProjectId, testSecurityGroupId) + request := testClient.ListSecurityGroupRules(testCtx, testProjectId, testRegion, testSecurityGroupId) for _, mod := range mods { mod(&request) } @@ -86,21 +91,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/security-group/update/update.go b/internal/cmd/security-group/update/update.go index d0aae546e..c9e255929 100644 --- a/internal/cmd/security-group/update/update.go +++ b/internal/cmd/security-group/update/update.go @@ -64,7 +64,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - groupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.SecurityGroupId) + groupLabel, err := iaasUtils.GetSecurityGroupName(ctx, apiClient, model.ProjectId, model.Region, model.SecurityGroupId) if err != nil { params.Printer.Warn("cannot retrieve groupname: %v", err) groupLabel = model.SecurityGroupId @@ -124,7 +124,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateSecurityGroupRequest { - request := apiClient.UpdateSecurityGroup(ctx, model.ProjectId, model.SecurityGroupId) + request := apiClient.UpdateSecurityGroup(ctx, model.ProjectId, model.Region, model.SecurityGroupId) payload := iaas.NewUpdateSecurityGroupPayload() payload.Description = model.Description payload.Labels = utils.ConvertStringMapToInterfaceMap(model.Labels) diff --git a/internal/cmd/security-group/update/update_test.go b/internal/cmd/security-group/update/update_test.go index e7c6c4f00..081875080 100644 --- a/internal/cmd/security-group/update/update_test.go +++ b/internal/cmd/security-group/update/update_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -46,7 +48,9 @@ func toStringAnyMapPtr(m map[string]string) map[string]any { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + descriptionArg: testDescription, labelsArg: "fooKey=fooValue,barKey=barValue,bazKey=bazValue", nameArg: testName, @@ -59,7 +63,11 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, Labels: &testLabels, Description: &testDescription, Name: &testName, @@ -72,7 +80,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdateSecurityGroupRequest)) iaas.ApiUpdateSecurityGroupRequest { - request := testClient.UpdateSecurityGroup(testCtx, testProjectId, testGroupId[0]) + request := testClient.UpdateSecurityGroup(testCtx, testProjectId, testRegion, testGroupId[0]) request = request.UpdateSecurityGroupPayload(iaas.UpdateSecurityGroupPayload{ Description: &testDescription, Labels: utils.Ptr(toStringAnyMapPtr(testLabels)), @@ -103,7 +111,7 @@ func TestParseInput(t *testing.T) { { description: "no values but valid group id", flagValues: map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, }, args: testGroupId, isValid: false, @@ -116,7 +124,7 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), args: testGroupId, isValid: false, @@ -124,7 +132,7 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), args: testGroupId, isValid: false, @@ -132,7 +140,7 @@ func TestParseInput(t *testing.T) { { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), args: testGroupId, isValid: false, diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index 824bbb0b9..4ee1b42a4 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go index 18acc9627..7fc57c79b 100644 --- a/internal/cmd/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go index 8194ca95e..369434d55 100644 --- a/internal/cmd/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go index 58259611f..0e9856d4f 100644 --- a/internal/cmd/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index 658ab27ee..415f58a8f 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/backup/schedule/delete/delete.go b/internal/cmd/server/backup/schedule/delete/delete.go index 3dd8632f4..344ad02c0 100644 --- a/internal/cmd/server/backup/schedule/delete/delete.go +++ b/internal/cmd/server/backup/schedule/delete/delete.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go index 1c396d0e1..3111ea55f 100644 --- a/internal/cmd/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index 0f489ee7a..a95838116 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -66,7 +66,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/command/list/list.go b/internal/cmd/server/command/list/list.go index f917b1689..052f13766 100644 --- a/internal/cmd/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/console/console.go b/internal/cmd/server/console/console.go index 45d884cec..ea363c540 100644 --- a/internal/cmd/server/console/console.go +++ b/internal/cmd/server/console/console.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -96,7 +96,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetServerConsoleRequest { - return apiClient.GetServerConsole(ctx, model.ProjectId, model.ServerId) + return apiClient.GetServerConsole(ctx, model.ProjectId, model.Region, model.ServerId) } func outputResult(p *print.Printer, outputFormat, serverLabel string, serverUrl iaas.ServerConsoleUrl) error { diff --git a/internal/cmd/server/console/console_test.go b/internal/cmd/server/console/console_test.go index ab80a7fc4..a449d49bc 100644 --- a/internal/cmd/server/console/console_test.go +++ b/internal/cmd/server/console/console_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,7 +39,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -50,6 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, } @@ -60,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetServerConsoleRequest)) iaas.ApiGetServerConsoleRequest { - request := testClient.GetServerConsole(testCtx, testProjectId, testServerId) + request := testClient.GetServerConsole(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -98,7 +102,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -106,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index b0142acec..00ebd8254 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -147,7 +147,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Creating server") - _, err = wait.CreateServerWaitHandler(ctx, apiClient, model.ProjectId, serverId).WaitWithContext(ctx) + _, err = wait.CreateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, serverId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for server creation: %w", err) } @@ -185,6 +185,7 @@ func configureFlags(cmd *cobra.Command) { cmd.MarkFlagsMutuallyExclusive(imageIdFlag, bootVolumeSourceIdFlag) cmd.MarkFlagsMutuallyExclusive(imageIdFlag, bootVolumeSourceTypeFlag) cmd.MarkFlagsMutuallyExclusive(networkIdFlag, networkInterfaceIdsFlag) + cmd.MarkFlagsOneRequired(networkIdFlag, networkInterfaceIdsFlag) cobra.CheckErr(err) } @@ -270,7 +271,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateServerRequest { - req := apiClient.CreateServer(ctx, model.ProjectId) + req := apiClient.CreateServer(ctx, model.ProjectId, model.Region) var userData *[]byte if model.UserData != nil { @@ -293,7 +294,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } if model.BootVolumePerformanceClass != nil || model.BootVolumeSize != nil || model.BootVolumeDeleteOnTermination != nil || model.BootVolumeSourceId != nil || model.BootVolumeSourceType != nil { - payload.BootVolume = &iaas.CreateServerPayloadBootVolume{ + payload.BootVolume = &iaas.ServerBootVolume{ PerformanceClass: model.BootVolumePerformanceClass, Size: model.BootVolumeSize, DeleteOnTermination: model.BootVolumeDeleteOnTermination, @@ -305,7 +306,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } if model.NetworkInterfaceIds != nil || model.NetworkId != nil { - payload.Networking = &iaas.CreateServerPayloadNetworking{} + payload.Networking = &iaas.CreateServerPayloadAllOfNetworking{} if model.NetworkInterfaceIds != nil { payload.Networking.CreateServerNetworkingWithNics = &iaas.CreateServerNetworkingWithNics{ diff --git a/internal/cmd/server/create/create_test.go b/internal/cmd/server/create/create_test.go index 192caac02..1270eed51 100644 --- a/internal/cmd/server/create/create_test.go +++ b/internal/cmd/server/create/create_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -31,7 +33,9 @@ var testVolumeId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + availabilityZoneFlag: "eu01-1", nameFlag: "test-server-name", machineTypeFlag: "t1.1", @@ -59,6 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, AvailabilityZone: utils.Ptr("eu01-1"), @@ -87,7 +92,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateServerRequest)) iaas.ApiCreateServerRequest { - request := testClient.CreateServer(testCtx, testProjectId) + request := testClient.CreateServer(testCtx, testProjectId, testRegion) request = request.CreateServerPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -96,7 +101,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateServerRequest)) iaas.Api } func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateServerRequest)) iaas.ApiCreateServerRequest { - request := testClient.CreateServer(testCtx, testProjectId) + request := testClient.CreateServer(testCtx, testProjectId, testRegion) request = request.CreateServerPayload(iaas.CreateServerPayload{ MachineType: utils.Ptr("t1.1"), Name: utils.Ptr("test-server-name"), @@ -121,7 +126,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateServerPayload)) iaas.Create ServiceAccountMails: utils.Ptr([]string{"test-service-account"}), UserData: utils.Ptr([]byte("test-user-data")), Volumes: utils.Ptr([]string{testVolumeId}), - BootVolume: &iaas.CreateServerPayloadBootVolume{ + BootVolume: &iaas.ServerBootVolume{ PerformanceClass: utils.Ptr("test-perf-class"), Size: utils.Ptr(int64(5)), DeleteOnTermination: utils.Ptr(false), @@ -130,7 +135,7 @@ func fixturePayload(mods ...func(payload *iaas.CreateServerPayload)) iaas.Create Type: utils.Ptr("test-source-type"), }, }, - Networking: &iaas.CreateServerPayloadNetworking{ + Networking: &iaas.CreateServerPayloadAllOfNetworking{ CreateServerNetworking: &iaas.CreateServerNetworking{ NetworkId: utils.Ptr(testNetworkId), }, @@ -168,7 +173,6 @@ func TestParseInput(t *testing.T) { delete(flagValues, bootVolumePerformanceClassFlag) delete(flagValues, bootVolumeDeleteOnTerminationFlag) delete(flagValues, keypairNameFlag) - delete(flagValues, networkIdFlag) delete(flagValues, networkInterfaceIdsFlag) delete(flagValues, securityGroupsFlag) delete(flagValues, serviceAccountEmailsFlag) @@ -187,7 +191,6 @@ func TestParseInput(t *testing.T) { model.BootVolumePerformanceClass = nil model.BootVolumeDeleteOnTermination = nil model.KeypairName = nil - model.NetworkId = nil model.NetworkInterfaceIds = nil model.SecurityGroups = nil model.ServiceAccountMails = nil @@ -218,21 +221,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -350,6 +353,7 @@ func TestBuildRequest(t *testing.T) { model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, MachineType: utils.Ptr("t1.1"), diff --git a/internal/cmd/server/deallocate/deallocate.go b/internal/cmd/server/deallocate/deallocate.go index 7d1d4e37d..b55da54b2 100644 --- a/internal/cmd/server/deallocate/deallocate.go +++ b/internal/cmd/server/deallocate/deallocate.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -81,7 +81,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Deallocating server") - _, err = wait.DeallocateServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + _, err = wait.DeallocateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for server deallocating: %w", err) } @@ -118,5 +118,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeallocateServerRequest { - return apiClient.DeallocateServer(ctx, model.ProjectId, model.ServerId) + return apiClient.DeallocateServer(ctx, model.ProjectId, model.Region, model.ServerId) } diff --git a/internal/cmd/server/deallocate/deallocate_test.go b/internal/cmd/server/deallocate/deallocate_test.go index 5f1c06bea..efb00e27f 100644 --- a/internal/cmd/server/deallocate/deallocate_test.go +++ b/internal/cmd/server/deallocate/deallocate_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -46,6 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, + Region: testRegion, ProjectId: testProjectId, }, ServerId: testServerId, @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeallocateServerRequest)) iaas.ApiDeallocateServerRequest { - request := testClient.DeallocateServer(testCtx, testProjectId, testServerId) + request := testClient.DeallocateServer(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -95,7 +99,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -103,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/delete/delete.go b/internal/cmd/server/delete/delete.go index f2f5e80db..1a63f5ae1 100644 --- a/internal/cmd/server/delete/delete.go +++ b/internal/cmd/server/delete/delete.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -84,7 +84,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Deleting server") - _, err = wait.DeleteServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + _, err = wait.DeleteServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for server deletion: %w", err) } @@ -120,5 +120,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteServerRequest { - return apiClient.DeleteServer(ctx, model.ProjectId, model.ServerId) + return apiClient.DeleteServer(ctx, model.ProjectId, model.Region, model.ServerId) } diff --git a/internal/cmd/server/delete/delete_test.go b/internal/cmd/server/delete/delete_test.go index 3b72baca3..9534c8b22 100644 --- a/internal/cmd/server/delete/delete_test.go +++ b/internal/cmd/server/delete/delete_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteServerRequest)) iaas.ApiDeleteServerRequest { - request := testClient.DeleteServer(testCtx, testProjectId, testServerId) + request := testClient.DeleteServer(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -101,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/describe/describe.go b/internal/cmd/server/describe/describe.go index 760444d26..3058cd465 100644 --- a/internal/cmd/server/describe/describe.go +++ b/internal/cmd/server/describe/describe.go @@ -90,7 +90,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetServerRequest { - req := apiClient.GetServer(ctx, model.ProjectId, model.ServerId) + req := apiClient.GetServer(ctx, model.ProjectId, model.Region, model.ServerId) req = req.Details(true) return req diff --git a/internal/cmd/server/describe/describe_test.go b/internal/cmd/server/describe/describe_test.go index 0d416e464..af975d7c6 100644 --- a/internal/cmd/server/describe/describe_test.go +++ b/internal/cmd/server/describe/describe_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -36,7 +38,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, ServerId: testServerId, @@ -59,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetServerRequest)) iaas.ApiGetServerRequest { - request := testClient.GetServer(testCtx, testProjectId, testServerId) + request := testClient.GetServer(testCtx, testProjectId, testRegion, testServerId) request = request.Details(true) for _, mod := range mods { mod(&request) @@ -104,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +124,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/list/list.go b/internal/cmd/server/list/list.go index 0918e1d91..98faf6365 100644 --- a/internal/cmd/server/list/list.go +++ b/internal/cmd/server/list/list.go @@ -130,7 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServersRequest { - req := apiClient.ListServers(ctx, model.ProjectId) + req := apiClient.ListServers(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) } diff --git a/internal/cmd/server/list/list_test.go b/internal/cmd/server/list/list_test.go index 1507be485..f23efc370 100644 --- a/internal/cmd/server/list/list_test.go +++ b/internal/cmd/server/list/list_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,7 +29,9 @@ var testLabelSelector = "label" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", labelSelectorFlag: testLabelSelector, } @@ -42,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), LabelSelector: utils.Ptr(testLabelSelector), @@ -53,7 +58,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListServersRequest)) iaas.ApiListServersRequest { - request := testClient.ListServers(testCtx, testProjectId) + request := testClient.ListServers(testCtx, testProjectId, testRegion) request = request.LabelSelector(testLabelSelector) request = request.Details(true) for _, mod := range mods { @@ -89,21 +94,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/log/log.go b/internal/cmd/server/log/log.go index f4015c298..6b6a59f67 100644 --- a/internal/cmd/server/log/log.go +++ b/internal/cmd/server/log/log.go @@ -66,7 +66,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -128,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetServerLogRequest { - return apiClient.GetServerLog(ctx, model.ProjectId, model.ServerId) + return apiClient.GetServerLog(ctx, model.ProjectId, model.Region, model.ServerId) } func outputResult(p *print.Printer, outputFormat, serverLabel, log string) error { diff --git a/internal/cmd/server/log/log_test.go b/internal/cmd/server/log/log_test.go index c1768f672..e9c0c657a 100644 --- a/internal/cmd/server/log/log_test.go +++ b/internal/cmd/server/log/log_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,7 +39,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + lengthLimitFlag: "3000", } for _, mod := range mods { @@ -51,6 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, Length: utils.Ptr(int64(3000)), @@ -62,7 +67,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetServerLogRequest)) iaas.ApiGetServerLogRequest { - request := testClient.GetServerLog(testCtx, testProjectId, testServerId) + request := testClient.GetServerLog(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -100,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -108,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/machine-type/describe/describe.go b/internal/cmd/server/machine-type/describe/describe.go index 83544b540..2fbdae1de 100644 --- a/internal/cmd/server/machine-type/describe/describe.go +++ b/internal/cmd/server/machine-type/describe/describe.go @@ -87,7 +87,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetMachineTypeRequest { - return apiClient.GetMachineType(ctx, model.ProjectId, model.MachineType) + return apiClient.GetMachineType(ctx, model.ProjectId, model.Region, model.MachineType) } func outputResult(p *print.Printer, outputFormat string, machineType *iaas.MachineType) error { diff --git a/internal/cmd/server/machine-type/describe/describe_test.go b/internal/cmd/server/machine-type/describe/describe_test.go index 81c992468..f423455f6 100644 --- a/internal/cmd/server/machine-type/describe/describe_test.go +++ b/internal/cmd/server/machine-type/describe/describe_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -36,7 +38,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, MachineType: testMachineType, @@ -59,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetMachineTypeRequest)) iaas.ApiGetMachineTypeRequest { - request := testClient.GetMachineType(testCtx, testProjectId, testMachineType) + request := testClient.GetMachineType(testCtx, testProjectId, testRegion, testMachineType) for _, mod := range mods { mod(&request) } @@ -103,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +123,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go index 833de684e..db88e7be5 100644 --- a/internal/cmd/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -120,7 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListMachineTypesRequest { - return apiClient.ListMachineTypes(ctx, model.ProjectId) + return apiClient.ListMachineTypes(ctx, model.ProjectId, model.Region) } func outputResult(p *print.Printer, outputFormat string, machineTypes iaas.MachineTypeListResponse) error { diff --git a/internal/cmd/server/machine-type/list/list_test.go b/internal/cmd/server/machine-type/list/list_test.go index db8906209..55b5c3c4a 100644 --- a/internal/cmd/server/machine-type/list/list_test.go +++ b/internal/cmd/server/machine-type/list/list_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -26,8 +28,10 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -40,6 +44,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), } @@ -50,7 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListMachineTypesRequest)) iaas.ApiListMachineTypesRequest { - request := testClient.ListMachineTypes(testCtx, testProjectId) + request := testClient.ListMachineTypes(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -84,21 +89,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/network-interface/attach/attach.go b/internal/cmd/server/network-interface/attach/attach.go index 1d774ffea..639c070a0 100644 --- a/internal/cmd/server/network-interface/attach/attach.go +++ b/internal/cmd/server/network-interface/attach/attach.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, *model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId @@ -73,7 +73,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { // if the create flag is provided a network interface will be created and attached if model.Create != nil && *model.Create { - networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.Region, *model.NetworkId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = *model.NetworkId @@ -157,9 +157,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequestAttach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddNicToServerRequest { - return apiClient.AddNicToServer(ctx, model.ProjectId, *model.ServerId, *model.NicId) + return apiClient.AddNicToServer(ctx, model.ProjectId, model.Region, *model.ServerId, *model.NicId) } func buildRequestCreateAndAttach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddNetworkToServerRequest { - return apiClient.AddNetworkToServer(ctx, model.ProjectId, *model.ServerId, *model.NetworkId) + return apiClient.AddNetworkToServer(ctx, model.ProjectId, model.Region, *model.ServerId, *model.NetworkId) } diff --git a/internal/cmd/server/network-interface/attach/attach_test.go b/internal/cmd/server/network-interface/attach/attach_test.go index 697562536..6e2898b32 100644 --- a/internal/cmd/server/network-interface/attach/attach_test.go +++ b/internal/cmd/server/network-interface/attach/attach_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -28,7 +30,9 @@ var testNetworkId = uuid.NewString() // contains nic id func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, networkInterfaceIdFlag: testNicId, } @@ -43,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: utils.Ptr(testServerId), NicId: utils.Ptr(testNicId), @@ -54,7 +59,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequestAttach(mods ...func(request *iaas.ApiAddNicToServerRequest)) iaas.ApiAddNicToServerRequest { - request := testClient.AddNicToServer(testCtx, testProjectId, testServerId, testNicId) + request := testClient.AddNicToServer(testCtx, testProjectId, testRegion, testServerId, testNicId) for _, mod := range mods { mod(&request) } @@ -62,7 +67,7 @@ func fixtureRequestAttach(mods ...func(request *iaas.ApiAddNicToServerRequest)) } func fixtureRequestCreateAndAttach(mods ...func(request *iaas.ApiAddNetworkToServerRequest)) iaas.ApiAddNetworkToServerRequest { - request := testClient.AddNetworkToServer(testCtx, testProjectId, testServerId, testNetworkId) + request := testClient.AddNetworkToServer(testCtx, testProjectId, testRegion, testServerId, testNetworkId) for _, mod := range mods { mod(&request) } @@ -91,21 +96,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/network-interface/detach/detach.go b/internal/cmd/server/network-interface/detach/detach.go index b8afad878..287b715f4 100644 --- a/internal/cmd/server/network-interface/detach/detach.go +++ b/internal/cmd/server/network-interface/detach/detach.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, *model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = *model.ServerId @@ -75,7 +75,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { // if the delete flag is provided a network interface is detached and deleted if model.Delete != nil && *model.Delete { - networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId) + networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.Region, *model.NetworkId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = *model.NetworkId @@ -159,9 +159,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequestDetach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveNicFromServerRequest { - return apiClient.RemoveNicFromServer(ctx, model.ProjectId, *model.ServerId, *model.NicId) + return apiClient.RemoveNicFromServer(ctx, model.ProjectId, model.Region, *model.ServerId, *model.NicId) } func buildRequestDetachAndDelete(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveNetworkFromServerRequest { - return apiClient.RemoveNetworkFromServer(ctx, model.ProjectId, *model.ServerId, *model.NetworkId) + return apiClient.RemoveNetworkFromServer(ctx, model.ProjectId, model.Region, *model.ServerId, *model.NetworkId) } diff --git a/internal/cmd/server/network-interface/detach/detach_test.go b/internal/cmd/server/network-interface/detach/detach_test.go index 1eef8529a..4946e3e41 100644 --- a/internal/cmd/server/network-interface/detach/detach_test.go +++ b/internal/cmd/server/network-interface/detach/detach_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -28,7 +30,9 @@ var testNetworkId = uuid.NewString() // contains nic id func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, networkInterfaceIdFlag: testNicId, } @@ -43,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: utils.Ptr(testServerId), NicId: utils.Ptr(testNicId), @@ -54,7 +59,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequestDetach(mods ...func(request *iaas.ApiRemoveNicFromServerRequest)) iaas.ApiRemoveNicFromServerRequest { - request := testClient.RemoveNicFromServer(testCtx, testProjectId, testServerId, testNicId) + request := testClient.RemoveNicFromServer(testCtx, testProjectId, testRegion, testServerId, testNicId) for _, mod := range mods { mod(&request) } @@ -62,7 +67,7 @@ func fixtureRequestDetach(mods ...func(request *iaas.ApiRemoveNicFromServerReque } func fixtureRequestDetachAndDelete(mods ...func(request *iaas.ApiRemoveNetworkFromServerRequest)) iaas.ApiRemoveNetworkFromServerRequest { - request := testClient.RemoveNetworkFromServer(testCtx, testProjectId, testServerId, testNetworkId) + request := testClient.RemoveNetworkFromServer(testCtx, testProjectId, testRegion, testServerId, testNetworkId) for _, mod := range mods { mod(&request) } @@ -91,21 +96,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/network-interface/list/list.go b/internal/cmd/server/network-interface/list/list.go index ef8f70ca7..a63095dd6 100644 --- a/internal/cmd/server/network-interface/list/list.go +++ b/internal/cmd/server/network-interface/list/list.go @@ -26,7 +26,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string Limit *int64 } @@ -71,12 +71,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } if resp.Items == nil || len(*resp.Items) == 0 { - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } params.Printer.Info("No attached network interfaces found for server %q\n", serverLabel) return nil @@ -88,7 +88,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { items = items[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, *model.ServerId, items) + return outputResult(params.Printer, model.OutputFormat, model.ServerId, items) }, } configureFlags(cmd) @@ -119,7 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), Limit: limit, } @@ -127,8 +127,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServerNicsRequest { - return apiClient.ListServerNics(ctx, model.ProjectId, *model.ServerId) +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServerNICsRequest { + return apiClient.ListServerNICs(ctx, model.ProjectId, model.Region, model.ServerId) } func outputResult(p *print.Printer, outputFormat, serverId string, serverNics []iaas.NIC) error { diff --git a/internal/cmd/server/network-interface/list/list_test.go b/internal/cmd/server/network-interface/list/list_test.go index 4b91f4742..3c93f92c3 100644 --- a/internal/cmd/server/network-interface/list/list_test.go +++ b/internal/cmd/server/network-interface/list/list_test.go @@ -16,7 +16,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,9 +29,11 @@ var testServerId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + limitFlag: "10", + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -42,9 +46,10 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, } for _, mod := range mods { mod(model) @@ -52,8 +57,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *iaas.ApiListServerNicsRequest)) iaas.ApiListServerNicsRequest { - request := testClient.ListServerNics(testCtx, testProjectId, testServerId) +func fixtureRequest(mods ...func(request *iaas.ApiListServerNICsRequest)) iaas.ApiListServerNICsRequest { + request := testClient.ListServerNICs(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -82,21 +87,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -148,7 +153,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest iaas.ApiListServerNicsRequest + expectedRequest iaas.ApiListServerNICsRequest }{ { description: "base", diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index 7af78387a..1c8bddf44 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -65,7 +65,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go index 3c9510b98..81086b85f 100644 --- a/internal/cmd/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go index c81c27b44..c2538aa0f 100644 --- a/internal/cmd/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go index 5ce2a5c27..94112f256 100644 --- a/internal/cmd/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -71,7 +71,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index 76dd76235..b9c1e3a1a 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -73,7 +73,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go index b9721cca8..4047fba6d 100644 --- a/internal/cmd/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -70,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serverLabel := model.ServerId // Get server name if iaasApiClient, err := iaasClient.ConfigureClient(params.Printer, params.CliVersion); err == nil { - serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, iaasApiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) } else if serverName != "" { diff --git a/internal/cmd/server/public-ip/attach/attach.go b/internal/cmd/server/public-ip/attach/attach.go index 763583606..3f76d8852 100644 --- a/internal/cmd/server/public-ip/attach/attach.go +++ b/internal/cmd/server/public-ip/attach/attach.go @@ -26,7 +26,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string PublicIpId string } @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.Region, model.PublicIpId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get public ip name: %v", err) publicIpLabel = model.PublicIpId @@ -62,12 +62,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { publicIpLabel = model.PublicIpId } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } if !model.AssumeYes { @@ -109,7 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), PublicIpId: volumeId, } @@ -118,5 +118,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddPublicIpToServerRequest { - return apiClient.AddPublicIpToServer(ctx, model.ProjectId, *model.ServerId, model.PublicIpId) + return apiClient.AddPublicIpToServer(ctx, model.ProjectId, model.Region, model.ServerId, model.PublicIpId) } diff --git a/internal/cmd/server/public-ip/attach/attach_test.go b/internal/cmd/server/public-ip/attach/attach_test.go index c58f7b280..3f0e10763 100644 --- a/internal/cmd/server/public-ip/attach/attach_test.go +++ b/internal/cmd/server/public-ip/attach/attach_test.go @@ -4,18 +4,18 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +37,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -51,8 +53,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, PublicIpId: testPublicIpId, } for _, mod := range mods { @@ -62,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiAddPublicIpToServerRequest)) iaas.ApiAddPublicIpToServerRequest { - request := testClient.AddPublicIpToServer(testCtx, testProjectId, testServerId, testPublicIpId) + request := testClient.AddPublicIpToServer(testCtx, testProjectId, testRegion, testServerId, testPublicIpId) for _, mod := range mods { mod(&request) } @@ -94,7 +97,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -102,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -110,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/public-ip/detach/detach.go b/internal/cmd/server/public-ip/detach/detach.go index 6294187d8..ecf43cba5 100644 --- a/internal/cmd/server/public-ip/detach/detach.go +++ b/internal/cmd/server/public-ip/detach/detach.go @@ -26,7 +26,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string PublicIpId string } @@ -55,7 +55,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.PublicIpId) + publicIpLabel, _, err := iaasUtils.GetPublicIP(ctx, apiClient, model.ProjectId, model.Region, model.PublicIpId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get public ip: %v", err) publicIpLabel = model.PublicIpId @@ -63,12 +63,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { publicIpLabel = model.PublicIpId } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } if !model.AssumeYes { @@ -110,7 +110,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), PublicIpId: publicIpId, } @@ -119,5 +119,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemovePublicIpFromServerRequest { - return apiClient.RemovePublicIpFromServer(ctx, model.ProjectId, *model.ServerId, model.PublicIpId) + return apiClient.RemovePublicIpFromServer(ctx, model.ProjectId, model.Region, model.ServerId, model.PublicIpId) } diff --git a/internal/cmd/server/public-ip/detach/detach_test.go b/internal/cmd/server/public-ip/detach/detach_test.go index 8a46591a7..ccea98e12 100644 --- a/internal/cmd/server/public-ip/detach/detach_test.go +++ b/internal/cmd/server/public-ip/detach/detach_test.go @@ -7,7 +7,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -15,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +38,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -51,8 +53,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, PublicIpId: testPublicIpId, } for _, mod := range mods { @@ -62,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiRemovePublicIpFromServerRequest)) iaas.ApiRemovePublicIpFromServerRequest { - request := testClient.RemovePublicIpFromServer(testCtx, testProjectId, testServerId, testPublicIpId) + request := testClient.RemovePublicIpFromServer(testCtx, testProjectId, testRegion, testServerId, testPublicIpId) for _, mod := range mods { mod(&request) } @@ -93,7 +96,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -101,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -109,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/reboot/reboot.go b/internal/cmd/server/reboot/reboot.go index 445321295..ed13d02ce 100644 --- a/internal/cmd/server/reboot/reboot.go +++ b/internal/cmd/server/reboot/reboot.go @@ -62,7 +62,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -116,7 +116,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRebootServerRequest { - req := apiClient.RebootServer(ctx, model.ProjectId, model.ServerId) + req := apiClient.RebootServer(ctx, model.ProjectId, model.Region, model.ServerId) // if hard reboot is set the action must be set (soft is default) if model.HardReboot { req = req.Action(hardRebootAction) diff --git a/internal/cmd/server/reboot/reboot_test.go b/internal/cmd/server/reboot/reboot_test.go index 074ba2a84..1a05016e1 100644 --- a/internal/cmd/server/reboot/reboot_test.go +++ b/internal/cmd/server/reboot/reboot_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + hardRebootFlag: "false", } for _, mod := range mods { @@ -48,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, HardReboot: false, @@ -59,7 +64,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiRebootServerRequest)) iaas.ApiRebootServerRequest { - request := testClient.RebootServer(testCtx, testProjectId, testServerId) + request := testClient.RebootServer(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -97,7 +102,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -105,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/rescue/rescue.go b/internal/cmd/server/rescue/rescue.go index 65dc2633d..3ae4f99b5 100644 --- a/internal/cmd/server/rescue/rescue.go +++ b/internal/cmd/server/rescue/rescue.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -85,7 +85,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Rescuing server") - _, err = wait.RescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + _, err = wait.RescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for server rescuing: %w", err) } @@ -131,7 +131,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRescueServerRequest { - req := apiClient.RescueServer(ctx, model.ProjectId, model.ServerId) + req := apiClient.RescueServer(ctx, model.ProjectId, model.Region, model.ServerId) payload := iaas.RescueServerPayload{ Image: model.ImageId, } diff --git a/internal/cmd/server/rescue/rescue_test.go b/internal/cmd/server/rescue/rescue_test.go index d3e6e3c50..b7ec93e90 100644 --- a/internal/cmd/server/rescue/rescue_test.go +++ b/internal/cmd/server/rescue/rescue_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -36,8 +38,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - imageIdFlag: testImageId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + imageIdFlag: testImageId, } for _, mod := range mods { mod(flagValues) @@ -50,6 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, ImageId: utils.Ptr(testImageId), @@ -61,7 +66,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiRescueServerRequest)) iaas.ApiRescueServerRequest { - request := testClient.RescueServer(testCtx, testProjectId, testServerId) + request := testClient.RescueServer(testCtx, testProjectId, testRegion, testServerId) request = request.RescueServerPayload(iaas.RescueServerPayload{ Image: utils.Ptr(testImageId), }) @@ -104,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +125,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/resize/resize.go b/internal/cmd/server/resize/resize.go index f23826188..329d5a6b4 100644 --- a/internal/cmd/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -58,7 +58,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -85,7 +85,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Resizing server") - _, err = wait.ResizeServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + _, err = wait.ResizeServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for server resizing: %w", err) } @@ -131,7 +131,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiResizeServerRequest { - req := apiClient.ResizeServer(ctx, model.ProjectId, model.ServerId) + req := apiClient.ResizeServer(ctx, model.ProjectId, model.Region, model.ServerId) payload := iaas.ResizeServerPayload{ MachineType: model.MachineType, } diff --git a/internal/cmd/server/resize/resize_test.go b/internal/cmd/server/resize/resize_test.go index 231d7c1c0..3ba39088f 100644 --- a/internal/cmd/server/resize/resize_test.go +++ b/internal/cmd/server/resize/resize_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -35,7 +37,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + machineTypeFlag: "t1.2", } for _, mod := range mods { @@ -49,6 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, MachineType: utils.Ptr("t1.2"), @@ -60,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiResizeServerRequest)) iaas.ApiResizeServerRequest { - request := testClient.ResizeServer(testCtx, testProjectId, testServerId) + request := testClient.ResizeServer(testCtx, testProjectId, testRegion, testServerId) request = request.ResizeServerPayload(iaas.ResizeServerPayload{ MachineType: utils.Ptr("t1.2"), }) @@ -103,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +124,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 3979e0398..5644ee45f 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -26,7 +26,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string ServiceAccMail string } @@ -54,12 +54,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } if !model.AssumeYes { @@ -100,7 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), ServiceAccMail: serviceAccMail, } @@ -109,7 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddServiceAccountToServerRequest { - req := apiClient.AddServiceAccountToServer(ctx, model.ProjectId, *model.ServerId, model.ServiceAccMail) + req := apiClient.AddServiceAccountToServer(ctx, model.ProjectId, model.Region, model.ServerId, model.ServiceAccMail) return req } diff --git a/internal/cmd/server/service-account/attach/attach_test.go b/internal/cmd/server/service-account/attach/attach_test.go index 96ed151ce..0edf073b4 100644 --- a/internal/cmd/server/service-account/attach/attach_test.go +++ b/internal/cmd/server/service-account/attach/attach_test.go @@ -7,7 +7,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/google/go-cmp/cmp" @@ -15,7 +14,9 @@ import ( "github.com/google/uuid" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +38,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -51,8 +54,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, ServiceAccMail: testServiceAccount, } for _, mod := range mods { @@ -62,7 +66,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiAddServiceAccountToServerRequest)) iaas.ApiAddServiceAccountToServerRequest { - request := testClient.AddServiceAccountToServer(testCtx, testProjectId, testServerId, testServiceAccount) + request := testClient.AddServiceAccountToServer(testCtx, testProjectId, testRegion, testServerId, testServiceAccount) for _, mod := range mods { mod(&request) } @@ -94,7 +98,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -102,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -110,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 934ed766d..59966f6d5 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -26,7 +26,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string ServiceAccMail string } @@ -54,12 +54,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } if !model.AssumeYes { @@ -100,7 +100,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), ServiceAccMail: serviceAccMail, } @@ -109,7 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveServiceAccountFromServerRequest { - req := apiClient.RemoveServiceAccountFromServer(ctx, model.ProjectId, *model.ServerId, model.ServiceAccMail) + req := apiClient.RemoveServiceAccountFromServer(ctx, model.ProjectId, model.Region, model.ServerId, model.ServiceAccMail) return req } diff --git a/internal/cmd/server/service-account/detach/detach_test.go b/internal/cmd/server/service-account/detach/detach_test.go index acfd02802..a1e6c89cd 100644 --- a/internal/cmd/server/service-account/detach/detach_test.go +++ b/internal/cmd/server/service-account/detach/detach_test.go @@ -7,7 +7,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" "github.com/google/go-cmp/cmp" @@ -15,7 +14,9 @@ import ( "github.com/google/uuid" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +38,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -51,8 +54,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, ServiceAccMail: testServiceAccount, } for _, mod := range mods { @@ -62,7 +66,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiRemoveServiceAccountFromServerRequest)) iaas.ApiRemoveServiceAccountFromServerRequest { - request := testClient.RemoveServiceAccountFromServer(testCtx, testProjectId, testServerId, testServiceAccount) + request := testClient.RemoveServiceAccountFromServer(testCtx, testProjectId, testRegion, testServerId, testServiceAccount) for _, mod := range mods { mod(&request) } @@ -94,7 +98,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -102,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -110,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/service-account/list/list.go b/internal/cmd/server/service-account/list/list.go index 5bf727bc7..95773fc6e 100644 --- a/internal/cmd/server/service-account/list/list.go +++ b/internal/cmd/server/service-account/list/list.go @@ -26,7 +26,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel Limit *int64 - ServerId *string + ServerId string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -62,12 +62,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverName, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverName, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverName = *model.ServerId + serverName = model.ServerId } else if serverName == "" { - serverName = *model.ServerId + serverName = model.ServerId } // Call API @@ -86,7 +86,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { serviceAccounts = serviceAccounts[:int(*model.Limit)] } - return outputResult(params.Printer, model.OutputFormat, *model.ServerId, serverName, serviceAccounts) + return outputResult(params.Printer, model.OutputFormat, model.ServerId, serverName, serviceAccounts) }, } configureFlags(cmd) @@ -118,7 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, model := inputModel{ GlobalFlagModel: globalFlags, Limit: limit, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } p.DebugInputModel(model) @@ -126,7 +126,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListServerServiceAccountsRequest { - req := apiClient.ListServerServiceAccounts(ctx, model.ProjectId, *model.ServerId) + req := apiClient.ListServerServiceAccounts(ctx, model.ProjectId, model.Region, model.ServerId) return req } diff --git a/internal/cmd/server/service-account/list/list_test.go b/internal/cmd/server/service-account/list/list_test.go index d2a0c159a..a58d5e671 100644 --- a/internal/cmd/server/service-account/list/list_test.go +++ b/internal/cmd/server/service-account/list/list_test.go @@ -17,7 +17,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -29,9 +31,11 @@ var testLimit = int64(10) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, - limitFlag: strconv.FormatInt(testLimit, 10), + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + serverIdFlag: testServerId, + limitFlag: strconv.FormatInt(testLimit, 10), } for _, mod := range mods { mod(flagValues) @@ -44,8 +48,9 @@ func fixtureInputModel(mods ...func(inputModel *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, Limit: utils.Ptr(testLimit), } for _, mod := range mods { @@ -55,7 +60,7 @@ func fixtureInputModel(mods ...func(inputModel *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListServerServiceAccountsRequest)) iaas.ApiListServerServiceAccountsRequest { - request := testClient.ListServerServiceAccounts(testCtx, testProjectId, testServerId) + request := testClient.ListServerServiceAccounts(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -84,21 +89,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/start/start.go b/internal/cmd/server/start/start.go index 9ebabdf70..e025e2890 100644 --- a/internal/cmd/server/start/start.go +++ b/internal/cmd/server/start/start.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -73,7 +73,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Starting server") - _, err = wait.StartServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + _, err = wait.StartServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for server starting: %w", err) } @@ -110,5 +110,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiStartServerRequest { - return apiClient.StartServer(ctx, model.ProjectId, model.ServerId) + return apiClient.StartServer(ctx, model.ProjectId, model.Region, model.ServerId) } diff --git a/internal/cmd/server/start/start_test.go b/internal/cmd/server/start/start_test.go index f028d85d9..f5e64b2d2 100644 --- a/internal/cmd/server/start/start_test.go +++ b/internal/cmd/server/start/start_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiStartServerRequest)) iaas.ApiStartServerRequest { - request := testClient.StartServer(testCtx, testProjectId, testServerId) + request := testClient.StartServer(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -95,7 +99,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -103,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/stop/stop.go b/internal/cmd/server/stop/stop.go index d91c1931c..958127da7 100644 --- a/internal/cmd/server/stop/stop.go +++ b/internal/cmd/server/stop/stop.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -81,7 +81,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Stopping server") - _, err = wait.StopServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + _, err = wait.StopServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for server stopping: %w", err) } @@ -118,5 +118,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiStopServerRequest { - return apiClient.StopServer(ctx, model.ProjectId, model.ServerId) + return apiClient.StopServer(ctx, model.ProjectId, model.Region, model.ServerId) } diff --git a/internal/cmd/server/stop/stop_test.go b/internal/cmd/server/stop/stop_test.go index 7aba2f968..29980a4b9 100644 --- a/internal/cmd/server/stop/stop_test.go +++ b/internal/cmd/server/stop/stop_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiStopServerRequest)) iaas.ApiStopServerRequest { - request := testClient.StopServer(testCtx, testProjectId, testServerId) + request := testClient.StopServer(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -95,7 +99,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -103,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/unrescue/unrescue.go b/internal/cmd/server/unrescue/unrescue.go index 47b6cf018..6f433ebeb 100644 --- a/internal/cmd/server/unrescue/unrescue.go +++ b/internal/cmd/server/unrescue/unrescue.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -81,7 +81,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Unrescuing server") - _, err = wait.UnrescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.ServerId).WaitWithContext(ctx) + _, err = wait.UnrescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for server unrescuing: %w", err) } @@ -118,5 +118,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUnrescueServerRequest { - return apiClient.UnrescueServer(ctx, model.ProjectId, model.ServerId) + return apiClient.UnrescueServer(ctx, model.ProjectId, model.Region, model.ServerId) } diff --git a/internal/cmd/server/unrescue/unrescue_test.go b/internal/cmd/server/unrescue/unrescue_test.go index 8161f03d4..708fe68d8 100644 --- a/internal/cmd/server/unrescue/unrescue_test.go +++ b/internal/cmd/server/unrescue/unrescue_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, ServerId: testServerId, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUnrescueServerRequest)) iaas.ApiUnrescueServerRequest { - request := testClient.UnrescueServer(testCtx, testProjectId, testServerId) + request := testClient.UnrescueServer(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -95,7 +99,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -103,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/update/update.go b/internal/cmd/server/update/update.go index 5567be1bf..f8b404794 100644 --- a/internal/cmd/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -61,7 +61,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) serverLabel = model.ServerId @@ -116,7 +116,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateServerRequest { - req := apiClient.UpdateServer(ctx, model.ProjectId, model.ServerId) + req := apiClient.UpdateServer(ctx, model.ProjectId, model.Region, model.ServerId) payload := iaas.UpdateServerPayload{ Name: model.Name, diff --git a/internal/cmd/server/update/update_test.go b/internal/cmd/server/update/update_test.go index 63398311e..d13d32c87 100644 --- a/internal/cmd/server/update/update_test.go +++ b/internal/cmd/server/update/update_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,9 +39,11 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - nameFlag: "example-server-name", - projectIdFlag: testProjectId, - labelFlag: "key=value", + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + nameFlag: "example-server-name", + labelFlag: "key=value", } for _, mod := range mods { mod(flagValues) @@ -51,6 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Name: utils.Ptr("example-server-name"), @@ -66,7 +71,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdateServerRequest)) iaas.ApiUpdateServerRequest { - request := testClient.UpdateServer(testCtx, testProjectId, testServerId) + request := testClient.UpdateServer(testCtx, testProjectId, testRegion, testServerId) request = request.UpdateServerPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -112,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -120,7 +125,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -128,7 +133,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go index ba736f285..65a631ddf 100644 --- a/internal/cmd/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -29,7 +29,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string VolumeId string DeleteOnTermination *bool } @@ -63,18 +63,18 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } if !model.AssumeYes { @@ -116,7 +116,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), DeleteOnTermination: flags.FlagToBoolPointer(p, cmd, deleteOnTerminationFlag), VolumeId: volumeId, } @@ -126,7 +126,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddVolumeToServerRequest { - req := apiClient.AddVolumeToServer(ctx, model.ProjectId, *model.ServerId, model.VolumeId) + req := apiClient.AddVolumeToServer(ctx, model.ProjectId, model.Region, model.ServerId, model.VolumeId) payload := iaas.AddVolumeToServerPayload{ DeleteOnTermination: model.DeleteOnTermination, } diff --git a/internal/cmd/server/volume/attach/attach_test.go b/internal/cmd/server/volume/attach/attach_test.go index 9a180a4c0..2f3ed3e69 100644 --- a/internal/cmd/server/volume/attach/attach_test.go +++ b/internal/cmd/server/volume/attach/attach_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,7 +39,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, deleteOnTerminationFlag: "true", } @@ -52,8 +56,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, VolumeId: testVolumeId, DeleteOnTermination: utils.Ptr(true), } @@ -74,7 +79,7 @@ func fixturePayload(mods ...func(payload *iaas.AddVolumeToServerPayload)) iaas.A } func fixtureRequest(mods ...func(request *iaas.ApiAddVolumeToServerRequest)) iaas.ApiAddVolumeToServerRequest { - request := testClient.AddVolumeToServer(testCtx, testProjectId, testServerId, testVolumeId) + request := testClient.AddVolumeToServer(testCtx, testProjectId, testRegion, testServerId, testVolumeId) request = request.AddVolumeToServerPayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -107,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -115,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -123,7 +128,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/volume/describe/describe.go b/internal/cmd/server/volume/describe/describe.go index 2a0a97d24..4c0288851 100644 --- a/internal/cmd/server/volume/describe/describe.go +++ b/internal/cmd/server/volume/describe/describe.go @@ -26,7 +26,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string VolumeId string } @@ -63,18 +63,18 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } // Call API @@ -107,7 +107,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), VolumeId: volumeId, } @@ -116,7 +116,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetAttachedVolumeRequest { - req := apiClient.GetAttachedVolume(ctx, model.ProjectId, *model.ServerId, model.VolumeId) + req := apiClient.GetAttachedVolume(ctx, model.ProjectId, model.Region, model.ServerId, model.VolumeId) return req } diff --git a/internal/cmd/server/volume/describe/describe_test.go b/internal/cmd/server/volume/describe/describe_test.go index f2182f04c..3d6634075 100644 --- a/internal/cmd/server/volume/describe/describe_test.go +++ b/internal/cmd/server/volume/describe/describe_test.go @@ -4,18 +4,18 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +37,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -51,8 +53,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, VolumeId: testVolumeId, } for _, mod := range mods { @@ -62,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetAttachedVolumeRequest)) iaas.ApiGetAttachedVolumeRequest { - request := testClient.GetAttachedVolume(testCtx, testProjectId, testServerId, testVolumeId) + request := testClient.GetAttachedVolume(testCtx, testProjectId, testRegion, testServerId, testVolumeId) for _, mod := range mods { mod(&request) } @@ -94,7 +97,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -102,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -110,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/volume/detach/detach.go b/internal/cmd/server/volume/detach/detach.go index e081295d6..5c271b8fe 100644 --- a/internal/cmd/server/volume/detach/detach.go +++ b/internal/cmd/server/volume/detach/detach.go @@ -26,7 +26,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string VolumeId string } @@ -55,18 +55,18 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } if !model.AssumeYes { @@ -108,7 +108,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), VolumeId: volumeId, } @@ -117,6 +117,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRemoveVolumeFromServerRequest { - req := apiClient.RemoveVolumeFromServer(ctx, model.ProjectId, *model.ServerId, model.VolumeId) + req := apiClient.RemoveVolumeFromServer(ctx, model.ProjectId, model.Region, model.ServerId, model.VolumeId) return req } diff --git a/internal/cmd/server/volume/detach/detach_test.go b/internal/cmd/server/volume/detach/detach_test.go index 4934e778d..e9ebecb32 100644 --- a/internal/cmd/server/volume/detach/detach_test.go +++ b/internal/cmd/server/volume/detach/detach_test.go @@ -4,18 +4,18 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +37,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -51,8 +53,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, VolumeId: testVolumeId, } for _, mod := range mods { @@ -62,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiRemoveVolumeFromServerRequest)) iaas.ApiRemoveVolumeFromServerRequest { - request := testClient.RemoveVolumeFromServer(testCtx, testProjectId, testServerId, testVolumeId) + request := testClient.RemoveVolumeFromServer(testCtx, testProjectId, testRegion, testServerId, testVolumeId) for _, mod := range mods { mod(&request) } @@ -93,7 +96,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -101,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -109,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go index 6f25321db..4dddab072 100644 --- a/internal/cmd/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -25,7 +25,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -55,12 +55,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } // Call API @@ -78,7 +78,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { // get volume names var volumeNames []string for i := range volumes { - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, *volumes[i].VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, *volumes[i].VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = "" @@ -108,7 +108,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), } p.DebugInputModel(model) @@ -116,7 +116,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListAttachedVolumesRequest { - req := apiClient.ListAttachedVolumes(ctx, model.ProjectId, *model.ServerId) + req := apiClient.ListAttachedVolumes(ctx, model.ProjectId, model.Region, model.ServerId) return req } diff --git a/internal/cmd/server/volume/list/list_test.go b/internal/cmd/server/volume/list/list_test.go index 6be36d7d6..82e73dff8 100644 --- a/internal/cmd/server/volume/list/list_test.go +++ b/internal/cmd/server/volume/list/list_test.go @@ -4,19 +4,19 @@ import ( "context" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,8 +27,10 @@ var testServerId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - serverIdFlag: testServerId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + serverIdFlag: testServerId, } for _, mod := range mods { mod(flagValues) @@ -41,8 +43,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, } for _, mod := range mods { mod(model) @@ -51,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListAttachedVolumesRequest)) iaas.ApiListAttachedVolumesRequest { - request := testClient.ListAttachedVolumes(testCtx, testProjectId, testServerId) + request := testClient.ListAttachedVolumes(testCtx, testProjectId, testRegion, testServerId) for _, mod := range mods { mod(&request) } @@ -80,21 +83,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go index 471dde5c0..12c7e66ee 100644 --- a/internal/cmd/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -29,7 +29,7 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - ServerId *string + ServerId string VolumeId string DeleteOnTermination *bool } @@ -59,18 +59,18 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId } - serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId) + serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, model.Region, model.ServerId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get server name: %v", err) - serverLabel = *model.ServerId + serverLabel = model.ServerId } else if serverLabel == "" { - serverLabel = *model.ServerId + serverLabel = model.ServerId } if !model.AssumeYes { @@ -112,7 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu model := inputModel{ GlobalFlagModel: globalFlags, - ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag), + ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), DeleteOnTermination: flags.FlagToBoolPointer(p, cmd, deleteOnTerminationFlag), VolumeId: volumeId, } @@ -122,7 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateAttachedVolumeRequest { - req := apiClient.UpdateAttachedVolume(ctx, model.ProjectId, *model.ServerId, model.VolumeId) + req := apiClient.UpdateAttachedVolume(ctx, model.ProjectId, model.Region, model.ServerId, model.VolumeId) payload := iaas.UpdateAttachedVolumePayload{ DeleteOnTermination: model.DeleteOnTermination, } diff --git a/internal/cmd/server/volume/update/update_test.go b/internal/cmd/server/volume/update/update_test.go index 1f820cff2..a15d5e810 100644 --- a/internal/cmd/server/volume/update/update_test.go +++ b/internal/cmd/server/volume/update/update_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,7 +39,9 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + serverIdFlag: testServerId, deleteOnTerminationFlag: "true", } @@ -52,8 +56,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, - ServerId: utils.Ptr(testServerId), + ServerId: testServerId, VolumeId: testVolumeId, DeleteOnTermination: utils.Ptr(true), } @@ -74,7 +79,7 @@ func fixturePayload(mods ...func(payload *iaas.UpdateAttachedVolumePayload)) iaa } func fixtureRequest(mods ...func(request *iaas.ApiUpdateAttachedVolumeRequest)) iaas.ApiUpdateAttachedVolumeRequest { - request := testClient.UpdateAttachedVolume(testCtx, testProjectId, testServerId, testVolumeId) + request := testClient.UpdateAttachedVolume(testCtx, testProjectId, testRegion, testServerId, testVolumeId) request = request.UpdateAttachedVolumePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -106,7 +111,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -114,7 +119,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -122,7 +127,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/volume/backup/create/create.go b/internal/cmd/volume/backup/create/create.go index 4245716e9..316efc520 100644 --- a/internal/cmd/volume/backup/create/create.go +++ b/internal/cmd/volume/backup/create/create.go @@ -78,14 +78,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { // Get source name for label (use ID if name not available) sourceLabel := model.SourceID if model.SourceType == "volume" { - name, err := iaasutils.GetVolumeName(ctx, apiClient, model.ProjectId, model.SourceID) + name, err := iaasutils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.SourceID) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) } else if name != "" { sourceLabel = name } } else if model.SourceType == "snapshot" { - name, err := iaasutils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.SourceID) + name, err := iaasutils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.Region, model.SourceID) if err != nil { params.Printer.Debug(print.ErrorLevel, "get snapshot name: %v", err) } else if name != "" { @@ -107,12 +107,16 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("create volume backup: %w", err) } + if resp == nil || resp.Id == nil { + return fmt.Errorf("create volume: empty response") + } + volumeId := *resp.Id // Wait for async operation, if async mode not enabled if !model.Async { s := spinner.New(params.Printer) s.Start("Creating backup") - resp, err = wait.CreateBackupWaitHandler(ctx, apiClient, model.ProjectId, *resp.Id).WaitWithContext(ctx) + resp, err = wait.CreateBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for backup creation: %w", err) } @@ -169,7 +173,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateBackupRequest { - req := apiClient.CreateBackup(ctx, model.ProjectId) + req := apiClient.CreateBackup(ctx, model.ProjectId, model.Region) payload := iaas.CreateBackupPayload{ Name: model.Name, diff --git a/internal/cmd/volume/backup/create/create_test.go b/internal/cmd/volume/backup/create/create_test.go index 2132d89f8..3f4e64d15 100644 --- a/internal/cmd/volume/backup/create/create_test.go +++ b/internal/cmd/volume/backup/create/create_test.go @@ -16,13 +16,14 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -type testCtxKey struct{} - const ( + testRegion = "eu01" testName = "my-backup" testSourceType = "volume" ) +type testCtxKey struct{} + var ( testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") testClient = &iaas.APIClient{} @@ -34,10 +35,12 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, - sourceIdFlag: testSourceId, - sourceTypeFlag: testSourceType, - nameFlag: testName, - labelsFlag: "key1=value1", + globalflags.RegionFlag: testRegion, + + sourceIdFlag: testSourceId, + sourceTypeFlag: testSourceType, + nameFlag: testName, + labelsFlag: "key1=value1", } for _, mod := range mods { mod(flagValues) @@ -50,6 +53,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, SourceID: testSourceId, SourceType: testSourceType, @@ -63,7 +67,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateBackupRequest)) iaas.ApiCreateBackupRequest { - request := testClient.CreateBackup(testCtx, testProjectId) + request := testClient.CreateBackup(testCtx, testProjectId, testRegion) createPayload := iaas.NewCreateBackupPayloadWithDefaults() createPayload.Name = utils.Ptr(testName) diff --git a/internal/cmd/volume/backup/delete/delete.go b/internal/cmd/volume/backup/delete/delete.go index de63990bd..b439f0d6d 100644 --- a/internal/cmd/volume/backup/delete/delete.go +++ b/internal/cmd/volume/backup/delete/delete.go @@ -52,7 +52,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.BackupId) + backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.Region, model.BackupId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get backup name: %v", err) } @@ -76,7 +76,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Deleting backup") - _, err = wait.DeleteBackupWaitHandler(ctx, apiClient, model.ProjectId, model.BackupId).WaitWithContext(ctx) + _, err = wait.DeleteBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for backup deletion: %w", err) } @@ -112,6 +112,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteBackupRequest { - req := apiClient.DeleteBackup(ctx, model.ProjectId, model.BackupId) + req := apiClient.DeleteBackup(ctx, model.ProjectId, model.Region, model.BackupId) return req } diff --git a/internal/cmd/volume/backup/delete/delete_test.go b/internal/cmd/volume/backup/delete/delete_test.go index a0146e406..26623975f 100644 --- a/internal/cmd/volume/backup/delete/delete_test.go +++ b/internal/cmd/volume/backup/delete/delete_test.go @@ -13,6 +13,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var ( @@ -35,6 +39,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { 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) @@ -47,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, BackupId: testBackupId, } @@ -57,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteBackupRequest)) iaas.ApiDeleteBackupRequest { - request := testClient.DeleteBackup(testCtx, testProjectId, testBackupId) + request := testClient.DeleteBackup(testCtx, testProjectId, testRegion, testBackupId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/volume/backup/describe/describe.go b/internal/cmd/volume/backup/describe/describe.go index f836b32b2..3f95fe355 100644 --- a/internal/cmd/volume/backup/describe/describe.go +++ b/internal/cmd/volume/backup/describe/describe.go @@ -86,7 +86,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetBackupRequest { - req := apiClient.GetBackup(ctx, model.ProjectId, model.BackupId) + req := apiClient.GetBackup(ctx, model.ProjectId, model.Region, model.BackupId) return req } diff --git a/internal/cmd/volume/backup/describe/describe_test.go b/internal/cmd/volume/backup/describe/describe_test.go index 0ff77ca24..1ba033cb2 100644 --- a/internal/cmd/volume/backup/describe/describe_test.go +++ b/internal/cmd/volume/backup/describe/describe_test.go @@ -15,6 +15,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var ( @@ -37,6 +41,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { 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) @@ -49,6 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, BackupId: testBackupId, } @@ -59,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetBackupRequest)) iaas.ApiGetBackupRequest { - request := testClient.GetBackup(testCtx, testProjectId, testBackupId) + request := testClient.GetBackup(testCtx, testProjectId, testRegion, testBackupId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/volume/backup/list/list.go b/internal/cmd/volume/backup/list/list.go index 82580a440..825a6793e 100644 --- a/internal/cmd/volume/backup/list/list.go +++ b/internal/cmd/volume/backup/list/list.go @@ -126,7 +126,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListBackupsRequest { - req := apiClient.ListBackups(ctx, model.ProjectId) + req := apiClient.ListBackups(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) diff --git a/internal/cmd/volume/backup/list/list_test.go b/internal/cmd/volume/backup/list/list_test.go index f3616ef3c..3734dc1f7 100644 --- a/internal/cmd/volume/backup/list/list_test.go +++ b/internal/cmd/volume/backup/list/list_test.go @@ -16,6 +16,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var ( @@ -27,8 +31,10 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, - limitFlag: "10", - labelSelectorFlag: "key1=value1", + globalflags.RegionFlag: testRegion, + + limitFlag: "10", + labelSelectorFlag: "key1=value1", } for _, mod := range mods { mod(flagValues) @@ -40,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -52,7 +59,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListBackupsRequest)) iaas.ApiListBackupsRequest { - request := testClient.ListBackups(testCtx, testProjectId) + request := testClient.ListBackups(testCtx, testProjectId, testRegion) request = request.LabelSelector("key1=value1") for _, mod := range mods { mod(&request) diff --git a/internal/cmd/volume/backup/restore/restore.go b/internal/cmd/volume/backup/restore/restore.go index 04301a51d..3922c4ae8 100644 --- a/internal/cmd/volume/backup/restore/restore.go +++ b/internal/cmd/volume/backup/restore/restore.go @@ -52,17 +52,17 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.BackupId) + backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.Region, model.BackupId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get backup details: %v", err) } // Get source details for labels var sourceLabel string - backup, err := apiClient.GetBackup(ctx, model.ProjectId, model.BackupId).Execute() + backup, err := apiClient.GetBackup(ctx, model.ProjectId, model.Region, model.BackupId).Execute() if err == nil && backup != nil && backup.VolumeId != nil { sourceLabel = *backup.VolumeId - name, err := iaasutils.GetVolumeName(ctx, apiClient, model.ProjectId, *backup.VolumeId) + name, err := iaasutils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, *backup.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume details: %v", err) } else if name != "" { @@ -89,7 +89,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Restoring backup") - _, err = wait.RestoreBackupWaitHandler(ctx, apiClient, model.ProjectId, model.BackupId).WaitWithContext(ctx) + _, err = wait.RestoreBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for backup restore: %w", err) } @@ -125,6 +125,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiRestoreBackupRequest { - req := apiClient.RestoreBackup(ctx, model.ProjectId, model.BackupId) + req := apiClient.RestoreBackup(ctx, model.ProjectId, model.Region, model.BackupId) return req } diff --git a/internal/cmd/volume/backup/restore/restore_test.go b/internal/cmd/volume/backup/restore/restore_test.go index 8532a05ee..1bd31ce17 100644 --- a/internal/cmd/volume/backup/restore/restore_test.go +++ b/internal/cmd/volume/backup/restore/restore_test.go @@ -13,6 +13,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var ( @@ -35,6 +39,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { 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) @@ -47,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, BackupId: testBackupId, } @@ -57,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiRestoreBackupRequest)) iaas.ApiRestoreBackupRequest { - request := testClient.RestoreBackup(testCtx, testProjectId, testBackupId) + request := testClient.RestoreBackup(testCtx, testProjectId, testRegion, testBackupId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/volume/backup/update/update.go b/internal/cmd/volume/backup/update/update.go index 9ede68fac..920ef6667 100644 --- a/internal/cmd/volume/backup/update/update.go +++ b/internal/cmd/volume/backup/update/update.go @@ -59,7 +59,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.BackupId) + backupLabel, err := iaasutils.GetBackupName(ctx, apiClient, model.ProjectId, model.Region, model.BackupId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get backup name: %v", err) } @@ -118,7 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateBackupRequest { - req := apiClient.UpdateBackup(ctx, model.ProjectId, model.BackupId) + req := apiClient.UpdateBackup(ctx, model.ProjectId, model.Region, model.BackupId) payload := iaas.UpdateBackupPayload{ Name: model.Name, diff --git a/internal/cmd/volume/backup/update/update_test.go b/internal/cmd/volume/backup/update/update_test.go index 85faf0764..94860245a 100644 --- a/internal/cmd/volume/backup/update/update_test.go +++ b/internal/cmd/volume/backup/update/update_test.go @@ -14,6 +14,11 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" + testName = "test-backup" +) + type testCtxKey struct{} var ( @@ -21,7 +26,6 @@ var ( testClient = &iaas.APIClient{} testProjectId = uuid.NewString() testBackupId = uuid.NewString() - testName = "test-backup" testLabels = map[string]string{"key1": "value1"} ) @@ -38,8 +42,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, - nameFlag: testName, - labelsFlag: "key1=value1", + globalflags.RegionFlag: testRegion, + + nameFlag: testName, + labelsFlag: "key1=value1", } for _, mod := range mods { mod(flagValues) @@ -52,9 +58,10 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, BackupId: testBackupId, - Name: &testName, + Name: utils.Ptr(testName), Labels: testLabels, } for _, mod := range mods { @@ -64,9 +71,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdateBackupRequest)) iaas.ApiUpdateBackupRequest { - request := testClient.UpdateBackup(testCtx, testProjectId, testBackupId) + request := testClient.UpdateBackup(testCtx, testProjectId, testRegion, testBackupId) payload := iaas.NewUpdateBackupPayloadWithDefaults() - payload.Name = &testName + payload.Name = utils.Ptr(testName) payload.Labels = utils.ConvertStringMapToInterfaceMap(utils.Ptr(testLabels)) diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index f5024261a..a9b624c67 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -107,7 +107,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Creating volume") - _, err = wait.CreateVolumeWaitHandler(ctx, apiClient, model.ProjectId, volumeId).WaitWithContext(ctx) + _, err = wait.CreateVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for volume creation: %w", err) } @@ -158,7 +158,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateVolumeRequest { - req := apiClient.CreateVolume(ctx, model.ProjectId) + req := apiClient.CreateVolume(ctx, model.ProjectId, model.Region) source := &iaas.VolumeSource{ Id: model.SourceId, Type: model.SourceType, diff --git a/internal/cmd/volume/create/create_test.go b/internal/cmd/volume/create/create_test.go index 35f163e21..dde4f7893 100644 --- a/internal/cmd/volume/create/create_test.go +++ b/internal/cmd/volume/create/create_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -27,7 +29,9 @@ var testSourceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + availabilityZoneFlag: "eu01-1", nameFlag: "example-volume-name", descriptionFlag: "example-volume-description", @@ -48,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, AvailabilityZone: utils.Ptr("eu01-1"), Name: utils.Ptr("example-volume-name"), @@ -67,7 +72,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateVolumeRequest)) iaas.ApiCreateVolumeRequest { - request := testClient.CreateVolume(testCtx, testProjectId) + request := testClient.CreateVolume(testCtx, testProjectId, testRegion) request = request.CreateVolumePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -76,7 +81,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateVolumeRequest)) iaas.Api } func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateVolumeRequest)) iaas.ApiCreateVolumeRequest { - request := testClient.CreateVolume(testCtx, testProjectId) + request := testClient.CreateVolume(testCtx, testProjectId, testRegion) request = request.CreateVolumePayload(iaas.CreateVolumePayload{ AvailabilityZone: utils.Ptr("eu01-1"), }) @@ -158,21 +163,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -226,6 +231,7 @@ func TestBuildRequest(t *testing.T) { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, AvailabilityZone: utils.Ptr("eu01-1"), }, diff --git a/internal/cmd/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go index 1c94e3dc2..58d47c8ae 100644 --- a/internal/cmd/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -57,7 +57,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId @@ -82,7 +82,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Deleting volume") - _, err = wait.DeleteVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.VolumeId).WaitWithContext(ctx) + _, err = wait.DeleteVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for volume deletion: %w", err) } @@ -118,5 +118,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteVolumeRequest { - return apiClient.DeleteVolume(ctx, model.ProjectId, model.VolumeId) + return apiClient.DeleteVolume(ctx, model.ProjectId, model.Region, model.VolumeId) } diff --git a/internal/cmd/volume/delete/delete_test.go b/internal/cmd/volume/delete/delete_test.go index db5545312..42d63db2b 100644 --- a/internal/cmd/volume/delete/delete_test.go +++ b/internal/cmd/volume/delete/delete_test.go @@ -13,7 +13,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -34,7 +36,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -47,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, VolumeId: testVolumeId, } @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteVolumeRequest)) iaas.ApiDeleteVolumeRequest { - request := testClient.DeleteVolume(testCtx, testProjectId, testVolumeId) + request := testClient.DeleteVolume(testCtx, testProjectId, testRegion, testVolumeId) for _, mod := range mods { mod(&request) } @@ -101,7 +105,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +113,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +121,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/volume/describe/describe.go b/internal/cmd/volume/describe/describe.go index 19e536d7b..0683ae255 100644 --- a/internal/cmd/volume/describe/describe.go +++ b/internal/cmd/volume/describe/describe.go @@ -88,7 +88,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetVolumeRequest { - return apiClient.GetVolume(ctx, model.ProjectId, model.VolumeId) + return apiClient.GetVolume(ctx, model.ProjectId, model.Region, model.VolumeId) } func outputResult(p *print.Printer, outputFormat string, volume *iaas.Volume) error { diff --git a/internal/cmd/volume/describe/describe_test.go b/internal/cmd/volume/describe/describe_test.go index 1c4e2b907..9396645d4 100644 --- a/internal/cmd/volume/describe/describe_test.go +++ b/internal/cmd/volume/describe/describe_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -35,7 +37,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, + Region: testRegion, }, VolumeId: testVolumeId, } @@ -58,7 +62,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetVolumeRequest)) iaas.ApiGetVolumeRequest { - request := testClient.GetVolume(testCtx, testProjectId, testVolumeId) + request := testClient.GetVolume(testCtx, testProjectId, testRegion, testVolumeId) for _, mod := range mods { mod(&request) } @@ -102,7 +106,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -110,7 +114,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -118,7 +122,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/volume/list/list.go b/internal/cmd/volume/list/list.go index d1c7b884f..586f8b721 100644 --- a/internal/cmd/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -127,7 +127,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListVolumesRequest { - req := apiClient.ListVolumes(ctx, model.ProjectId) + req := apiClient.ListVolumes(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) } diff --git a/internal/cmd/volume/list/list_test.go b/internal/cmd/volume/list/list_test.go index cb54d2e1f..4fdeab7b2 100644 --- a/internal/cmd/volume/list/list_test.go +++ b/internal/cmd/volume/list/list_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -26,7 +28,9 @@ var testLabelSelector = "label" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", labelSelectorFlag: testLabelSelector, } @@ -41,6 +45,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), LabelSelector: utils.Ptr(testLabelSelector), @@ -52,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListVolumesRequest)) iaas.ApiListVolumesRequest { - request := testClient.ListVolumes(testCtx, testProjectId) + request := testClient.ListVolumes(testCtx, testProjectId, testRegion) request = request.LabelSelector(testLabelSelector) for _, mod := range mods { mod(&request) @@ -87,21 +92,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/volume/performance-class/describe/describe.go b/internal/cmd/volume/performance-class/describe/describe.go index 24a158239..324609ada 100644 --- a/internal/cmd/volume/performance-class/describe/describe.go +++ b/internal/cmd/volume/performance-class/describe/describe.go @@ -88,7 +88,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetVolumePerformanceClassRequest { - return apiClient.GetVolumePerformanceClass(ctx, model.ProjectId, model.VolumePerformanceClass) + return apiClient.GetVolumePerformanceClass(ctx, model.ProjectId, model.Region, model.VolumePerformanceClass) } func outputResult(p *print.Printer, outputFormat string, performanceClass *iaas.VolumePerformanceClass) error { diff --git a/internal/cmd/volume/performance-class/describe/describe_test.go b/internal/cmd/volume/performance-class/describe/describe_test.go index 737335164..269dae052 100644 --- a/internal/cmd/volume/performance-class/describe/describe_test.go +++ b/internal/cmd/volume/performance-class/describe/describe_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -36,7 +38,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -48,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, VolumePerformanceClass: testVolumePerformanceClass, @@ -59,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetVolumePerformanceClassRequest)) iaas.ApiGetVolumePerformanceClassRequest { - request := testClient.GetVolumePerformanceClass(testCtx, testProjectId, testVolumePerformanceClass) + request := testClient.GetVolumePerformanceClass(testCtx, testProjectId, testRegion, testVolumePerformanceClass) for _, mod := range mods { mod(&request) } @@ -103,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +123,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/volume/performance-class/list/list.go b/internal/cmd/volume/performance-class/list/list.go index 0c8a5de64..46ef6574b 100644 --- a/internal/cmd/volume/performance-class/list/list.go +++ b/internal/cmd/volume/performance-class/list/list.go @@ -128,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListVolumePerformanceClassesRequest { - req := apiClient.ListVolumePerformanceClasses(ctx, model.ProjectId) + req := apiClient.ListVolumePerformanceClasses(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) } diff --git a/internal/cmd/volume/performance-class/list/list_test.go b/internal/cmd/volume/performance-class/list/list_test.go index 4a36b5333..7bbd048f0 100644 --- a/internal/cmd/volume/performance-class/list/list_test.go +++ b/internal/cmd/volume/performance-class/list/list_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -26,7 +28,9 @@ var testLabelSelector = "label" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", labelSelectorFlag: testLabelSelector, } @@ -41,6 +45,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { GlobalFlagModel: &globalflags.GlobalFlagModel{ Verbosity: globalflags.VerbosityDefault, ProjectId: testProjectId, + Region: testRegion, }, Limit: utils.Ptr(int64(10)), LabelSelector: utils.Ptr(testLabelSelector), @@ -52,7 +57,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiListVolumePerformanceClassesRequest)) iaas.ApiListVolumePerformanceClassesRequest { - request := testClient.ListVolumePerformanceClasses(testCtx, testProjectId) + request := testClient.ListVolumePerformanceClasses(testCtx, testProjectId, testRegion) request = request.LabelSelector(testLabelSelector) for _, mod := range mods { mod(&request) @@ -87,21 +92,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/volume/resize/resize.go b/internal/cmd/volume/resize/resize.go index 4d1a0d03a..58be4800d 100644 --- a/internal/cmd/volume/resize/resize.go +++ b/internal/cmd/volume/resize/resize.go @@ -56,7 +56,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId @@ -111,7 +111,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiResizeVolumeRequest { - req := apiClient.ResizeVolume(ctx, model.ProjectId, model.VolumeId) + req := apiClient.ResizeVolume(ctx, model.ProjectId, model.Region, model.VolumeId) payload := iaas.ResizeVolumePayload{ Size: model.Size, diff --git a/internal/cmd/volume/resize/resize_test.go b/internal/cmd/volume/resize/resize_test.go index 54d02a47f..094cb7864 100644 --- a/internal/cmd/volume/resize/resize_test.go +++ b/internal/cmd/volume/resize/resize_test.go @@ -15,7 +15,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -37,8 +39,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - sizeFlag: "10", - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + sizeFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -50,6 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Size: utils.Ptr(int64(10)), @@ -62,7 +67,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiResizeVolumeRequest)) iaas.ApiResizeVolumeRequest { - request := testClient.ResizeVolume(testCtx, testProjectId, testVolumeId) + request := testClient.ResizeVolume(testCtx, testProjectId, testRegion, testVolumeId) request = request.ResizeVolumePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -105,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +118,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +126,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/volume/snapshot/create/create.go b/internal/cmd/volume/snapshot/create/create.go index 1146ccaba..a49b89da4 100644 --- a/internal/cmd/volume/snapshot/create/create.go +++ b/internal/cmd/volume/snapshot/create/create.go @@ -72,7 +72,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Get volume name for label - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeID) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.VolumeID) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeID @@ -97,7 +97,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Creating snapshot") - resp, err = wait.CreateSnapshotWaitHandler(ctx, apiClient, model.ProjectId, *resp.Id).WaitWithContext(ctx) + resp, err = wait.CreateSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Id).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for snapshot creation: %w", err) } @@ -152,7 +152,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiCreateSnapshotRequest { - req := apiClient.CreateSnapshot(ctx, model.ProjectId) + req := apiClient.CreateSnapshot(ctx, model.ProjectId, model.Region) payload := iaas.NewCreateSnapshotPayloadWithDefaults() payload.VolumeId = &model.VolumeID payload.Name = model.Name diff --git a/internal/cmd/volume/snapshot/create/create_test.go b/internal/cmd/volume/snapshot/create/create_test.go index 00111c28f..d2ee79608 100644 --- a/internal/cmd/volume/snapshot/create/create_test.go +++ b/internal/cmd/volume/snapshot/create/create_test.go @@ -16,7 +16,8 @@ import ( type testCtxKey struct{} const ( - testName = "test-snapshot" + testRegion = "eu01" + testName = "test-snapshot" ) var ( @@ -30,9 +31,11 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, - volumeIdFlag: testVolumeId, - nameFlag: testName, - labelsFlag: "key1=value1", + globalflags.RegionFlag: testRegion, + + volumeIdFlag: testVolumeId, + nameFlag: testName, + labelsFlag: "key1=value1", } for _, mod := range mods { mod(flagValues) @@ -44,6 +47,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, VolumeID: testVolumeId, @@ -57,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiCreateSnapshotRequest)) iaas.ApiCreateSnapshotRequest { - request := testClient.CreateSnapshot(testCtx, testProjectId) + request := testClient.CreateSnapshot(testCtx, testProjectId, testRegion) payload := iaas.NewCreateSnapshotPayloadWithDefaults() payload.VolumeId = &testVolumeId payload.Name = utils.Ptr(testName) diff --git a/internal/cmd/volume/snapshot/delete/delete.go b/internal/cmd/volume/snapshot/delete/delete.go index 11c4d1f1d..a94ef6bf1 100644 --- a/internal/cmd/volume/snapshot/delete/delete.go +++ b/internal/cmd/volume/snapshot/delete/delete.go @@ -54,7 +54,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Get snapshot name for label - snapshotLabel, err := iaasUtils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.SnapshotId) + snapshotLabel, err := iaasUtils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.Region, model.SnapshotId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get snapshot name: %v", err) snapshotLabel = model.SnapshotId @@ -79,7 +79,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if !model.Async { s := spinner.New(params.Printer) s.Start("Deleting snapshot") - _, err = wait.DeleteSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.SnapshotId).WaitWithContext(ctx) + _, err = wait.DeleteSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.SnapshotId).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for snapshot deletion: %w", err) } @@ -115,5 +115,5 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiDeleteSnapshotRequest { - return apiClient.DeleteSnapshot(ctx, model.ProjectId, model.SnapshotId) + return apiClient.DeleteSnapshot(ctx, model.ProjectId, model.Region, model.SnapshotId) } diff --git a/internal/cmd/volume/snapshot/delete/delete_test.go b/internal/cmd/volume/snapshot/delete/delete_test.go index f97165703..6ffa3d880 100644 --- a/internal/cmd/volume/snapshot/delete/delete_test.go +++ b/internal/cmd/volume/snapshot/delete/delete_test.go @@ -13,6 +13,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var ( @@ -35,6 +39,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { 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) @@ -46,6 +51,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, SnapshotId: testSnapshotId, @@ -57,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiDeleteSnapshotRequest)) iaas.ApiDeleteSnapshotRequest { - request := testClient.DeleteSnapshot(testCtx, testProjectId, testSnapshotId) + request := testClient.DeleteSnapshot(testCtx, testProjectId, testRegion, testSnapshotId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/volume/snapshot/describe/describe.go b/internal/cmd/volume/snapshot/describe/describe.go index bf78cb603..17ed41c88 100644 --- a/internal/cmd/volume/snapshot/describe/describe.go +++ b/internal/cmd/volume/snapshot/describe/describe.go @@ -86,7 +86,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiGetSnapshotRequest { - return apiClient.GetSnapshot(ctx, model.ProjectId, model.SnapshotId) + return apiClient.GetSnapshot(ctx, model.ProjectId, model.Region, model.SnapshotId) } func outputResult(p *print.Printer, outputFormat string, snapshot *iaas.Snapshot) error { diff --git a/internal/cmd/volume/snapshot/describe/describe_test.go b/internal/cmd/volume/snapshot/describe/describe_test.go index 7da9d09a4..ff1e25aec 100644 --- a/internal/cmd/volume/snapshot/describe/describe_test.go +++ b/internal/cmd/volume/snapshot/describe/describe_test.go @@ -16,6 +16,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var ( @@ -38,6 +42,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { 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) @@ -49,6 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, SnapshotId: testSnapshotId, @@ -60,7 +66,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiGetSnapshotRequest)) iaas.ApiGetSnapshotRequest { - request := testClient.GetSnapshot(testCtx, testProjectId, testSnapshotId) + request := testClient.GetSnapshot(testCtx, testProjectId, testRegion, testSnapshotId) for _, mod := range mods { mod(&request) } diff --git a/internal/cmd/volume/snapshot/list/list.go b/internal/cmd/volume/snapshot/list/list.go index 2ef8c9d4d..ce8052287 100644 --- a/internal/cmd/volume/snapshot/list/list.go +++ b/internal/cmd/volume/snapshot/list/list.go @@ -126,8 +126,8 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, return &model, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListSnapshotsRequest { - req := apiClient.ListSnapshots(ctx, model.ProjectId) +func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListSnapshotsInProjectRequest { + req := apiClient.ListSnapshotsInProject(ctx, model.ProjectId, model.Region) if model.LabelSelector != nil { req = req.LabelSelector(*model.LabelSelector) } diff --git a/internal/cmd/volume/snapshot/list/list_test.go b/internal/cmd/volume/snapshot/list/list_test.go index c9facab11..5e9c8b0c8 100644 --- a/internal/cmd/volume/snapshot/list/list_test.go +++ b/internal/cmd/volume/snapshot/list/list_test.go @@ -16,6 +16,10 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" +) + type testCtxKey struct{} var ( @@ -27,8 +31,10 @@ var ( func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, - limitFlag: "10", - labelSelectorFlag: "key1=value1", + globalflags.RegionFlag: testRegion, + + limitFlag: "10", + labelSelectorFlag: "key1=value1", } for _, mod := range mods { mod(flagValues) @@ -40,6 +46,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -51,8 +58,8 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *iaas.ApiListSnapshotsRequest)) iaas.ApiListSnapshotsRequest { - request := testClient.ListSnapshots(testCtx, testProjectId) +func fixtureRequest(mods ...func(request *iaas.ApiListSnapshotsInProjectRequest)) iaas.ApiListSnapshotsInProjectRequest { + request := testClient.ListSnapshotsInProject(testCtx, testProjectId, testRegion) request = request.LabelSelector("key1=value1") for _, mod := range mods { mod(&request) @@ -139,7 +146,7 @@ func TestBuildRequest(t *testing.T) { tests := []struct { description string model *inputModel - expectedRequest iaas.ApiListSnapshotsRequest + expectedRequest iaas.ApiListSnapshotsInProjectRequest }{ { description: "base", @@ -151,8 +158,8 @@ func TestBuildRequest(t *testing.T) { model: fixtureInputModel(func(model *inputModel) { model.LabelSelector = nil }), - expectedRequest: fixtureRequest(func(request *iaas.ApiListSnapshotsRequest) { - *request = testClient.ListSnapshots(testCtx, testProjectId) + expectedRequest: fixtureRequest(func(request *iaas.ApiListSnapshotsInProjectRequest) { + *request = testClient.ListSnapshotsInProject(testCtx, testProjectId, testRegion) }), }, } diff --git a/internal/cmd/volume/snapshot/update/update.go b/internal/cmd/volume/snapshot/update/update.go index 889b2cae4..766c33b34 100644 --- a/internal/cmd/volume/snapshot/update/update.go +++ b/internal/cmd/volume/snapshot/update/update.go @@ -60,7 +60,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } // Get snapshot name for label - snapshotLabel, err := iaasUtils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.SnapshotId) + snapshotLabel, err := iaasUtils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.Region, model.SnapshotId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get snapshot name: %v", err) snapshotLabel = model.SnapshotId @@ -125,7 +125,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateSnapshotRequest { - req := apiClient.UpdateSnapshot(ctx, model.ProjectId, model.SnapshotId) + req := apiClient.UpdateSnapshot(ctx, model.ProjectId, model.Region, model.SnapshotId) payload := iaas.NewUpdateSnapshotPayloadWithDefaults() payload.Name = model.Name payload.Labels = utils.ConvertStringMapToInterfaceMap(utils.Ptr(model.Labels)) diff --git a/internal/cmd/volume/snapshot/update/update_test.go b/internal/cmd/volume/snapshot/update/update_test.go index b96da76f1..d5e159315 100644 --- a/internal/cmd/volume/snapshot/update/update_test.go +++ b/internal/cmd/volume/snapshot/update/update_test.go @@ -14,6 +14,11 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +const ( + testRegion = "eu01" + testName = "test-snapshot" +) + type testCtxKey struct{} var ( @@ -21,7 +26,6 @@ var ( testClient = &iaas.APIClient{} testProjectId = uuid.NewString() testSnapshotId = uuid.NewString() - testName = "test-snapshot" testLabels = map[string]string{"key1": "value1"} ) @@ -38,8 +42,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, - nameFlag: testName, - labelsFlag: "key1=value1", + globalflags.RegionFlag: testRegion, + + nameFlag: testName, + labelsFlag: "key1=value1", } for _, mod := range mods { mod(flagValues) @@ -51,10 +57,11 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, SnapshotId: testSnapshotId, - Name: &testName, + Name: utils.Ptr(testName), Labels: testLabels, } for _, mod := range mods { @@ -64,9 +71,9 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdateSnapshotRequest)) iaas.ApiUpdateSnapshotRequest { - request := testClient.UpdateSnapshot(testCtx, testProjectId, testSnapshotId) + request := testClient.UpdateSnapshot(testCtx, testProjectId, testRegion, testSnapshotId) payload := iaas.NewUpdateSnapshotPayloadWithDefaults() - payload.Name = &testName + payload.Name = utils.Ptr(testName) payload.Labels = utils.ConvertStringMapToInterfaceMap(utils.Ptr(testLabels)) request = request.UpdateSnapshotPayload(*payload) diff --git a/internal/cmd/volume/update/update.go b/internal/cmd/volume/update/update.go index 0af92ab77..55e2e2a70 100644 --- a/internal/cmd/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -67,7 +67,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return err } - volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.VolumeId) + volumeLabel, err := iaasUtils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) volumeLabel = model.VolumeId @@ -122,7 +122,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateVolumeRequest { - req := apiClient.UpdateVolume(ctx, model.ProjectId, model.VolumeId) + req := apiClient.UpdateVolume(ctx, model.ProjectId, model.Region, model.VolumeId) payload := iaas.UpdateVolumePayload{ Name: model.Name, diff --git a/internal/cmd/volume/update/update_test.go b/internal/cmd/volume/update/update_test.go index 1628bf26a..6b890a82c 100644 --- a/internal/cmd/volume/update/update_test.go +++ b/internal/cmd/volume/update/update_test.go @@ -14,7 +14,9 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) -var projectIdFlag = globalflags.ProjectIdFlag +const ( + testRegion = "eu01" +) type testCtxKey struct{} @@ -36,8 +38,10 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + nameFlag: "example-volume-name", - projectIdFlag: testProjectId, descriptionFlag: "example-volume-desc", labelFlag: "key=value", } @@ -51,6 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Name: utils.Ptr("example-volume-name"), @@ -67,7 +72,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *iaas.ApiUpdateVolumeRequest)) iaas.ApiUpdateVolumeRequest { - request := testClient.UpdateVolume(testCtx, testProjectId, testVolumeId) + request := testClient.UpdateVolume(testCtx, testProjectId, testRegion, testVolumeId) request = request.UpdateVolumePayload(fixturePayload()) for _, mod := range mods { mod(&request) @@ -114,7 +119,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -122,7 +127,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -130,7 +135,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index 9c83fb4f1..814929497 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -18,6 +18,16 @@ You can configure it for all commands by running: or you can also set it through the environment variable [STACKIT_PROJECT_ID]` + MISSING_REGION = `the region is not currently set. + +It can be set on the command level by re-running your command with the --region flag. + +You can configure it for all commands by running: + + $ stackit config set --region xxx + +or you can also set it through the environment variable [STACKIT_REGION]` + EMPTY_UPDATE = `please specify at least one field to update. Get details on the available flags by re-running your command with the --help flag.` @@ -178,6 +188,12 @@ To list all profiles, run: $ stackit config profile list` FILE_ALREADY_EXISTS = `file %q already exists in the export path. Delete the existing file or define a different export path` + + FLAG_MUST_BE_PROVIDED_WHEN_ANOTHER_FLAG_IS_SET = `The flag %[1]q must be provided when %[2]q is set` + + MULTIPLE_FLAGS_MUST_BE_PROVIDED_WHEN_ANOTHER_FLAG_IS_SET = `The flags %[1]v must be provided when one of the flags %[2]v is set` + + ONE_OF_THE_FLAGS_MUST_BE_PROVIDED_WHEN_ANOTHER_FLAG_IS_SET = `One of the flags %[1]v must be provided when %[2]q is set` ) type ServerNicAttachMissingNicIdError struct { @@ -234,6 +250,12 @@ func (e *ProjectIdError) Error() string { return MISSING_PROJECT_ID } +type RegionError struct{} + +func (e *RegionError) Error() string { + return MISSING_REGION +} + type EmptyUpdateError struct{} func (e *EmptyUpdateError) Error() string { @@ -499,3 +521,30 @@ type FileAlreadyExistsError struct { } func (e *FileAlreadyExistsError) Error() string { return fmt.Sprintf(FILE_ALREADY_EXISTS, e.Filename) } + +type DependingFlagIsMissing struct { + MissingFlag string + SetFlag string +} + +func (e *DependingFlagIsMissing) Error() string { + return fmt.Sprintf(FLAG_MUST_BE_PROVIDED_WHEN_ANOTHER_FLAG_IS_SET, fmt.Sprintf("--%s", e.MissingFlag), fmt.Sprintf("--%s", e.SetFlag)) +} + +type MultipleFlagsAreMissing struct { + MissingFlags []string + SetFlags []string +} + +func (e *MultipleFlagsAreMissing) Error() string { + return fmt.Sprintf(MULTIPLE_FLAGS_MUST_BE_PROVIDED_WHEN_ANOTHER_FLAG_IS_SET, e.MissingFlags, e.SetFlags) +} + +type OneOfFlagsIsMissing struct { + MissingFlags []string + SetFlag string +} + +func (e *OneOfFlagsIsMissing) Error() string { + return fmt.Sprintf(ONE_OF_THE_FLAGS_MUST_BE_PROVIDED_WHEN_ANOTHER_FLAG_IS_SET, e.MissingFlags, e.SetFlag) +} diff --git a/internal/pkg/services/iaas/client/client.go b/internal/pkg/services/iaas/client/client.go index c9401016a..a49f04b7c 100644 --- a/internal/pkg/services/iaas/client/client.go +++ b/internal/pkg/services/iaas/client/client.go @@ -10,5 +10,5 @@ import ( ) func ConfigureClient(p *print.Printer, cliVersion string) (*iaas.APIClient, error) { - return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.IaaSCustomEndpointKey), true, genericclient.CreateApiClient[*iaas.APIClient](iaas.NewAPIClient)) + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.IaaSCustomEndpointKey), false, genericclient.CreateApiClient[*iaas.APIClient](iaas.NewAPIClient)) } diff --git a/internal/pkg/services/iaas/utils/utils.go b/internal/pkg/services/iaas/utils/utils.go index 2cf460334..b7973c265 100644 --- a/internal/pkg/services/iaas/utils/utils.go +++ b/internal/pkg/services/iaas/utils/utils.go @@ -15,23 +15,23 @@ var ( ) type IaaSClient interface { - GetSecurityGroupRuleExecute(ctx context.Context, projectId, securityGroupRuleId, securityGroupId string) (*iaas.SecurityGroupRule, error) - GetSecurityGroupExecute(ctx context.Context, projectId, securityGroupId string) (*iaas.SecurityGroup, error) - GetPublicIPExecute(ctx context.Context, projectId, publicIpId string) (*iaas.PublicIp, error) - GetServerExecute(ctx context.Context, projectId, serverId string) (*iaas.Server, error) - GetVolumeExecute(ctx context.Context, projectId, volumeId string) (*iaas.Volume, error) - GetNetworkExecute(ctx context.Context, projectId, networkId string) (*iaas.Network, error) + GetSecurityGroupRuleExecute(ctx context.Context, projectId, region, securityGroupRuleId, securityGroupId string) (*iaas.SecurityGroupRule, error) + GetSecurityGroupExecute(ctx context.Context, projectId, region, securityGroupId string) (*iaas.SecurityGroup, error) + GetPublicIPExecute(ctx context.Context, projectId, region, publicIpId string) (*iaas.PublicIp, error) + GetServerExecute(ctx context.Context, projectId, region, serverId string) (*iaas.Server, error) + GetVolumeExecute(ctx context.Context, projectId, region, volumeId string) (*iaas.Volume, error) + GetNetworkExecute(ctx context.Context, projectId, region, networkId string) (*iaas.Network, error) GetNetworkAreaExecute(ctx context.Context, organizationId, areaId string) (*iaas.NetworkArea, error) ListNetworkAreaProjectsExecute(ctx context.Context, organizationId, areaId string) (*iaas.ProjectListResponse, error) - GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, networkRangeId string) (*iaas.NetworkRange, error) - GetImageExecute(ctx context.Context, projectId string, imageId string) (*iaas.Image, error) - GetAffinityGroupExecute(ctx context.Context, projectId string, affinityGroupId string) (*iaas.AffinityGroup, error) - GetSnapshotExecute(ctx context.Context, projectId, snapshotId string) (*iaas.Snapshot, error) - GetBackupExecute(ctx context.Context, projectId, backupId string) (*iaas.Backup, error) + GetNetworkAreaRangeExecute(ctx context.Context, organizationId, areaId, region, networkRangeId string) (*iaas.NetworkRange, error) + GetImageExecute(ctx context.Context, projectId, region, imageId string) (*iaas.Image, error) + GetAffinityGroupExecute(ctx context.Context, projectId, region, affinityGroupId string) (*iaas.AffinityGroup, error) + GetSnapshotExecute(ctx context.Context, projectId, region, snapshotId string) (*iaas.Snapshot, error) + GetBackupExecute(ctx context.Context, projectId, region, backupId string) (*iaas.Backup, error) } -func GetSecurityGroupRuleName(ctx context.Context, apiClient IaaSClient, projectId, securityGroupRuleId, securityGroupId string) (string, error) { - resp, err := apiClient.GetSecurityGroupRuleExecute(ctx, projectId, securityGroupRuleId, securityGroupId) +func GetSecurityGroupRuleName(ctx context.Context, apiClient IaaSClient, projectId, region, securityGroupRuleId, securityGroupId string) (string, error) { + resp, err := apiClient.GetSecurityGroupRuleExecute(ctx, projectId, region, securityGroupRuleId, securityGroupId) if err != nil { return "", fmt.Errorf("get security group rule: %w", err) } @@ -39,8 +39,8 @@ func GetSecurityGroupRuleName(ctx context.Context, apiClient IaaSClient, project return securityGroupRuleName, nil } -func GetSecurityGroupName(ctx context.Context, apiClient IaaSClient, projectId, securityGroupId string) (string, error) { - resp, err := apiClient.GetSecurityGroupExecute(ctx, projectId, securityGroupId) +func GetSecurityGroupName(ctx context.Context, apiClient IaaSClient, projectId, region, securityGroupId string) (string, error) { + resp, err := apiClient.GetSecurityGroupExecute(ctx, projectId, region, securityGroupId) if err != nil { return "", fmt.Errorf("get security group: %w", err) } else if resp == nil { @@ -51,8 +51,8 @@ func GetSecurityGroupName(ctx context.Context, apiClient IaaSClient, projectId, return *resp.Name, nil } -func GetPublicIP(ctx context.Context, apiClient IaaSClient, projectId, publicIpId string) (ip, associatedResource string, err error) { - resp, err := apiClient.GetPublicIPExecute(ctx, projectId, publicIpId) +func GetPublicIP(ctx context.Context, apiClient IaaSClient, projectId, region, publicIpId string) (ip, associatedResource string, err error) { + resp, err := apiClient.GetPublicIPExecute(ctx, projectId, region, publicIpId) if err != nil { return "", "", fmt.Errorf("get public ip: %w", err) } @@ -63,16 +63,16 @@ func GetPublicIP(ctx context.Context, apiClient IaaSClient, projectId, publicIpI return *resp.Ip, associatedResourceId, nil } -func GetServerName(ctx context.Context, apiClient IaaSClient, projectId, serverId string) (string, error) { - resp, err := apiClient.GetServerExecute(ctx, projectId, serverId) +func GetServerName(ctx context.Context, apiClient IaaSClient, projectId, region, serverId string) (string, error) { + resp, err := apiClient.GetServerExecute(ctx, projectId, region, serverId) if err != nil { return "", fmt.Errorf("get server: %w", err) } return *resp.Name, nil } -func GetVolumeName(ctx context.Context, apiClient IaaSClient, projectId, volumeId string) (string, error) { - resp, err := apiClient.GetVolumeExecute(ctx, projectId, volumeId) +func GetVolumeName(ctx context.Context, apiClient IaaSClient, projectId, region, volumeId string) (string, error) { + resp, err := apiClient.GetVolumeExecute(ctx, projectId, region, volumeId) if err != nil { return "", fmt.Errorf("get volume: %w", err) } else if resp == nil { @@ -83,8 +83,8 @@ func GetVolumeName(ctx context.Context, apiClient IaaSClient, projectId, volumeI return *resp.Name, nil } -func GetNetworkName(ctx context.Context, apiClient IaaSClient, projectId, networkId string) (string, error) { - resp, err := apiClient.GetNetworkExecute(ctx, projectId, networkId) +func GetNetworkName(ctx context.Context, apiClient IaaSClient, projectId, region, networkId string) (string, error) { + resp, err := apiClient.GetNetworkExecute(ctx, projectId, region, networkId) if err != nil { return "", fmt.Errorf("get network: %w", err) } else if resp == nil { @@ -119,8 +119,8 @@ func ListAttachedProjects(ctx context.Context, apiClient IaaSClient, organizatio return *resp.Items, nil } -func GetNetworkRangePrefix(ctx context.Context, apiClient IaaSClient, organizationId, areaId, networkRangeId string) (string, error) { - resp, err := apiClient.GetNetworkAreaRangeExecute(ctx, organizationId, areaId, networkRangeId) +func GetNetworkRangePrefix(ctx context.Context, apiClient IaaSClient, organizationId, areaId, region, networkRangeId string) (string, error) { + resp, err := apiClient.GetNetworkAreaRangeExecute(ctx, organizationId, areaId, region, networkRangeId) if err != nil { return "", fmt.Errorf("get network range: %w", err) } @@ -129,10 +129,47 @@ func GetNetworkRangePrefix(ctx context.Context, apiClient IaaSClient, organizati // GetRouteFromAPIResponse returns the static route from the API response that matches the prefix and nexthop // This works because static routes are unique by prefix and nexthop -func GetRouteFromAPIResponse(prefix, nexthop string, routes *[]iaas.Route) (iaas.Route, error) { +func GetRouteFromAPIResponse(destination, nexthop string, routes *[]iaas.Route) (iaas.Route, error) { for _, route := range *routes { - if *route.Prefix == prefix && *route.Nexthop == nexthop { - return route, nil + // Check if destination matches + if dest := route.Destination; dest != nil { + match := false + if destV4 := dest.DestinationCIDRv4; destV4 != nil { + if destV4.Value != nil && *destV4.Value == destination { + match = true + } + } else if destV6 := dest.DestinationCIDRv6; destV6 != nil { + if destV6.Value != nil && *destV6.Value == destination { + match = true + } + } + if !match { + continue + } + } + // Check if nexthop matches + if routeNexthop := route.Nexthop; routeNexthop != nil { + match := false + if nexthopIPv4 := routeNexthop.NexthopIPv4; nexthopIPv4 != nil { + if nexthopIPv4.Value != nil && *nexthopIPv4.Value == nexthop { + match = true + } + } else if nexthopIPv6 := routeNexthop.NexthopIPv6; nexthopIPv6 != nil { + if nexthopIPv6.Value != nil && *nexthopIPv6.Value == nexthop { + match = true + } + } else if nexthopInternet := routeNexthop.NexthopInternet; nexthopInternet != nil { + if nexthopInternet.Type != nil && *nexthopInternet.Type == nexthop { + match = true + } + } else if nexthopBlackhole := routeNexthop.NexthopBlackhole; nexthopBlackhole != nil { + if nexthopBlackhole.Type != nil && *nexthopBlackhole.Type == nexthop { + match = true + } + } + if match { + return route, nil + } } } return iaas.Route{}, fmt.Errorf("new static route not found in API response") @@ -149,8 +186,8 @@ func GetNetworkRangeFromAPIResponse(prefix string, networkRanges *[]iaas.Network return iaas.NetworkRange{}, fmt.Errorf("new network range not found in API response") } -func GetImageName(ctx context.Context, apiClient IaaSClient, projectId, imageId string) (string, error) { - resp, err := apiClient.GetImageExecute(ctx, projectId, imageId) +func GetImageName(ctx context.Context, apiClient IaaSClient, projectId, region, imageId string) (string, error) { + resp, err := apiClient.GetImageExecute(ctx, projectId, region, imageId) if err != nil { return "", fmt.Errorf("get image: %w", err) } else if resp == nil { @@ -161,8 +198,8 @@ func GetImageName(ctx context.Context, apiClient IaaSClient, projectId, imageId return *resp.Name, nil } -func GetAffinityGroupName(ctx context.Context, apiClient IaaSClient, projectId, affinityGroupId string) (string, error) { - resp, err := apiClient.GetAffinityGroupExecute(ctx, projectId, affinityGroupId) +func GetAffinityGroupName(ctx context.Context, apiClient IaaSClient, projectId, region, affinityGroupId string) (string, error) { + resp, err := apiClient.GetAffinityGroupExecute(ctx, projectId, region, affinityGroupId) if err != nil { return "", fmt.Errorf("get affinity group: %w", err) } else if resp == nil { @@ -173,8 +210,8 @@ func GetAffinityGroupName(ctx context.Context, apiClient IaaSClient, projectId, return *resp.Name, nil } -func GetSnapshotName(ctx context.Context, apiClient IaaSClient, projectId, snapshotId string) (string, error) { - resp, err := apiClient.GetSnapshotExecute(ctx, projectId, snapshotId) +func GetSnapshotName(ctx context.Context, apiClient IaaSClient, projectId, region, snapshotId string) (string, error) { + resp, err := apiClient.GetSnapshotExecute(ctx, projectId, region, snapshotId) if err != nil { return "", fmt.Errorf("get snapshot: %w", err) } else if resp == nil { @@ -185,8 +222,8 @@ func GetSnapshotName(ctx context.Context, apiClient IaaSClient, projectId, snaps return *resp.Name, nil } -func GetBackupName(ctx context.Context, apiClient IaaSClient, projectId, backupId string) (string, error) { - resp, err := apiClient.GetBackupExecute(ctx, projectId, backupId) +func GetBackupName(ctx context.Context, apiClient IaaSClient, projectId, region, backupId string) (string, error) { + resp, err := apiClient.GetBackupExecute(ctx, projectId, region, backupId) if err != nil { return backupId, fmt.Errorf("get backup: %w", err) } diff --git a/internal/pkg/services/iaas/utils/utils_test.go b/internal/pkg/services/iaas/utils/utils_test.go index e2ccdc469..a8f530533 100644 --- a/internal/pkg/services/iaas/utils/utils_test.go +++ b/internal/pkg/services/iaas/utils/utils_test.go @@ -10,6 +10,8 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/iaas" ) +var _ IaaSClient = &IaaSClientMocked{} + type IaaSClientMocked struct { GetSecurityGroupRuleFails bool GetSecurityGroupRuleResp *iaas.SecurityGroupRule @@ -39,49 +41,49 @@ type IaaSClientMocked struct { GetSnapshotResp *iaas.Snapshot } -func (m *IaaSClientMocked) GetAffinityGroupExecute(_ context.Context, _, _ string) (*iaas.AffinityGroup, error) { +func (m *IaaSClientMocked) GetAffinityGroupExecute(_ context.Context, _, _, _ string) (*iaas.AffinityGroup, error) { if m.GetAffinityGroupsFails { return nil, fmt.Errorf("could not get affinity groups") } return m.GetAffinityGroupResp, nil } -func (m *IaaSClientMocked) GetSecurityGroupRuleExecute(_ context.Context, _, _, _ string) (*iaas.SecurityGroupRule, error) { +func (m *IaaSClientMocked) GetSecurityGroupRuleExecute(_ context.Context, _, _, _, _ string) (*iaas.SecurityGroupRule, error) { if m.GetSecurityGroupRuleFails { return nil, fmt.Errorf("could not get security group rule") } return m.GetSecurityGroupRuleResp, nil } -func (m *IaaSClientMocked) GetSecurityGroupExecute(_ context.Context, _, _ string) (*iaas.SecurityGroup, error) { +func (m *IaaSClientMocked) GetSecurityGroupExecute(_ context.Context, _, _, _ string) (*iaas.SecurityGroup, error) { if m.GetSecurityGroupFails { return nil, fmt.Errorf("could not get security group") } return m.GetSecurityGroupResp, nil } -func (m *IaaSClientMocked) GetPublicIPExecute(_ context.Context, _, _ string) (*iaas.PublicIp, error) { +func (m *IaaSClientMocked) GetPublicIPExecute(_ context.Context, _, _, _ string) (*iaas.PublicIp, error) { if m.GetPublicIpFails { return nil, fmt.Errorf("could not get public ip") } return m.GetPublicIpResp, nil } -func (m *IaaSClientMocked) GetServerExecute(_ context.Context, _, _ string) (*iaas.Server, error) { +func (m *IaaSClientMocked) GetServerExecute(_ context.Context, _, _, _ string) (*iaas.Server, error) { if m.GetServerFails { return nil, fmt.Errorf("could not get server") } return m.GetServerResp, nil } -func (m *IaaSClientMocked) GetVolumeExecute(_ context.Context, _, _ string) (*iaas.Volume, error) { +func (m *IaaSClientMocked) GetVolumeExecute(_ context.Context, _, _, _ string) (*iaas.Volume, error) { if m.GetVolumeFails { return nil, fmt.Errorf("could not get volume") } return m.GetVolumeResp, nil } -func (m *IaaSClientMocked) GetNetworkExecute(_ context.Context, _, _ string) (*iaas.Network, error) { +func (m *IaaSClientMocked) GetNetworkExecute(_ context.Context, _, _, _ string) (*iaas.Network, error) { if m.GetNetworkFails { return nil, fmt.Errorf("could not get network") } @@ -102,28 +104,28 @@ func (m *IaaSClientMocked) ListNetworkAreaProjectsExecute(_ context.Context, _, return m.GetAttachedProjectsResp, nil } -func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _ string) (*iaas.NetworkRange, error) { +func (m *IaaSClientMocked) GetNetworkAreaRangeExecute(_ context.Context, _, _, _, _ string) (*iaas.NetworkRange, error) { if m.GetNetworkAreaRangeFails { return nil, fmt.Errorf("could not get network range") } return m.GetNetworkAreaRangeResp, nil } -func (m *IaaSClientMocked) GetImageExecute(_ context.Context, _, _ string) (*iaas.Image, error) { +func (m *IaaSClientMocked) GetImageExecute(_ context.Context, _, _, _ string) (*iaas.Image, error) { if m.GetImageFails { return nil, fmt.Errorf("could not get image") } return m.GetImageResp, nil } -func (m *IaaSClientMocked) GetBackupExecute(_ context.Context, _, _ string) (*iaas.Backup, error) { +func (m *IaaSClientMocked) GetBackupExecute(_ context.Context, _, _, _ string) (*iaas.Backup, error) { if m.GetBackupFails { return nil, fmt.Errorf("could not get backup") } return m.GetBackupResp, nil } -func (m *IaaSClientMocked) GetSnapshotExecute(_ context.Context, _, _ string) (*iaas.Snapshot, error) { +func (m *IaaSClientMocked) GetSnapshotExecute(_ context.Context, _, _, _ string) (*iaas.Snapshot, error) { if m.GetSnapshotFails { return nil, fmt.Errorf("could not get snapshot") } @@ -164,7 +166,7 @@ func TestGetSecurityGroupRuleName(t *testing.T) { GetSecurityGroupRuleFails: tt.args.getInstanceFails, GetSecurityGroupRuleResp: tt.args.getInstanceResp, } - got, err := GetSecurityGroupRuleName(context.Background(), m, "", "", "") + got, err := GetSecurityGroupRuleName(context.Background(), m, "", "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetSecurityGroupRuleName() error = %v, wantErr %v", err, tt.wantErr) return @@ -230,7 +232,7 @@ func TestGetSecurityGroupName(t *testing.T) { GetSecurityGroupFails: tt.args.getInstanceFails, GetSecurityGroupResp: tt.args.getInstanceResp, } - got, err := GetSecurityGroupName(context.Background(), m, "", "") + got, err := GetSecurityGroupName(context.Background(), m, "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetSecurityGroupName() error = %v, wantErr %v", err, tt.wantErr) return @@ -279,7 +281,7 @@ func TestGetPublicIp(t *testing.T) { GetPublicIpFails: tt.args.getPublicIpFails, GetPublicIpResp: tt.args.getPublicIpResp, } - gotPublicIP, gotAssociatedResource, err := GetPublicIP(context.Background(), m, "", "") + gotPublicIP, gotAssociatedResource, err := GetPublicIP(context.Background(), m, "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetPublicIP() error = %v, wantErr %v", err, tt.wantErr) return @@ -328,7 +330,7 @@ func TestGetServerName(t *testing.T) { GetServerFails: tt.args.getInstanceFails, GetServerResp: tt.args.getInstanceResp, } - got, err := GetServerName(context.Background(), m, "", "") + got, err := GetServerName(context.Background(), m, "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetServerName() error = %v, wantErr %v", err, tt.wantErr) return @@ -394,7 +396,7 @@ func TestGetVolumeName(t *testing.T) { GetVolumeFails: tt.args.getInstanceFails, GetVolumeResp: tt.args.getInstanceResp, } - got, err := GetVolumeName(context.Background(), m, "", "") + got, err := GetVolumeName(context.Background(), m, "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetVolumeName() error = %v, wantErr %v", err, tt.wantErr) return @@ -460,7 +462,7 @@ func TestGetNetworkName(t *testing.T) { GetNetworkFails: tt.args.getInstanceFails, GetNetworkResp: tt.args.getInstanceResp, } - got, err := GetNetworkName(context.Background(), m, "", "") + got, err := GetNetworkName(context.Background(), m, "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetNetworkName() error = %v, wantErr %v", err, tt.wantErr) return @@ -619,7 +621,7 @@ func TestGetNetworkRangePrefix(t *testing.T) { GetNetworkAreaRangeFails: tt.args.getNetworkAreaRangeFails, GetNetworkAreaRangeResp: tt.args.getNetworkAreaRangeResp, } - got, err := GetNetworkRangePrefix(context.Background(), m, "", "", "") + got, err := GetNetworkRangePrefix(context.Background(), m, "", "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetNetworkRangePrefix() error = %v, wantErr %v", err, tt.wantErr) return @@ -650,22 +652,210 @@ func TestGetRouteFromAPIResponse(t *testing.T) { nexthop: "1.1.1.1", routes: &[]iaas.Route{ { - Prefix: utils.Ptr("1.1.1.0/24"), - Nexthop: utils.Ptr("1.1.1.1"), + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Type: utils.Ptr("cidrv4"), + Value: utils.Ptr("1.1.1.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Type: utils.Ptr("ipv4"), + Value: utils.Ptr("1.1.1.1"), + }, + }, + }, + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Type: utils.Ptr("cidrv4"), + Value: utils.Ptr("2.2.2.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Type: utils.Ptr("ipv4"), + Value: utils.Ptr("2.2.2.2"), + }, + }, + }, + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("3.3.3.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopBlackhole: &iaas.NexthopBlackhole{ + Type: utils.Ptr("blackhole"), + }, + }, + }, + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("4.4.4.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopInternet: &iaas.NexthopInternet{ + Type: utils.Ptr("internet"), + }, + }, + }, + }, + }, + want: iaas.Route{ + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Type: utils.Ptr("cidrv4"), + Value: utils.Ptr("1.1.1.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Type: utils.Ptr("ipv4"), + Value: utils.Ptr("1.1.1.1"), + }, + }, + }, + }, + { + name: "nexthop internet", + args: args{ + prefix: "4.4.4.0/24", + nexthop: "internet", + routes: &[]iaas.Route{ + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("1.1.1.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Value: utils.Ptr("1.1.1.1"), + }, + }, }, { - Prefix: utils.Ptr("2.2.2.0/24"), - Nexthop: utils.Ptr("2.2.2.2"), + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("2.2.2.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Value: utils.Ptr("2.2.2.2"), + }, + }, }, { - Prefix: utils.Ptr("3.3.3.0/24"), - Nexthop: utils.Ptr("3.3.3.3"), + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("3.3.3.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopBlackhole: &iaas.NexthopBlackhole{ + Type: utils.Ptr("blackhole"), + }, + }, + }, + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("4.4.4.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopInternet: &iaas.NexthopInternet{ + Type: utils.Ptr("internet"), + }, + }, }, }, }, want: iaas.Route{ - Prefix: utils.Ptr("1.1.1.0/24"), - Nexthop: utils.Ptr("1.1.1.1"), + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("4.4.4.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopInternet: &iaas.NexthopInternet{ + Type: utils.Ptr("internet"), + }, + }, + }, + }, + { + name: "nexthop backhole", + args: args{ + prefix: "3.3.3.0/24", + nexthop: "blackhole", + routes: &[]iaas.Route{ + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("1.1.1.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Value: utils.Ptr("1.1.1.1"), + }, + }, + }, + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("2.2.2.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Value: utils.Ptr("2.2.2.2"), + }, + }, + }, + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("3.3.3.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopBlackhole: &iaas.NexthopBlackhole{ + Type: utils.Ptr("blackhole"), + }, + }, + }, + { + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("4.4.4.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopInternet: &iaas.NexthopInternet{ + Type: utils.Ptr("internet"), + }, + }, + }, + }, + }, + want: iaas.Route{ + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("3.3.3.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopBlackhole: &iaas.NexthopBlackhole{ + Type: utils.Ptr("blackhole"), + }, + }, }, }, { @@ -675,12 +865,28 @@ func TestGetRouteFromAPIResponse(t *testing.T) { nexthop: "1.1.1.1", routes: &[]iaas.Route{ { - Prefix: utils.Ptr("2.2.2.0/24"), - Nexthop: utils.Ptr("2.2.2.2"), + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("2.2.2.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Value: utils.Ptr("2.2.2.2"), + }, + }, }, { - Prefix: utils.Ptr("3.3.3.0/24"), - Nexthop: utils.Ptr("3.3.3.3"), + Destination: &iaas.RouteDestination{ + DestinationCIDRv4: &iaas.DestinationCIDRv4{ + Value: utils.Ptr("3.3.3.0/24"), + }, + }, + Nexthop: &iaas.RouteNexthop{ + NexthopIPv4: &iaas.NexthopIPv4{ + Value: utils.Ptr("3.3.3.3"), + }, + }, }, }, }, @@ -819,7 +1025,7 @@ func TestGetImageName(t *testing.T) { GetImageFails: tt.imageErr, GetImageResp: tt.imageResp, } - got, err := GetImageName(context.Background(), client, "", "") + got, err := GetImageName(context.Background(), client, "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetImageName() error = %v, wantErr %v", err, tt.wantErr) return @@ -876,7 +1082,7 @@ func TestGetAffinityGroupName(t *testing.T) { GetAffinityGroupsFails: tt.affinityErr, GetAffinityGroupResp: tt.affinityResp, } - got, err := GetAffinityGroupName(ctx, client, "", "") + got, err := GetAffinityGroupName(ctx, client, "", "", "") if (err != nil) != tt.wantErr { t.Errorf("GetAffinityGroupName() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index 2a68bc14c..862b92c8f 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -168,29 +168,29 @@ func (b Base64Bytes) MarshalYAML() (interface{}, error) { } type Base64PatchedServer struct { - Id *string `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Status *string `json:"status,omitempty"` - AvailabilityZone *string `json:"availabilityZone,omitempty"` - BootVolume *iaas.CreateServerPayloadBootVolume `json:"bootVolume,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - ErrorMessage *string `json:"errorMessage,omitempty"` - PowerStatus *string `json:"powerStatus,omitempty"` - AffinityGroup *string `json:"affinityGroup,omitempty"` - ImageId *string `json:"imageId,omitempty"` - KeypairName *string `json:"keypairName,omitempty"` - MachineType *string `json:"machineType,omitempty"` - Labels *map[string]interface{} `json:"labels,omitempty"` - LaunchedAt *time.Time `json:"launchedAt,omitempty"` - MaintenanceWindow *iaas.ServerMaintenance `json:"maintenanceWindow,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` - Networking *iaas.CreateServerPayloadNetworking `json:"networking,omitempty"` - Nics *[]iaas.ServerNetwork `json:"nics,omitempty"` - SecurityGroups *[]string `json:"securityGroups,omitempty"` - ServiceAccountMails *[]string `json:"serviceAccountMails,omitempty"` - UpdatedAt *time.Time `json:"updatedAt,omitempty"` - UserData *Base64Bytes `json:"userData,omitempty"` - Volumes *[]string `json:"volumes,omitempty"` + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + AvailabilityZone *string `json:"availabilityZone,omitempty"` + BootVolume *iaas.ServerBootVolume `json:"bootVolume,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + ErrorMessage *string `json:"errorMessage,omitempty"` + PowerStatus *string `json:"powerStatus,omitempty"` + AffinityGroup *string `json:"affinityGroup,omitempty"` + ImageId *string `json:"imageId,omitempty"` + KeypairName *string `json:"keypairName,omitempty"` + MachineType *string `json:"machineType,omitempty"` + Labels *map[string]interface{} `json:"labels,omitempty"` + LaunchedAt *time.Time `json:"launchedAt,omitempty"` + MaintenanceWindow *iaas.ServerMaintenance `json:"maintenanceWindow,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + Networking *iaas.ServerNetworking `json:"networking,omitempty"` + Nics *[]iaas.ServerNetwork `json:"nics,omitempty"` + SecurityGroups *[]string `json:"securityGroups,omitempty"` + ServiceAccountMails *[]string `json:"serviceAccountMails,omitempty"` + UpdatedAt *time.Time `json:"updatedAt,omitempty"` + UserData *Base64Bytes `json:"userData,omitempty"` + Volumes *[]string `json:"volumes,omitempty"` } // ConvertToBase64PatchedServer converts an iaas.Server to Base64PatchedServer From d68210bd6eb5e829cfc639fb325e182b9e136364 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Nov 2025 09:36:22 +0100 Subject: [PATCH 485/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/iaas (#1065) Bumps [github.com/stackitcloud/stackit-sdk-go/services/iaas](https://github.com/stackitcloud/stackit-sdk-go) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/iaas/v1.0.0...services/iaas/v1.1.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/iaas dependency-version: 1.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1d4e8ac4f..a01a8da65 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 diff --git a/go.sum b/go.sum index 850d60dfe..6e4bb10f3 100644 --- a/go.sum +++ b/go.sum @@ -571,8 +571,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4r github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 h1:zuoJnsLnjxdQcQbs7gUXYzrN0Ip5NXj+6LFBp1EO6cg= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0 h1:qLMpd5whPMLnaLEdFQjK51q/o9V6eMFMORBDSsyGyNI= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.1.0 h1:0NS+NTxr1emS5hg/f62y8H9YtsL1+0P4EVQ+CBOEzjY= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.1.0/go.mod h1:cUYlmptRGD5gizrzxiOnseow4l/g5ZSMmoYbpfeGCI8= github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 h1:zxoOv7Fu+FmdsvTKiKkbmLItrMKfL+QoVtz9ReEF30E= github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0/go.mod h1:KEPVoO21pC4bjy5l0nyhjUJ0+uVwVWb+k2TYrzJ8xYw= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= From 2f8acaec5903dd88c1d685c6e92fdf731560c41f Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 7 Nov 2025 11:22:06 +0100 Subject: [PATCH 486/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.7.0 (#1071) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a01a8da65..20f8e8977 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.6.9 + github.com/jedib0t/go-pretty/v6 v6.7.0 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index 6e4bb10f3..18f2201f0 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.6.9 h1:PQecJLK3L8ODuVyMe2223b61oRJjrKnmXAncbWTv9MY= -github.com/jedib0t/go-pretty/v6 v6.6.9/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.7.0 h1:DanoN1RnjXTwDN+B8yqtixXzXqNBCs2Vxo2ARsnrpsY= +github.com/jedib0t/go-pretty/v6 v6.7.0/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From 9f8ab6f316df4a05c3cd577cff4fd48c7f539bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 7 Nov 2025 11:40:36 +0100 Subject: [PATCH 487/619] fix(auth): hide misleading parameters in get access token cmd (#1069) relates to #1001 / STACKITCLI-282 --- internal/cmd/auth/get-access-token/get_access_token.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index a26b71b20..5ff3da916 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -67,6 +67,13 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } }, } + + // hide project id flag from help command because it could mislead users + cmd.SetHelpFunc(func(command *cobra.Command, strings []string) { + _ = command.Flags().MarkHidden(globalflags.ProjectIdFlag) // nolint:errcheck // there's no chance to handle the error here + command.Parent().HelpFunc()(command, strings) + }) + return cmd } From 12de8eb4d8eef31b0770fd5a31680bc3f8a6be77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20F=C3=BCrtsch?= <49522775+Benjosh95@users.noreply.github.com> Date: Fri, 7 Nov 2025 15:18:17 +0100 Subject: [PATCH 488/619] fix(kms): use fixed wait handler for disableKeyVersion command (#1064) --- go.mod | 2 +- go.sum | 4 ++-- internal/cmd/beta/kms/version/disable/disable.go | 13 ++++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 20f8e8977..5b637c224 100644 --- a/go.mod +++ b/go.mod @@ -242,7 +242,7 @@ require ( github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 + github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 diff --git a/go.sum b/go.sum index 18f2201f0..393b32da9 100644 --- a/go.sum +++ b/go.sum @@ -573,8 +573,8 @@ github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 h1:zuoJnsLnjxdQcQbs7g github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.1.0 h1:0NS+NTxr1emS5hg/f62y8H9YtsL1+0P4EVQ+CBOEzjY= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.1.0/go.mod h1:cUYlmptRGD5gizrzxiOnseow4l/g5ZSMmoYbpfeGCI8= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0 h1:zxoOv7Fu+FmdsvTKiKkbmLItrMKfL+QoVtz9ReEF30E= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.0.0/go.mod h1:KEPVoO21pC4bjy5l0nyhjUJ0+uVwVWb+k2TYrzJ8xYw= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0 h1:bgMV+hi/530htdSMAyRBrltR7Czinb56HQBT36wnVMU= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0/go.mod h1:QswbIN9TUYELIwkjO+Bu8Nk/FGcd3kZYDlf2n0PdFAk= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0/go.mod h1:20QOZ3rBC9wTGgzXzLz9M6YheX0VaxWE0/JI+s8On7k= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= diff --git a/internal/cmd/beta/kms/version/disable/disable.go b/internal/cmd/beta/kms/version/disable/disable.go index 095a870e4..bfb641d56 100644 --- a/internal/cmd/beta/kms/version/disable/disable.go +++ b/internal/cmd/beta/kms/version/disable/disable.go @@ -16,8 +16,10 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/kms" + "github.com/stackitcloud/stackit-sdk-go/services/kms/wait" ) const ( @@ -67,7 +69,16 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("disable key version: %w", err) } - // kms v1.0.0 has a waiter, but it get's stuck even though the disable api call was already successfully completed. + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for key version to be disabled: %w", err) + } + s.Stop() + } // Get the key version in its state afterwards resp, err := apiClient.GetVersionExecute(ctx, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber) From 076d7a9f22ed6db7bb1494601a9af1c48fbfca33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:31:59 +0000 Subject: [PATCH 489/619] chore(deps): bump renovatebot/github-action from 43.0.20 to 44.0.0 (#1072) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index fc34b9b41..84ad52710 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v43.0.20 + uses: renovatebot/github-action@v44.0.0 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From ece1975524ea97b0733c047208f5ee2a43828a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Mon, 10 Nov 2025 11:12:45 +0100 Subject: [PATCH 490/619] fix(opensearch): print valid JSON/YAML output for list cmds (#1046) relates to STACKITCLI-269 / #893 --- .../credentials/create/create_test.go | 12 ++--- .../credentials/delete/delete_test.go | 12 ++--- .../credentials/describe/describe_test.go | 12 ++--- .../cmd/opensearch/credentials/list/list.go | 25 ++++++---- .../opensearch/credentials/list/list_test.go | 21 ++++---- .../opensearch/instance/create/create_test.go | 50 +++++++++---------- .../opensearch/instance/delete/delete_test.go | 10 ++-- .../instance/describe/describe_test.go | 10 ++-- internal/cmd/opensearch/instance/list/list.go | 24 +++++---- .../cmd/opensearch/instance/list/list_test.go | 15 +++--- .../opensearch/instance/update/update_test.go | 42 ++++++++-------- internal/cmd/opensearch/plans/plans.go | 24 +++++---- internal/cmd/opensearch/plans/plans_test.go | 15 +++--- 13 files changed, 131 insertions(+), 141 deletions(-) diff --git a/internal/cmd/opensearch/credentials/create/create_test.go b/internal/cmd/opensearch/credentials/create/create_test.go index 8943eede7..9b9057414 100644 --- a/internal/cmd/opensearch/credentials/create/create_test.go +++ b/internal/cmd/opensearch/credentials/create/create_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,8 +24,8 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -89,21 +87,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/opensearch/credentials/delete/delete_test.go b/internal/cmd/opensearch/credentials/delete/delete_test.go index 53b987e9f..dcaa66ee1 100644 --- a/internal/cmd/opensearch/credentials/delete/delete_test.go +++ b/internal/cmd/opensearch/credentials/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -35,8 +33,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -104,7 +102,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +118,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/opensearch/credentials/describe/describe_test.go b/internal/cmd/opensearch/credentials/describe/describe_test.go index c1c2f3b2d..f9b43012d 100644 --- a/internal/cmd/opensearch/credentials/describe/describe_test.go +++ b/internal/cmd/opensearch/credentials/describe/describe_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -37,8 +35,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, } for _, mod := range mods { mod(flagValues) @@ -106,7 +104,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -114,7 +112,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -122,7 +120,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index 2e5451ec2..7a086385b 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -67,22 +67,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list OpenSearch credentials: %w", err) } - credentials := *resp.CredentialsList - if len(credentials) == 0 { - instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) - if err != nil { - params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) - instanceLabel = model.InstanceId - } - params.Printer.Info("No credentials found for instance %q\n", instanceLabel) - return nil + credentials := resp.GetCredentialsList() + + instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) + instanceLabel = model.InstanceId } // Truncate output if model.Limit != nil && len(credentials) > int(*model.Limit) { credentials = credentials[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, credentials) + + return outputResult(params.Printer, model.OutputFormat, instanceLabel, credentials) }, } configureFlags(cmd) @@ -126,8 +124,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. return req } -func outputResult(p *print.Printer, outputFormat string, credentials []opensearch.CredentialsListItem) error { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, credentials []opensearch.CredentialsListItem) error { return p.OutputResult(outputFormat, credentials, func() error { + if len(credentials) == 0 { + p.Outputf("No credentials found for instance %q\n", instanceLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID") for i := range credentials { diff --git a/internal/cmd/opensearch/credentials/list/list_test.go b/internal/cmd/opensearch/credentials/list/list_test.go index 8375506e1..ee376658f 100644 --- a/internal/cmd/opensearch/credentials/list/list_test.go +++ b/internal/cmd/opensearch/credentials/list/list_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -27,9 +25,9 @@ var testInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + instanceIdFlag: testInstanceId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -82,21 +80,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -174,8 +172,9 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - outputFormat string - credentials []opensearch.CredentialsListItem + outputFormat string + instanceLabel string + credentials []opensearch.CredentialsListItem } tests := []struct { name string @@ -206,7 +205,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/opensearch/instance/create/create_test.go b/internal/cmd/opensearch/instance/create/create_test.go index fe8afe7d3..9d14e0bd4 100644 --- a/internal/cmd/opensearch/instance/create/create_test.go +++ b/internal/cmd/opensearch/instance/create/create_test.go @@ -18,8 +18,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -47,17 +45,17 @@ var testMonitoringInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - instanceNameFlag: "example-name", - enableMonitoringFlag: "true", - graphiteFlag: "example-graphite", - metricsFrequencyFlag: "100", - metricsPrefixFlag: "example-prefix", - monitoringInstanceIdFlag: testMonitoringInstanceId, - pluginFlag: "example-plugin", - sgwAclFlag: "198.51.100.14/24", - syslogFlag: "example-syslog", - planIdFlag: testPlanId, + globalflags.ProjectIdFlag: testProjectId, + instanceNameFlag: "example-name", + enableMonitoringFlag: "true", + graphiteFlag: "example-graphite", + metricsFrequencyFlag: "100", + metricsPrefixFlag: "example-prefix", + monitoringInstanceIdFlag: testMonitoringInstanceId, + pluginFlag: "example-plugin", + sgwAclFlag: "198.51.100.14/24", + syslogFlag: "example-syslog", + planIdFlag: testPlanId, } for _, mod := range mods { mod(flagValues) @@ -149,9 +147,9 @@ func TestParseInput(t *testing.T) { { description: "required fields only", flagValues: map[string]string{ - projectIdFlag: testProjectId, - instanceNameFlag: "example-name", - planIdFlag: testPlanId, + globalflags.ProjectIdFlag: testProjectId, + instanceNameFlag: "example-name", + planIdFlag: testPlanId, }, isValid: true, expectedModel: &inputModel{ @@ -166,13 +164,13 @@ func TestParseInput(t *testing.T) { { description: "zero values", flagValues: map[string]string{ - projectIdFlag: testProjectId, - planIdFlag: testPlanId, - instanceNameFlag: "", - enableMonitoringFlag: "false", - graphiteFlag: "", - metricsFrequencyFlag: "0", - metricsPrefixFlag: "", + globalflags.ProjectIdFlag: testProjectId, + planIdFlag: testPlanId, + instanceNameFlag: "", + enableMonitoringFlag: "false", + graphiteFlag: "", + metricsFrequencyFlag: "0", + metricsPrefixFlag: "", }, isValid: true, expectedModel: &inputModel{ @@ -191,21 +189,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/opensearch/instance/delete/delete_test.go b/internal/cmd/opensearch/instance/delete/delete_test.go index c6ab9693d..f9943acf7 100644 --- a/internal/cmd/opensearch/instance/delete/delete_test.go +++ b/internal/cmd/opensearch/instance/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -34,7 +32,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -101,7 +99,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/opensearch/instance/describe/describe_test.go b/internal/cmd/opensearch/instance/describe/describe_test.go index 8ae93fa8f..633d7da44 100644 --- a/internal/cmd/opensearch/instance/describe/describe_test.go +++ b/internal/cmd/opensearch/instance/describe/describe_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,7 +34,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -103,7 +101,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -111,7 +109,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -119,7 +117,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index 03e18c79d..a6c57bc29 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -64,15 +64,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get OpenSearch instances: %w", err) } - instances := *resp.Instances - if len(instances) == 0 { - 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 - } - params.Printer.Info("No instances found for project %q\n", projectLabel) - return nil + instances := resp.GetInstances() + + 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 } // Truncate output @@ -80,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { instances = instances[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, projectLabel, instances) }, } @@ -120,8 +117,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. return req } -func outputResult(p *print.Printer, outputFormat string, instances []opensearch.Instance) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []opensearch.Instance) error { return p.OutputResult(outputFormat, instances, func() error { + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "LAST OPERATION TYPE", "LAST OPERATION STATE") for i := range instances { diff --git a/internal/cmd/opensearch/instance/list/list_test.go b/internal/cmd/opensearch/instance/list/list_test.go index 86ac78970..15f772725 100644 --- a/internal/cmd/opensearch/instance/list/list_test.go +++ b/internal/cmd/opensearch/instance/list/list_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,8 +24,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -79,21 +77,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -151,6 +149,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string instances []opensearch.Instance } tests := []struct { @@ -182,7 +181,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.instances); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/opensearch/instance/update/update_test.go b/internal/cmd/opensearch/instance/update/update_test.go index 70168bbc2..934088f02 100644 --- a/internal/cmd/opensearch/instance/update/update_test.go +++ b/internal/cmd/opensearch/instance/update/update_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -58,16 +56,16 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - enableMonitoringFlag: "true", - graphiteFlag: "example-graphite", - metricsFrequencyFlag: "100", - metricsPrefixFlag: "example-prefix", - monitoringInstanceIdFlag: testMonitoringInstanceId, - pluginFlag: "example-plugin", - sgwAclFlag: "198.51.100.14/24", - syslogFlag: "example-syslog", - planIdFlag: testPlanId, + globalflags.ProjectIdFlag: testProjectId, + enableMonitoringFlag: "true", + graphiteFlag: "example-graphite", + metricsFrequencyFlag: "100", + metricsPrefixFlag: "example-prefix", + monitoringInstanceIdFlag: testMonitoringInstanceId, + pluginFlag: "example-plugin", + sgwAclFlag: "198.51.100.14/24", + syslogFlag: "example-syslog", + planIdFlag: testPlanId, } for _, mod := range mods { mod(flagValues) @@ -159,7 +157,7 @@ func TestParseInput(t *testing.T) { description: "required flags only (no values to update)", argValues: fixtureArgValues(), flagValues: map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, }, isValid: false, expectedModel: &inputModel{ @@ -174,12 +172,12 @@ func TestParseInput(t *testing.T) { description: "zero values", argValues: fixtureArgValues(), flagValues: map[string]string{ - projectIdFlag: testProjectId, - planIdFlag: testPlanId, - enableMonitoringFlag: "false", - graphiteFlag: "", - metricsFrequencyFlag: "0", - metricsPrefixFlag: "", + globalflags.ProjectIdFlag: testProjectId, + planIdFlag: testPlanId, + enableMonitoringFlag: "false", + graphiteFlag: "", + metricsFrequencyFlag: "0", + metricsPrefixFlag: "", }, isValid: true, expectedModel: &inputModel{ @@ -199,7 +197,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -207,7 +205,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -215,7 +213,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index 45a026ab9..5ba348f99 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -64,15 +64,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get OpenSearch service plans: %w", err) } - plans := *resp.Offerings - if len(plans) == 0 { - 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 - } - params.Printer.Info("No plans found for project %q\n", projectLabel) - return nil + plans := resp.GetOfferings() + + 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 } // Truncate output @@ -80,7 +77,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { plans = plans[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, plans) + return outputResult(params.Printer, model.OutputFormat, projectLabel, plans) }, } @@ -120,8 +117,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. return req } -func outputResult(p *print.Printer, outputFormat string, plans []opensearch.Offering) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, plans []opensearch.Offering) error { return p.OutputResult(outputFormat, plans, func() error { + if len(plans) == 0 { + p.Outputf("No plans found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { diff --git a/internal/cmd/opensearch/plans/plans_test.go b/internal/cmd/opensearch/plans/plans_test.go index 4cafef6ba..093e129fd 100644 --- a/internal/cmd/opensearch/plans/plans_test.go +++ b/internal/cmd/opensearch/plans/plans_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -26,8 +24,8 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - limitFlag: "10", + globalflags.ProjectIdFlag: testProjectId, + limitFlag: "10", } for _, mod := range mods { mod(flagValues) @@ -79,21 +77,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -151,6 +149,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string plans []opensearch.Offering } tests := []struct { @@ -182,7 +181,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.plans); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From e806dc0729c8565ea1065e106cf69a4ffafa5e5c Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 10 Nov 2025 11:19:56 +0100 Subject: [PATCH 491/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.7.1 (#1074) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5b637c224..a593c2302 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.7.0 + github.com/jedib0t/go-pretty/v6 v6.7.1 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index 393b32da9..8377b0d1e 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.7.0 h1:DanoN1RnjXTwDN+B8yqtixXzXqNBCs2Vxo2ARsnrpsY= -github.com/jedib0t/go-pretty/v6 v6.7.0/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.7.1 h1:bHDSsj93NuJ563hHuM7ohk/wpX7BmRFNIsVv1ssI2/M= +github.com/jedib0t/go-pretty/v6 v6.7.1/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From cb77ba02e231bdef1d01976dced6ff3231311787 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:07:55 +0100 Subject: [PATCH 492/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/iaas (#1075) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a593c2302..1bbfe0f4a 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 diff --git a/go.sum b/go.sum index 8377b0d1e..dd2220b81 100644 --- a/go.sum +++ b/go.sum @@ -571,8 +571,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4r github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 h1:zuoJnsLnjxdQcQbs7gUXYzrN0Ip5NXj+6LFBp1EO6cg= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.1.0 h1:0NS+NTxr1emS5hg/f62y8H9YtsL1+0P4EVQ+CBOEzjY= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.1.0/go.mod h1:cUYlmptRGD5gizrzxiOnseow4l/g5ZSMmoYbpfeGCI8= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 h1:bkvq3Y4OcGyCR5N69tyY7ZTcrVN+htGTa2ZBJL5BQTQ= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0/go.mod h1:tg1rHvgFRG9gNCYnTepZFaSCBahhLLjkIb3nRbtyjDQ= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0 h1:bgMV+hi/530htdSMAyRBrltR7Czinb56HQBT36wnVMU= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0/go.mod h1:QswbIN9TUYELIwkjO+Bu8Nk/FGcd3kZYDlf2n0PdFAk= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= From 2d403370ae730877fd2579da44fd862236d5440b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:17:29 +0000 Subject: [PATCH 493/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/alb (#1076) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1bbfe0f4a..253f91312 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.18.0 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 diff --git a/go.sum b/go.sum index dd2220b81..8ba03fc45 100644 --- a/go.sum +++ b/go.sum @@ -563,8 +563,8 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.18.0 h1:+4v8sjQpQXPihO3crgTp0Kz/XRIi5p7oKV28dw6jsEQ= github.com/stackitcloud/stackit-sdk-go/core v0.18.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0 h1:UM/HvewAgELEvZ4zk++Ykd6jUTSL+asRqtK+DszDOzE= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.0/go.mod h1:mOmGoNLPXLJ5tKLnhOnhKW7wL9Giy/4DowiDZNLlQCY= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 h1:DaJkEN/6l+AJEQ3Dr+3IdKM4jywDQsTvuYHmRvFj3ho= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1/go.mod h1:SzA+UsSNv4D9IvNT7hwYPewgAvUgj5WXIU2tZ0XaMBI= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= From f83a5683e6cfdfde1f552f9de1adfa0ef5ee4f76 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:12:19 +0100 Subject: [PATCH 494/619] chore(deps): update renovatebot/github-action action to v44.0.2 (#1079) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 84ad52710..41bef42a1 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v44.0.0 + uses: renovatebot/github-action@v44.0.2 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From cafabc57f106d67e7162a3cc2cc18a9a92513b51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:20:20 +0100 Subject: [PATCH 495/619] chore(deps): bump golang.org/x/oauth2 from 0.32.0 to 0.33.0 (#1077) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 253f91312..e9086d410 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.29.0 - golang.org/x/oauth2 v0.32.0 + golang.org/x/oauth2 v0.33.0 golang.org/x/term v0.36.0 golang.org/x/text v0.30.0 k8s.io/apimachinery v0.34.1 diff --git a/go.sum b/go.sum index 8ba03fc45..654c20ab6 100644 --- a/go.sum +++ b/go.sum @@ -807,8 +807,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= -golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= +golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 6e9982fdd1ad4a6cbcfeac861e17c2c1fc96261e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 12 Nov 2025 07:36:30 +0100 Subject: [PATCH 496/619] fix(deps): update module golang.org/x/mod to v0.30.0 (#1081) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e9086d410..f0fd1a783 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.29.0 + golang.org/x/mod v0.30.0 golang.org/x/oauth2 v0.33.0 golang.org/x/term v0.36.0 golang.org/x/text v0.30.0 diff --git a/go.sum b/go.sum index 654c20ab6..34d600326 100644 --- a/go.sum +++ b/go.sum @@ -757,8 +757,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 872c509b1a1f641bdf533e840642b68d034d32ff Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 12 Nov 2025 07:46:39 +0100 Subject: [PATCH 497/619] fix(deps): update module golang.org/x/term to v0.37.0 (#1082) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f0fd1a783..8b3c7c538 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.30.0 golang.org/x/oauth2 v0.33.0 - golang.org/x/term v0.36.0 + golang.org/x/term v0.37.0 golang.org/x/text v0.30.0 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 @@ -252,7 +252,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.37.0 // indirect + golang.org/x/sys v0.38.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 34d600326..aaf1a8f5c 100644 --- a/go.sum +++ b/go.sum @@ -877,8 +877,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -889,8 +889,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From a941843c03705a4761eff8433f15bc85ca7715ef Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:06:33 +0100 Subject: [PATCH 498/619] fix(deps): update module golang.org/x/text to v0.31.0 (#1083) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 8b3c7c538..4f3001015 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( golang.org/x/mod v0.30.0 golang.org/x/oauth2 v0.33.0 golang.org/x/term v0.37.0 - golang.org/x/text v0.30.0 + golang.org/x/text v0.31.0 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 ) @@ -208,7 +208,7 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/sync v0.17.0 // indirect + golang.org/x/sync v0.18.0 // indirect golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect golang.org/x/tools v0.38.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect diff --git a/go.sum b/go.sum index aaf1a8f5c..d119f696d 100644 --- a/go.sum +++ b/go.sum @@ -824,8 +824,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -903,8 +903,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From fd2b40667e88d6de05dc4aa603ea8d29ca2969da Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 13 Nov 2025 07:37:58 +0100 Subject: [PATCH 499/619] fix(deps): update kubernetes packages to v0.34.2 (#1085) Co-authored-by: Renovate Bot --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 4f3001015..e222307af 100644 --- a/go.mod +++ b/go.mod @@ -38,8 +38,8 @@ require ( golang.org/x/oauth2 v0.33.0 golang.org/x/term v0.37.0 golang.org/x/text v0.31.0 - k8s.io/apimachinery v0.34.1 - k8s.io/client-go v0.34.1 + k8s.io/apimachinery v0.34.2 + k8s.io/client-go v0.34.2 ) require ( @@ -254,7 +254,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.38.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.34.1 // indirect + k8s.io/api v0.34.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect diff --git a/go.sum b/go.sum index d119f696d..c3b3ab1b7 100644 --- a/go.sum +++ b/go.sum @@ -1085,12 +1085,12 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= -k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= -k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= -k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= -k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= +k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY= +k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw= +k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4= +k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M= +k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= From b79dc00b2c532e40e45fedee17f8e93f0c8f67a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 13 Nov 2025 16:41:33 +0100 Subject: [PATCH 500/619] fix(sqlserverflex): print valid JSON/YAML output for list cmds (#1044) relates to STACKITCLI-272 / #893 --- .../beta/sqlserverflex/database/list/list.go | 24 ++++++++++--------- .../sqlserverflex/database/list/list_test.go | 7 ++++-- .../beta/sqlserverflex/instance/list/list.go | 24 ++++++++++--------- .../sqlserverflex/instance/list/list_test.go | 6 +++-- .../cmd/beta/sqlserverflex/user/list/list.go | 24 ++++++++++--------- .../beta/sqlserverflex/user/list/list_test.go | 10 ++++---- 6 files changed, 54 insertions(+), 41 deletions(-) diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index 38f630a3f..12738a9ab 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -66,23 +66,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get SQLServer Flex databases: %w", err) } - if resp.Databases == nil || len(*resp.Databases) == 0 { - 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 - } - params.Printer.Info("No databases found for instance %s on project %s\n", model.InstanceId, projectLabel) - return nil + databases := resp.GetDatabases() + + 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 } - databases := *resp.Databases // Truncate output if model.Limit != nil && len(databases) > int(*model.Limit) { databases = databases[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, databases) + return outputResult(params.Printer, model.OutputFormat, model.InstanceId, projectLabel, databases) }, } @@ -127,8 +124,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, outputFormat string, databases []sqlserverflex.Database) error { +func outputResult(p *print.Printer, outputFormat, instanceId, projectLabel string, databases []sqlserverflex.Database) error { return p.OutputResult(outputFormat, databases, func() error { + if len(databases) == 0 { + p.Outputf("No databases found for instance %s on project %s\n", instanceId, projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME") for i := range databases { diff --git a/internal/cmd/beta/sqlserverflex/database/list/list_test.go b/internal/cmd/beta/sqlserverflex/database/list/list_test.go index ae340d0db..36674a923 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list_test.go @@ -21,7 +21,8 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -var testRegion = "eu01" + +const testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ @@ -175,6 +176,8 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + instanceId string + projectLabel string databases []sqlserverflex.Database } tests := []struct { @@ -199,7 +202,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.databases); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceId, tt.args.projectLabel, tt.args.databases); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 76cf59d8a..27dada066 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -64,23 +64,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get SQLServer Flex instances: %w", err) } - if resp.Items == nil || len(*resp.Items) == 0 { - 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 - } - params.Printer.Info("No instances found for project %q\n", projectLabel) - return nil + instances := resp.GetItems() + + 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 } - instances := *resp.Items // Truncate output if model.Limit != nil && len(instances) > int(*model.Limit) { instances = instances[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, instances) + return outputResult(params.Printer, model.OutputFormat, projectLabel, instances) }, } @@ -120,8 +117,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, outputFormat string, instances []sqlserverflex.InstanceListInstance) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []sqlserverflex.InstanceListInstance) error { return p.OutputResult(outputFormat, instances, func() error { + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "STATUS") for i := range instances { diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go index 59711594b..4105384df 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go @@ -20,7 +20,8 @@ type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() -var testRegion = "eu01" + +const testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ @@ -151,6 +152,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string instances []sqlserverflex.InstanceListInstance } tests := []struct { @@ -175,7 +177,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.instances); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index 0c131e32b..c74dc7866 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -67,23 +67,20 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("get SQLServer Flex users: %w", err) } - if resp.Items == nil || len(*resp.Items) == 0 { - instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) - if err != nil { - params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) - instanceLabel = *model.InstanceId - } - params.Printer.Info("No users found for instance %q\n", instanceLabel) - return nil + users := resp.GetItems() + + instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, *model.InstanceId, model.Region) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) + instanceLabel = *model.InstanceId } - users := *resp.Items // Truncate output if model.Limit != nil && len(users) > int(*model.Limit) { users = users[:*model.Limit] } - return outputResult(params.Printer, model.OutputFormat, users) + return outputResult(params.Printer, model.OutputFormat, instanceLabel, users) }, } @@ -128,8 +125,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverfl return req } -func outputResult(p *print.Printer, outputFormat string, users []sqlserverflex.InstanceListUser) error { +func outputResult(p *print.Printer, outputFormat, instanceLabel string, users []sqlserverflex.InstanceListUser) error { return p.OutputResult(outputFormat, users, func() error { + if len(users) == 0 { + p.Outputf("No users found for instance %q\n", instanceLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "USERNAME") for i := range users { diff --git a/internal/cmd/beta/sqlserverflex/user/list/list_test.go b/internal/cmd/beta/sqlserverflex/user/list/list_test.go index ef80e6252..44deacf77 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list_test.go @@ -21,7 +21,8 @@ var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") var testClient = &sqlserverflex.APIClient{} var testProjectId = uuid.NewString() var testInstanceId = uuid.NewString() -var testRegion = "eu01" + +const testRegion = "eu01" func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ @@ -167,8 +168,9 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - outputFormat string - users []sqlserverflex.InstanceListUser + outputFormat string + instanceLabel string + users []sqlserverflex.InstanceListUser } tests := []struct { name string @@ -192,7 +194,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.users); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.instanceLabel, tt.args.users); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From 79ea76d2dbf08411c315825b05fbe0ded5087560 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Fri, 14 Nov 2025 07:39:57 +0100 Subject: [PATCH 501/619] chore(deps): update module golang.org/x/tools to v0.39.0 (#1087) Co-authored-by: Renovate Bot --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index e222307af..d37be0e7e 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( ) require ( - golang.org/x/net v0.46.0 // indirect + golang.org/x/net v0.47.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -209,8 +209,8 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.18.0 // indirect - golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect - golang.org/x/tools v0.38.0 // indirect + golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect + golang.org/x/tools v0.39.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect google.golang.org/protobuf v1.36.6 // indirect diff --git a/go.sum b/go.sum index c3b3ab1b7..42be8a8c0 100644 --- a/go.sum +++ b/go.sum @@ -799,8 +799,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -879,8 +879,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= -golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= +golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 h1:E2/AqCUMZGgd73TQkxUMcMla25GB9i/5HOdLr+uH7Vo= +golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -968,8 +968,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= From 128b545d996f9a7f09ccdd15e9ab68a64e8e1393 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Nov 2025 06:48:22 +0000 Subject: [PATCH 502/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/core (#1086) Bumps [github.com/stackitcloud/stackit-sdk-go/core](https://github.com/stackitcloud/stackit-sdk-go) from 0.18.0 to 0.19.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.18.0...core/v0.19.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/core dependency-version: 0.19.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d37be0e7e..27664ec41 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/spf13/cobra v1.10.1 github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 - github.com/stackitcloud/stackit-sdk-go/core v0.18.0 + github.com/stackitcloud/stackit-sdk-go/core v0.19.0 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 diff --git a/go.sum b/go.sum index 42be8a8c0..2d88b3d6c 100644 --- a/go.sum +++ b/go.sum @@ -561,8 +561,8 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stackitcloud/stackit-sdk-go/core v0.18.0 h1:+4v8sjQpQXPihO3crgTp0Kz/XRIi5p7oKV28dw6jsEQ= -github.com/stackitcloud/stackit-sdk-go/core v0.18.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= +github.com/stackitcloud/stackit-sdk-go/core v0.19.0 h1:dtJcs6/TTCzzb2RKI7HJugDrbCkaFEDmn1pOeFe8qnI= +github.com/stackitcloud/stackit-sdk-go/core v0.19.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 h1:DaJkEN/6l+AJEQ3Dr+3IdKM4jywDQsTvuYHmRvFj3ho= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1/go.mod h1:SzA+UsSNv4D9IvNT7hwYPewgAvUgj5WXIU2tZ0XaMBI= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo= From 46b890557446fd571f80c2bb30ac11c4e89bb9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 14 Nov 2025 10:24:47 +0100 Subject: [PATCH 503/619] fix(dns): print valid JSON/YAML output for list cmds (#1040) relates to STACKITCLI-266 / #893 --- .../cmd/dns/record-set/create/create_test.go | 42 ++++++------ .../cmd/dns/record-set/delete/delete_test.go | 12 ++-- .../dns/record-set/describe/describe_test.go | 12 ++-- internal/cmd/dns/record-set/list/list.go | 23 ++++--- internal/cmd/dns/record-set/list/list_test.go | 23 +++---- .../cmd/dns/record-set/update/update_test.go | 36 +++++----- internal/cmd/dns/zone/clone/clone_test.go | 22 +++--- internal/cmd/dns/zone/create/create_test.go | 68 +++++++++---------- internal/cmd/dns/zone/delete/delete_test.go | 10 ++- .../cmd/dns/zone/describe/describe_test.go | 10 ++- internal/cmd/dns/zone/list/list.go | 22 +++--- internal/cmd/dns/zone/list/list_test.go | 19 +++--- internal/cmd/dns/zone/update/update_test.go | 54 +++++++-------- 13 files changed, 169 insertions(+), 184 deletions(-) diff --git a/internal/cmd/dns/record-set/create/create_test.go b/internal/cmd/dns/record-set/create/create_test.go index d284504bf..b08de66aa 100644 --- a/internal/cmd/dns/record-set/create/create_test.go +++ b/internal/cmd/dns/record-set/create/create_test.go @@ -17,8 +17,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -34,13 +32,13 @@ var recordTxtOver255Char = []string{ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, - commentFlag: "comment", - nameFlag: "example.com", - recordFlag: "1.1.1.1", - ttlFlag: "3600", - typeFlag: "SOA", // Non-default value + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, + commentFlag: "comment", + nameFlag: "example.com", + recordFlag: "1.1.1.1", + ttlFlag: "3600", + typeFlag: "SOA", // Non-default value } for _, mod := range mods { mod(flagValues) @@ -107,10 +105,10 @@ func TestParseInput(t *testing.T) { { description: "required fields only", flagValues: map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, - nameFlag: "example.com", - recordFlag: "1.1.1.1", + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, + nameFlag: "example.com", + recordFlag: "1.1.1.1", }, isValid: true, expectedModel: &inputModel{ @@ -127,12 +125,12 @@ func TestParseInput(t *testing.T) { { description: "zero values", flagValues: map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, - commentFlag: "", - nameFlag: "", - recordFlag: "1.1.1.1", - ttlFlag: "0", + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, + commentFlag: "", + nameFlag: "", + recordFlag: "1.1.1.1", + ttlFlag: "0", }, isValid: true, expectedModel: &inputModel{ @@ -151,21 +149,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/dns/record-set/delete/delete_test.go b/internal/cmd/dns/record-set/delete/delete_test.go index c02628dd1..46a5c6d28 100644 --- a/internal/cmd/dns/record-set/delete/delete_test.go +++ b/internal/cmd/dns/record-set/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -35,8 +33,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, } for _, mod := range mods { mod(flagValues) @@ -104,7 +102,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -112,7 +110,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -120,7 +118,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/dns/record-set/describe/describe_test.go b/internal/cmd/dns/record-set/describe/describe_test.go index 45d58c2a1..05d60ebcd 100644 --- a/internal/cmd/dns/record-set/describe/describe_test.go +++ b/internal/cmd/dns/record-set/describe/describe_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,8 +34,8 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, } for _, mod := range mods { mod(flagValues) @@ -105,7 +103,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -113,7 +111,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -121,7 +119,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index eedc2a59e..309013a2c 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -90,16 +90,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return err } - if len(recordSets) == 0 { - zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) - if err != nil { - params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) - zoneLabel = model.ZoneId - } - params.Printer.Info("No record sets found for zone %s matching the criteria\n", zoneLabel) - return nil + + zoneLabel, err := dnsUtils.GetZoneName(ctx, apiClient, model.ProjectId, model.ZoneId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) + zoneLabel = model.ZoneId } - return outputResult(params.Printer, model.OutputFormat, recordSets) + + return outputResult(params.Printer, model.OutputFormat, zoneLabel, recordSets) }, } @@ -239,8 +237,13 @@ func fetchRecordSets(ctx context.Context, model *inputModel, apiClient dnsClient return recordSets, nil } -func outputResult(p *print.Printer, outputFormat string, recordSets []dns.RecordSet) error { +func outputResult(p *print.Printer, outputFormat, zoneLabel string, recordSets []dns.RecordSet) error { return p.OutputResult(outputFormat, recordSets, func() error { + if len(recordSets) == 0 { + p.Outputf("No record sets found for zone %s matching the criteria\n", zoneLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "STATUS", "TTL", "TYPE", "RECORD DATA") for i := range recordSets { diff --git a/internal/cmd/dns/record-set/list/list_test.go b/internal/cmd/dns/record-set/list/list_test.go index 6eaf5504b..67c60a202 100644 --- a/internal/cmd/dns/record-set/list/list_test.go +++ b/internal/cmd/dns/record-set/list/list_test.go @@ -20,8 +20,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -31,10 +29,10 @@ var testZoneId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, - nameLikeFlag: "some-pattern", - orderByNameFlag: "asc", + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, + nameLikeFlag: "some-pattern", + orderByNameFlag: "asc", } for _, mod := range mods { mod(flagValues) @@ -130,8 +128,8 @@ func TestParseInput(t *testing.T) { { description: "required fields only", flagValues: map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, }, isValid: true, expectedModel: &inputModel{ @@ -146,21 +144,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -468,6 +466,7 @@ func TestFetchRecordSets(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + zoneLabel string recordSets []dns.RecordSet } tests := []struct { @@ -485,7 +484,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.recordSets); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.zoneLabel, tt.args.recordSets); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/dns/record-set/update/update_test.go b/internal/cmd/dns/record-set/update/update_test.go index 228b4b956..ccb5df9ee 100644 --- a/internal/cmd/dns/record-set/update/update_test.go +++ b/internal/cmd/dns/record-set/update/update_test.go @@ -16,8 +16,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -45,12 +43,12 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, - commentFlag: "comment", - nameFlag: "example.com", - recordFlag: "1.1.1.1", - ttlFlag: "3600", + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, + commentFlag: "comment", + nameFlag: "example.com", + recordFlag: "1.1.1.1", + ttlFlag: "3600", } for _, mod := range mods { mod(flagValues) @@ -132,8 +130,8 @@ func TestParseInput(t *testing.T) { description: "required flags only (no values to update)", argValues: fixtureArgValues(), flagValues: map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, }, isValid: false, expectedModel: &inputModel{ @@ -149,12 +147,12 @@ func TestParseInput(t *testing.T) { description: "zero values", argValues: fixtureArgValues(), flagValues: map[string]string{ - projectIdFlag: testProjectId, - zoneIdFlag: testZoneId, - commentFlag: "", - nameFlag: "", - recordFlag: "1.1.1.1", - ttlFlag: "0", + globalflags.ProjectIdFlag: testProjectId, + zoneIdFlag: testZoneId, + commentFlag: "", + nameFlag: "", + recordFlag: "1.1.1.1", + ttlFlag: "0", }, isValid: true, expectedModel: &inputModel{ @@ -174,7 +172,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -182,7 +180,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -190,7 +188,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/dns/zone/clone/clone_test.go b/internal/cmd/dns/zone/clone/clone_test.go index b17d634fe..59d0d13a8 100644 --- a/internal/cmd/dns/zone/clone/clone_test.go +++ b/internal/cmd/dns/zone/clone/clone_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,11 +34,11 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - nameFlag: "example", - dnsNameFlag: "example.com", - descriptionFlag: "Example", - adjustRecordsFlag: "false", + globalflags.ProjectIdFlag: testProjectId, + nameFlag: "example", + dnsNameFlag: "example.com", + descriptionFlag: "Example", + adjustRecordsFlag: "false", } for _, mod := range mods { mod(flagValues) @@ -117,8 +115,8 @@ func TestParseInput(t *testing.T) { description: "required fields only", argValues: []string{testZoneId}, flagValues: map[string]string{ - projectIdFlag: testProjectId, - dnsNameFlag: "example.com", + globalflags.ProjectIdFlag: testProjectId, + dnsNameFlag: "example.com", }, isValid: true, expectedModel: &inputModel{ @@ -134,7 +132,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -142,7 +140,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -150,7 +148,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/dns/zone/create/create_test.go b/internal/cmd/dns/zone/create/create_test.go index 8c7f58bc0..319147da1 100644 --- a/internal/cmd/dns/zone/create/create_test.go +++ b/internal/cmd/dns/zone/create/create_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -25,20 +23,20 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - nameFlag: "example", - dnsNameFlag: "example.com", - defaultTTLFlag: "3600", - aclFlag: "0.0.0.0/0", - typeFlag: string(dns.CREATEZONEPAYLOADTYPE_PRIMARY), - primaryFlag: "1.1.1.1", - retryTimeFlag: "600", - refreshTimeFlag: "3600", - negativeCacheFlag: "60", - isReverseZoneFlag: "false", - expireTimeFlag: "36000000", - descriptionFlag: "Example", - contactEmailFlag: "example@example.com", + globalflags.ProjectIdFlag: testProjectId, + nameFlag: "example", + dnsNameFlag: "example.com", + defaultTTLFlag: "3600", + aclFlag: "0.0.0.0/0", + typeFlag: string(dns.CREATEZONEPAYLOADTYPE_PRIMARY), + primaryFlag: "1.1.1.1", + retryTimeFlag: "600", + refreshTimeFlag: "3600", + negativeCacheFlag: "60", + isReverseZoneFlag: "false", + expireTimeFlag: "36000000", + descriptionFlag: "Example", + contactEmailFlag: "example@example.com", } for _, mod := range mods { mod(flagValues) @@ -118,9 +116,9 @@ func TestParseInput(t *testing.T) { { description: "required fields only", flagValues: map[string]string{ - projectIdFlag: testProjectId, - nameFlag: "example", - dnsNameFlag: "example.com", + globalflags.ProjectIdFlag: testProjectId, + nameFlag: "example", + dnsNameFlag: "example.com", }, isValid: true, expectedModel: &inputModel{ @@ -135,19 +133,19 @@ func TestParseInput(t *testing.T) { { description: "zero values", flagValues: map[string]string{ - projectIdFlag: testProjectId, - nameFlag: "", - dnsNameFlag: "", - defaultTTLFlag: "0", - aclFlag: "", - typeFlag: "", - retryTimeFlag: "0", - refreshTimeFlag: "0", - negativeCacheFlag: "0", - isReverseZoneFlag: "false", - expireTimeFlag: "0", - descriptionFlag: "", - contactEmailFlag: "", + globalflags.ProjectIdFlag: testProjectId, + nameFlag: "", + dnsNameFlag: "", + defaultTTLFlag: "0", + aclFlag: "", + typeFlag: "", + retryTimeFlag: "0", + refreshTimeFlag: "0", + negativeCacheFlag: "0", + isReverseZoneFlag: "false", + expireTimeFlag: "0", + descriptionFlag: "", + contactEmailFlag: "", }, isValid: true, expectedModel: &inputModel{ @@ -173,21 +171,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/dns/zone/delete/delete_test.go b/internal/cmd/dns/zone/delete/delete_test.go index a4b967998..32eabe63b 100644 --- a/internal/cmd/dns/zone/delete/delete_test.go +++ b/internal/cmd/dns/zone/delete/delete_test.go @@ -13,8 +13,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -34,7 +32,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -101,7 +99,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -109,7 +107,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -117,7 +115,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/dns/zone/describe/describe_test.go b/internal/cmd/dns/zone/describe/describe_test.go index 69a7f0587..a205a5cfd 100644 --- a/internal/cmd/dns/zone/describe/describe_test.go +++ b/internal/cmd/dns/zone/describe/describe_test.go @@ -14,8 +14,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -35,7 +33,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -102,7 +100,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -110,7 +108,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -118,7 +116,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index e86c8ec78..132a362c7 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -86,17 +86,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return err } - if len(zones) == 0 { - 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 - } - params.Printer.Info("No zones found for project %q matching the criteria\n", projectLabel) - return nil + + 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 } - return outputResult(params.Printer, model.OutputFormat, zones) + return outputResult(params.Printer, model.OutputFormat, projectLabel, zones) }, } configureFlags(cmd) @@ -228,8 +225,13 @@ func fetchZones(ctx context.Context, model *inputModel, apiClient dnsClient) ([] return zones, nil } -func outputResult(p *print.Printer, outputFormat string, zones []dns.Zone) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, zones []dns.Zone) error { return p.OutputResult(outputFormat, zones, func() error { + if len(zones) == 0 { + p.Outputf("No zones found for project %q matching the criteria\n", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("ID", "NAME", "STATE", "TYPE", "DNS NAME", "RECORD COUNT") for i := range zones { diff --git a/internal/cmd/dns/zone/list/list_test.go b/internal/cmd/dns/zone/list/list_test.go index bb46d6aea..14a7082f9 100644 --- a/internal/cmd/dns/zone/list/list_test.go +++ b/internal/cmd/dns/zone/list/list_test.go @@ -20,8 +20,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -30,9 +28,9 @@ var testProjectId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - nameLikeFlag: "some-pattern", - orderByNameFlag: "asc", + globalflags.ProjectIdFlag: testProjectId, + nameLikeFlag: "some-pattern", + orderByNameFlag: "asc", } for _, mod := range mods { mod(flagValues) @@ -127,7 +125,7 @@ func TestParseInput(t *testing.T) { { description: "required fields only", flagValues: map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, }, isValid: true, expectedModel: &inputModel{ @@ -141,21 +139,21 @@ func TestParseInput(t *testing.T) { { description: "project id missing", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, { description: "project id invalid 1", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, { description: "project id invalid 2", flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, @@ -462,6 +460,7 @@ func TestFetchZones(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string zones []dns.Zone } tests := []struct { @@ -479,7 +478,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.zones); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.zones); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/dns/zone/update/update_test.go b/internal/cmd/dns/zone/update/update_test.go index adea3637d..4610849bd 100644 --- a/internal/cmd/dns/zone/update/update_test.go +++ b/internal/cmd/dns/zone/update/update_test.go @@ -15,8 +15,6 @@ import ( "github.com/stackitcloud/stackit-sdk-go/services/dns" ) -var projectIdFlag = globalflags.ProjectIdFlag - type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") @@ -36,17 +34,17 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ - projectIdFlag: testProjectId, - nameFlag: "example", - defaultTTLFlag: "3600", - aclFlag: "0.0.0.0/0", - primaryFlag: "1.1.1.1", - retryTimeFlag: "600", - refreshTimeFlag: "3600", - negativeCacheFlag: "60", - expireTimeFlag: "36000000", - descriptionFlag: "Example", - contactEmailFlag: "example@example.com", + globalflags.ProjectIdFlag: testProjectId, + nameFlag: "example", + defaultTTLFlag: "3600", + aclFlag: "0.0.0.0/0", + primaryFlag: "1.1.1.1", + retryTimeFlag: "600", + refreshTimeFlag: "3600", + negativeCacheFlag: "60", + expireTimeFlag: "36000000", + descriptionFlag: "Example", + contactEmailFlag: "example@example.com", } for _, mod := range mods { mod(flagValues) @@ -136,7 +134,7 @@ func TestParseInput(t *testing.T) { description: "required flags only (no values to update)", argValues: fixtureArgValues(), flagValues: map[string]string{ - projectIdFlag: testProjectId, + globalflags.ProjectIdFlag: testProjectId, }, isValid: false, expectedModel: &inputModel{ @@ -151,17 +149,17 @@ func TestParseInput(t *testing.T) { description: "zero values", argValues: fixtureArgValues(), flagValues: map[string]string{ - projectIdFlag: testProjectId, - nameFlag: "", - defaultTTLFlag: "0", - aclFlag: "", - primaryFlag: "", - retryTimeFlag: "0", - refreshTimeFlag: "0", - negativeCacheFlag: "0", - expireTimeFlag: "0", - descriptionFlag: "", - contactEmailFlag: "", + globalflags.ProjectIdFlag: testProjectId, + nameFlag: "", + defaultTTLFlag: "0", + aclFlag: "", + primaryFlag: "", + retryTimeFlag: "0", + refreshTimeFlag: "0", + negativeCacheFlag: "0", + expireTimeFlag: "0", + descriptionFlag: "", + contactEmailFlag: "", }, isValid: true, expectedModel: &inputModel{ @@ -186,7 +184,7 @@ func TestParseInput(t *testing.T) { description: "project id missing", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - delete(flagValues, projectIdFlag) + delete(flagValues, globalflags.ProjectIdFlag) }), isValid: false, }, @@ -194,7 +192,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 1", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "" + flagValues[globalflags.ProjectIdFlag] = "" }), isValid: false, }, @@ -202,7 +200,7 @@ func TestParseInput(t *testing.T) { description: "project id invalid 2", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { - flagValues[projectIdFlag] = "invalid-uuid" + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" }), isValid: false, }, From 122503be4e33ce868c7a7170fd12fedb9b22f894 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 17 Nov 2025 08:56:44 +0100 Subject: [PATCH 504/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.7.2 (#1088) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 27664ec41..9fc4511c3 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.7.1 + github.com/jedib0t/go-pretty/v6 v6.7.2 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index 2d88b3d6c..65d126b27 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.7.1 h1:bHDSsj93NuJ563hHuM7ohk/wpX7BmRFNIsVv1ssI2/M= -github.com/jedib0t/go-pretty/v6 v6.7.1/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.7.2 h1:EYWgQNIH/+JsyHki7ns9OHyBKuHPkzrBo02uYjran7w= +github.com/jedib0t/go-pretty/v6 v6.7.2/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From 235238399c260a4e075e0d2c0e17e90f425cefe7 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Tue, 18 Nov 2025 09:21:54 +0100 Subject: [PATCH 505/619] chore: remove typo in server create example (#1090) --- docs/stackit_server_create.md | 2 +- internal/cmd/server/create/create.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/stackit_server_create.md b/docs/stackit_server_create.md index 23378c5fa..27412840a 100644 --- a/docs/stackit_server_create.md +++ b/docs/stackit_server_create.md @@ -38,7 +38,7 @@ stackit server create [flags] $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --volumes yyy Create a server with user data (cloud-init) - $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml") + $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml ``` ### Options diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 00ebd8254..afd46385c 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -105,7 +105,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { ), examples.NewExample( `Create a server with user data (cloud-init)`, - `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml")`, + `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml`, ), ), RunE: func(cmd *cobra.Command, args []string) error { From 9b86268dec8844953778ab510b91a79e2132cb26 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:11:42 +0100 Subject: [PATCH 506/619] chore(deps): bump renovatebot/github-action from 44.0.2 to 44.0.3 (#1089) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 44.0.2 to 44.0.3. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v44.0.2...v44.0.3) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 44.0.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 41bef42a1..804c3206d 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Self-hosted Renovate - uses: renovatebot/github-action@v44.0.2 + uses: renovatebot/github-action@v44.0.3 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From b7f6a9e387d648140142b291a7edce9de3eee4cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:39:28 +0100 Subject: [PATCH 507/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/core from 0.19.0 to 0.20.0 (#1092) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9fc4511c3..558137a85 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/spf13/cobra v1.10.1 github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 - github.com/stackitcloud/stackit-sdk-go/core v0.19.0 + github.com/stackitcloud/stackit-sdk-go/core v0.20.0 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 diff --git a/go.sum b/go.sum index 65d126b27..ad13b3f6c 100644 --- a/go.sum +++ b/go.sum @@ -561,8 +561,8 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stackitcloud/stackit-sdk-go/core v0.19.0 h1:dtJcs6/TTCzzb2RKI7HJugDrbCkaFEDmn1pOeFe8qnI= -github.com/stackitcloud/stackit-sdk-go/core v0.19.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= +github.com/stackitcloud/stackit-sdk-go/core v0.20.0 h1:4rrUk6uT1g4nOn5/g1uXukP07Tux/o5xbMz/f/qE1rY= +github.com/stackitcloud/stackit-sdk-go/core v0.20.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 h1:DaJkEN/6l+AJEQ3Dr+3IdKM4jywDQsTvuYHmRvFj3ho= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1/go.mod h1:SzA+UsSNv4D9IvNT7hwYPewgAvUgj5WXIU2tZ0XaMBI= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo= From e42758d070856e3e9543ec835d86c8359cf19f49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:05:43 +0100 Subject: [PATCH 508/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex (#1098) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 558137a85..583daa5d5 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.30.0 golang.org/x/oauth2 v0.33.0 diff --git a/go.sum b/go.sum index ad13b3f6c..edba3a9de 100644 --- a/go.sum +++ b/go.sum @@ -611,8 +611,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2ia github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 h1:V6RFvybDeJvvmT3g7/BZodF0gozz3TEpahbpiTftbeY= github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0/go.mod h1:xRBgpJ8P5Nf1T5tD0tGAeNg1FNQzx5VF7qqOXt2Fp3s= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1 h1:r5808lRhtY8l5anft/UwgJEaef1XsoYObmwd3FVai48= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.1/go.mod h1:+LYy2pB+tpF0lkkmCf524wvv2Sa49REgEaNh7JGzN6Y= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 h1:aW8ehdoNRaCEs3xDr+YnGb6pru8zZTB8f7kl5lozlJE= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2/go.mod h1:Jsry+gfhuXv2P0ldfa48BaL605NhDjdQMgaoV8czlbo= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 240257027ebddef0121830f54dd0914a491b5eda Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 14:15:01 +0000 Subject: [PATCH 509/619] chore(deps): bump github.com/jedib0t/go-pretty/v6 from 6.7.2 to 6.7.3 (#1097) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 583daa5d5..7357dd57a 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.7.2 + github.com/jedib0t/go-pretty/v6 v6.7.3 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index edba3a9de..d9dc64bc4 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.7.2 h1:EYWgQNIH/+JsyHki7ns9OHyBKuHPkzrBo02uYjran7w= -github.com/jedib0t/go-pretty/v6 v6.7.2/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.7.3 h1:i6IhmHUcZxxvxdgRTcIQk5N3ZMZqyQQyXLHDWxMxb3Y= +github.com/jedib0t/go-pretty/v6 v6.7.3/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From 18ea31b40dbfb6a5f32211061f03f4f43ddbd53f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 14:23:43 +0000 Subject: [PATCH 510/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/objectstorage (#1096) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7357dd57a..96fb45834 100644 --- a/go.mod +++ b/go.mod @@ -246,7 +246,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 diff --git a/go.sum b/go.sum index d9dc64bc4..084d5e0ca 100644 --- a/go.sum +++ b/go.sum @@ -583,8 +583,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 h1:Db/ebOL2vbpIe github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1/go.mod h1:8jdN4v2euK3f9gfdzbRi8e4nBJ8g/Q5YF9aPB4M4fCQ= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/aGHepE/+gVsvSg1sRkPOyIUI/jkCyUOrWg= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0 h1:g3yNDUc3JydAikezUrI9bQ4nuMJpVeAQ35jOFfFmq1U= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.0/go.mod h1:foslkEiICdtHR3v0A/i/Rgo6EP9MMula9XNC9luNOgw= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 h1:I9B/zUU7R74xuH/ztcPrDIuMp2KV3QQMjeE7lFudboM= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1/go.mod h1:h4aX5tyTQoO6KLrugkvfkqgKTjIzh7e4q9N92kT5OBs= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0 h1:MA5i1ScjXLWe5CYeFCLHeZzNS1AH4mbx1kUyiVbxKjI= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= From a4510768062a2a022b4054f5ba63ff3a3d7f5eae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 14:32:19 +0000 Subject: [PATCH 511/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/logme (#1095) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 96fb45834..aff55ecea 100644 --- a/go.mod +++ b/go.mod @@ -244,7 +244,7 @@ require ( github.com/spf13/cast v1.10.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0 diff --git a/go.sum b/go.sum index 084d5e0ca..ce063455b 100644 --- a/go.sum +++ b/go.sum @@ -577,8 +577,8 @@ github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0 h1:bgMV+hi/530htdSMAy github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0/go.mod h1:QswbIN9TUYELIwkjO+Bu8Nk/FGcd3kZYDlf2n0PdFAk= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0/go.mod h1:20QOZ3rBC9wTGgzXzLz9M6YheX0VaxWE0/JI+s8On7k= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1 h1:hv5WrRU9rN6Jx4OwdOGJRyaQrfA9p1tzEoQK6/CDyoA= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.1/go.mod h1:ivt8lvnAoBZsde2jSAuicyn6RgTmHvvNAJ3whaUbAD4= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 h1:g3xzRqwul8W638gOKTZRAnnQuMhYqaliuz/A8BcfjhU= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2/go.mod h1:OlGmMlXKp33ZYpUm9TqaLYf8SdzhDW5uBKcbgq1zXOk= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 h1:Db/ebOL2vbpIeh5XB2Ews2B9Lj5DJlMWIEJh60FfZ4Y= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1/go.mod h1:8jdN4v2euK3f9gfdzbRi8e4nBJ8g/Q5YF9aPB4M4fCQ= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/aGHepE/+gVsvSg1sRkPOyIUI/jkCyUOrWg= From f7d13600861f5e17549f5d5f0de99a156cbbcbd5 Mon Sep 17 00:00:00 2001 From: Yago Date: Fri, 21 Nov 2025 18:26:04 +0100 Subject: [PATCH 512/619] feat(intake): add runner command (#952) relates to STACKITINT-1349 --- docs/stackit_beta.md | 1 + docs/stackit_beta_intake.md | 34 ++ docs/stackit_beta_intake_runner.md | 38 +++ docs/stackit_beta_intake_runner_create.md | 48 +++ docs/stackit_beta_intake_runner_delete.md | 40 +++ docs/stackit_beta_intake_runner_describe.md | 43 +++ docs/stackit_beta_intake_runner_list.md | 47 +++ docs/stackit_beta_intake_runner_update.md | 48 +++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 2 + internal/cmd/beta/beta.go | 2 + internal/cmd/beta/intake/intake.go | 26 ++ .../cmd/beta/intake/runner/create/create.go | 170 ++++++++++ .../beta/intake/runner/create/create_test.go | 293 ++++++++++++++++++ .../cmd/beta/intake/runner/delete/delete.go | 115 +++++++ .../beta/intake/runner/delete/delete_test.go | 155 +++++++++ .../beta/intake/runner/describe/describe.go | 117 +++++++ .../intake/runner/describe/describe_test.go | 192 ++++++++++++ internal/cmd/beta/intake/runner/list/list.go | 152 +++++++++ .../cmd/beta/intake/runner/list/list_test.go | 197 ++++++++++++ internal/cmd/beta/intake/runner/runner.go | 31 ++ .../cmd/beta/intake/runner/update/update.go | 176 +++++++++++ .../beta/intake/runner/update/update_test.go | 277 +++++++++++++++++ internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 3 + internal/pkg/config/config.go | 3 + internal/pkg/services/intake/client/client.go | 14 + 30 files changed, 2238 insertions(+) create mode 100644 docs/stackit_beta_intake.md create mode 100644 docs/stackit_beta_intake_runner.md create mode 100644 docs/stackit_beta_intake_runner_create.md create mode 100644 docs/stackit_beta_intake_runner_delete.md create mode 100644 docs/stackit_beta_intake_runner_describe.md create mode 100644 docs/stackit_beta_intake_runner_list.md create mode 100644 docs/stackit_beta_intake_runner_update.md create mode 100644 internal/cmd/beta/intake/intake.go create mode 100644 internal/cmd/beta/intake/runner/create/create.go create mode 100644 internal/cmd/beta/intake/runner/create/create_test.go create mode 100644 internal/cmd/beta/intake/runner/delete/delete.go create mode 100644 internal/cmd/beta/intake/runner/delete/delete_test.go create mode 100644 internal/cmd/beta/intake/runner/describe/describe.go create mode 100644 internal/cmd/beta/intake/runner/describe/describe_test.go create mode 100644 internal/cmd/beta/intake/runner/list/list.go create mode 100644 internal/cmd/beta/intake/runner/list/list_test.go create mode 100644 internal/cmd/beta/intake/runner/runner.go create mode 100644 internal/cmd/beta/intake/runner/update/update.go create mode 100644 internal/cmd/beta/intake/runner/update/update_test.go create mode 100644 internal/pkg/services/intake/client/client.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 23097f8ca..c099db5b3 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -42,6 +42,7 @@ stackit beta [flags] * [stackit](./stackit.md) - Manage STACKIT resources using the command line * [stackit beta alb](./stackit_beta_alb.md) - Manages application loadbalancers +* [stackit beta intake](./stackit_beta_intake.md) - Provides functionality for intake * [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_intake.md b/docs/stackit_beta_intake.md new file mode 100644 index 000000000..f44d3c12d --- /dev/null +++ b/docs/stackit_beta_intake.md @@ -0,0 +1,34 @@ +## stackit beta intake + +Provides functionality for intake + +### Synopsis + +Provides functionality for intake. + +``` +stackit beta intake [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta intake" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta intake runner](./stackit_beta_intake_runner.md) - Provides functionality for Intake Runners + diff --git a/docs/stackit_beta_intake_runner.md b/docs/stackit_beta_intake_runner.md new file mode 100644 index 000000000..7d5c60ff3 --- /dev/null +++ b/docs/stackit_beta_intake_runner.md @@ -0,0 +1,38 @@ +## stackit beta intake runner + +Provides functionality for Intake Runners + +### Synopsis + +Provides functionality for Intake Runners. + +``` +stackit beta intake runner [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta intake runner" +``` + +### 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 beta intake](./stackit_beta_intake.md) - Provides functionality for intake +* [stackit beta intake runner create](./stackit_beta_intake_runner_create.md) - Creates a new Intake Runner +* [stackit beta intake runner delete](./stackit_beta_intake_runner_delete.md) - Deletes an Intake Runner +* [stackit beta intake runner describe](./stackit_beta_intake_runner_describe.md) - Shows details of an Intake Runner +* [stackit beta intake runner list](./stackit_beta_intake_runner_list.md) - Lists all Intake Runners +* [stackit beta intake runner update](./stackit_beta_intake_runner_update.md) - Updates an Intake Runner + diff --git a/docs/stackit_beta_intake_runner_create.md b/docs/stackit_beta_intake_runner_create.md new file mode 100644 index 000000000..8903cef9d --- /dev/null +++ b/docs/stackit_beta_intake_runner_create.md @@ -0,0 +1,48 @@ +## stackit beta intake runner create + +Creates a new Intake Runner + +### Synopsis + +Creates a new Intake Runner. + +``` +stackit beta intake runner create [flags] +``` + +### Examples + +``` + Create a new Intake Runner with a display name and message capacity limits + $ stackit beta intake runner create --display-name my-runner --max-message-size-kib 1000 --max-messages-per-hour 5000 + + Create a new Intake Runner with a description and labels + $ stackit beta intake runner create --display-name my-runner --max-message-size-kib 1000 --max-messages-per-hour 5000 --description "Main runner for production" --labels="env=prod,team=billing" +``` + +### Options + +``` + --description string Description + --display-name string Display name + -h, --help Help for "stackit beta intake runner create" + --labels stringToString Labels in key=value format, separated by commas. Example: --labels "key1=value1,key2=value2" (default []) + --max-message-size-kib int Maximum message size in KiB + --max-messages-per-hour int Maximum number of messages per hour +``` + +### 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 beta intake runner](./stackit_beta_intake_runner.md) - Provides functionality for Intake Runners + diff --git a/docs/stackit_beta_intake_runner_delete.md b/docs/stackit_beta_intake_runner_delete.md new file mode 100644 index 000000000..0fa94ae5f --- /dev/null +++ b/docs/stackit_beta_intake_runner_delete.md @@ -0,0 +1,40 @@ +## stackit beta intake runner delete + +Deletes an Intake Runner + +### Synopsis + +Deletes an Intake Runner. + +``` +stackit beta intake runner delete RUNNER_ID [flags] +``` + +### Examples + +``` + Delete an Intake Runner with ID "xxx" + $ stackit beta intake runner delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta intake runner delete" +``` + +### 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 beta intake runner](./stackit_beta_intake_runner.md) - Provides functionality for Intake Runners + diff --git a/docs/stackit_beta_intake_runner_describe.md b/docs/stackit_beta_intake_runner_describe.md new file mode 100644 index 000000000..11814b10d --- /dev/null +++ b/docs/stackit_beta_intake_runner_describe.md @@ -0,0 +1,43 @@ +## stackit beta intake runner describe + +Shows details of an Intake Runner + +### Synopsis + +Shows details of an Intake Runner. + +``` +stackit beta intake runner describe RUNNER_ID [flags] +``` + +### Examples + +``` + Get details of an Intake Runner with ID "xxx" + $ stackit beta intake runner describe xxx + + Get details of an Intake Runner with ID "xxx" in JSON format + $ stackit beta intake runner describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta intake runner 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 beta intake runner](./stackit_beta_intake_runner.md) - Provides functionality for Intake Runners + diff --git a/docs/stackit_beta_intake_runner_list.md b/docs/stackit_beta_intake_runner_list.md new file mode 100644 index 000000000..aaf5c9e59 --- /dev/null +++ b/docs/stackit_beta_intake_runner_list.md @@ -0,0 +1,47 @@ +## stackit beta intake runner list + +Lists all Intake Runners + +### Synopsis + +Lists all Intake Runners for the current project. + +``` +stackit beta intake runner list [flags] +``` + +### Examples + +``` + List all Intake Runners + $ stackit beta intake runner list + + List all Intake Runners in JSON format + $ stackit beta intake runner list --output-format json + + List up to 5 Intake Runners + $ stackit beta intake runner list --limit 5 +``` + +### Options + +``` + -h, --help Help for "stackit beta intake runner list" + --limit int Maximum number of entries to list +``` + +### 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 beta intake runner](./stackit_beta_intake_runner.md) - Provides functionality for Intake Runners + diff --git a/docs/stackit_beta_intake_runner_update.md b/docs/stackit_beta_intake_runner_update.md new file mode 100644 index 000000000..d02cb7c84 --- /dev/null +++ b/docs/stackit_beta_intake_runner_update.md @@ -0,0 +1,48 @@ +## stackit beta intake runner update + +Updates an Intake Runner + +### Synopsis + +Updates an Intake Runner. Only the specified fields are updated. + +``` +stackit beta intake runner update RUNNER_ID [flags] +``` + +### Examples + +``` + Update the display name of an Intake Runner with ID "xxx" + $ stackit beta intake runner update xxx --display-name "new-runner-name" + + Update the message capacity limits for an Intake Runner with ID "xxx" + $ stackit beta intake runner update xxx --max-message-size-kib 1000 --max-messages-per-hour 10000 +``` + +### Options + +``` + --description string Description + --display-name string Display name + -h, --help Help for "stackit beta intake runner update" + --labels stringToString Labels in key=value format, separated by commas. Example: --labels "key1=value1,key2=value2". (default []) + --max-message-size-kib int Maximum message size in KiB. Note: Overall message capacity cannot be decreased. + --max-messages-per-hour int Maximum number of messages per hour. Note: Overall message capacity cannot be decreased. +``` + +### 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 beta intake runner](./stackit_beta_intake_runner.md) - Provides functionality for Intake Runners + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 9b07e46b5..1b4549617 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -36,6 +36,7 @@ stackit config set [flags] --iaas-custom-endpoint string IaaS API base URL, used in calls to this API --identity-provider-custom-client-id string Identity Provider client ID, used for user authentication --identity-provider-custom-well-known-configuration string Identity Provider well-known OpenID configuration URL, used for user authentication + --intake-custom-endpoint string Intake API base URL, used in calls to this API --kms-custom-endpoint string KMS API base URL, used in calls to this API --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API --logme-custom-endpoint string LogMe API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 9d4c83088..cfe34ab0b 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -34,6 +34,7 @@ stackit config unset [flags] --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL --identity-provider-custom-client-id Identity Provider client ID, used for user authentication --identity-provider-custom-well-known-configuration Identity Provider well-known OpenID configuration URL. If unset, uses the default identity provider + --intake-custom-endpoint Intake API base URL. If unset, uses the default base URL --kms-custom-endpoint KMS API base URL. If unset, uses the default base URL --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL diff --git a/go.mod b/go.mod index aff55ecea..36c488755 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 diff --git a/go.sum b/go.sum index ce063455b..edd2192ab 100644 --- a/go.sum +++ b/go.sum @@ -573,6 +573,8 @@ github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 h1:zuoJnsLnjxdQcQbs7g github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 h1:bkvq3Y4OcGyCR5N69tyY7ZTcrVN+htGTa2ZBJL5BQTQ= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0/go.mod h1:tg1rHvgFRG9gNCYnTepZFaSCBahhLLjkIb3nRbtyjDQ= +github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 h1:OdY3eXn98hWIhZBH8qQTFsYP6cag8B29UdwTjMwAjfw= +github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0/go.mod h1:mf+DQwwTVfc8MD0vwTNPzin2unKAIyQRYywv3wUyH38= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0 h1:bgMV+hi/530htdSMAyRBrltR7Czinb56HQBT36wnVMU= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0/go.mod h1:QswbIN9TUYELIwkjO+Bu8Nk/FGcd3kZYDlf2n0PdFAk= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index b026da770..a60570613 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/cmd/params" @@ -39,5 +40,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(sqlserverflex.NewCmd(params)) cmd.AddCommand(alb.NewCmd(params)) + cmd.AddCommand(intake.NewCmd(params)) cmd.AddCommand(kms.NewCmd(params)) } diff --git a/internal/cmd/beta/intake/intake.go b/internal/cmd/beta/intake/intake.go new file mode 100644 index 000000000..96533f29c --- /dev/null +++ b/internal/cmd/beta/intake/intake.go @@ -0,0 +1,26 @@ +package intake + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +// NewCmd creates the 'stackit intake' command +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "intake", + Short: "Provides functionality for intake", + Long: "Provides functionality for intake.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { + cmd.AddCommand(runner.NewCmd(params)) +} diff --git a/internal/cmd/beta/intake/runner/create/create.go b/internal/cmd/beta/intake/runner/create/create.go new file mode 100644 index 000000000..1a6ed58ec --- /dev/null +++ b/internal/cmd/beta/intake/runner/create/create.go @@ -0,0 +1,170 @@ +package create + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/intake" + "github.com/stackitcloud/stackit-sdk-go/services/intake/wait" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/intake/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +const ( + displayNameFlag = "display-name" + maxMessageSizeKiBFlag = "max-message-size-kib" + maxMessagesPerHourFlag = "max-messages-per-hour" + descriptionFlag = "description" + labelFlag = "labels" +) + +// inputModel struct holds all the input parameters for the command +type inputModel struct { + *globalflags.GlobalFlagModel + DisplayName *string + MaxMessageSizeKiB *int64 + MaxMessagesPerHour *int64 + Description *string + Labels *map[string]string +} + +func NewCmd(p *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a new Intake Runner", + Long: "Creates a new Intake Runner.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a new Intake Runner with a display name and message capacity limits`, + `$ stackit beta intake runner create --display-name my-runner --max-message-size-kib 1000 --max-messages-per-hour 5000`), + examples.NewExample( + `Create a new Intake Runner with a description and labels`, + `$ stackit beta intake runner create --display-name my-runner --max-message-size-kib 1000 --max-messages-per-hour 5000 --description "Main runner for production" --labels="env=prod,team=billing"`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p.Printer, p.CliVersion) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p.Printer, p.CliVersion, cmd) + if err != nil { + p.Printer.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create an Intake Runner for project %q?", projectLabel) + err = p.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create Intake Runner: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for STACKIT Intake Runner creation: %w", err) + } + s.Stop() + } + + return outputResult(p.Printer, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(displayNameFlag, "", "Display name") + cmd.Flags().Int64(maxMessageSizeKiBFlag, 0, "Maximum message size in KiB") + cmd.Flags().Int64(maxMessagesPerHourFlag, 0, "Maximum number of messages per hour") + cmd.Flags().String(descriptionFlag, "", "Description") + cmd.Flags().StringToString(labelFlag, nil, "Labels in key=value format, separated by commas. Example: --labels \"key1=value1,key2=value2\"") + + err := flags.MarkFlagsRequired(cmd, displayNameFlag, maxMessageSizeKiBFlag, maxMessagesPerHourFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + DisplayName: flags.FlagToStringPointer(p, cmd, displayNameFlag), + MaxMessageSizeKiB: flags.FlagToInt64Pointer(p, cmd, maxMessageSizeKiBFlag), + MaxMessagesPerHour: flags.FlagToInt64Pointer(p, cmd, maxMessagesPerHourFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *intake.APIClient) intake.ApiCreateIntakeRunnerRequest { + // Start building the request by calling the base method with path parameters + req := apiClient.CreateIntakeRunner(ctx, model.ProjectId, model.Region) + + // Create the payload struct with data from the input model + payload := intake.CreateIntakeRunnerPayload{ + DisplayName: model.DisplayName, + MaxMessageSizeKiB: model.MaxMessageSizeKiB, + MaxMessagesPerHour: model.MaxMessagesPerHour, + Description: model.Description, + Labels: model.Labels, + } + // Attach the payload to the request builder + req = req.CreateIntakeRunnerPayload(payload) + + return req +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *intake.IntakeRunnerResponse) error { + return p.OutputResult(model.OutputFormat, resp, func() error { + if resp == nil { + p.Outputf("Triggered creation of Intake Runner for project %q, but no runner ID was returned.\n", projectLabel) + return nil + } + + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s Intake Runner for project %q. Runner ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Id)) + return nil + }) +} diff --git a/internal/cmd/beta/intake/runner/create/create_test.go b/internal/cmd/beta/intake/runner/create/create_test.go new file mode 100644 index 000000000..6ddcaa4a1 --- /dev/null +++ b/internal/cmd/beta/intake/runner/create/create_test.go @@ -0,0 +1,293 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/intake" +) + +// Define a unique key for the context to avoid collisions +type testCtxKey struct{} + +const ( + testRegion = "eu01" + testDisplayName = "testrunner" + testMaxMessageSizeKiB = int64(1024) + testMaxMessagesPerHour = int64(10000) + testDescription = "This is a test runner" + testLabelsString = "env=test,team=dev" +) + +var ( + // testCtx dummy context for testing purposes + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + // testClient mock API client + testClient = &intake.APIClient{} + testProjectId = uuid.NewString() + + testLabels = map[string]string{"env": "test", "team": "dev"} +) + +// fixtureFlagValues generates a map of flag values for tests +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + displayNameFlag: testDisplayName, + maxMessageSizeKiBFlag: "1024", + maxMessagesPerHourFlag: "10000", + descriptionFlag: testDescription, + labelFlag: testLabelsString, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// fixtureInputModel generates an input model for tests +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + DisplayName: utils.Ptr(testDisplayName), + MaxMessageSizeKiB: utils.Ptr(testMaxMessageSizeKiB), + MaxMessagesPerHour: utils.Ptr(testMaxMessagesPerHour), + Description: utils.Ptr(testDescription), + Labels: utils.Ptr(testLabels), + } + for _, mod := range mods { + mod(model) + } + return model +} + +// fixtureCreatePayload generates a CreateIntakeRunnerPayload for tests +func fixtureCreatePayload(mods ...func(payload *intake.CreateIntakeRunnerPayload)) intake.CreateIntakeRunnerPayload { + payload := intake.CreateIntakeRunnerPayload{ + DisplayName: utils.Ptr(testDisplayName), + MaxMessageSizeKiB: utils.Ptr(testMaxMessageSizeKiB), + MaxMessagesPerHour: utils.Ptr(testMaxMessagesPerHour), + Description: utils.Ptr(testDescription), + Labels: utils.Ptr(testLabels), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +// fixtureRequest generates an API request for tests +func fixtureRequest(mods ...func(request *intake.ApiCreateIntakeRunnerRequest)) intake.ApiCreateIntakeRunnerRequest { + request := testClient.CreateIntakeRunner(testCtx, testProjectId, testRegion) + request = request.CreateIntakeRunnerPayload(fixtureCreatePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "display name missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, displayNameFlag) + }), + isValid: false, + }, + { + description: "max message size missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, maxMessageSizeKiBFlag) + }), + isValid: false, + }, + { + description: "max messages per hour missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, maxMessagesPerHourFlag) + }), + isValid: false, + }, + { + description: "required fields only", + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + displayNameFlag: testDisplayName, + maxMessageSizeKiBFlag: "1024", + maxMessagesPerHourFlag: "10000", + }, + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Description = nil + model.Labels = nil + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + parseInputWrapper := func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + } + testutils.TestParseInput(t, NewCmd, parseInputWrapper, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest intake.ApiCreateIntakeRunnerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no optionals", + model: fixtureInputModel(func(model *inputModel) { + model.Description = nil + model.Labels = nil + }), + expectedRequest: fixtureRequest(func(request *intake.ApiCreateIntakeRunnerRequest) { + *request = (*request).CreateIntakeRunnerPayload(fixtureCreatePayload(func(payload *intake.CreateIntakeRunnerPayload) { + payload.Description = nil + payload.Labels = nil + })) + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + resp *intake.IntakeRunnerResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "default output", + args: args{ + model: fixtureInputModel(), + projectLabel: "my-project", + resp: &intake.IntakeRunnerResponse{Id: utils.Ptr("runner-id-123")}, + }, + wantErr: false, + }, + { + name: "default output - async", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.Async = true + }), + projectLabel: "my-project", + resp: &intake.IntakeRunnerResponse{Id: utils.Ptr("runner-id-123")}, + }, + wantErr: false, + }, + { + name: "json output", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + }), + resp: &intake.IntakeRunnerResponse{Id: utils.Ptr("runner-id-123")}, + }, + wantErr: false, + }, + { + name: "nil response - default output", + args: args{ + model: fixtureInputModel(), + resp: nil, + }, + wantErr: false, + }, + { + name: "nil response - json output", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + }), + resp: nil, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/intake/runner/delete/delete.go b/internal/cmd/beta/intake/runner/delete/delete.go new file mode 100644 index 000000000..e74551a7d --- /dev/null +++ b/internal/cmd/beta/intake/runner/delete/delete.go @@ -0,0 +1,115 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "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/intake/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/intake" + "github.com/stackitcloud/stackit-sdk-go/services/intake/wait" +) + +const ( + runnerIdArg = "RUNNER_ID" +) + +// inputModel struct holds all the input parameters for the command +type inputModel struct { + *globalflags.GlobalFlagModel + RunnerId string +} + +// NewCmd creates a new cobra command for deleting an Intake Runner +func NewCmd(p *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", runnerIdArg), + Short: "Deletes an Intake Runner", + Long: "Deletes an Intake Runner.", + Args: args.SingleArg(runnerIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete an Intake Runner with ID "xxx"`, + `$ stackit beta intake runner delete xxx`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p.Printer, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p.Printer, p.CliVersion) + if err != nil { + return err + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete Intake Runner %q?", model.RunnerId) + err = p.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + if err = req.Execute(); err != nil { + return fmt.Errorf("delete Intake Runner: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for STACKIT Intake Runner deletion: %w", err) + } + s.Stop() + } + + operationState := "Deleted" + if model.Async { + operationState = "Triggered deletion of" + } + p.Printer.Outputf("%s stackit Intake Runner %s \n", operationState, model.RunnerId) + + return nil + }, + } + return cmd +} + +// parseInput parses the command arguments and flags into a standardized model +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + runnerId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + RunnerId: runnerId, + } + + p.DebugInputModel(model) + return &model, nil +} + +// buildRequest creates the API request to delete an Intake Runner +func buildRequest(ctx context.Context, model *inputModel, apiClient *intake.APIClient) intake.ApiDeleteIntakeRunnerRequest { + req := apiClient.DeleteIntakeRunner(ctx, model.ProjectId, model.Region, model.RunnerId) + return req +} diff --git a/internal/cmd/beta/intake/runner/delete/delete_test.go b/internal/cmd/beta/intake/runner/delete/delete_test.go new file mode 100644 index 000000000..b99edac92 --- /dev/null +++ b/internal/cmd/beta/intake/runner/delete/delete_test.go @@ -0,0 +1,155 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/services/intake" +) + +// Define a unique key for the context to avoid collisions +type testCtxKey struct{} + +const ( + testRegion = "eu01" +) + +var ( + // testCtx is a dummy context for testing purposes + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + // testClient is a mock API client + testClient = &intake.APIClient{} + testProjectId = uuid.NewString() + testRunnerId = uuid.NewString() +) + +// fixtureArgValues generates a slice of arguments for tests +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testRunnerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// fixtureFlagValues generates a map of flag values for tests +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 +} + +// fixtureInputModel generates an input model for tests +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + RunnerId: testRunnerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// fixtureRequest generates an API request for tests +func fixtureRequest(mods ...func(request *intake.ApiDeleteIntakeRunnerRequest)) intake.ApiDeleteIntakeRunnerRequest { + request := testClient.DeleteIntakeRunner(testCtx, testProjectId, testRegion, testRunnerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "runner id invalid", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest intake.ApiDeleteIntakeRunnerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/intake/runner/describe/describe.go b/internal/cmd/beta/intake/runner/describe/describe.go new file mode 100644 index 000000000..b5ba12ae7 --- /dev/null +++ b/internal/cmd/beta/intake/runner/describe/describe.go @@ -0,0 +1,117 @@ +package describe + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/intake" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "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/intake/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +const ( + runnerIdArg = "RUNNER_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + RunnerId string +} + +func NewCmd(p *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", runnerIdArg), + Short: "Shows details of an Intake Runner", + Long: "Shows details of an Intake Runner.", + Args: args.SingleArg(runnerIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get details of an Intake Runner with ID "xxx"`, + `$ stackit beta intake runner describe xxx`), + examples.NewExample( + `Get details of an Intake Runner with ID "xxx" in JSON format`, + `$ stackit beta intake runner describe xxx --output-format json`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p.Printer, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p.Printer, p.CliVersion) + if err != nil { + return err + } + + // Call API to get a single runner + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get Intake Runner: %w", err) + } + + return outputResult(p.Printer, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + runnerId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + RunnerId: runnerId, + } + + p.DebugInputModel(model) + return &model, nil +} + +// buildRequest creates the API request to get a single Intake Runner +func buildRequest(ctx context.Context, model *inputModel, apiClient *intake.APIClient) intake.ApiGetIntakeRunnerRequest { + req := apiClient.GetIntakeRunner(ctx, model.ProjectId, model.Region, model.RunnerId) + return req +} + +// outputResult formats the API response and prints it to the console +func outputResult(p *print.Printer, outputFormat string, runner *intake.IntakeRunnerResponse) error { + if runner == nil { + return fmt.Errorf("received nil runner, could not display details") + } + return p.OutputResult(outputFormat, runner, func() error { + table := tables.NewTable() + table.SetHeader("Attribute", "Value") + table.AddRow("ID", runner.GetId()) + table.AddRow("Name", runner.GetDisplayName()) + table.AddRow("State", runner.GetState()) + table.AddRow("Created", runner.GetCreateTime()) + table.AddRow("Labels", runner.GetLabels()) + table.AddRow("Description", runner.GetDescription()) + table.AddRow("Max Message Size (KiB)", runner.GetMaxMessageSizeKiB()) + table.AddRow("Max Messages/Hour", runner.GetMaxMessagesPerHour()) + table.AddRow("Ingestion URI", runner.GetUri()) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/intake/runner/describe/describe_test.go b/internal/cmd/beta/intake/runner/describe/describe_test.go new file mode 100644 index 000000000..9235ac723 --- /dev/null +++ b/internal/cmd/beta/intake/runner/describe/describe_test.go @@ -0,0 +1,192 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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-sdk-go/services/intake" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu01" +) + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &intake.APIClient{} + testProjectId = uuid.NewString() + testRunnerId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testRunnerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +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, + }, + RunnerId: testRunnerId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *intake.ApiGetIntakeRunnerRequest)) intake.ApiGetIntakeRunnerRequest { + request := testClient.GetIntakeRunner(testCtx, testProjectId, testRegion, testRunnerId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "runner id invalid", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest intake.ApiGetIntakeRunnerRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + runner *intake.IntakeRunnerResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "default output", + args: args{outputFormat: "default", runner: &intake.IntakeRunnerResponse{}}, + wantErr: false, + }, + { + name: "json output", + args: args{outputFormat: print.JSONOutputFormat, runner: &intake.IntakeRunnerResponse{}}, + wantErr: false, + }, + { + name: "yaml output", + args: args{outputFormat: print.YAMLOutputFormat, runner: &intake.IntakeRunnerResponse{}}, + wantErr: false, + }, + { + name: "nil runner", + args: args{runner: nil}, + wantErr: true, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.runner); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/intake/runner/list/list.go b/internal/cmd/beta/intake/runner/list/list.go new file mode 100644 index 000000000..d3df6751f --- /dev/null +++ b/internal/cmd/beta/intake/runner/list/list.go @@ -0,0 +1,152 @@ +package list + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/intake/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-sdk-go/services/intake" +) + +const ( + limitFlag = "limit" +) + +// inputModel struct holds all the input parameters for the command +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +// NewCmd creates a new cobra command for listing Intake Runners +func NewCmd(p *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all Intake Runners", + Long: "Lists all Intake Runners for the current project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all Intake Runners`, + `$ stackit beta intake runner list`), + examples.NewExample( + `List all Intake Runners in JSON format`, + `$ stackit beta intake runner list --output-format json`), + examples.NewExample( + `List up to 5 Intake Runners`, + `$ stackit beta intake runner list --limit 5`), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + model, err := parseInput(p.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p.Printer, p.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list Intake Runners: %w", err) + } + runners := resp.GetIntakeRunners() + + // Truncate output + if model.Limit != nil && len(runners) > int(*model.Limit) { + runners = runners[:*model.Limit] + } + + projectLabel := model.ProjectId + if len(runners) == 0 { + projectLabel, err = projectname.GetProjectName(ctx, p.Printer, p.CliVersion, cmd) + if err != nil { + p.Printer.Debug(print.ErrorLevel, "get project name: %v", err) + } + } + + return outputResult(p.Printer, model.OutputFormat, projectLabel, runners) + }, + } + configureFlags(cmd) + return cmd +} + +// configureFlags adds the --limit flag to the command +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +// parseInput parses the command flags into a standardized model +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + p.DebugInputModel(model) + return &model, nil +} + +// buildRequest creates the API request to list Intake Runners +func buildRequest(ctx context.Context, model *inputModel, apiClient *intake.APIClient) intake.ApiListIntakeRunnersRequest { + req := apiClient.ListIntakeRunners(ctx, model.ProjectId, model.Region) + // Note: we do support API pagination, but for consistency with other services, we fetch all items and apply + // client-side limit. + // A more advanced implementation could use the --limit flag to set the API's PageSize. + return req +} + +// outputResult formats the API response and prints it to the console +func outputResult(p *print.Printer, outputFormat, projectLabel string, runners []intake.IntakeRunnerResponse) error { + return p.OutputResult(outputFormat, runners, func() error { + if len(runners) == 0 { + p.Outputf("No intake runners found for project %q\n", projectLabel) + return nil + } + + table := tables.NewTable() + + table.SetHeader("ID", "NAME", "STATE") + for _, runner := range runners { + table.AddRow( + runner.GetId(), + runner.GetDisplayName(), + runner.GetState(), + ) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/intake/runner/list/list_test.go b/internal/cmd/beta/intake/runner/list/list_test.go new file mode 100644 index 000000000..582adab2c --- /dev/null +++ b/internal/cmd/beta/intake/runner/list/list_test.go @@ -0,0 +1,197 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/intake" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu01" + testLimit = int64(5) +) + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &intake.APIClient{} + testProjectId = uuid.NewString() +) + +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 *intake.ApiListIntakeRunnersRequest)) intake.ApiListIntakeRunnersRequest { + request := testClient.ListIntakeRunners(testCtx, testProjectId, testRegion) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "with limit", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = strconv.FormatInt(testLimit, 10) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(testLimit) + }), + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "limit is zero", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "limit is negative", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "-1" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest intake.ApiListIntakeRunnersRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + runners []intake.IntakeRunnerResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "default output", + args: args{outputFormat: "default", runners: []intake.IntakeRunnerResponse{}}, + wantErr: false, + }, + { + name: "json output", + args: args{outputFormat: print.JSONOutputFormat, runners: []intake.IntakeRunnerResponse{}}, + wantErr: false, + }, + { + name: "empty slice", + args: args{runners: []intake.IntakeRunnerResponse{}}, + wantErr: false, + }, + { + name: "nil slice", + args: args{runners: nil}, + wantErr: false, + }, + { + name: "empty intake runner in slice", + args: args{ + runners: []intake.IntakeRunnerResponse{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, "dummy-projectlabel", tt.args.runners); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/intake/runner/runner.go b/internal/cmd/beta/intake/runner/runner.go new file mode 100644 index 000000000..0708b4ae2 --- /dev/null +++ b/internal/cmd/beta/intake/runner/runner.go @@ -0,0 +1,31 @@ +package runner + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner/update" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "runner", + Short: "Provides functionality for Intake Runners", + Long: "Provides functionality for Intake Runners.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + // Pass the params down to each action command + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + + return cmd +} diff --git a/internal/cmd/beta/intake/runner/update/update.go b/internal/cmd/beta/intake/runner/update/update.go new file mode 100644 index 000000000..9ebb4a81e --- /dev/null +++ b/internal/cmd/beta/intake/runner/update/update.go @@ -0,0 +1,176 @@ +package update + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/intake/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/intake" + "github.com/stackitcloud/stackit-sdk-go/services/intake/wait" +) + +const ( + runnerIdArg = "RUNNER_ID" +) + +const ( + displayNameFlag = "display-name" + maxMessageSizeKiBFlag = "max-message-size-kib" + maxMessagesPerHourFlag = "max-messages-per-hour" + descriptionFlag = "description" + labelFlag = "labels" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + RunnerId string + DisplayName *string + MaxMessageSizeKiB *int64 + MaxMessagesPerHour *int64 + Description *string + Labels *map[string]string +} + +func NewCmd(p *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", runnerIdArg), + Short: "Updates an Intake Runner", + Long: "Updates an Intake Runner. Only the specified fields are updated.", + Args: args.SingleArg(runnerIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update the display name of an Intake Runner with ID "xxx"`, + `$ stackit beta intake runner update xxx --display-name "new-runner-name"`), + examples.NewExample( + `Update the message capacity limits for an Intake Runner with ID "xxx"`, + `$ stackit beta intake runner update xxx --max-message-size-kib 1000 --max-messages-per-hour 10000`), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(p.Printer, cmd, args) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(p.Printer, p.CliVersion) + if err != nil { + return err + } + + projectLabel, err := projectname.GetProjectName(ctx, p.Printer, p.CliVersion, cmd) + if err != nil { + p.Printer.Debug(print.ErrorLevel, "get project name: %v", err) + projectLabel = model.ProjectId + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update Intake Runner: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for STACKIT Intake Runner update: %w", err) + } + s.Stop() + } + + return outputResult(p.Printer, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(displayNameFlag, "", "Display name") + cmd.Flags().Int64(maxMessageSizeKiBFlag, 0, "Maximum message size in KiB. Note: Overall message capacity cannot be decreased.") + cmd.Flags().Int64(maxMessagesPerHourFlag, 0, "Maximum number of messages per hour. Note: Overall message capacity cannot be decreased.") + cmd.Flags().String(descriptionFlag, "", "Description") + cmd.Flags().StringToString(labelFlag, nil, `Labels in key=value format, separated by commas. Example: --labels "key1=value1,key2=value2".`) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + runnerId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + RunnerId: runnerId, + DisplayName: flags.FlagToStringPointer(p, cmd, displayNameFlag), + MaxMessageSizeKiB: flags.FlagToInt64Pointer(p, cmd, maxMessageSizeKiBFlag), + MaxMessagesPerHour: flags.FlagToInt64Pointer(p, cmd, maxMessagesPerHourFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + Labels: flags.FlagToStringToStringPointer(p, cmd, labelFlag), + } + + if model.DisplayName == nil && model.MaxMessageSizeKiB == nil && model.MaxMessagesPerHour == nil && model.Description == nil && model.Labels == nil { + return nil, &cliErr.EmptyUpdateError{} + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *intake.APIClient) intake.ApiUpdateIntakeRunnerRequest { + req := apiClient.UpdateIntakeRunner(ctx, model.ProjectId, model.Region, model.RunnerId) + + payload := intake.UpdateIntakeRunnerPayload{} + if model.DisplayName != nil { + payload.DisplayName = model.DisplayName + } + if model.MaxMessageSizeKiB != nil { + payload.MaxMessageSizeKiB = model.MaxMessageSizeKiB + } + if model.MaxMessagesPerHour != nil { + payload.MaxMessagesPerHour = model.MaxMessagesPerHour + } + if model.Description != nil { + payload.Description = model.Description + } + if model.Labels != nil { + payload.Labels = model.Labels + } + + req = req.UpdateIntakeRunnerPayload(payload) + return req +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *intake.IntakeRunnerResponse) error { + return p.OutputResult(model.OutputFormat, resp, func() error { + if resp == nil { + p.Outputf("Triggered update of Intake Runner for project %q, but no runner ID was returned.\n", projectLabel) + return nil + } + + operationState := "Updated" + if model.Async { + operationState = "Triggered update of" + } + p.Outputf("%s Intake Runner for project %q. Runner ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Id)) + return nil + }) +} diff --git a/internal/cmd/beta/intake/runner/update/update_test.go b/internal/cmd/beta/intake/runner/update/update_test.go new file mode 100644 index 000000000..9b4ae7afa --- /dev/null +++ b/internal/cmd/beta/intake/runner/update/update_test.go @@ -0,0 +1,277 @@ +package update + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/intake" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu01" +) + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &intake.APIClient{} + testProjectId = uuid.NewString() + testRunnerId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testRunnerId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + displayNameFlag: "new-runner-name", + } + 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, + }, + RunnerId: testRunnerId, + DisplayName: utils.Ptr("new-runner-name"), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *intake.ApiUpdateIntakeRunnerRequest)) intake.ApiUpdateIntakeRunnerRequest { + request := testClient.UpdateIntakeRunner(testCtx, testProjectId, testRegion, testRunnerId) + payload := intake.UpdateIntakeRunnerPayload{ + DisplayName: utils.Ptr("new-runner-name"), + } + request = request.UpdateIntakeRunnerPayload(payload) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no update flags provided", + argValues: fixtureArgValues(), + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: false, + }, + { + description: "update all fields", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[maxMessageSizeKiBFlag] = "2048" + flagValues[maxMessagesPerHourFlag] = "10000" + flagValues[descriptionFlag] = "new description" + flagValues[labelFlag] = "env=prod,team=sre" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.MaxMessageSizeKiB = utils.Ptr(int64(2048)) + model.MaxMessagesPerHour = utils.Ptr(int64(10000)) + model.Description = utils.Ptr("new description") + model.Labels = utils.Ptr(map[string]string{"env": "prod", "team": "sre"}) + }), + }, + { + description: "no args", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest intake.ApiUpdateIntakeRunnerRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "update description and labels", + model: fixtureInputModel(func(model *inputModel) { + model.DisplayName = nil + model.Description = utils.Ptr("new-desc") + model.Labels = utils.Ptr(map[string]string{"key": "value"}) + }), + expectedRequest: fixtureRequest(func(request *intake.ApiUpdateIntakeRunnerRequest) { + payload := intake.UpdateIntakeRunnerPayload{ + Description: utils.Ptr("new-desc"), + Labels: utils.Ptr(map[string]string{"key": "value"}), + } + *request = (*request).UpdateIntakeRunnerPayload(payload) + }), + }, + { + description: "update all fields", + model: fixtureInputModel(func(model *inputModel) { + model.DisplayName = utils.Ptr("another-name") + model.MaxMessageSizeKiB = utils.Ptr(int64(4096)) + model.MaxMessagesPerHour = utils.Ptr(int64(20000)) + model.Description = utils.Ptr("final-desc") + model.Labels = utils.Ptr(map[string]string{"a": "b"}) + }), + expectedRequest: fixtureRequest(func(request *intake.ApiUpdateIntakeRunnerRequest) { + payload := intake.UpdateIntakeRunnerPayload{ + DisplayName: utils.Ptr("another-name"), + MaxMessageSizeKiB: utils.Ptr(int64(4096)), + MaxMessagesPerHour: utils.Ptr(int64(20000)), + Description: utils.Ptr("final-desc"), + Labels: utils.Ptr(map[string]string{"a": "b"}), + } + *request = (*request).UpdateIntakeRunnerPayload(payload) + }), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + projectLabel string + resp *intake.IntakeRunnerResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "default output", + args: args{ + model: fixtureInputModel(), + projectLabel: "my-project", + resp: &intake.IntakeRunnerResponse{Id: utils.Ptr("runner-id-123")}, + }, + wantErr: false, + }, + { + name: "default output - async", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.Async = true + }), + projectLabel: "my-project", + resp: &intake.IntakeRunnerResponse{Id: utils.Ptr("runner-id-123")}, + }, + wantErr: false, + }, + { + name: "json output", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + }), + resp: &intake.IntakeRunnerResponse{Id: utils.Ptr("runner-id-123")}, + }, + wantErr: false, + }, + { + name: "nil response - default output", + args: args{ + model: fixtureInputModel(), + resp: nil, + }, + wantErr: false, + }, + { + name: "nil response - json output", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + }), + resp: nil, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index e694e8901..7487f8ca3 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -47,6 +47,7 @@ const ( sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" iaasCustomEndpointFlag = "iaas-custom-endpoint" tokenCustomEndpointFlag = "token-custom-endpoint" + intakeCustomEndpointFlag = "intake-custom-endpoint" ) type inputModel struct { @@ -161,6 +162,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(sqlServerFlexCustomEndpointFlag, "", "SQLServer Flex API base URL, used in calls to this API") cmd.Flags().String(iaasCustomEndpointFlag, "", "IaaS API base URL, used in calls to this API") cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication.") + cmd.Flags().String(intakeCustomEndpointFlag, "", "Intake API base URL, used in calls to this API") err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) cobra.CheckErr(err) @@ -219,6 +221,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.TokenCustomEndpointKey, cmd.Flags().Lookup(tokenCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.IntakeCustomEndpointKey, cmd.Flags().Lookup(intakeCustomEndpointFlag)) + cobra.CheckErr(err) } func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 28ed935b9..359248096 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -51,6 +51,7 @@ const ( sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" iaasCustomEndpointFlag = "iaas-custom-endpoint" tokenCustomEndpointFlag = "token-custom-endpoint" + intakeCustomEndpointFlag = "intake-custom-endpoint" ) type inputModel struct { @@ -89,6 +90,7 @@ type inputModel struct { SQLServerFlexCustomEndpoint bool IaaSCustomEndpoint bool TokenCustomEndpoint bool + IntakeCustomEndpoint bool } func NewCmd(params *params.CmdParams) *cobra.Command { @@ -212,6 +214,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if model.TokenCustomEndpoint { viper.Set(config.TokenCustomEndpointKey, "") } + if model.IntakeCustomEndpoint { + viper.Set(config.IntakeCustomEndpointKey, "") + } err := config.Write() if err != nil { @@ -260,6 +265,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(sqlServerFlexCustomEndpointFlag, false, "SQLServer Flex API base URL. If unset, uses the default base URL") cmd.Flags().Bool(iaasCustomEndpointFlag, false, "IaaS API base URL. If unset, uses the default base URL") cmd.Flags().Bool(tokenCustomEndpointFlag, false, "Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication.") + cmd.Flags().Bool(intakeCustomEndpointFlag, false, "Intake API base URL. If unset, uses the default base URL") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { @@ -299,6 +305,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), IaaSCustomEndpoint: flags.FlagToBoolValue(p, cmd, iaasCustomEndpointFlag), TokenCustomEndpoint: flags.FlagToBoolValue(p, cmd, tokenCustomEndpointFlag), + IntakeCustomEndpoint: flags.FlagToBoolValue(p, cmd, intakeCustomEndpointFlag), } p.DebugInputModel(model) diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index e48dff384..12eb2424f 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -44,6 +44,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool sqlServerFlexCustomEndpointFlag: true, iaasCustomEndpointFlag: true, tokenCustomEndpointFlag: true, + intakeCustomEndpointFlag: true, } for _, mod := range mods { mod(flagValues) @@ -84,6 +85,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { SQLServerFlexCustomEndpoint: true, IaaSCustomEndpoint: true, TokenCustomEndpoint: true, + IntakeCustomEndpoint: true, } for _, mod := range mods { mod(model) @@ -140,6 +142,7 @@ func TestParseInput(t *testing.T) { model.SQLServerFlexCustomEndpoint = false model.IaaSCustomEndpoint = false model.TokenCustomEndpoint = false + model.IntakeCustomEndpoint = false }), }, { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 9a03ac3b8..89cc4decb 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -48,6 +48,7 @@ const ( IaaSCustomEndpointKey = "iaas_custom_endpoint" TokenCustomEndpointKey = "token_custom_endpoint" GitCustomEndpointKey = "git_custom_endpoint" + IntakeCustomEndpointKey = "intake_custom_endpoint" ProjectNameKey = "project_name" DefaultProfileName = "default" @@ -108,6 +109,7 @@ var ConfigKeys = []string{ IaaSCustomEndpointKey, TokenCustomEndpointKey, GitCustomEndpointKey, + IntakeCustomEndpointKey, AlbCustomEndpoint, } @@ -195,6 +197,7 @@ func setConfigDefaults() { viper.SetDefault(IaaSCustomEndpointKey, "") viper.SetDefault(TokenCustomEndpointKey, "") viper.SetDefault(GitCustomEndpointKey, "") + viper.SetDefault(IntakeCustomEndpointKey, "") viper.SetDefault(AlbCustomEndpoint, "") } diff --git a/internal/pkg/services/intake/client/client.go b/internal/pkg/services/intake/client/client.go new file mode 100644 index 000000000..efb8d0cfd --- /dev/null +++ b/internal/pkg/services/intake/client/client.go @@ -0,0 +1,14 @@ +package client + +import ( + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/intake" +) + +// ConfigureClient creates and configures a new Intake API client +func ConfigureClient(p *print.Printer, cliVersion string) (*intake.APIClient, error) { + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.IntakeCustomEndpointKey), true, genericclient.CreateApiClient[*intake.APIClient](intake.NewAPIClient)) +} From fa5b42a9d0d924f7dba480928abccf78c0b73583 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 17:35:30 +0000 Subject: [PATCH 513/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/kms (#1103) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 36c488755..56391d6a4 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0 + github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 diff --git a/go.sum b/go.sum index edd2192ab..4bb38a2ba 100644 --- a/go.sum +++ b/go.sum @@ -575,8 +575,8 @@ github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 h1:bkvq3Y4OcGyCR5N69 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0/go.mod h1:tg1rHvgFRG9gNCYnTepZFaSCBahhLLjkIb3nRbtyjDQ= github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 h1:OdY3eXn98hWIhZBH8qQTFsYP6cag8B29UdwTjMwAjfw= github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0/go.mod h1:mf+DQwwTVfc8MD0vwTNPzin2unKAIyQRYywv3wUyH38= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0 h1:bgMV+hi/530htdSMAyRBrltR7Czinb56HQBT36wnVMU= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.0/go.mod h1:QswbIN9TUYELIwkjO+Bu8Nk/FGcd3kZYDlf2n0PdFAk= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EGbsmSX9CLFp3nBcWV8JAeTz4p8= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1/go.mod h1:Wh1NKX5ZI0FuIdYavOYu0Cjh0yA3S9rlm4j5g0vuPVI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0/go.mod h1:20QOZ3rBC9wTGgzXzLz9M6YheX0VaxWE0/JI+s8On7k= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 h1:g3xzRqwul8W638gOKTZRAnnQuMhYqaliuz/A8BcfjhU= From 01089965768aeb1b62615e8705174e51703f24c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 08:50:00 +0000 Subject: [PATCH 514/619] chore(deps): bump actions/checkout from 5 to 6 (#1106) --- .github/workflows/ci.yaml | 4 ++-- .github/workflows/release.yaml | 6 +++--- .github/workflows/renovate.yaml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1bf4b205f..48e304976 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Install go uses: actions/setup-go@v6 @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Check GoReleaser uses: goreleaser/goreleaser-action@v6 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8eb074ead..108d24521 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,7 +23,7 @@ jobs: SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }} steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: # Allow goreleaser to access older tag information. fetch-depth: 0 @@ -106,7 +106,7 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.OBJECT_STORAGE_SECRET_ACCESS_KEY }} steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 # use the artifacts from the "goreleaser" job - name: Download artifacts from workflow @@ -144,7 +144,7 @@ jobs: AWS_ENDPOINT_URL: https://object.storage.eu01.onstackit.cloud steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Download artifacts from workflow uses: actions/download-artifact@v6 diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 804c3206d..8c230c100 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Self-hosted Renovate uses: renovatebot/github-action@v44.0.3 with: From 3a8198364b0f8b5c65c73216e4e500ec9c4efe9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 10:20:08 +0100 Subject: [PATCH 515/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/git (#1101) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 56391d6a4..322507bdf 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 - github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 + github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 diff --git a/go.sum b/go.sum index 4bb38a2ba..a83c30625 100644 --- a/go.sum +++ b/go.sum @@ -569,8 +569,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= -github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 h1:zuoJnsLnjxdQcQbs7gUXYzrN0Ip5NXj+6LFBp1EO6cg= -github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0/go.mod h1:AXFfYBJZIW1o0W0zZEb/proQMhMsb3Nn5E1htS8NDPE= +github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 h1:RgWfaWDY8ZGZp5gEBe/A1r7s5NCRuLiYuHhscH6Ej9U= +github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1/go.mod h1:HgScss2f+/k/wDxcsM1K8SzLgDso/EZyhoJC2eZ+tFA= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 h1:bkvq3Y4OcGyCR5N69tyY7ZTcrVN+htGTa2ZBJL5BQTQ= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0/go.mod h1:tg1rHvgFRG9gNCYnTepZFaSCBahhLLjkIb3nRbtyjDQ= github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 h1:OdY3eXn98hWIhZBH8qQTFsYP6cag8B29UdwTjMwAjfw= From 63a0aae1932a7e52b5545f5cae92050107aed711 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 09:29:18 +0000 Subject: [PATCH 516/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/opensearch (#1102) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 322507bdf..cbc6d3613 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 diff --git a/go.sum b/go.sum index a83c30625..6bd8ca723 100644 --- a/go.sum +++ b/go.sum @@ -589,8 +589,8 @@ github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 h1:I9B/zUU7 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1/go.mod h1:h4aX5tyTQoO6KLrugkvfkqgKTjIzh7e4q9N92kT5OBs= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0 h1:MA5i1ScjXLWe5CYeFCLHeZzNS1AH4mbx1kUyiVbxKjI= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1 h1:50n87uZn0EvSP9hJGLqd3Wm2hfqbyh7BMGGCk7axgqA= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.1/go.mod h1:jfguuSPa56Z5Bzs/Xg/CI37XzPo5Zn5lzC5LhfuT8Qc= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 h1:J9WP0lBoqmaQF/OjDw4MwDUbmhwlNBTi9zHdwsXJ3ug= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2/go.mod h1:QenOJF1LD39d/arGFGZFCzHoQuwF6VuWCvS8CbdoMBw= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1/go.mod h1:hyhw+I19NtjKmRLcUkY4boaTxnYSPFGbpn4RxvGqH2s= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 h1:ALrDCBih8Fu8e6530KdOjuH0iMxOLntO381BbKFlTFY= From 69306e34c7f3310ac77c948d70fc518c9d6b68ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 10:28:22 +0000 Subject: [PATCH 517/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/observability (#1104) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cbc6d3613..460ee1488 100644 --- a/go.mod +++ b/go.mod @@ -248,7 +248,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 - github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0 + github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 6bd8ca723..ce3834241 100644 --- a/go.sum +++ b/go.sum @@ -587,8 +587,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/a github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 h1:I9B/zUU7R74xuH/ztcPrDIuMp2KV3QQMjeE7lFudboM= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1/go.mod h1:h4aX5tyTQoO6KLrugkvfkqgKTjIzh7e4q9N92kT5OBs= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0 h1:MA5i1ScjXLWe5CYeFCLHeZzNS1AH4mbx1kUyiVbxKjI= -github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.0/go.mod h1:tJEOi6L0le4yQZPGwalup/PZ13gqs1aCQDqlUs2cYW0= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 h1:zk+47GhutK2ajO4Yiek0laGm2PdXvY8BvFZc8yHFnSE= +github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1/go.mod h1:vapb/sJqbHlf+c7pZWdE9GqrbyI8wesGvUc9o7oJ1Xk= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 h1:J9WP0lBoqmaQF/OjDw4MwDUbmhwlNBTi9zHdwsXJ3ug= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2/go.mod h1:QenOJF1LD39d/arGFGZFCzHoQuwF6VuWCvS8CbdoMBw= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= From 7c49ae1772389c4e091eb8c779b357f5e494461a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 24 Nov 2025 12:05:17 +0100 Subject: [PATCH 518/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.7.5 (#1105) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 460ee1488..37dc9c476 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.7.3 + github.com/jedib0t/go-pretty/v6 v6.7.5 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index ce3834241..56bc40147 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.7.3 h1:i6IhmHUcZxxvxdgRTcIQk5N3ZMZqyQQyXLHDWxMxb3Y= -github.com/jedib0t/go-pretty/v6 v6.7.3/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.7.5 h1:9dJSWTJnsXJVVAbvxIFxeHf/JxoJd7GUl5o3UzhtuiM= +github.com/jedib0t/go-pretty/v6 v6.7.5/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From 5b700d95c61bca13a3bd5492752a813da71e0ceb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:52:08 +0100 Subject: [PATCH 519/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/secretsmanager (#1112) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 37dc9c476..b17c57e91 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 diff --git a/go.sum b/go.sum index 56bc40147..a72d1eee9 100644 --- a/go.sum +++ b/go.sum @@ -601,8 +601,8 @@ github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 h1:en8Io github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0/go.mod h1:0wVdzrB4PhwhTE6drOVA6rETTmJ+k3eHa0neuxpDM/g= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 h1:CPIuqhQw+oPt08I2WLsxJDoVDsPMW2VkvKW7/SlUv10= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1/go.mod h1:tip0Ob6x06luy3CmRrmnCMtU5cha95fQLdvZlno3J4w= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1 h1:WKFzlHllql3JsVcAq+Y1m5pSMkvwp1qH3Vf2N7i8CPg= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.1/go.mod h1:WGMFtGugBmUxI+nibI7eUZIQk4AGlDvwqX+m17W1y5w= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp742W6AgleV2eEXrJFZ7ai9rXu9V1Lkmir0drI= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2/go.mod h1:xm0ARtIbfzmqw8e8qThtrYdHHEkpuYvKt13SZGBoWSE= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 h1:tfKC4Z6Uah9AQZrtCn/ytqOgc//ChQRfJ6ozxovgads= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2/go.mod h1:wV7/BUV3BCLq5+E1bHXrKKt/eOPVdWgLArWLAq7rZ/U= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 h1:hcHX2n5pUsOcv2PPPbSJph1fQ/I6P7g7781T1f1ycEI= From 34053aada0efab5041af673b1fdabbdc2b503ae3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:01:25 +0000 Subject: [PATCH 520/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serverbackup (#1111) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b17c57e91..6cf90af5f 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 diff --git a/go.sum b/go.sum index a72d1eee9..79e862952 100644 --- a/go.sum +++ b/go.sum @@ -603,8 +603,8 @@ github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 h1:CPIuqhQw+oP github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1/go.mod h1:tip0Ob6x06luy3CmRrmnCMtU5cha95fQLdvZlno3J4w= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp742W6AgleV2eEXrJFZ7ai9rXu9V1Lkmir0drI= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2/go.mod h1:xm0ARtIbfzmqw8e8qThtrYdHHEkpuYvKt13SZGBoWSE= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2 h1:tfKC4Z6Uah9AQZrtCn/ytqOgc//ChQRfJ6ozxovgads= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.2/go.mod h1:wV7/BUV3BCLq5+E1bHXrKKt/eOPVdWgLArWLAq7rZ/U= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 h1:LONKouoyrgDfu4Tu152YFjd5cw3SoG8P7PHdd8tsBOU= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3/go.mod h1:mCiDOqMHQKM9cFs5/GULaYz6Ni0QA2TTMQZJcj4GFUE= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 h1:hcHX2n5pUsOcv2PPPbSJph1fQ/I6P7g7781T1f1ycEI= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1/go.mod h1:jZwTg3wU4/UxgNJ7TKlFZ3dTIlnfvppnW8kJTc4UXy8= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 h1:crKlHl7QVF97A8CTBK3PBtVpO9c/7qwFvRJi5UN/F7Y= From bb0a5e6ab088b60cbccf7794b2f22e7d4dbca298 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 13:19:02 +0100 Subject: [PATCH 521/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/ske (#1110) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6cf90af5f..98382a6a2 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 - github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.30.0 diff --git a/go.sum b/go.sum index 79e862952..067a35f22 100644 --- a/go.sum +++ b/go.sum @@ -611,8 +611,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 h1:crKlHl github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1/go.mod h1:QCrAW/Rmf+styT25ke8cUV6hDHpdKNmAY14kkJ3+Fd8= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0 h1:V6RFvybDeJvvmT3g7/BZodF0gozz3TEpahbpiTftbeY= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.4.0/go.mod h1:xRBgpJ8P5Nf1T5tD0tGAeNg1FNQzx5VF7qqOXt2Fp3s= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 h1:bQk5qKid5Kv3fZ2miWlS5Dvo+cW90hbePaxOyWF67EE= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0/go.mod h1:/Ujlw+qo6RgKm69dD8y6MgmJFcUmrHjuJPO6VFoQX9U= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 h1:aW8ehdoNRaCEs3xDr+YnGb6pru8zZTB8f7kl5lozlJE= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2/go.mod h1:Jsry+gfhuXv2P0ldfa48BaL605NhDjdQMgaoV8czlbo= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= From 5d8a48c045e56ec8a22b2fc943b019eb7e2d2031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:27:53 +0000 Subject: [PATCH 522/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serverupdate (#1109) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 98382a6a2..cdccad46f 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 diff --git a/go.sum b/go.sum index 067a35f22..4323cb7d3 100644 --- a/go.sum +++ b/go.sum @@ -605,8 +605,8 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2/go.mod h1:xm0ARtIbfzmqw8e8qThtrYdHHEkpuYvKt13SZGBoWSE= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 h1:LONKouoyrgDfu4Tu152YFjd5cw3SoG8P7PHdd8tsBOU= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3/go.mod h1:mCiDOqMHQKM9cFs5/GULaYz6Ni0QA2TTMQZJcj4GFUE= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1 h1:hcHX2n5pUsOcv2PPPbSJph1fQ/I6P7g7781T1f1ycEI= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.1/go.mod h1:jZwTg3wU4/UxgNJ7TKlFZ3dTIlnfvppnW8kJTc4UXy8= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 h1:ubaIeflBZ70evMhU5Xl4NzzDUTk0Z309jnv18OikXgs= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2/go.mod h1:NH6dyKSkJ0WezDgIpXr5PkhSGUXJvwEFcsQmeGScDs8= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 h1:crKlHl7QVF97A8CTBK3PBtVpO9c/7qwFvRJi5UN/F7Y= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1/go.mod h1:QCrAW/Rmf+styT25ke8cUV6hDHpdKNmAY14kkJ3+Fd8= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= From ce65339f8abc44f58b514fff977bdf5597f7cd1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:39:36 +0000 Subject: [PATCH 523/619] chore(deps): bump renovatebot/github-action from 44.0.3 to 44.0.4 (#1113) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 8c230c100..8551dd43e 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Self-hosted Renovate - uses: renovatebot/github-action@v44.0.3 + uses: renovatebot/github-action@v44.0.4 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From c573f95684616d093c560d6930e8be39ed9240a5 Mon Sep 17 00:00:00 2001 From: cgoetz-inovex Date: Tue, 25 Nov 2025 14:52:38 +0100 Subject: [PATCH 524/619] feat(kms) describe key, keyring, wrappingkey (#1107) * feat(kms) describe key, keyring, wrappingkey * fix(kms): do not reuse buffer during output tests * fix(kms) use constant Time for TestOutputResult for constant table widths --- docs/stackit_beta_kms_key.md | 1 + docs/stackit_beta_kms_key_describe.md | 41 ++++ docs/stackit_beta_kms_keyring.md | 1 + docs/stackit_beta_kms_keyring_describe.md | 40 ++++ docs/stackit_beta_kms_wrapping-key.md | 1 + .../stackit_beta_kms_wrapping-key_describe.md | 41 ++++ .../cmd/beta/kms/key/describe/describe.go | 131 +++++++++++ .../beta/kms/key/describe/describe_test.go | 222 ++++++++++++++++++ internal/cmd/beta/kms/key/key.go | 2 + .../cmd/beta/kms/keyring/describe/describe.go | 106 +++++++++ .../kms/keyring/describe/describe_test.go | 183 +++++++++++++++ internal/cmd/beta/kms/keyring/keyring.go | 2 + .../beta/kms/wrappingkey/describe/describe.go | 131 +++++++++++ .../kms/wrappingkey/describe/describe_test.go | 215 +++++++++++++++++ .../cmd/beta/kms/wrappingkey/wrappingkey.go | 2 + 15 files changed, 1119 insertions(+) create mode 100644 docs/stackit_beta_kms_key_describe.md create mode 100644 docs/stackit_beta_kms_keyring_describe.md create mode 100644 docs/stackit_beta_kms_wrapping-key_describe.md create mode 100644 internal/cmd/beta/kms/key/describe/describe.go create mode 100644 internal/cmd/beta/kms/key/describe/describe_test.go create mode 100644 internal/cmd/beta/kms/keyring/describe/describe.go create mode 100644 internal/cmd/beta/kms/keyring/describe/describe_test.go create mode 100644 internal/cmd/beta/kms/wrappingkey/describe/describe.go create mode 100644 internal/cmd/beta/kms/wrappingkey/describe/describe_test.go diff --git a/docs/stackit_beta_kms_key.md b/docs/stackit_beta_kms_key.md index 631808f53..a22f3d97b 100644 --- a/docs/stackit_beta_kms_key.md +++ b/docs/stackit_beta_kms_key.md @@ -32,6 +32,7 @@ stackit beta kms key [flags] * [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS * [stackit beta kms key create](./stackit_beta_kms_key_create.md) - Creates a KMS key * [stackit beta kms key delete](./stackit_beta_kms_key_delete.md) - Deletes a KMS key +* [stackit beta kms key describe](./stackit_beta_kms_key_describe.md) - Describe a KMS key * [stackit beta kms key import](./stackit_beta_kms_key_import.md) - Import a KMS key * [stackit beta kms key list](./stackit_beta_kms_key_list.md) - List all KMS keys * [stackit beta kms key restore](./stackit_beta_kms_key_restore.md) - Restore a key diff --git a/docs/stackit_beta_kms_key_describe.md b/docs/stackit_beta_kms_key_describe.md new file mode 100644 index 000000000..05e876491 --- /dev/null +++ b/docs/stackit_beta_kms_key_describe.md @@ -0,0 +1,41 @@ +## stackit beta kms key describe + +Describe a KMS key + +### Synopsis + +Describe a KMS key + +``` +stackit beta kms key describe KEY_ID [flags] +``` + +### Examples + +``` + Describe a KMS key with ID xxx of keyring yyy + $ stackit beta kms key describe xxx --keyring-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta kms key describe" + --keyring-id string Key Ring ID +``` + +### 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 beta kms key](./stackit_beta_kms_key.md) - Manage KMS keys + diff --git a/docs/stackit_beta_kms_keyring.md b/docs/stackit_beta_kms_keyring.md index 6e65f3a47..2d87f99d3 100644 --- a/docs/stackit_beta_kms_keyring.md +++ b/docs/stackit_beta_kms_keyring.md @@ -32,5 +32,6 @@ stackit beta kms keyring [flags] * [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS * [stackit beta kms keyring create](./stackit_beta_kms_keyring_create.md) - Creates a KMS key ring * [stackit beta kms keyring delete](./stackit_beta_kms_keyring_delete.md) - Deletes a KMS key ring +* [stackit beta kms keyring describe](./stackit_beta_kms_keyring_describe.md) - Describe a KMS key ring * [stackit beta kms keyring list](./stackit_beta_kms_keyring_list.md) - Lists all KMS key rings diff --git a/docs/stackit_beta_kms_keyring_describe.md b/docs/stackit_beta_kms_keyring_describe.md new file mode 100644 index 000000000..9b1381dc0 --- /dev/null +++ b/docs/stackit_beta_kms_keyring_describe.md @@ -0,0 +1,40 @@ +## stackit beta kms keyring describe + +Describe a KMS key ring + +### Synopsis + +Describe a KMS key ring + +``` +stackit beta kms keyring describe KEYRING_ID [flags] +``` + +### Examples + +``` + Describe a KMS key ring with ID xxx + $ stackit beta kms keyring describe xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta kms keyring 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 beta kms keyring](./stackit_beta_kms_keyring.md) - Manage KMS key rings + diff --git a/docs/stackit_beta_kms_wrapping-key.md b/docs/stackit_beta_kms_wrapping-key.md index c10cb4946..2cef6b863 100644 --- a/docs/stackit_beta_kms_wrapping-key.md +++ b/docs/stackit_beta_kms_wrapping-key.md @@ -32,5 +32,6 @@ stackit beta kms wrapping-key [flags] * [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS * [stackit beta kms wrapping-key create](./stackit_beta_kms_wrapping-key_create.md) - Creates a KMS wrapping key * [stackit beta kms wrapping-key delete](./stackit_beta_kms_wrapping-key_delete.md) - Deletes a KMS wrapping key +* [stackit beta kms wrapping-key describe](./stackit_beta_kms_wrapping-key_describe.md) - Describe a KMS wrapping key * [stackit beta kms wrapping-key list](./stackit_beta_kms_wrapping-key_list.md) - Lists all KMS wrapping keys diff --git a/docs/stackit_beta_kms_wrapping-key_describe.md b/docs/stackit_beta_kms_wrapping-key_describe.md new file mode 100644 index 000000000..6e82cd595 --- /dev/null +++ b/docs/stackit_beta_kms_wrapping-key_describe.md @@ -0,0 +1,41 @@ +## stackit beta kms wrapping-key describe + +Describe a KMS wrapping key + +### Synopsis + +Describe a KMS wrapping key + +``` +stackit beta kms wrapping-key describe WRAPPING_KEY_ID [flags] +``` + +### Examples + +``` + Describe a KMS wrapping key with ID xxx of keyring yyy + $ stackit beta kms wrappingkey describe xxx --keyring-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta kms wrapping-key describe" + --keyring-id string Key Ring ID +``` + +### 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 beta kms wrapping-key](./stackit_beta_kms_wrapping-key.md) - Manage KMS wrapping keys + diff --git a/internal/cmd/beta/kms/key/describe/describe.go b/internal/cmd/beta/kms/key/describe/describe.go new file mode 100644 index 000000000..113cf96de --- /dev/null +++ b/internal/cmd/beta/kms/key/describe/describe.go @@ -0,0 +1,131 @@ +package describe + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + argKeyID = "KEY_ID" + flagKeyRingID = "keyring-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyID string + KeyRingID string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", argKeyID), + Short: "Describe a KMS key", + Long: "Describe a KMS key", + Args: args.SingleArg(argKeyID, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Describe a KMS key with ID xxx of keyring yyy`, + `$ stackit beta kms key describe xxx --keyring-id yyy`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return err + } + + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + req := buildRequest(ctx, model, apiClient) + + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get key: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), flagKeyRingID, "Key Ring ID") + err := flags.MarkFlagsRequired(cmd, flagKeyRingID) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, args []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + model := &inputModel{ + GlobalFlagModel: globalFlags, + KeyID: args[0], + KeyRingID: flags.FlagToStringValue(p, cmd, flagKeyRingID), + } + p.DebugInputModel(model) + return model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiGetKeyRequest { + return apiClient.GetKey(ctx, model.ProjectId, model.Region, model.KeyRingID, model.KeyID) +} + +func outputResult(p *print.Printer, outputFormat string, key *kms.Key) error { + if key == nil { + return fmt.Errorf("key response is empty") + } + return p.OutputResult(outputFormat, key, func() error { + table := tables.NewTable() + table.AddRow("ID", utils.PtrString(key.Id)) + table.AddSeparator() + table.AddRow("DISPLAY NAME", utils.PtrString(key.DisplayName)) + table.AddSeparator() + table.AddRow("CREATED AT", utils.PtrString(key.CreatedAt)) + table.AddSeparator() + table.AddRow("STATE", utils.PtrString(key.State)) + table.AddSeparator() + table.AddRow("DESCRIPTION", utils.PtrString(key.Description)) + table.AddSeparator() + table.AddRow("ACCESS SCOPE", utils.PtrString(key.AccessScope)) + table.AddSeparator() + table.AddRow("ALGORITHM", utils.PtrString(key.Algorithm)) + table.AddSeparator() + table.AddRow("DELETION DATE", utils.PtrString(key.DeletionDate)) + table.AddSeparator() + table.AddRow("IMPORT ONLY", utils.PtrString(key.ImportOnly)) + table.AddSeparator() + table.AddRow("KEYRING ID", utils.PtrString(key.KeyRingId)) + table.AddSeparator() + table.AddRow("PROTECTION", utils.PtrString(key.Protection)) + table.AddSeparator() + table.AddRow("PURPOSE", utils.PtrString(key.Purpose)) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("display table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/kms/key/describe/describe_test.go b/internal/cmd/beta/kms/key/describe/describe_test.go new file mode 100644 index 000000000..6abb30a09 --- /dev/null +++ b/internal/cmd/beta/kms/key/describe/describe_test.go @@ -0,0 +1,222 @@ +package describe + +import ( + "bytes" + "context" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &kms.APIClient{} +var testProjectId = uuid.NewString() +var testKeyRingID = uuid.NewString() +var testKeyID = uuid.NewString() +var testTime = time.Time{} + +const testRegion = "eu01" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + flagKeyRingID: testKeyRingID, + } + 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, + }, + KeyID: testKeyID, + KeyRingID: testKeyRingID, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: []string{testKeyID}, + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: []string{testKeyID}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "invalid key id", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "missing key ring id", + argValues: []string{testKeyID}, + flagValues: fixtureFlagValues(func(m map[string]string) { delete(m, flagKeyRingID) }), + isValid: false, + }, + { + description: "invalid key ring id", + argValues: []string{testKeyID}, + flagValues: fixtureFlagValues(func(m map[string]string) { + m[flagKeyRingID] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "missing project id", + argValues: []string{testKeyID}, + flagValues: fixtureFlagValues(func(m map[string]string) { delete(m, globalflags.ProjectIdFlag) }), + isValid: false, + }, + { + description: "invalid project id", + argValues: []string{testKeyID}, + flagValues: fixtureFlagValues(func(m map[string]string) { m[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, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + got := buildRequest(testCtx, fixtureInputModel(), testClient) + want := testClient.GetKey(testCtx, testProjectId, testRegion, testKeyRingID, testKeyID) + diff := cmp.Diff(got, want, + cmp.AllowUnexported(want), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("buildRequest() mismatch (-want +got):\n%s", diff) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + outputFmt string + keyRing *kms.Key + wantErr bool + expected string + }{ + { + description: "empty", + outputFmt: "table", + wantErr: true, + }, + { + description: "table format", + outputFmt: "table", + keyRing: &kms.Key{ + AccessScope: utils.Ptr(kms.ACCESSSCOPE_PUBLIC), + Algorithm: utils.Ptr(kms.ALGORITHM_AES_256_GCM), + CreatedAt: utils.Ptr(testTime), + DeletionDate: nil, + Description: utils.Ptr("very secure and secret key"), + DisplayName: utils.Ptr("Test Key"), + Id: utils.Ptr(testKeyID), + ImportOnly: utils.Ptr(true), + KeyRingId: utils.Ptr(testKeyRingID), + Protection: utils.Ptr(kms.PROTECTION_SOFTWARE), + Purpose: utils.Ptr(kms.PURPOSE_SYMMETRIC_ENCRYPT_DECRYPT), + State: utils.Ptr(kms.KEYSTATE_ACTIVE), + }, + expected: fmt.Sprintf(` + ID │ %-37s +───────────────┼────────────────────────────────────── + DISPLAY NAME │ Test Key +───────────────┼────────────────────────────────────── + CREATED AT │ %-37s +───────────────┼────────────────────────────────────── + STATE │ active +───────────────┼────────────────────────────────────── + DESCRIPTION │ very secure and secret key +───────────────┼────────────────────────────────────── + ACCESS SCOPE │ PUBLIC +───────────────┼────────────────────────────────────── + ALGORITHM │ aes_256_gcm +───────────────┼────────────────────────────────────── + DELETION DATE │ +───────────────┼────────────────────────────────────── + IMPORT ONLY │ true +───────────────┼────────────────────────────────────── + KEYRING ID │ %-37s +───────────────┼────────────────────────────────────── + PROTECTION │ software +───────────────┼────────────────────────────────────── + PURPOSE │ symmetric_encrypt_decrypt + +`, + testKeyID, + testTime, + testKeyRingID, + ), + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + var buf bytes.Buffer + p.Cmd.SetOut(&buf) + if err := outputResult(p, tt.outputFmt, tt.keyRing); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + diff := cmp.Diff(buf.String(), tt.expected) + if diff != "" { + t.Fatalf("outputResult() output mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/kms/key/key.go b/internal/cmd/beta/kms/key/key.go index 4b2f7d8fa..b6ff239bc 100644 --- a/internal/cmd/beta/kms/key/key.go +++ b/internal/cmd/beta/kms/key/key.go @@ -3,6 +3,7 @@ package key import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/create" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/importKey" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/restore" @@ -33,4 +34,5 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(restore.NewCmd(params)) cmd.AddCommand(rotate.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) } diff --git a/internal/cmd/beta/kms/keyring/describe/describe.go b/internal/cmd/beta/kms/keyring/describe/describe.go new file mode 100644 index 000000000..f9dc11d0a --- /dev/null +++ b/internal/cmd/beta/kms/keyring/describe/describe.go @@ -0,0 +1,106 @@ +package describe + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + argKeyRingID = "KEYRING_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + KeyRingID string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", argKeyRingID), + Short: "Describe a KMS key ring", + Long: "Describe a KMS key ring", + Args: args.SingleArg(argKeyRingID, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Describe a KMS key ring with ID xxx`, + `$ stackit beta kms keyring describe xxx`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return err + } + + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + req := buildRequest(ctx, model, apiClient) + + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get key ring: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, args []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + model := &inputModel{ + GlobalFlagModel: globalFlags, + KeyRingID: args[0], + } + p.DebugInputModel(model) + return model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiGetKeyRingRequest { + return apiClient.GetKeyRing(ctx, model.ProjectId, model.Region, model.KeyRingID) +} + +func outputResult(p *print.Printer, outputFormat string, keyRing *kms.KeyRing) error { + if keyRing == nil { + return fmt.Errorf("key ring response is empty") + } + return p.OutputResult(outputFormat, keyRing, func() error { + table := tables.NewTable() + table.AddRow("ID", utils.PtrString(keyRing.Id)) + table.AddSeparator() + table.AddRow("DISPLAY NAME", utils.PtrString(keyRing.DisplayName)) + table.AddSeparator() + table.AddRow("CREATED AT", utils.PtrString(keyRing.CreatedAt)) + table.AddSeparator() + table.AddRow("STATE", utils.PtrString(keyRing.State)) + table.AddSeparator() + table.AddRow("DESCRIPTION", utils.PtrString(keyRing.Description)) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("display table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/kms/keyring/describe/describe_test.go b/internal/cmd/beta/kms/keyring/describe/describe_test.go new file mode 100644 index 000000000..bdc3caa88 --- /dev/null +++ b/internal/cmd/beta/kms/keyring/describe/describe_test.go @@ -0,0 +1,183 @@ +package describe + +import ( + "bytes" + "context" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &kms.APIClient{} +var testProjectId = uuid.NewString() +var testKeyRingID = uuid.NewString() +var testTime = time.Time{} + +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, + }, + KeyRingID: testKeyRingID, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: []string{testKeyRingID}, + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: []string{testKeyRingID}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "invalid key ring id", + argValues: []string{"!invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "missing project id", + argValues: []string{testKeyRingID}, + flagValues: fixtureFlagValues(func(m map[string]string) { delete(m, globalflags.ProjectIdFlag) }), + isValid: false, + }, + { + description: "invalid project id", + argValues: []string{testKeyRingID}, + flagValues: fixtureFlagValues(func(m map[string]string) { m[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, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + got := buildRequest(testCtx, fixtureInputModel(), testClient) + want := testClient.GetKeyRing(testCtx, testProjectId, testRegion, testKeyRingID) + diff := cmp.Diff(got, want, + cmp.AllowUnexported(want), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("buildRequest() mismatch (-want +got):\n%s", diff) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + outputFmt string + keyRing *kms.KeyRing + wantErr bool + expected string + }{ + { + description: "empty", + outputFmt: "table", + wantErr: true, + }, + { + description: "table format", + outputFmt: "table", + keyRing: &kms.KeyRing{ + Id: utils.Ptr(testKeyRingID), + DisplayName: utils.Ptr("Test Key Ring"), + CreatedAt: utils.Ptr(testTime), + Description: utils.Ptr("This is a test key ring."), + State: utils.Ptr(kms.KEYRINGSTATE_ACTIVE), + }, + expected: fmt.Sprintf(` + ID │ %-37s +──────────────┼────────────────────────────────────── + DISPLAY NAME │ Test Key Ring +──────────────┼────────────────────────────────────── + CREATED AT │ %-37s +──────────────┼────────────────────────────────────── + STATE │ active +──────────────┼────────────────────────────────────── + DESCRIPTION │ This is a test key ring. + +`, + testKeyRingID, + testTime, + ), + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + var buf bytes.Buffer + p.Cmd.SetOut(&buf) + if err := outputResult(p, tt.outputFmt, tt.keyRing); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + diff := cmp.Diff(buf.String(), tt.expected) + if diff != "" { + t.Fatalf("outputResult() output mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/kms/keyring/keyring.go b/internal/cmd/beta/kms/keyring/keyring.go index 7a42ce131..f948fae41 100644 --- a/internal/cmd/beta/kms/keyring/keyring.go +++ b/internal/cmd/beta/kms/keyring/keyring.go @@ -3,6 +3,7 @@ package keyring import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/create" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/list" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -27,4 +28,5 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) } diff --git a/internal/cmd/beta/kms/wrappingkey/describe/describe.go b/internal/cmd/beta/kms/wrappingkey/describe/describe.go new file mode 100644 index 000000000..2c25a288e --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/describe/describe.go @@ -0,0 +1,131 @@ +package describe + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +const ( + argWrappingKeyID = "WRAPPING_KEY_ID" + flagKeyRingID = "keyring-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + WrappingKeyID string + KeyRingID string +} + +func NewCmd(params *params.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", argWrappingKeyID), + Short: "Describe a KMS wrapping key", + Long: "Describe a KMS wrapping key", + Args: args.SingleArg(argWrappingKeyID, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Describe a KMS wrapping key with ID xxx of keyring yyy`, + `$ stackit beta kms wrappingkey describe xxx --keyring-id yyy`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return err + } + + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + req := buildRequest(ctx, model, apiClient) + + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get wrapping key: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), flagKeyRingID, "Key Ring ID") + err := flags.MarkFlagsRequired(cmd, flagKeyRingID) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, args []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + model := &inputModel{ + GlobalFlagModel: globalFlags, + WrappingKeyID: args[0], + KeyRingID: flags.FlagToStringValue(p, cmd, flagKeyRingID), + } + p.DebugInputModel(model) + return model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *kms.APIClient) kms.ApiGetWrappingKeyRequest { + return apiClient.GetWrappingKey(ctx, model.ProjectId, model.Region, model.KeyRingID, model.WrappingKeyID) +} + +func outputResult(p *print.Printer, outputFormat string, wrappingKey *kms.WrappingKey) error { + if wrappingKey == nil { + return fmt.Errorf("wrapping key response is empty") + } + return p.OutputResult(outputFormat, wrappingKey, func() error { + table := tables.NewTable() + table.AddRow("ID", utils.PtrString(wrappingKey.Id)) + table.AddSeparator() + table.AddRow("DISPLAY NAME", utils.PtrString(wrappingKey.DisplayName)) + table.AddSeparator() + table.AddRow("CREATED AT", utils.PtrString(wrappingKey.CreatedAt)) + table.AddSeparator() + table.AddRow("STATE", utils.PtrString(wrappingKey.State)) + table.AddSeparator() + table.AddRow("DESCRIPTION", utils.PtrString(wrappingKey.Description)) + table.AddSeparator() + table.AddRow("ACCESS SCOPE", utils.PtrString(wrappingKey.AccessScope)) + table.AddSeparator() + table.AddRow("ALGORITHM", utils.PtrString(wrappingKey.Algorithm)) + table.AddSeparator() + table.AddRow("EXPIRES AT", utils.PtrString(wrappingKey.ExpiresAt)) + table.AddSeparator() + table.AddRow("KEYRING ID", utils.PtrString(wrappingKey.KeyRingId)) + table.AddSeparator() + table.AddRow("PROTECTION", utils.PtrString(wrappingKey.Protection)) + table.AddSeparator() + table.AddRow("PUBLIC KEY", utils.PtrString(wrappingKey.PublicKey)) + table.AddSeparator() + table.AddRow("PURPOSE", utils.PtrString(wrappingKey.Purpose)) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("display table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/kms/wrappingkey/describe/describe_test.go b/internal/cmd/beta/kms/wrappingkey/describe/describe_test.go new file mode 100644 index 000000000..9589b33fb --- /dev/null +++ b/internal/cmd/beta/kms/wrappingkey/describe/describe_test.go @@ -0,0 +1,215 @@ +package describe + +import ( + "bytes" + "context" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" + "github.com/stackitcloud/stackit-sdk-go/services/kms" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &kms.APIClient{} +var testProjectId = uuid.NewString() +var testKeyRingID = uuid.NewString() +var testWrappingKeyID = uuid.NewString() +var testTime = time.Time{} + +const testRegion = "eu01" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + flagKeyRingID: testKeyRingID, + } + 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, + }, + KeyRingID: testKeyRingID, + WrappingKeyID: testWrappingKeyID, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: []string{testWrappingKeyID}, + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: []string{testWrappingKeyID}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "invalid key ring id", + argValues: []string{testWrappingKeyID}, + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[flagKeyRingID] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "missing project id", + argValues: []string{testWrappingKeyID}, + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "invalid project id", + argValues: []string{testWrappingKeyID}, + 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, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + got := buildRequest(testCtx, fixtureInputModel(), testClient) + want := testClient.GetWrappingKey(testCtx, testProjectId, testRegion, testKeyRingID, testWrappingKeyID) + diff := cmp.Diff(got, want, + cmp.AllowUnexported(want), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("buildRequest() mismatch (-want +got):\n%s", diff) + } +} +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + outputFmt string + keyRing *kms.WrappingKey + wantErr bool + expected string + }{ + { + description: "empty", + outputFmt: "table", + wantErr: true, + }, + { + description: "table format", + outputFmt: "table", + keyRing: &kms.WrappingKey{ + Id: utils.Ptr(testWrappingKeyID), + DisplayName: utils.Ptr("Test Key Ring"), + CreatedAt: utils.Ptr(testTime), + Description: utils.Ptr("This is a test key ring."), + State: utils.Ptr(kms.WRAPPINGKEYSTATE_ACTIVE), + AccessScope: utils.Ptr(kms.ACCESSSCOPE_PUBLIC), + Algorithm: utils.Ptr(kms.WRAPPINGALGORITHM__2048_OAEP_SHA256), + ExpiresAt: utils.Ptr(testTime), + KeyRingId: utils.Ptr(testKeyRingID), + Protection: utils.Ptr(kms.PROTECTION_SOFTWARE), + PublicKey: utils.Ptr("-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ...\n-----END PUBLIC KEY-----"), + Purpose: utils.Ptr(kms.WRAPPINGPURPOSE_ASYMMETRIC_KEY), + }, + expected: fmt.Sprintf(` + ID │ %-46s +──────────────┼─────────────────────────────────────────────── + DISPLAY NAME │ Test Key Ring +──────────────┼─────────────────────────────────────────────── + CREATED AT │ %-46s +──────────────┼─────────────────────────────────────────────── + STATE │ active +──────────────┼─────────────────────────────────────────────── + DESCRIPTION │ This is a test key ring. +──────────────┼─────────────────────────────────────────────── + ACCESS SCOPE │ PUBLIC +──────────────┼─────────────────────────────────────────────── + ALGORITHM │ rsa_2048_oaep_sha256 +──────────────┼─────────────────────────────────────────────── + EXPIRES AT │ %-46s +──────────────┼─────────────────────────────────────────────── + KEYRING ID │ %-46s +──────────────┼─────────────────────────────────────────────── + PROTECTION │ software +──────────────┼─────────────────────────────────────────────── + PUBLIC KEY │ -----BEGIN PUBLIC KEY----- + │ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ... + │ -----END PUBLIC KEY----- +──────────────┼─────────────────────────────────────────────── + PURPOSE │ wrap_asymmetric_key + +`, + testWrappingKeyID, + testTime, + testTime, + testKeyRingID), + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + var buf bytes.Buffer + p.Cmd.SetOut(&buf) + if err := outputResult(p, tt.outputFmt, tt.keyRing); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + diff := cmp.Diff(buf.String(), tt.expected) + if diff != "" { + t.Fatalf("outputResult() output mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/kms/wrappingkey/wrappingkey.go b/internal/cmd/beta/kms/wrappingkey/wrappingkey.go index 00184a521..168808e37 100644 --- a/internal/cmd/beta/kms/wrappingkey/wrappingkey.go +++ b/internal/cmd/beta/kms/wrappingkey/wrappingkey.go @@ -3,6 +3,7 @@ package wrappingkey import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/create" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/list" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -27,4 +28,5 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) } From 7dbd264aa82dde17ec1cdcaae763c882294865d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:21:24 +0000 Subject: [PATCH 525/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/rabbitmq (#1118) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cdccad46f..3ace14a71 100644 --- a/go.mod +++ b/go.mod @@ -249,7 +249,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum index 4323cb7d3..6f56c4c97 100644 --- a/go.sum +++ b/go.sum @@ -593,8 +593,8 @@ github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 h1:J9WP0lBoqm github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2/go.mod h1:QenOJF1LD39d/arGFGZFCzHoQuwF6VuWCvS8CbdoMBw= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1/go.mod h1:hyhw+I19NtjKmRLcUkY4boaTxnYSPFGbpn4RxvGqH2s= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1 h1:ALrDCBih8Fu8e6530KdOjuH0iMxOLntO381BbKFlTFY= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.1/go.mod h1:+qGWSehoV0Js3FalgvT/bOgPj+UqW4I7lP5s8uAxP+o= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 h1:Ww0baLTiZha4H1thfEEsDq+O0Ce0hNhdbkJ5eDdGEoE= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2/go.mod h1:lPz9iQ3kLvpzPR7jt6P1VJyjSumo2+D1i3RkjFGpVTI= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 h1:8uPt82Ez34OYMOijjEYxB1zUW6kiybkt6veQKl0AL68= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1/go.mod h1:1Y2GEICmZDt+kr8aGnBx/sjYVAIYHmtfC8xYi9oxNEE= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 h1:en8IomJeGqZZgGOyLH53PNDCv2F/x4zURz4mGSlhTKs= From 36bd0f52f30ae92a8d42eb57214164fe9ecca5d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:31:04 +0000 Subject: [PATCH 526/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/alb (#1117) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3ace14a71..922626d6f 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.20.0 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 diff --git a/go.sum b/go.sum index 6f56c4c97..2468f2453 100644 --- a/go.sum +++ b/go.sum @@ -563,8 +563,8 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.20.0 h1:4rrUk6uT1g4nOn5/g1uXukP07Tux/o5xbMz/f/qE1rY= github.com/stackitcloud/stackit-sdk-go/core v0.20.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 h1:DaJkEN/6l+AJEQ3Dr+3IdKM4jywDQsTvuYHmRvFj3ho= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1/go.mod h1:SzA+UsSNv4D9IvNT7hwYPewgAvUgj5WXIU2tZ0XaMBI= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 h1:x7ndqw6yaOw+TmThNeAkI+eN9vK5hWgjIJlFZrYPREo= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2/go.mod h1:wbPNu6e5r/5xhzznCKbC7fEJahrAOb89gmaIm+0w2/s= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= From 7570af4a2b646c5cd876499000224dfb48fb4b81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 09:59:26 +0100 Subject: [PATCH 527/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex (#1116) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 922626d6f..7df5a05df 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 diff --git a/go.sum b/go.sum index 2468f2453..0cfbb3753 100644 --- a/go.sum +++ b/go.sum @@ -583,8 +583,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 h1:g3xzRqwul8W638g github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2/go.mod h1:OlGmMlXKp33ZYpUm9TqaLYf8SdzhDW5uBKcbgq1zXOk= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 h1:Db/ebOL2vbpIeh5XB2Ews2B9Lj5DJlMWIEJh60FfZ4Y= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1/go.mod h1:8jdN4v2euK3f9gfdzbRi8e4nBJ8g/Q5YF9aPB4M4fCQ= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2 h1:BQ+qAkVS/aGHepE/+gVsvSg1sRkPOyIUI/jkCyUOrWg= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.2/go.mod h1:oc8Mpwl7O6EZwG0YxfhOzNCJwNQBWK5rFh764OtxoMY= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 h1:tGa+NcjNKTWvChN+0OMdLomb9Jod4MmY6YAiPTJMgfo= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3/go.mod h1:ciuOzwN5GcqplRy95fXRaS44dFmhfNxvmzTl/ALwV/k= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 h1:I9B/zUU7R74xuH/ztcPrDIuMp2KV3QQMjeE7lFudboM= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1/go.mod h1:h4aX5tyTQoO6KLrugkvfkqgKTjIzh7e4q9N92kT5OBs= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 h1:zk+47GhutK2ajO4Yiek0laGm2PdXvY8BvFZc8yHFnSE= From 2dda12a4a96c0f2e55993d2cd78aaf4a31d1784d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 09:07:54 +0000 Subject: [PATCH 528/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serviceaccount (#1115) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7df5a05df..893989a6b 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 diff --git a/go.sum b/go.sum index 0cfbb3753..01c693f96 100644 --- a/go.sum +++ b/go.sum @@ -607,8 +607,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 h1:LONKouoyr github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3/go.mod h1:mCiDOqMHQKM9cFs5/GULaYz6Ni0QA2TTMQZJcj4GFUE= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 h1:ubaIeflBZ70evMhU5Xl4NzzDUTk0Z309jnv18OikXgs= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2/go.mod h1:NH6dyKSkJ0WezDgIpXr5PkhSGUXJvwEFcsQmeGScDs8= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1 h1:crKlHl7QVF97A8CTBK3PBtVpO9c/7qwFvRJi5UN/F7Y= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.1/go.mod h1:QCrAW/Rmf+styT25ke8cUV6hDHpdKNmAY14kkJ3+Fd8= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 h1:+S5yPftGLH99ByzDCwzdI927bvKOKMQxMkd/tuPeQTE= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2/go.mod h1:gaHXopzXPDP1AmquUVhMmz9opAr2QYVBL0XbBdPtB7s= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 h1:bQk5qKid5Kv3fZ2miWlS5Dvo+cW90hbePaxOyWF67EE= From 8e1489be2122bb33185f5bd638cdabc655453d2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:08:40 +0100 Subject: [PATCH 529/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serviceenablement (#1123) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 893989a6b..3d1233690 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 github.com/zalando/go-keyring v0.2.6 diff --git a/go.sum b/go.sum index 01c693f96..5f93fd0e8 100644 --- a/go.sum +++ b/go.sum @@ -609,8 +609,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 h1:ubaIeflBZ github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2/go.mod h1:NH6dyKSkJ0WezDgIpXr5PkhSGUXJvwEFcsQmeGScDs8= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 h1:+S5yPftGLH99ByzDCwzdI927bvKOKMQxMkd/tuPeQTE= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2/go.mod h1:gaHXopzXPDP1AmquUVhMmz9opAr2QYVBL0XbBdPtB7s= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2 h1:s2iag/Gc4tuQH7x5I0n4mQWVhpfl/cj+SVNAFAB5ck0= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.2/go.mod h1:DFEamKVoOjm/rjMwzfZK0Zg/hwsSkXOibdA4HcC6swk= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 h1:zcfL+rpQZWXZazL8w8DqXYxGbIOInaUc155BWTshNRA= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3/go.mod h1:icu5WtsZ8c57/pUrXeFLmZu29Qhwr/rsjTkVRWJYTqY= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 h1:bQk5qKid5Kv3fZ2miWlS5Dvo+cW90hbePaxOyWF67EE= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0/go.mod h1:/Ujlw+qo6RgKm69dD8y6MgmJFcUmrHjuJPO6VFoQX9U= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 h1:aW8ehdoNRaCEs3xDr+YnGb6pru8zZTB8f7kl5lozlJE= From e72410c13fa603be36d6ae50fe25e51c8064e0a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:56:42 +0100 Subject: [PATCH 530/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/dns (#1122) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3d1233690..bc5f4fc17 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.20.0 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 diff --git a/go.sum b/go.sum index 5f93fd0e8..14abaf6bd 100644 --- a/go.sum +++ b/go.sum @@ -567,8 +567,8 @@ github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 h1:x7ndqw6yaOw+TmThNe github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2/go.mod h1:wbPNu6e5r/5xhzznCKbC7fEJahrAOb89gmaIm+0w2/s= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 h1:x1i5rqhEVuUPq5M0eb68ZD2KL1C8OFD8RG2sWMQGL6o= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2/go.mod h1:nOdpHeRWeiPlioOGovHzLpojlilbxAxoXsAy+TiOpw4= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 h1:RgWfaWDY8ZGZp5gEBe/A1r7s5NCRuLiYuHhscH6Ej9U= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1/go.mod h1:HgScss2f+/k/wDxcsM1K8SzLgDso/EZyhoJC2eZ+tFA= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 h1:bkvq3Y4OcGyCR5N69tyY7ZTcrVN+htGTa2ZBJL5BQTQ= From 74d5ceb890ac81841781d8691e09aeb66797c999 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:05:38 +0000 Subject: [PATCH 531/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/iaas (#1121) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index bc5f4fc17..27390aaa3 100644 --- a/go.mod +++ b/go.mod @@ -20,12 +20,12 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 + github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 diff --git a/go.sum b/go.sum index 14abaf6bd..4e7df87f2 100644 --- a/go.sum +++ b/go.sum @@ -571,8 +571,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 h1:x1i5rqhEVuUPq5M0e github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2/go.mod h1:nOdpHeRWeiPlioOGovHzLpojlilbxAxoXsAy+TiOpw4= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 h1:RgWfaWDY8ZGZp5gEBe/A1r7s5NCRuLiYuHhscH6Ej9U= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1/go.mod h1:HgScss2f+/k/wDxcsM1K8SzLgDso/EZyhoJC2eZ+tFA= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0 h1:bkvq3Y4OcGyCR5N69tyY7ZTcrVN+htGTa2ZBJL5BQTQ= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0/go.mod h1:tg1rHvgFRG9gNCYnTepZFaSCBahhLLjkIb3nRbtyjDQ= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 h1:afGHMCqBM/E/FPUvbfSTFb9ddI+eDm2a7DpWPCkxMzs= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2/go.mod h1:/DlO7+cOqyYKROIxkBYIUdMoEfFevkVXhsShglxyUOQ= github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 h1:OdY3eXn98hWIhZBH8qQTFsYP6cag8B29UdwTjMwAjfw= github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0/go.mod h1:mf+DQwwTVfc8MD0vwTNPzin2unKAIyQRYywv3wUyH38= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EGbsmSX9CLFp3nBcWV8JAeTz4p8= @@ -597,8 +597,8 @@ github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 h1:Ww0baLTiZha4 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2/go.mod h1:lPz9iQ3kLvpzPR7jt6P1VJyjSumo2+D1i3RkjFGpVTI= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 h1:8uPt82Ez34OYMOijjEYxB1zUW6kiybkt6veQKl0AL68= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1/go.mod h1:1Y2GEICmZDt+kr8aGnBx/sjYVAIYHmtfC8xYi9oxNEE= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0 h1:en8IomJeGqZZgGOyLH53PNDCv2F/x4zURz4mGSlhTKs= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.0/go.mod h1:0wVdzrB4PhwhTE6drOVA6rETTmJ+k3eHa0neuxpDM/g= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 h1:KDa5sy6NSzMOXaf4a9skxOm8oUoleI45fLbD3ww7qsc= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1/go.mod h1:+k3iHkWpehO+FLC5WsW7eGhYdNjDklYqRcpIxQBLbZg= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 h1:CPIuqhQw+oPt08I2WLsxJDoVDsPMW2VkvKW7/SlUv10= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1/go.mod h1:tip0Ob6x06luy3CmRrmnCMtU5cha95fQLdvZlno3J4w= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp742W6AgleV2eEXrJFZ7ai9rXu9V1Lkmir0drI= From 67440f2cc21072c1a5901e688ce39efc77a8a8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Thu, 27 Nov 2025 11:11:46 +0100 Subject: [PATCH 532/619] fix(alb): print valid JSON/YAML output for list cmds (#1045) relates to STACKITCLI-273 / #893 --- internal/cmd/beta/alb/list/list.go | 25 +++++++++---------- internal/cmd/beta/alb/list/list_test.go | 20 +++++++++------ .../observability-credentials/list/list.go | 18 ++++++------- internal/cmd/beta/alb/plans/plans.go | 18 ++++++------- internal/cmd/beta/alb/plans/plans_test.go | 6 +++-- 5 files changed, 44 insertions(+), 43 deletions(-) diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go index 2c4d8924d..292e2e3ae 100644 --- a/internal/cmd/beta/alb/list/list.go +++ b/internal/cmd/beta/alb/list/list.go @@ -25,8 +25,7 @@ type inputModel struct { } const ( - labelSelectorFlag = "label-selector" - limitFlag = "limit" + limitFlag = "limit" ) func NewCmd(params *params.CmdParams) *cobra.Command { @@ -73,19 +72,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list load balancerse: %w", err) } + items := response.GetLoadBalancers() - if items := response.LoadBalancers; items == nil || len(*items) == 0 { - params.Printer.Info("No load balancers found for project %q", projectLabel) - } else { - if model.Limit != nil && len(*items) > int(*model.Limit) { - *items = (*items)[:*model.Limit] - } - if err := outputResult(params.Printer, model.OutputFormat, *items); err != nil { - return fmt.Errorf("output loadbalancers: %w", err) - } + // Truncate output + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] } - return nil + return outputResult(params.Printer, model.OutputFormat, projectLabel, items) }, } @@ -125,8 +119,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClie return request } -func outputResult(p *print.Printer, outputFormat string, items []alb.LoadBalancer) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, items []alb.LoadBalancer) error { return p.OutputResult(outputFormat, items, func() error { + if len(items) == 0 { + p.Outputf("No load balancers found for project %q", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("NAME", "EXTERNAL ADDRESS", "REGION", "STATUS", "VERSION", "ERRORS") for i := range items { diff --git a/internal/cmd/beta/alb/list/list_test.go b/internal/cmd/beta/alb/list/list_test.go index c623ea0b8..5ffc642e2 100644 --- a/internal/cmd/beta/alb/list/list_test.go +++ b/internal/cmd/beta/alb/list/list_test.go @@ -5,6 +5,8 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -19,11 +21,14 @@ import ( type testCtxKey struct{} var ( - testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") - testClient = &alb.APIClient{} - testProjectId = uuid.NewString() - testRegion = "eu01" - testLimit int64 = 10 + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &alb.APIClient{} + testProjectId = uuid.NewString() +) + +const ( + testRegion = "eu01" + testLimit int64 = 10 ) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { @@ -41,7 +46,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Region: testRegion, Verbosity: globalflags.VerbosityDefault}, - Limit: &testLimit, + Limit: utils.Ptr(testLimit), } for _, mod := range mods { mod(model) @@ -136,6 +141,7 @@ func TestBuildRequest(t *testing.T) { func Test_outputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string items []alb.LoadBalancer } tests := []struct { @@ -164,7 +170,7 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.items); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/beta/alb/observability-credentials/list/list.go b/internal/cmd/beta/alb/observability-credentials/list/list.go index 961455b53..51347cae2 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list.go @@ -68,13 +68,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list credentials: %w", err) } + items := resp.GetCredentials() - if resp.Credentials == nil || len(*resp.Credentials) == 0 { - params.Printer.Info("No credentials found\n") - return nil - } - - items := *resp.Credentials + // Truncate output if model.Limit != nil && len(items) > int(*model.Limit) { items = items[:*model.Limit] } @@ -116,12 +112,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClie } func outputResult(p *print.Printer, outputFormat string, items []alb.CredentialsResponse) error { - if items == nil { - p.Outputln("no credentials found") - return nil - } - return p.OutputResult(outputFormat, items, func() error { + if len(items) == 0 { + p.Outputf("No credentials found\n") + return nil + } + table := tables.NewTable() table.SetHeader("CREDENTIAL REF", "DISPLAYNAME", "USERNAME", "REGION") diff --git a/internal/cmd/beta/alb/plans/plans.go b/internal/cmd/beta/alb/plans/plans.go index 6bb5e01fc..0724860a1 100644 --- a/internal/cmd/beta/alb/plans/plans.go +++ b/internal/cmd/beta/alb/plans/plans.go @@ -62,16 +62,9 @@ func NewCmd(params *params.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("list plans: %w", err) } + items := response.GetValidPlans() - if items := response.ValidPlans; items == nil || len(*items) == 0 { - params.Printer.Info("No plans found for project %q", projectLabel) - } else { - if err := outputResult(params.Printer, model.OutputFormat, *items); err != nil { - return fmt.Errorf("output plans: %w", err) - } - } - - return nil + return outputResult(params.Printer, model.OutputFormat, projectLabel, items) }, } @@ -98,8 +91,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClie return request } -func outputResult(p *print.Printer, outputFormat string, items []alb.PlanDetails) error { +func outputResult(p *print.Printer, outputFormat, projectLabel string, items []alb.PlanDetails) error { return p.OutputResult(outputFormat, items, func() error { + if len(items) == 0 { + p.Outputf("No plans found for project %q", projectLabel) + return nil + } + table := tables.NewTable() table.SetHeader("PLAN ID", "NAME", "FLAVOR", "MAX CONNS", "DESCRIPTION") for _, item := range items { diff --git a/internal/cmd/beta/alb/plans/plans_test.go b/internal/cmd/beta/alb/plans/plans_test.go index 1a31d711b..ebb7ed8f0 100644 --- a/internal/cmd/beta/alb/plans/plans_test.go +++ b/internal/cmd/beta/alb/plans/plans_test.go @@ -21,9 +21,10 @@ var ( testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") testClient = &alb.APIClient{} testProjectId = uuid.NewString() - testRegion = "eu01" ) +const testRegion = "eu01" + func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, @@ -132,6 +133,7 @@ func TestBuildRequest(t *testing.T) { func Test_outputResult(t *testing.T) { type args struct { outputFormat string + projectLabel string items []alb.PlanDetails } tests := []struct { @@ -160,7 +162,7 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.items); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.items); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From d98da15248c04766b2eac344d89539e30286c52d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 09:14:55 +0100 Subject: [PATCH 533/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mariadb (#1129) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 27390aaa3..c01feafd1 100644 --- a/go.mod +++ b/go.mod @@ -246,7 +246,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 diff --git a/go.sum b/go.sum index 4e7df87f2..7eeff2bf4 100644 --- a/go.sum +++ b/go.sum @@ -581,8 +581,8 @@ github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVE github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0/go.mod h1:20QOZ3rBC9wTGgzXzLz9M6YheX0VaxWE0/JI+s8On7k= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 h1:g3xzRqwul8W638gOKTZRAnnQuMhYqaliuz/A8BcfjhU= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2/go.mod h1:OlGmMlXKp33ZYpUm9TqaLYf8SdzhDW5uBKcbgq1zXOk= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1 h1:Db/ebOL2vbpIeh5XB2Ews2B9Lj5DJlMWIEJh60FfZ4Y= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.1/go.mod h1:8jdN4v2euK3f9gfdzbRi8e4nBJ8g/Q5YF9aPB4M4fCQ= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.2 h1:SfRbw3DxvDnZF2q6D9xfSy8EKHyrG5TgLMP0qRW8r9o= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.2/go.mod h1:VmXwRQHZsGUjGWdLf8d2WhKNyuPi5+JgCAF/meOp4DE= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 h1:tGa+NcjNKTWvChN+0OMdLomb9Jod4MmY6YAiPTJMgfo= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3/go.mod h1:ciuOzwN5GcqplRy95fXRaS44dFmhfNxvmzTl/ALwV/k= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 h1:I9B/zUU7R74xuH/ztcPrDIuMp2KV3QQMjeE7lFudboM= From da73b8fd730fb9f711a83a9574289c17099a7501 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 08:24:31 +0000 Subject: [PATCH 534/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/redis (#1128) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c01feafd1..bd67ff359 100644 --- a/go.mod +++ b/go.mod @@ -250,7 +250,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.38.0 // indirect diff --git a/go.sum b/go.sum index 7eeff2bf4..3e9a56c8f 100644 --- a/go.sum +++ b/go.sum @@ -595,8 +595,8 @@ github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1/go.mod h1:hyhw+I19NtjKmRLcUkY4boaTxnYSPFGbpn4RxvGqH2s= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 h1:Ww0baLTiZha4H1thfEEsDq+O0Ce0hNhdbkJ5eDdGEoE= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2/go.mod h1:lPz9iQ3kLvpzPR7jt6P1VJyjSumo2+D1i3RkjFGpVTI= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1 h1:8uPt82Ez34OYMOijjEYxB1zUW6kiybkt6veQKl0AL68= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.1/go.mod h1:1Y2GEICmZDt+kr8aGnBx/sjYVAIYHmtfC8xYi9oxNEE= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2 h1:VWx+u5b9r+HEm2rCtGlS7OFKl6Fnqe6s2xyCBA3IbM8= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2/go.mod h1:fg1pAqju7q5A696aiok2L4SHZIjZCCiBCpsm7FrQZMA= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 h1:KDa5sy6NSzMOXaf4a9skxOm8oUoleI45fLbD3ww7qsc= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1/go.mod h1:+k3iHkWpehO+FLC5WsW7eGhYdNjDklYqRcpIxQBLbZg= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 h1:CPIuqhQw+oPt08I2WLsxJDoVDsPMW2VkvKW7/SlUv10= From e1823682316c41d198159315f03eb342728dd06b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 08:34:22 +0000 Subject: [PATCH 535/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/runcommand (#1127) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bd67ff359..5d51e5f9a 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 diff --git a/go.sum b/go.sum index 3e9a56c8f..c53db8904 100644 --- a/go.sum +++ b/go.sum @@ -599,8 +599,8 @@ github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2 h1:VWx+u5b9r+HEm2r github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2/go.mod h1:fg1pAqju7q5A696aiok2L4SHZIjZCCiBCpsm7FrQZMA= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 h1:KDa5sy6NSzMOXaf4a9skxOm8oUoleI45fLbD3ww7qsc= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1/go.mod h1:+k3iHkWpehO+FLC5WsW7eGhYdNjDklYqRcpIxQBLbZg= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1 h1:CPIuqhQw+oPt08I2WLsxJDoVDsPMW2VkvKW7/SlUv10= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.1/go.mod h1:tip0Ob6x06luy3CmRrmnCMtU5cha95fQLdvZlno3J4w= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 h1:Jts49V7XvLLr7MwI9o5Mo0NW3iUVVt8DtqNqRDt6ags= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2/go.mod h1:hV1rmsyb3jlL5kWO+flhtXTbm5EM9vU+BJsV4U/YEUU= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp742W6AgleV2eEXrJFZ7ai9rXu9V1Lkmir0drI= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2/go.mod h1:xm0ARtIbfzmqw8e8qThtrYdHHEkpuYvKt13SZGBoWSE= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 h1:LONKouoyrgDfu4Tu152YFjd5cw3SoG8P7PHdd8tsBOU= From 5102b0afa2098fd39bea2f94bacdd27a1b06c3c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 09:44:40 +0100 Subject: [PATCH 536/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/authorization (#1120) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5d51e5f9a..1c480a62e 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.20.0 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 diff --git a/go.sum b/go.sum index c53db8904..73058335f 100644 --- a/go.sum +++ b/go.sum @@ -565,8 +565,8 @@ github.com/stackitcloud/stackit-sdk-go/core v0.20.0 h1:4rrUk6uT1g4nOn5/g1uXukP07 github.com/stackitcloud/stackit-sdk-go/core v0.20.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 h1:x7ndqw6yaOw+TmThNeAkI+eN9vK5hWgjIJlFZrYPREo= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2/go.mod h1:wbPNu6e5r/5xhzznCKbC7fEJahrAOb89gmaIm+0w2/s= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 h1:6Buzw5CuPb5ixdMHx4tKjmsQkMn0Hpj0xJ+aNDimKnk= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0/go.mod h1:40XVgsSOcVCjoIAsbSycDh8Ikp2y88AdAeqwqIIHvZE= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 h1:x1i5rqhEVuUPq5M0eb68ZD2KL1C8OFD8RG2sWMQGL6o= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2/go.mod h1:nOdpHeRWeiPlioOGovHzLpojlilbxAxoXsAy+TiOpw4= github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 h1:RgWfaWDY8ZGZp5gEBe/A1r7s5NCRuLiYuHhscH6Ej9U= From bdcdd1151e71aaac624f5de2132832057a757d4e Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Fri, 28 Nov 2025 09:57:57 +0100 Subject: [PATCH 537/619] chore: increase linter timeout (#1131) --- golang-ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golang-ci.yaml b/golang-ci.yaml index 3487f7456..611e2e172 100644 --- a/golang-ci.yaml +++ b/golang-ci.yaml @@ -7,7 +7,7 @@ run: concurrency: 4 # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 5m + timeout: 10m linters-settings: goimports: # put imports beginning with prefix after 3rd-party packages; From bb0b77b509e0b63d9f2308c1c82b5cb1820bab95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:29:23 +0100 Subject: [PATCH 538/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/intake (#1132) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1c480a62e..1d1b566c7 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 - github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 diff --git a/go.sum b/go.sum index 73058335f..6c5568826 100644 --- a/go.sum +++ b/go.sum @@ -573,8 +573,8 @@ github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 h1:RgWfaWDY8ZGZp5gEBe github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1/go.mod h1:HgScss2f+/k/wDxcsM1K8SzLgDso/EZyhoJC2eZ+tFA= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 h1:afGHMCqBM/E/FPUvbfSTFb9ddI+eDm2a7DpWPCkxMzs= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2/go.mod h1:/DlO7+cOqyYKROIxkBYIUdMoEfFevkVXhsShglxyUOQ= -github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0 h1:OdY3eXn98hWIhZBH8qQTFsYP6cag8B29UdwTjMwAjfw= -github.com/stackitcloud/stackit-sdk-go/services/intake v0.3.0/go.mod h1:mf+DQwwTVfc8MD0vwTNPzin2unKAIyQRYywv3wUyH38= +github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 h1:KwjR5L+IoUbRYS8k3dyqHgtBUuq8cqRPrUrzzZSSnRI= +github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0/go.mod h1:Nea8wkoPGvcjKCsjfbAB3pE3kA7oZLi+Zk9hUtunjRI= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EGbsmSX9CLFp3nBcWV8JAeTz4p8= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1/go.mod h1:Wh1NKX5ZI0FuIdYavOYu0Cjh0yA3S9rlm4j5g0vuPVI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= From 6a53617685574ec0088ab1ca5284144012edf3e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 14:40:03 +0000 Subject: [PATCH 539/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/loadbalancer (#1133) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1d1b566c7..1b9b1d69c 100644 --- a/go.mod +++ b/go.mod @@ -244,7 +244,7 @@ require ( github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 diff --git a/go.sum b/go.sum index 6c5568826..390cffab1 100644 --- a/go.sum +++ b/go.sum @@ -577,8 +577,8 @@ github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 h1:KwjR5L+IoUbRYS8 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0/go.mod h1:Nea8wkoPGvcjKCsjfbAB3pE3kA7oZLi+Zk9hUtunjRI= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EGbsmSX9CLFp3nBcWV8JAeTz4p8= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1/go.mod h1:Wh1NKX5ZI0FuIdYavOYu0Cjh0yA3S9rlm4j5g0vuPVI= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0 h1:q33ZaCBVEBUsnMDxYyuJKtJvGcE5nKgvuPed3s8zXNI= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.0/go.mod h1:20QOZ3rBC9wTGgzXzLz9M6YheX0VaxWE0/JI+s8On7k= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 h1:BHNjq4+OsmVrGu1KBOv0dh/++nwysyINtAUTxNFz2Uo= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1/go.mod h1:sTV6ylmBoMOrOxUED8Ebts4a1PaJSPLtmNh5m+s5fus= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 h1:g3xzRqwul8W638gOKTZRAnnQuMhYqaliuz/A8BcfjhU= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2/go.mod h1:OlGmMlXKp33ZYpUm9TqaLYf8SdzhDW5uBKcbgq1zXOk= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.2 h1:SfRbw3DxvDnZF2q6D9xfSy8EKHyrG5TgLMP0qRW8r9o= From 58a4b77aaad4a2c62dd503abe75f563ca2742f51 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Fri, 28 Nov 2025 17:19:33 +0100 Subject: [PATCH 540/619] fix: log browser url to stderr instead of stdout (#1136) fixes #1125 --- internal/pkg/auth/user_login.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index 2ec2040dd..c01dbccba 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -245,8 +245,8 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { } // Print the link - p.Outputln("Your browser has been opened to visit:\n") - p.Outputf("%s\n\n", authorizationURL) + p.Info("Your browser has been opened to visit:\n\n") + p.Info("%s\n\n", authorizationURL) // Start the blocking web server loop // It will exit when the handlers get fired and call server.Close() From 21985b286e47786027bf26ad2d5c2a2ef13edec1 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 1 Dec 2025 14:44:33 +0100 Subject: [PATCH 541/619] fix(deps): update module github.com/goccy/go-yaml to v1.19.0 (#1137) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1b9b1d69c..2857d30bd 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.0 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.18.0 + github.com/goccy/go-yaml v1.19.0 github.com/golang-jwt/jwt/v5 v5.3.0 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 390cffab1..d1d11505a 100644 --- a/go.sum +++ b/go.sum @@ -213,8 +213,8 @@ github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUW github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= -github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE= +github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= From 437c1adc5cd466374b3c4efc301adcf26a288e7c Mon Sep 17 00:00:00 2001 From: Piet van der Meulen Date: Mon, 1 Dec 2025 16:17:18 +0100 Subject: [PATCH 542/619] feat(mongodbflex): add readAnyDatabase and stackitAdmin roles for users (#1049) Co-authored-by: Ruben Hoenle --- docs/stackit_mongodbflex_user_create.md | 2 +- docs/stackit_mongodbflex_user_update.md | 2 +- internal/cmd/mongodbflex/user/create/create.go | 4 ++-- internal/cmd/mongodbflex/user/update/update.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/stackit_mongodbflex_user_create.md b/docs/stackit_mongodbflex_user_create.md index 99075fee8..e8d4cdace 100644 --- a/docs/stackit_mongodbflex_user_create.md +++ b/docs/stackit_mongodbflex_user_create.md @@ -29,7 +29,7 @@ stackit mongodbflex user create [flags] --database string The database inside the MongoDB instance that the user has access to. If it does not exist, it will be created once the user writes to it -h, --help Help for "stackit mongodbflex user create" --instance-id string ID of the instance - --role strings Roles of the user, possible values are ["read" "readWrite" "readWriteAnyDatabase"] (default [read]) + --role strings Roles of the user, possible values are ["read" "readWrite" "readAnyDatabase" "readWriteAnyDatabase" "stackitAdmin"]. The "readAnyDatabase", "readWriteAnyDatabase" and "stackitAdmin" roles will always be created in the admin database. (default [read]) --username string Username of the user. If not specified, a random username will be assigned ``` diff --git a/docs/stackit_mongodbflex_user_update.md b/docs/stackit_mongodbflex_user_update.md index 31a674972..02e0d42af 100644 --- a/docs/stackit_mongodbflex_user_update.md +++ b/docs/stackit_mongodbflex_user_update.md @@ -23,7 +23,7 @@ stackit mongodbflex user update USER_ID [flags] --database string The database inside the MongoDB instance that the user has access to. If it does not exist, it will be created once the user writes to it -h, --help Help for "stackit mongodbflex user update" --instance-id string ID of the instance - --role strings Roles of the user, possible values are ["read" "readWrite" "readWriteAnyDatabase"] (default []) + --role strings Roles of the user, possible values are ["read" "readWrite" "readAnyDatabase" "readWriteAnyDatabase" "stackitAdmin"]. The "readAnyDatabase", "readWriteAnyDatabase" and "stackitAdmin" roles will always be created in the admin database. (default []) ``` ### Options inherited from parent commands diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index f589c3996..cfeb7b6ba 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -101,12 +101,12 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func configureFlags(cmd *cobra.Command) { - roleOptions := []string{"read", "readWrite", "readWriteAnyDatabase"} + roleOptions := []string{"read", "readWrite", "readAnyDatabase", "readWriteAnyDatabase", "stackitAdmin"} cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance") cmd.Flags().String(usernameFlag, "", "Username of the user. If not specified, a random username will be assigned") cmd.Flags().String(databaseFlag, "", "The database inside the MongoDB instance that the user has access to. If it does not exist, it will be created once the user writes to it") - cmd.Flags().Var(flags.EnumSliceFlag(false, rolesDefault, roleOptions...), roleFlag, fmt.Sprintf("Roles of the user, possible values are %q", roleOptions)) + cmd.Flags().Var(flags.EnumSliceFlag(false, rolesDefault, roleOptions...), roleFlag, fmt.Sprintf("Roles of the user, possible values are %q. The \"readAnyDatabase\", \"readWriteAnyDatabase\" and \"stackitAdmin\" roles will always be created in the admin database.", roleOptions)) err := flags.MarkFlagsRequired(cmd, instanceIdFlag, databaseFlag) cobra.CheckErr(err) diff --git a/internal/cmd/mongodbflex/user/update/update.go b/internal/cmd/mongodbflex/user/update/update.go index df408025e..a8fcfee3e 100644 --- a/internal/cmd/mongodbflex/user/update/update.go +++ b/internal/cmd/mongodbflex/user/update/update.go @@ -97,11 +97,11 @@ func NewCmd(params *params.CmdParams) *cobra.Command { } func configureFlags(cmd *cobra.Command) { - roleOptions := []string{"read", "readWrite", "readWriteAnyDatabase"} + roleOptions := []string{"read", "readWrite", "readAnyDatabase", "readWriteAnyDatabase", "stackitAdmin"} cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance") cmd.Flags().String(databaseFlag, "", "The database inside the MongoDB instance that the user has access to. If it does not exist, it will be created once the user writes to it") - cmd.Flags().Var(flags.EnumSliceFlag(false, nil, roleOptions...), roleFlag, fmt.Sprintf("Roles of the user, possible values are %q", roleOptions)) + cmd.Flags().Var(flags.EnumSliceFlag(false, nil, roleOptions...), roleFlag, fmt.Sprintf("Roles of the user, possible values are %q. The \"readAnyDatabase\", \"readWriteAnyDatabase\" and \"stackitAdmin\" roles will always be created in the admin database.", roleOptions)) err := flags.MarkFlagsRequired(cmd, instanceIdFlag) cobra.CheckErr(err) From f352d44020ea2c7e2820d70fc125b4dc82ab766d Mon Sep 17 00:00:00 2001 From: Jorge Turrado Ferrero Date: Mon, 1 Dec 2025 16:52:31 +0100 Subject: [PATCH 543/619] fix: refresh token flow uses x-www-form encoding (#1135) --- internal/pkg/auth/user_token_flow.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/internal/pkg/auth/user_token_flow.go b/internal/pkg/auth/user_token_flow.go index 215db2fa3..cdb852f77 100644 --- a/internal/pkg/auth/user_token_flow.go +++ b/internal/pkg/auth/user_token_flow.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "net/url" + "strings" "time" "github.com/golang-jwt/jwt/v5" @@ -166,21 +167,21 @@ func buildRequestToRefreshTokens(utf *userTokenFlow) (*http.Request, error) { return nil, err } + form := url.Values{} + form.Set("grant_type", "refresh_token") + form.Set("client_id", idpClientID) + form.Set("refresh_token", utf.refreshToken) + req, err := http.NewRequest( http.MethodPost, utf.tokenEndpoint, - http.NoBody, + strings.NewReader(form.Encode()), ) + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + if err != nil { return nil, err } - reqQuery := url.Values{} - reqQuery.Set("grant_type", "refresh_token") - reqQuery.Set("client_id", idpClientID) - reqQuery.Set("refresh_token", utf.refreshToken) - reqQuery.Set("token_format", "jwt") - req.URL.RawQuery = reqQuery.Encode() - return req, nil } From afbf59d3aa0a81af2c898f4dd62432f57ef185b5 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 2 Dec 2025 08:59:29 +0100 Subject: [PATCH 544/619] chore(deps): update renovatebot/github-action action to v44.0.5 (#1141) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 8551dd43e..d9eddd18a 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Self-hosted Renovate - uses: renovatebot/github-action@v44.0.4 + uses: renovatebot/github-action@v44.0.5 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From d5e084927b9028bb3edce474e73141b839adf5f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 08:08:35 +0000 Subject: [PATCH 545/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex (#1139) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2857d30bd..0a1369791 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.3 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.30.0 golang.org/x/oauth2 v0.33.0 diff --git a/go.sum b/go.sum index d1d11505a..94e312bbd 100644 --- a/go.sum +++ b/go.sum @@ -613,8 +613,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 h1:zcfL github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3/go.mod h1:icu5WtsZ8c57/pUrXeFLmZu29Qhwr/rsjTkVRWJYTqY= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 h1:bQk5qKid5Kv3fZ2miWlS5Dvo+cW90hbePaxOyWF67EE= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0/go.mod h1:/Ujlw+qo6RgKm69dD8y6MgmJFcUmrHjuJPO6VFoQX9U= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2 h1:aW8ehdoNRaCEs3xDr+YnGb6pru8zZTB8f7kl5lozlJE= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.2/go.mod h1:Jsry+gfhuXv2P0ldfa48BaL605NhDjdQMgaoV8czlbo= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.3 h1:TFefEGGxvcI7euqyosbLS/zSEOy+3JMGOirW3vNj/84= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.3/go.mod h1:Jsry+gfhuXv2P0ldfa48BaL605NhDjdQMgaoV8czlbo= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From b824fb3173b03a0650dbe6989e322b779dc94465 Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Tue, 2 Dec 2025 10:25:49 +0100 Subject: [PATCH 546/619] chore(linter): remove duplicate linter timeout configuration (#1142) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a3b64bb3d..836e41ad4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ ROOT_DIR ?= $(shell git rev-parse --show-toplevel) SCRIPTS_BASE ?= $(ROOT_DIR)/scripts GOLANG_CI_YAML_PATH ?= ${ROOT_DIR}/golang-ci.yaml -GOLANG_CI_ARGS ?= --allow-parallel-runners --timeout=5m --config=${GOLANG_CI_YAML_PATH} +GOLANG_CI_ARGS ?= --allow-parallel-runners --config=${GOLANG_CI_YAML_PATH} # Build build: From 4fca05266d0fe4e7d0dd1db094b751be8a5b22a7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 4 Dec 2025 07:43:48 +0100 Subject: [PATCH 547/619] fix(deps): update module github.com/spf13/cobra to v1.10.2 (#1145) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0a1369791..eab844658 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/jedib0t/go-pretty/v6 v6.7.5 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 - github.com/spf13/cobra v1.10.1 + github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.20.0 diff --git a/go.sum b/go.sum index 94e312bbd..7f62cc374 100644 --- a/go.sum +++ b/go.sum @@ -551,8 +551,8 @@ github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= From 98a09dd59c41467277dda114bcacc4084afb9fbc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Dec 2025 06:52:25 +0000 Subject: [PATCH 548/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/git (#1144) Bumps [github.com/stackitcloud/stackit-sdk-go/services/git](https://github.com/stackitcloud/stackit-sdk-go) from 0.9.1 to 0.10.0. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/dns/v0.9.1...core/v0.10.0) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/git dependency-version: 0.10.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eab844658..faa3677e0 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 - github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 + github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 diff --git a/go.sum b/go.sum index 7f62cc374..23bd2f366 100644 --- a/go.sum +++ b/go.sum @@ -569,8 +569,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 h1:6Buzw5C github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0/go.mod h1:40XVgsSOcVCjoIAsbSycDh8Ikp2y88AdAeqwqIIHvZE= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 h1:x1i5rqhEVuUPq5M0eb68ZD2KL1C8OFD8RG2sWMQGL6o= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2/go.mod h1:nOdpHeRWeiPlioOGovHzLpojlilbxAxoXsAy+TiOpw4= -github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1 h1:RgWfaWDY8ZGZp5gEBe/A1r7s5NCRuLiYuHhscH6Ej9U= -github.com/stackitcloud/stackit-sdk-go/services/git v0.9.1/go.mod h1:HgScss2f+/k/wDxcsM1K8SzLgDso/EZyhoJC2eZ+tFA= +github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0 h1:fWAjxvf5D1jc1hvziGxJq68RO4pDXBUAPVrIumHb5mw= +github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0/go.mod h1:HgScss2f+/k/wDxcsM1K8SzLgDso/EZyhoJC2eZ+tFA= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 h1:afGHMCqBM/E/FPUvbfSTFb9ddI+eDm2a7DpWPCkxMzs= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2/go.mod h1:/DlO7+cOqyYKROIxkBYIUdMoEfFevkVXhsShglxyUOQ= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 h1:KwjR5L+IoUbRYS8k3dyqHgtBUuq8cqRPrUrzzZSSnRI= From a25a7774cc5c72da73218774403f161f0b9b6c0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 07:25:58 +0100 Subject: [PATCH 549/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/core (#1147) Bumps [github.com/stackitcloud/stackit-sdk-go/core](https://github.com/stackitcloud/stackit-sdk-go) from 0.20.0 to 0.20.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.20.0...core/v0.20.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/core dependency-version: 0.20.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index faa3677e0..dc4c28008 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 - github.com/stackitcloud/stackit-sdk-go/core v0.20.0 + github.com/stackitcloud/stackit-sdk-go/core v0.20.1 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 diff --git a/go.sum b/go.sum index 23bd2f366..8d09c805b 100644 --- a/go.sum +++ b/go.sum @@ -561,8 +561,8 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stackitcloud/stackit-sdk-go/core v0.20.0 h1:4rrUk6uT1g4nOn5/g1uXukP07Tux/o5xbMz/f/qE1rY= -github.com/stackitcloud/stackit-sdk-go/core v0.20.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= +github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98edvw2Cd3DcnkepncP3M= +github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 h1:x7ndqw6yaOw+TmThNeAkI+eN9vK5hWgjIJlFZrYPREo= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2/go.mod h1:wbPNu6e5r/5xhzznCKbC7fEJahrAOb89gmaIm+0w2/s= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 h1:6Buzw5CuPb5ixdMHx4tKjmsQkMn0Hpj0xJ+aNDimKnk= From fb6cfcaf6e36eb5fdb8dbc164916278632c6c009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Fri, 5 Dec 2025 11:30:14 +0100 Subject: [PATCH 550/619] chore(deps): bump golangci-lint from v1 to v2 (#1148) relates to STACKITTPR-438, STACKITTPR-253 --- .github/docs/contribution-guide/cmd.go | 5 +- go.mod | 151 ++++---- go.sum | 339 +++++++++--------- golang-ci.yaml | 146 ++++---- .../cmd/affinity-groups/affinity-groups.go | 6 +- internal/cmd/affinity-groups/create/create.go | 7 +- .../cmd/affinity-groups/create/create_test.go | 5 +- internal/cmd/affinity-groups/delete/delete.go | 5 +- .../cmd/affinity-groups/delete/delete_test.go | 5 +- .../cmd/affinity-groups/describe/describe.go | 7 +- .../affinity-groups/describe/describe_test.go | 7 +- internal/cmd/affinity-groups/list/list.go | 7 +- .../cmd/affinity-groups/list/list_test.go | 5 +- .../activate_service_account.go | 5 +- internal/cmd/auth/auth.go | 6 +- .../auth/get-access-token/get_access_token.go | 5 +- internal/cmd/auth/login/login.go | 5 +- internal/cmd/auth/logout/logout.go | 5 +- internal/cmd/beta/alb/alb.go | 6 +- internal/cmd/beta/alb/create/create.go | 5 +- internal/cmd/beta/alb/create/create_test.go | 5 +- internal/cmd/beta/alb/delete/delete.go | 5 +- internal/cmd/beta/alb/describe/describe.go | 5 +- .../cmd/beta/alb/describe/describe_test.go | 5 +- internal/cmd/beta/alb/list/list.go | 5 +- internal/cmd/beta/alb/list/list_test.go | 5 +- .../alb/observability-credentials/add/add.go | 7 +- .../observability-credentials/add/add_test.go | 5 +- .../delete/delete.go | 5 +- .../delete/delete_test.go | 5 +- .../describe/describe.go | 5 +- .../describe/describe_test.go | 5 +- .../observability-credentials/list/list.go | 5 +- .../list/list_test.go | 5 +- .../observability-credentials.go | 6 +- .../update/update.go | 7 +- .../update/update_test.go | 7 +- internal/cmd/beta/alb/plans/plans.go | 5 +- internal/cmd/beta/alb/plans/plans_test.go | 5 +- internal/cmd/beta/alb/pool/pool.go | 6 +- internal/cmd/beta/alb/pool/update/update.go | 5 +- .../cmd/beta/alb/pool/update/update_test.go | 5 +- internal/cmd/beta/alb/quotas/quotas.go | 5 +- internal/cmd/beta/alb/quotas/quotas_test.go | 5 +- internal/cmd/beta/alb/template/template.go | 5 +- internal/cmd/beta/alb/update/update.go | 5 +- internal/cmd/beta/alb/update/update_test.go | 5 +- internal/cmd/beta/beta.go | 7 +- internal/cmd/beta/intake/intake.go | 6 +- .../cmd/beta/intake/runner/create/create.go | 5 +- .../beta/intake/runner/create/create_test.go | 5 +- .../cmd/beta/intake/runner/delete/delete.go | 5 +- .../beta/intake/runner/describe/describe.go | 5 +- .../intake/runner/describe/describe_test.go | 5 +- internal/cmd/beta/intake/runner/list/list.go | 5 +- .../cmd/beta/intake/runner/list/list_test.go | 5 +- internal/cmd/beta/intake/runner/runner.go | 4 +- .../cmd/beta/intake/runner/update/update.go | 5 +- .../beta/intake/runner/update/update_test.go | 5 +- internal/cmd/beta/kms/key/create/create.go | 5 +- .../cmd/beta/kms/key/create/create_test.go | 5 +- internal/cmd/beta/kms/key/delete/delete.go | 5 +- .../cmd/beta/kms/key/delete/delete_test.go | 7 +- .../cmd/beta/kms/key/describe/describe.go | 9 +- .../beta/kms/key/describe/describe_test.go | 5 +- .../cmd/beta/kms/key/importKey/importKey.go | 7 +- .../beta/kms/key/importKey/importKey_test.go | 7 +- internal/cmd/beta/kms/key/key.go | 6 +- internal/cmd/beta/kms/key/list/list.go | 5 +- internal/cmd/beta/kms/key/list/list_test.go | 5 +- internal/cmd/beta/kms/key/restore/restore.go | 5 +- .../cmd/beta/kms/key/restore/restore_test.go | 7 +- internal/cmd/beta/kms/key/rotate/rotate.go | 5 +- .../cmd/beta/kms/key/rotate/rotate_test.go | 7 +- .../cmd/beta/kms/keyring/create/create.go | 5 +- .../beta/kms/keyring/create/create_test.go | 5 +- .../cmd/beta/kms/keyring/delete/delete.go | 5 +- .../beta/kms/keyring/delete/delete_test.go | 5 +- .../cmd/beta/kms/keyring/describe/describe.go | 9 +- .../kms/keyring/describe/describe_test.go | 5 +- internal/cmd/beta/kms/keyring/keyring.go | 6 +- internal/cmd/beta/kms/keyring/list/list.go | 5 +- .../cmd/beta/kms/keyring/list/list_test.go | 5 +- internal/cmd/beta/kms/kms.go | 6 +- .../cmd/beta/kms/version/destroy/destroy.go | 5 +- .../beta/kms/version/destroy/destroy_test.go | 7 +- .../cmd/beta/kms/version/disable/disable.go | 5 +- .../beta/kms/version/disable/disable_test.go | 7 +- .../cmd/beta/kms/version/enable/enable.go | 5 +- .../beta/kms/version/enable/enable_test.go | 7 +- internal/cmd/beta/kms/version/list/list.go | 5 +- .../cmd/beta/kms/version/list/list_test.go | 5 +- .../cmd/beta/kms/version/restore/restore.go | 5 +- .../beta/kms/version/restore/restore_test.go | 7 +- internal/cmd/beta/kms/version/version.go | 6 +- .../cmd/beta/kms/wrappingkey/create/create.go | 5 +- .../kms/wrappingkey/create/create_test.go | 5 +- .../cmd/beta/kms/wrappingkey/delete/delete.go | 5 +- .../kms/wrappingkey/delete/delete_test.go | 5 +- .../beta/kms/wrappingkey/describe/describe.go | 9 +- .../kms/wrappingkey/describe/describe_test.go | 5 +- .../cmd/beta/kms/wrappingkey/list/list.go | 5 +- .../beta/kms/wrappingkey/list/list_test.go | 5 +- .../cmd/beta/kms/wrappingkey/wrappingkey.go | 6 +- .../sqlserverflex/database/create/create.go | 5 +- .../database/create/create_test.go | 5 +- .../beta/sqlserverflex/database/database.go | 6 +- .../sqlserverflex/database/delete/delete.go | 5 +- .../database/describe/describe.go | 5 +- .../database/describe/describe_test.go | 5 +- .../beta/sqlserverflex/database/list/list.go | 5 +- .../sqlserverflex/database/list/list_test.go | 5 +- .../sqlserverflex/instance/create/create.go | 5 +- .../instance/create/create_test.go | 5 +- .../sqlserverflex/instance/delete/delete.go | 5 +- .../instance/describe/describe.go | 5 +- .../instance/describe/describe_test.go | 5 +- .../beta/sqlserverflex/instance/instance.go | 6 +- .../beta/sqlserverflex/instance/list/list.go | 5 +- .../sqlserverflex/instance/list/list_test.go | 5 +- .../sqlserverflex/instance/update/update.go | 5 +- .../instance/update/update_test.go | 7 +- .../cmd/beta/sqlserverflex/options/options.go | 5 +- .../sqlserverflex/options/options_test.go | 7 +- .../cmd/beta/sqlserverflex/sqlserverflex.go | 6 +- .../beta/sqlserverflex/user/create/create.go | 5 +- .../sqlserverflex/user/create/create_test.go | 5 +- .../beta/sqlserverflex/user/delete/delete.go | 5 +- .../sqlserverflex/user/describe/describe.go | 5 +- .../user/describe/describe_test.go | 5 +- .../cmd/beta/sqlserverflex/user/list/list.go | 5 +- .../beta/sqlserverflex/user/list/list_test.go | 5 +- .../user/reset-password/reset_password.go | 5 +- .../reset-password/reset_password_test.go | 5 +- internal/cmd/beta/sqlserverflex/user/user.go | 6 +- internal/cmd/config/config.go | 7 +- internal/cmd/config/list/list.go | 5 +- internal/cmd/config/list/list_test.go | 4 +- internal/cmd/config/profile/create/create.go | 4 +- .../cmd/config/profile/create/create_test.go | 2 +- internal/cmd/config/profile/delete/delete.go | 4 +- .../cmd/config/profile/delete/delete_test.go | 2 +- internal/cmd/config/profile/export/export.go | 5 +- internal/cmd/config/profile/import/import.go | 4 +- internal/cmd/config/profile/list/list.go | 5 +- internal/cmd/config/profile/list/list_test.go | 5 +- internal/cmd/config/profile/profile.go | 7 +- internal/cmd/config/profile/set/set.go | 5 +- internal/cmd/config/profile/set/set_test.go | 2 +- internal/cmd/config/profile/unset/unset.go | 5 +- internal/cmd/config/set/set.go | 10 +- internal/cmd/config/unset/unset.go | 5 +- internal/cmd/config/unset/unset_test.go | 4 +- internal/cmd/curl/curl.go | 5 +- internal/cmd/curl/curl_test.go | 7 +- internal/cmd/dns/dns.go | 6 +- internal/cmd/dns/record-set/create/create.go | 5 +- .../cmd/dns/record-set/create/create_test.go | 5 +- internal/cmd/dns/record-set/delete/delete.go | 5 +- .../cmd/dns/record-set/describe/describe.go | 5 +- .../dns/record-set/describe/describe_test.go | 5 +- internal/cmd/dns/record-set/list/list.go | 5 +- internal/cmd/dns/record-set/list/list_test.go | 5 +- internal/cmd/dns/record-set/record_set.go | 6 +- internal/cmd/dns/record-set/update/update.go | 5 +- .../cmd/dns/record-set/update/update_test.go | 4 +- internal/cmd/dns/zone/clone/clone.go | 5 +- internal/cmd/dns/zone/clone/clone_test.go | 5 +- internal/cmd/dns/zone/create/create.go | 5 +- internal/cmd/dns/zone/create/create_test.go | 5 +- internal/cmd/dns/zone/delete/delete.go | 5 +- internal/cmd/dns/zone/describe/describe.go | 5 +- .../cmd/dns/zone/describe/describe_test.go | 5 +- internal/cmd/dns/zone/list/list.go | 5 +- internal/cmd/dns/zone/list/list_test.go | 5 +- internal/cmd/dns/zone/update/update.go | 5 +- internal/cmd/dns/zone/update/update_test.go | 5 +- internal/cmd/dns/zone/zone.go | 6 +- internal/cmd/git/flavor/flavor.go | 6 +- internal/cmd/git/flavor/list/list.go | 5 +- internal/cmd/git/flavor/list/list_test.go | 5 +- internal/cmd/git/git.go | 6 +- internal/cmd/git/instance/create/create.go | 5 +- .../cmd/git/instance/create/create_test.go | 5 +- internal/cmd/git/instance/delete/delete.go | 4 +- .../cmd/git/instance/delete/delete_test.go | 5 +- .../cmd/git/instance/describe/describe.go | 4 +- .../git/instance/describe/describe_test.go | 7 +- internal/cmd/git/instance/instance.go | 6 +- internal/cmd/git/instance/list/list.go | 4 +- internal/cmd/git/instance/list/list_test.go | 5 +- internal/cmd/image/create/create.go | 5 +- internal/cmd/image/create/create_test.go | 5 +- internal/cmd/image/delete/delete.go | 5 +- internal/cmd/image/delete/delete_test.go | 5 +- internal/cmd/image/describe/describe.go | 5 +- internal/cmd/image/describe/describe_test.go | 7 +- internal/cmd/image/image.go | 6 +- internal/cmd/image/list/list.go | 13 +- internal/cmd/image/list/list_test.go | 5 +- internal/cmd/image/update/update.go | 5 +- internal/cmd/image/update/update_test.go | 5 +- internal/cmd/key-pair/create/create.go | 7 +- internal/cmd/key-pair/create/create_test.go | 5 +- internal/cmd/key-pair/delete/delete.go | 5 +- internal/cmd/key-pair/delete/delete_test.go | 5 +- internal/cmd/key-pair/describe/describe.go | 5 +- .../cmd/key-pair/describe/describe_test.go | 5 +- internal/cmd/key-pair/key-pair.go | 6 +- internal/cmd/key-pair/list/list.go | 5 +- internal/cmd/key-pair/list/list_test.go | 5 +- internal/cmd/key-pair/update/update.go | 7 +- internal/cmd/key-pair/update/update_test.go | 7 +- internal/cmd/load-balancer/create/create.go | 5 +- internal/cmd/load-balancer/delete/delete.go | 5 +- .../cmd/load-balancer/describe/describe.go | 5 +- .../load-balancer/describe/describe_test.go | 5 +- .../generate-payload/generate_payload.go | 5 +- .../generate-payload/generate_payload_test.go | 7 +- internal/cmd/load-balancer/list/list.go | 5 +- internal/cmd/load-balancer/list/list_test.go | 5 +- internal/cmd/load-balancer/load_balancer.go | 6 +- .../observability-credentials/add/add.go | 5 +- .../observability-credentials/add/add_test.go | 5 +- .../cleanup/cleanup.go | 5 +- .../delete/delete.go | 5 +- .../describe/describe.go | 5 +- .../describe/describe_test.go | 5 +- .../observability-credentials/list/list.go | 5 +- .../list/list_test.go | 5 +- .../observability-credentials.go | 6 +- .../update/update.go | 5 +- internal/cmd/load-balancer/quota/quota.go | 5 +- .../cmd/load-balancer/quota/quota_test.go | 5 +- .../target-pool/add-target/add_target.go | 5 +- .../target-pool/add-target/add_target_test.go | 5 +- .../target-pool/describe/describe.go | 5 +- .../target-pool/describe/describe_test.go | 7 +- .../remove-target/remove_target.go | 5 +- .../remove-target/remove_target_test.go | 5 +- .../load-balancer/target-pool/target_pool.go | 6 +- internal/cmd/load-balancer/update/update.go | 5 +- .../cmd/logme/credentials/create/create.go | 5 +- .../logme/credentials/create/create_test.go | 5 +- internal/cmd/logme/credentials/credentials.go | 6 +- .../cmd/logme/credentials/delete/delete.go | 5 +- .../logme/credentials/describe/describe.go | 5 +- .../credentials/describe/describe_test.go | 5 +- internal/cmd/logme/credentials/list/list.go | 5 +- .../cmd/logme/credentials/list/list_test.go | 5 +- internal/cmd/logme/instance/create/create.go | 5 +- .../cmd/logme/instance/create/create_test.go | 5 +- internal/cmd/logme/instance/delete/delete.go | 5 +- .../cmd/logme/instance/describe/describe.go | 5 +- .../logme/instance/describe/describe_test.go | 5 +- internal/cmd/logme/instance/instance.go | 6 +- internal/cmd/logme/instance/list/list.go | 5 +- internal/cmd/logme/instance/list/list_test.go | 5 +- internal/cmd/logme/instance/update/update.go | 5 +- .../cmd/logme/instance/update/update_test.go | 5 +- internal/cmd/logme/logme.go | 6 +- internal/cmd/logme/plans/plans.go | 5 +- internal/cmd/logme/plans/plans_test.go | 5 +- .../cmd/mariadb/credentials/create/create.go | 5 +- .../mariadb/credentials/create/create_test.go | 5 +- .../cmd/mariadb/credentials/credentials.go | 6 +- .../cmd/mariadb/credentials/delete/delete.go | 5 +- .../mariadb/credentials/describe/describe.go | 5 +- .../credentials/describe/describe_test.go | 5 +- internal/cmd/mariadb/credentials/list/list.go | 5 +- .../cmd/mariadb/credentials/list/list_test.go | 5 +- .../cmd/mariadb/instance/create/create.go | 5 +- .../mariadb/instance/create/create_test.go | 5 +- .../cmd/mariadb/instance/delete/delete.go | 5 +- .../cmd/mariadb/instance/describe/describe.go | 5 +- .../instance/describe/describe_test.go | 5 +- internal/cmd/mariadb/instance/instance.go | 6 +- internal/cmd/mariadb/instance/list/list.go | 5 +- .../cmd/mariadb/instance/list/list_test.go | 5 +- .../cmd/mariadb/instance/update/update.go | 5 +- .../mariadb/instance/update/update_test.go | 5 +- internal/cmd/mariadb/mariadb.go | 6 +- internal/cmd/mariadb/plans/plans.go | 5 +- internal/cmd/mariadb/plans/plans_test.go | 5 +- internal/cmd/mongodbflex/backup/backup.go | 6 +- .../mongodbflex/backup/describe/describe.go | 5 +- .../backup/describe/describe_test.go | 5 +- internal/cmd/mongodbflex/backup/list/list.go | 5 +- .../cmd/mongodbflex/backup/list/list_test.go | 5 +- .../backup/restore-jobs/restore_jobs.go | 5 +- .../backup/restore-jobs/restore_jobs_test.go | 5 +- .../cmd/mongodbflex/backup/restore/restore.go | 5 +- .../mongodbflex/backup/schedule/schedule.go | 5 +- .../backup/schedule/schedule_test.go | 5 +- .../backup/update-schedule/update_schedule.go | 5 +- .../cmd/mongodbflex/instance/create/create.go | 5 +- .../instance/create/create_test.go | 5 +- .../cmd/mongodbflex/instance/delete/delete.go | 5 +- .../mongodbflex/instance/describe/describe.go | 5 +- .../instance/describe/describe_test.go | 5 +- internal/cmd/mongodbflex/instance/instance.go | 6 +- .../cmd/mongodbflex/instance/list/list.go | 5 +- .../mongodbflex/instance/list/list_test.go | 5 +- .../cmd/mongodbflex/instance/update/update.go | 5 +- .../instance/update/update_test.go | 7 +- internal/cmd/mongodbflex/mongodbflex.go | 6 +- internal/cmd/mongodbflex/options/options.go | 4 +- .../cmd/mongodbflex/options/options_test.go | 9 +- .../cmd/mongodbflex/user/create/create.go | 5 +- .../mongodbflex/user/create/create_test.go | 5 +- .../cmd/mongodbflex/user/delete/delete.go | 5 +- .../cmd/mongodbflex/user/describe/describe.go | 5 +- .../user/describe/describe_test.go | 5 +- internal/cmd/mongodbflex/user/list/list.go | 5 +- .../cmd/mongodbflex/user/list/list_test.go | 5 +- .../user/reset-password/reset_password.go | 5 +- .../reset-password/reset_password_test.go | 5 +- .../cmd/mongodbflex/user/update/update.go | 5 +- internal/cmd/mongodbflex/user/user.go | 6 +- internal/cmd/network-area/create/create.go | 5 +- .../cmd/network-area/create/create_test.go | 5 +- internal/cmd/network-area/delete/delete.go | 5 +- .../cmd/network-area/describe/describe.go | 5 +- .../network-area/describe/describe_test.go | 5 +- internal/cmd/network-area/list/list.go | 5 +- internal/cmd/network-area/list/list_test.go | 5 +- .../network-range/create/create.go | 5 +- .../network-range/create/create_test.go | 5 +- .../network-range/delete/delete.go | 5 +- .../network-range/delete/delete_test.go | 5 +- .../network-range/describe/describe.go | 5 +- .../network-range/describe/describe_test.go | 7 +- .../network-area/network-range/list/list.go | 5 +- .../network-range/list/list_test.go | 5 +- .../network-range/network_range.go | 6 +- internal/cmd/network-area/network_area.go | 6 +- .../cmd/network-area/region/create/create.go | 5 +- .../network-area/region/create/create_test.go | 5 +- .../cmd/network-area/region/delete/delete.go | 5 +- .../network-area/region/describe/describe.go | 5 +- .../region/describe/describe_test.go | 5 +- internal/cmd/network-area/region/list/list.go | 5 +- .../cmd/network-area/region/list/list_test.go | 5 +- internal/cmd/network-area/region/region.go | 6 +- .../cmd/network-area/region/update/update.go | 5 +- .../network-area/region/update/update_test.go | 5 +- .../cmd/network-area/route/create/create.go | 5 +- .../network-area/route/create/create_test.go | 5 +- .../cmd/network-area/route/delete/delete.go | 5 +- .../network-area/route/delete/delete_test.go | 5 +- .../network-area/route/describe/describe.go | 5 +- .../route/describe/describe_test.go | 7 +- internal/cmd/network-area/route/list/list.go | 5 +- .../cmd/network-area/route/list/list_test.go | 5 +- internal/cmd/network-area/route/routes.go | 6 +- .../cmd/network-area/route/update/update.go | 5 +- .../network-area/route/update/update_test.go | 7 +- internal/cmd/network-area/update/update.go | 5 +- .../cmd/network-area/update/update_test.go | 7 +- .../cmd/network-interface/create/create.go | 5 +- .../network-interface/create/create_test.go | 9 +- .../cmd/network-interface/delete/delete.go | 5 +- .../network-interface/delete/delete_test.go | 5 +- .../network-interface/describe/describe.go | 5 +- .../describe/describe_test.go | 7 +- internal/cmd/network-interface/list/list.go | 5 +- .../cmd/network-interface/list/list_test.go | 5 +- .../network-interface/network-interface.go | 6 +- .../cmd/network-interface/update/update.go | 5 +- .../network-interface/update/update_test.go | 11 +- internal/cmd/network/create/create.go | 12 +- internal/cmd/network/create/create_test.go | 5 +- internal/cmd/network/delete/delete.go | 5 +- internal/cmd/network/describe/describe.go | 5 +- .../cmd/network/describe/describe_test.go | 5 +- internal/cmd/network/list/list.go | 5 +- internal/cmd/network/list/list_test.go | 5 +- internal/cmd/network/network.go | 6 +- internal/cmd/network/update/update.go | 5 +- internal/cmd/network/update/update_test.go | 5 +- internal/cmd/object-storage/bucket/bucket.go | 6 +- .../object-storage/bucket/create/create.go | 5 +- .../bucket/create/create_test.go | 5 +- .../object-storage/bucket/delete/delete.go | 5 +- .../bucket/describe/describe.go | 5 +- .../bucket/describe/describe_test.go | 5 +- .../cmd/object-storage/bucket/list/list.go | 5 +- .../object-storage/bucket/list/list_test.go | 5 +- .../credentials-group/create/create.go | 5 +- .../credentials-group/create/create_test.go | 5 +- .../credentials-group/credentials_group.go | 6 +- .../credentials-group/delete/delete.go | 5 +- .../credentials-group/list/list.go | 5 +- .../credentials-group/list/list_test.go | 5 +- .../credentials/create/create.go | 5 +- .../credentials/create/create_test.go | 5 +- .../object-storage/credentials/credentials.go | 6 +- .../credentials/delete/delete.go | 5 +- .../object-storage/credentials/list/list.go | 5 +- .../credentials/list/list_test.go | 5 +- .../cmd/object-storage/disable/disable.go | 5 +- internal/cmd/object-storage/enable/enable.go | 5 +- internal/cmd/object-storage/object_storage.go | 6 +- .../credentials/create/create.go | 5 +- .../credentials/create/create_test.go | 5 +- .../observability/credentials/credentials.go | 6 +- .../credentials/delete/delete.go | 5 +- .../observability/credentials/list/list.go | 5 +- .../credentials/list/list_test.go | 5 +- .../grafana/describe/describe.go | 5 +- .../grafana/describe/describe_test.go | 7 +- internal/cmd/observability/grafana/grafana.go | 6 +- .../public-read-access/disable/disable.go | 5 +- .../public-read-access/enable/enable.go | 5 +- .../public-read-access/public_read_access.go | 7 +- .../grafana/single-sign-on/disable/disable.go | 5 +- .../grafana/single-sign-on/enable/enable.go | 5 +- .../grafana/single-sign-on/single_sign_on.go | 7 +- .../observability/instance/create/create.go | 5 +- .../instance/create/create_test.go | 5 +- .../observability/instance/delete/delete.go | 5 +- .../instance/describe/describe.go | 5 +- .../instance/describe/describe_test.go | 5 +- .../cmd/observability/instance/instance.go | 6 +- .../cmd/observability/instance/list/list.go | 5 +- .../observability/instance/list/list_test.go | 5 +- .../observability/instance/update/update.go | 5 +- internal/cmd/observability/observability.go | 6 +- internal/cmd/observability/plans/plans.go | 5 +- .../cmd/observability/plans/plans_test.go | 5 +- .../scrape-config/create/create.go | 5 +- .../scrape-config/delete/delete.go | 5 +- .../scrape-config/describe/describe.go | 5 +- .../scrape-config/describe/describe_test.go | 5 +- .../generate-payload/generate_payload.go | 5 +- .../generate-payload/generate_payload_test.go | 7 +- .../observability/scrape-config/list/list.go | 5 +- .../scrape-config/list/list_test.go | 5 +- .../scrape-config/scrape_config.go | 6 +- .../scrape-config/update/update.go | 5 +- .../opensearch/credentials/create/create.go | 5 +- .../credentials/create/create_test.go | 5 +- .../cmd/opensearch/credentials/credentials.go | 6 +- .../opensearch/credentials/delete/delete.go | 5 +- .../credentials/describe/describe.go | 5 +- .../credentials/describe/describe_test.go | 5 +- .../cmd/opensearch/credentials/list/list.go | 5 +- .../opensearch/credentials/list/list_test.go | 5 +- .../cmd/opensearch/instance/create/create.go | 5 +- .../opensearch/instance/create/create_test.go | 5 +- .../cmd/opensearch/instance/delete/delete.go | 5 +- .../opensearch/instance/describe/describe.go | 5 +- .../instance/describe/describe_test.go | 5 +- internal/cmd/opensearch/instance/instance.go | 6 +- internal/cmd/opensearch/instance/list/list.go | 5 +- .../cmd/opensearch/instance/list/list_test.go | 5 +- .../cmd/opensearch/instance/update/update.go | 5 +- .../opensearch/instance/update/update_test.go | 5 +- internal/cmd/opensearch/opensearch.go | 6 +- internal/cmd/opensearch/plans/plans.go | 5 +- internal/cmd/opensearch/plans/plans_test.go | 5 +- internal/cmd/organization/member/add/add.go | 5 +- internal/cmd/organization/member/list/list.go | 10 +- .../cmd/organization/member/list/list_test.go | 5 +- internal/cmd/organization/member/member.go | 6 +- .../cmd/organization/member/remove/remove.go | 5 +- internal/cmd/organization/organization.go | 7 +- internal/cmd/organization/role/list/list.go | 5 +- .../cmd/organization/role/list/list_test.go | 5 +- internal/cmd/organization/role/role.go | 6 +- internal/cmd/postgresflex/backup/backup.go | 6 +- .../postgresflex/backup/describe/describe.go | 5 +- .../backup/describe/describe_test.go | 5 +- internal/cmd/postgresflex/backup/list/list.go | 9 +- .../cmd/postgresflex/backup/list/list_test.go | 5 +- .../backup/update-schedule/update_schedule.go | 5 +- .../cmd/postgresflex/instance/clone/clone.go | 5 +- .../postgresflex/instance/clone/clone_test.go | 5 +- .../postgresflex/instance/create/create.go | 5 +- .../instance/create/create_test.go | 5 +- .../postgresflex/instance/delete/delete.go | 5 +- .../instance/describe/describe.go | 5 +- .../instance/describe/describe_test.go | 5 +- .../cmd/postgresflex/instance/instance.go | 6 +- .../cmd/postgresflex/instance/list/list.go | 5 +- .../postgresflex/instance/list/list_test.go | 5 +- .../postgresflex/instance/update/update.go | 5 +- .../instance/update/update_test.go | 7 +- internal/cmd/postgresflex/options/options.go | 4 +- .../cmd/postgresflex/options/options_test.go | 7 +- internal/cmd/postgresflex/postgresflex.go | 6 +- .../cmd/postgresflex/user/create/create.go | 5 +- .../postgresflex/user/create/create_test.go | 5 +- .../cmd/postgresflex/user/delete/delete.go | 5 +- .../postgresflex/user/describe/describe.go | 5 +- .../user/describe/describe_test.go | 5 +- internal/cmd/postgresflex/user/list/list.go | 5 +- .../cmd/postgresflex/user/list/list_test.go | 5 +- .../user/reset-password/reset_password.go | 5 +- .../reset-password/reset_password_test.go | 5 +- .../cmd/postgresflex/user/update/update.go | 5 +- internal/cmd/postgresflex/user/user.go | 6 +- internal/cmd/project/create/create.go | 5 +- internal/cmd/project/create/create_test.go | 5 +- internal/cmd/project/delete/delete.go | 5 +- internal/cmd/project/describe/describe.go | 7 +- .../cmd/project/describe/describe_test.go | 5 +- internal/cmd/project/list/list.go | 5 +- internal/cmd/project/list/list_test.go | 5 +- internal/cmd/project/member/add/add.go | 7 +- internal/cmd/project/member/list/list.go | 12 +- internal/cmd/project/member/list/list_test.go | 5 +- internal/cmd/project/member/member.go | 6 +- internal/cmd/project/member/remove/remove.go | 7 +- internal/cmd/project/project.go | 7 +- internal/cmd/project/role/list/list.go | 7 +- internal/cmd/project/role/list/list_test.go | 5 +- internal/cmd/project/role/role.go | 6 +- internal/cmd/project/update/update.go | 5 +- internal/cmd/public-ip/associate/associate.go | 5 +- .../cmd/public-ip/associate/associate_test.go | 5 +- internal/cmd/public-ip/create/create.go | 5 +- internal/cmd/public-ip/create/create_test.go | 5 +- internal/cmd/public-ip/delete/delete.go | 5 +- internal/cmd/public-ip/describe/describe.go | 5 +- .../cmd/public-ip/describe/describe_test.go | 5 +- .../public-ip/disassociate/disassociate.go | 5 +- .../disassociate/disassociate_test.go | 5 +- internal/cmd/public-ip/list/list.go | 5 +- internal/cmd/public-ip/list/list_test.go | 5 +- internal/cmd/public-ip/public-ip.go | 6 +- internal/cmd/public-ip/ranges/list/list.go | 5 +- .../cmd/public-ip/ranges/list/list_test.go | 5 +- internal/cmd/public-ip/ranges/ranges.go | 6 +- internal/cmd/public-ip/update/update.go | 8 +- internal/cmd/public-ip/update/update_test.go | 5 +- internal/cmd/quota/list/list.go | 5 +- internal/cmd/quota/list/list_test.go | 5 +- internal/cmd/quota/quota.go | 6 +- .../cmd/rabbitmq/credentials/create/create.go | 5 +- .../credentials/create/create_test.go | 5 +- .../cmd/rabbitmq/credentials/credentials.go | 6 +- .../cmd/rabbitmq/credentials/delete/delete.go | 5 +- .../rabbitmq/credentials/describe/describe.go | 5 +- .../credentials/describe/describe_test.go | 5 +- .../cmd/rabbitmq/credentials/list/list.go | 5 +- .../rabbitmq/credentials/list/list_test.go | 5 +- .../cmd/rabbitmq/instance/create/create.go | 5 +- .../rabbitmq/instance/create/create_test.go | 5 +- .../cmd/rabbitmq/instance/delete/delete.go | 5 +- .../rabbitmq/instance/describe/describe.go | 5 +- .../instance/describe/describe_test.go | 5 +- internal/cmd/rabbitmq/instance/instance.go | 6 +- internal/cmd/rabbitmq/instance/list/list.go | 5 +- .../cmd/rabbitmq/instance/list/list_test.go | 5 +- .../cmd/rabbitmq/instance/update/update.go | 5 +- .../rabbitmq/instance/update/update_test.go | 5 +- internal/cmd/rabbitmq/plans/plans.go | 5 +- internal/cmd/rabbitmq/plans/plans_test.go | 5 +- internal/cmd/rabbitmq/rabbitmq.go | 6 +- .../cmd/redis/credentials/create/create.go | 5 +- .../redis/credentials/create/create_test.go | 5 +- internal/cmd/redis/credentials/credentials.go | 6 +- .../cmd/redis/credentials/delete/delete.go | 5 +- .../redis/credentials/describe/describe.go | 5 +- .../credentials/describe/describe_test.go | 5 +- internal/cmd/redis/credentials/list/list.go | 5 +- .../cmd/redis/credentials/list/list_test.go | 5 +- internal/cmd/redis/instance/create/create.go | 5 +- .../cmd/redis/instance/create/create_test.go | 5 +- internal/cmd/redis/instance/delete/delete.go | 5 +- .../cmd/redis/instance/describe/describe.go | 5 +- .../redis/instance/describe/describe_test.go | 5 +- internal/cmd/redis/instance/instance.go | 6 +- internal/cmd/redis/instance/list/list.go | 5 +- internal/cmd/redis/instance/list/list_test.go | 5 +- internal/cmd/redis/instance/update/update.go | 5 +- .../cmd/redis/instance/update/update_test.go | 5 +- internal/cmd/redis/plans/plans.go | 5 +- internal/cmd/redis/plans/plans_test.go | 5 +- internal/cmd/redis/redis.go | 6 +- internal/cmd/root.go | 7 +- .../secrets-manager/instance/create/create.go | 5 +- .../instance/create/create_test.go | 5 +- .../secrets-manager/instance/delete/delete.go | 5 +- .../instance/describe/describe.go | 5 +- .../instance/describe/describe_test.go | 5 +- .../cmd/secrets-manager/instance/instance.go | 6 +- .../cmd/secrets-manager/instance/list/list.go | 5 +- .../instance/list/list_test.go | 5 +- .../secrets-manager/instance/update/update.go | 5 +- .../instance/update/update_test.go | 5 +- .../cmd/secrets-manager/secrets_manager.go | 6 +- .../cmd/secrets-manager/user/create/create.go | 5 +- .../user/create/create_test.go | 5 +- .../cmd/secrets-manager/user/delete/delete.go | 5 +- .../secrets-manager/user/describe/describe.go | 5 +- .../user/describe/describe_test.go | 5 +- .../cmd/secrets-manager/user/list/list.go | 5 +- .../secrets-manager/user/list/list_test.go | 5 +- .../cmd/secrets-manager/user/update/update.go | 5 +- .../user/update/update_test.go | 5 +- internal/cmd/secrets-manager/user/user.go | 6 +- internal/cmd/security-group/create/create.go | 5 +- .../cmd/security-group/create/create_test.go | 5 +- internal/cmd/security-group/delete/delete.go | 5 +- .../cmd/security-group/delete/delete_test.go | 5 +- .../cmd/security-group/describe/describe.go | 5 +- .../security-group/describe/describe_test.go | 7 +- internal/cmd/security-group/list/list.go | 5 +- internal/cmd/security-group/list/list_test.go | 5 +- .../cmd/security-group/rule/create/create.go | 5 +- .../security-group/rule/create/create_test.go | 5 +- .../cmd/security-group/rule/delete/delete.go | 5 +- .../security-group/rule/delete/delete_test.go | 5 +- .../security-group/rule/describe/describe.go | 5 +- .../rule/describe/describe_test.go | 5 +- internal/cmd/security-group/rule/list/list.go | 5 +- .../cmd/security-group/rule/list/list_test.go | 5 +- .../rule/security_group_rule.go | 6 +- internal/cmd/security-group/security_group.go | 6 +- internal/cmd/security-group/update/update.go | 5 +- .../cmd/security-group/update/update_test.go | 5 +- internal/cmd/server/backup/backup.go | 6 +- internal/cmd/server/backup/create/create.go | 5 +- .../cmd/server/backup/create/create_test.go | 5 +- internal/cmd/server/backup/delete/delete.go | 5 +- .../cmd/server/backup/describe/describe.go | 5 +- .../server/backup/describe/describe_test.go | 5 +- internal/cmd/server/backup/disable/disable.go | 5 +- internal/cmd/server/backup/enable/enable.go | 5 +- internal/cmd/server/backup/list/list.go | 5 +- internal/cmd/server/backup/list/list_test.go | 5 +- internal/cmd/server/backup/restore/restore.go | 5 +- .../server/backup/schedule/create/create.go | 5 +- .../backup/schedule/create/create_test.go | 5 +- .../server/backup/schedule/delete/delete.go | 5 +- .../backup/schedule/describe/describe.go | 5 +- .../backup/schedule/describe/describe_test.go | 5 +- .../cmd/server/backup/schedule/list/list.go | 5 +- .../server/backup/schedule/list/list_test.go | 5 +- .../cmd/server/backup/schedule/schedule.go | 6 +- .../server/backup/schedule/update/update.go | 5 +- .../backup/schedule/update/update_test.go | 7 +- .../backup/volume-backup/delete/delete.go | 5 +- .../backup/volume-backup/restore/restore.go | 5 +- .../backup/volume-backup/volumebackup.go | 6 +- internal/cmd/server/command/command.go | 6 +- internal/cmd/server/command/create/create.go | 5 +- .../cmd/server/command/create/create_test.go | 5 +- .../cmd/server/command/describe/describe.go | 5 +- .../server/command/describe/describe_test.go | 5 +- internal/cmd/server/command/list/list.go | 5 +- internal/cmd/server/command/list/list_test.go | 5 +- .../command/template/describe/describe.go | 5 +- .../template/describe/describe_test.go | 5 +- .../cmd/server/command/template/list/list.go | 5 +- .../server/command/template/list/list_test.go | 5 +- .../cmd/server/command/template/template.go | 6 +- internal/cmd/server/console/console.go | 5 +- internal/cmd/server/console/console_test.go | 5 +- internal/cmd/server/create/create.go | 5 +- internal/cmd/server/create/create_test.go | 5 +- internal/cmd/server/deallocate/deallocate.go | 5 +- internal/cmd/server/delete/delete.go | 5 +- internal/cmd/server/describe/describe.go | 5 +- internal/cmd/server/describe/describe_test.go | 5 +- internal/cmd/server/list/list.go | 5 +- internal/cmd/server/list/list_test.go | 5 +- internal/cmd/server/log/log.go | 5 +- internal/cmd/server/log/log_test.go | 5 +- .../server/machine-type/describe/describe.go | 5 +- .../machine-type/describe/describe_test.go | 5 +- internal/cmd/server/machine-type/list/list.go | 5 +- .../cmd/server/machine-type/list/list_test.go | 5 +- .../cmd/server/machine-type/machine-type.go | 6 +- .../server/network-interface/attach/attach.go | 8 +- .../server/network-interface/detach/detach.go | 8 +- .../cmd/server/network-interface/list/list.go | 5 +- .../network-interface/list/list_test.go | 5 +- .../network-interface/network-interface.go | 6 +- .../cmd/server/os-update/create/create.go | 5 +- .../server/os-update/create/create_test.go | 5 +- .../cmd/server/os-update/describe/describe.go | 5 +- .../os-update/describe/describe_test.go | 5 +- .../cmd/server/os-update/disable/disable.go | 5 +- .../cmd/server/os-update/enable/enable.go | 5 +- internal/cmd/server/os-update/list/list.go | 5 +- .../cmd/server/os-update/list/list_test.go | 5 +- internal/cmd/server/os-update/os-update.go | 6 +- .../os-update/schedule/create/create.go | 5 +- .../os-update/schedule/create/create_test.go | 5 +- .../os-update/schedule/delete/delete.go | 5 +- .../os-update/schedule/describe/describe.go | 5 +- .../schedule/describe/describe_test.go | 5 +- .../server/os-update/schedule/list/list.go | 5 +- .../os-update/schedule/list/list_test.go | 5 +- .../cmd/server/os-update/schedule/schedule.go | 6 +- .../os-update/schedule/update/update.go | 5 +- .../os-update/schedule/update/update_test.go | 7 +- .../cmd/server/public-ip/attach/attach.go | 5 +- .../server/public-ip/attach/attach_test.go | 5 +- .../cmd/server/public-ip/detach/detach.go | 5 +- .../server/public-ip/detach/detach_test.go | 5 +- internal/cmd/server/public-ip/public_ip.go | 6 +- internal/cmd/server/reboot/reboot.go | 5 +- internal/cmd/server/rescue/rescue.go | 5 +- internal/cmd/server/resize/resize.go | 5 +- internal/cmd/server/server.go | 6 +- .../server/service-account/attach/attach.go | 5 +- .../service-account/attach/attach_test.go | 7 +- .../server/service-account/detach/detach.go | 5 +- .../service-account/detach/detach_test.go | 7 +- .../cmd/server/service-account/list/list.go | 5 +- .../server/service-account/list/list_test.go | 5 +- .../server/service-account/service-account.go | 6 +- internal/cmd/server/start/start.go | 5 +- internal/cmd/server/stop/stop.go | 5 +- internal/cmd/server/unrescue/unrescue.go | 5 +- internal/cmd/server/update/update.go | 5 +- internal/cmd/server/update/update_test.go | 7 +- internal/cmd/server/volume/attach/attach.go | 5 +- .../cmd/server/volume/attach/attach_test.go | 7 +- .../cmd/server/volume/describe/describe.go | 5 +- .../server/volume/describe/describe_test.go | 7 +- internal/cmd/server/volume/detach/detach.go | 5 +- .../cmd/server/volume/detach/detach_test.go | 5 +- internal/cmd/server/volume/list/list.go | 5 +- internal/cmd/server/volume/list/list_test.go | 5 +- internal/cmd/server/volume/update/update.go | 5 +- .../cmd/server/volume/update/update_test.go | 7 +- internal/cmd/server/volume/volume.go | 6 +- internal/cmd/service-account/create/create.go | 5 +- .../cmd/service-account/create/create_test.go | 5 +- internal/cmd/service-account/delete/delete.go | 5 +- .../cmd/service-account/get-jwks/get_jwks.go | 5 +- .../service-account/get-jwks/get_jwks_test.go | 7 +- .../cmd/service-account/key/create/create.go | 5 +- .../cmd/service-account/key/delete/delete.go | 5 +- .../service-account/key/describe/describe.go | 5 +- .../key/describe/describe_test.go | 5 +- internal/cmd/service-account/key/key.go | 6 +- internal/cmd/service-account/key/list/list.go | 5 +- .../cmd/service-account/key/list/list_test.go | 5 +- .../cmd/service-account/key/update/update.go | 5 +- internal/cmd/service-account/list/list.go | 5 +- .../cmd/service-account/list/list_test.go | 5 +- .../cmd/service-account/service_account.go | 6 +- .../service-account/token/create/create.go | 5 +- .../token/create/create_test.go | 5 +- .../cmd/service-account/token/list/list.go | 5 +- .../service-account/token/list/list_test.go | 5 +- .../service-account/token/revoke/revoke.go | 5 +- internal/cmd/service-account/token/token.go | 6 +- internal/cmd/ske/cluster/cluster.go | 6 +- internal/cmd/ske/cluster/create/create.go | 5 +- .../cmd/ske/cluster/create/create_test.go | 5 +- internal/cmd/ske/cluster/delete/delete.go | 5 +- internal/cmd/ske/cluster/describe/describe.go | 5 +- .../cmd/ske/cluster/describe/describe_test.go | 5 +- .../generate-payload/generate_payload.go | 5 +- .../generate-payload/generate_payload_test.go | 5 +- .../cmd/ske/cluster/hibernate/hibernate.go | 5 +- internal/cmd/ske/cluster/list/list.go | 5 +- internal/cmd/ske/cluster/list/list_test.go | 5 +- .../ske/cluster/maintenance/maintenance.go | 5 +- .../cmd/ske/cluster/reconcile/reconcile.go | 5 +- internal/cmd/ske/cluster/update/update.go | 5 +- .../cmd/ske/cluster/update/update_test.go | 5 +- internal/cmd/ske/cluster/wakeup/wakeup.go | 5 +- .../complete-rotation/complete_rotation.go | 5 +- internal/cmd/ske/credentials/credentials.go | 6 +- .../start-rotation/start_rotation.go | 5 +- internal/cmd/ske/describe/describe.go | 5 +- internal/cmd/ske/describe/describe_test.go | 5 +- internal/cmd/ske/disable/disable.go | 5 +- internal/cmd/ske/enable/enable.go | 5 +- internal/cmd/ske/kubeconfig/create/create.go | 5 +- .../cmd/ske/kubeconfig/create/create_test.go | 5 +- internal/cmd/ske/kubeconfig/kubeconfig.go | 6 +- internal/cmd/ske/kubeconfig/login/login.go | 5 +- internal/cmd/ske/options/options.go | 17 +- internal/cmd/ske/options/options_test.go | 7 +- internal/cmd/ske/ske.go | 6 +- internal/cmd/volume/backup/backup.go | 6 +- internal/cmd/volume/backup/create/create.go | 11 +- .../cmd/volume/backup/create/create_test.go | 5 +- internal/cmd/volume/backup/delete/delete.go | 5 +- .../cmd/volume/backup/describe/describe.go | 5 +- .../volume/backup/describe/describe_test.go | 5 +- internal/cmd/volume/backup/list/list.go | 5 +- internal/cmd/volume/backup/list/list_test.go | 5 +- internal/cmd/volume/backup/restore/restore.go | 5 +- internal/cmd/volume/backup/update/update.go | 5 +- internal/cmd/volume/create/create.go | 5 +- internal/cmd/volume/create/create_test.go | 5 +- internal/cmd/volume/delete/delete.go | 5 +- internal/cmd/volume/describe/describe.go | 5 +- internal/cmd/volume/describe/describe_test.go | 5 +- internal/cmd/volume/list/list.go | 5 +- internal/cmd/volume/list/list_test.go | 5 +- .../performance-class/describe/describe.go | 5 +- .../describe/describe_test.go | 5 +- .../cmd/volume/performance-class/list/list.go | 5 +- .../performance-class/list/list_test.go | 5 +- .../performance-class/performance_class.go | 6 +- internal/cmd/volume/resize/resize.go | 5 +- internal/cmd/volume/resize/resize_test.go | 5 +- internal/cmd/volume/snapshot/create/create.go | 5 +- internal/cmd/volume/snapshot/delete/delete.go | 5 +- .../cmd/volume/snapshot/describe/describe.go | 5 +- .../volume/snapshot/describe/describe_test.go | 5 +- internal/cmd/volume/snapshot/list/list.go | 5 +- .../cmd/volume/snapshot/list/list_test.go | 5 +- internal/cmd/volume/snapshot/snapshot.go | 6 +- internal/cmd/volume/snapshot/update/update.go | 5 +- internal/cmd/volume/update/update.go | 5 +- internal/cmd/volume/update/update_test.go | 7 +- internal/cmd/volume/volume.go | 6 +- internal/pkg/projectname/project_name.go | 12 +- internal/pkg/testutils/testutils.go | 9 +- .../{cmd/params => pkg/types}/cmd_params.go | 2 +- 822 files changed, 2869 insertions(+), 2158 deletions(-) rename internal/{cmd/params => pkg/types}/cmd_params.go (90%) diff --git a/.github/docs/contribution-guide/cmd.go b/.github/docs/contribution-guide/cmd.go index 1373ebbb0..d9184fb00 100644 --- a/.github/docs/contribution-guide/cmd.go +++ b/.github/docs/contribution-guide/cmd.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { } // "bar" command constructor -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "bar", Short: "Short description of the command (is shown in the help of parent command)", diff --git a/go.mod b/go.mod index dc4c28008..bae42f51f 100644 --- a/go.mod +++ b/go.mod @@ -53,40 +53,53 @@ require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect al.essio.dev/pkg/shellescape v1.5.1 // indirect - github.com/4meepo/tagalign v1.4.2 // indirect - github.com/Abirdcfly/dupword v0.1.3 // indirect - github.com/Antonboom/errname v1.1.0 // indirect - github.com/Antonboom/nilnil v1.1.0 // indirect - github.com/Antonboom/testifylint v1.6.1 // indirect + codeberg.org/chavacava/garif v0.2.0 // indirect + dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect + dev.gaijin.team/go/golib v0.6.0 // indirect + github.com/4meepo/tagalign v1.4.3 // indirect + github.com/Abirdcfly/dupword v0.1.7 // indirect + github.com/AdminBenni/iota-mixing v1.0.0 // indirect + github.com/AlwxSin/noinlineerr v1.0.5 // indirect + github.com/Antonboom/errname v1.1.1 // indirect + github.com/Antonboom/nilnil v1.1.1 // indirect + github.com/Antonboom/testifylint v1.6.4 // indirect github.com/BurntSushi/toml v1.5.0 // indirect - github.com/Crocmagnon/fatcontext v0.7.1 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect - github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/Djarvur/go-err113 v0.1.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/MirrexOne/unqueryvet v1.2.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect + github.com/alecthomas/chroma/v2 v2.20.0 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect - github.com/alexkohler/nakedret/v2 v2.0.5 // indirect + github.com/alexkohler/nakedret/v2 v2.0.6 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/alingse/nilnesserr v0.2.0 // indirect - github.com/ashanbrown/forbidigo v1.6.0 // indirect - github.com/ashanbrown/makezero v1.2.0 // indirect + github.com/ashanbrown/forbidigo/v2 v2.3.0 // indirect + github.com/ashanbrown/makezero/v2 v2.1.0 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect github.com/bombsimon/wsl/v4 v4.7.0 // indirect + github.com/bombsimon/wsl/v5 v5.3.0 // indirect github.com/breml/bidichk v0.3.3 // indirect github.com/breml/errchkjson v0.4.1 // indirect github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect - github.com/catenacyber/perfsprint v0.9.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/catenacyber/perfsprint v0.10.0 // indirect + github.com/ccojocar/zxcvbn-go v1.0.4 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/charithe/durationcheck v0.0.10 // indirect - github.com/chavacava/garif v0.1.0 // indirect + github.com/charithe/durationcheck v0.0.11 // indirect + github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect + github.com/charmbracelet/lipgloss v1.1.0 // indirect + github.com/charmbracelet/x/ansi v0.8.0 // indirect + github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect github.com/ckaznocha/intrange v0.3.1 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect - github.com/daixiang0/gci v0.13.6 // indirect + github.com/daixiang0/gci v0.13.7 // indirect + github.com/dave/dst v0.27.3 // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect github.com/ettle/strcase v0.2.0 // indirect @@ -94,8 +107,8 @@ require ( github.com/firefart/nonamedreturns v1.0.6 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.15 // indirect - github.com/go-critic/go-critic v0.13.0 // indirect + github.com/ghostiam/protogetter v0.3.17 // indirect + github.com/go-critic/go-critic v0.14.2 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.2.0 // indirect @@ -106,64 +119,71 @@ require ( github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/flock v0.12.1 // indirect - github.com/golang/protobuf v1.5.4 // indirect + github.com/godoc-lint/godoc-lint v0.10.1 // indirect + github.com/gofrs/flock v0.13.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect - github.com/golangci/go-printf-func-name v0.1.0 // indirect + github.com/golangci/go-printf-func-name v0.1.1 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golangci-lint v1.64.8 // indirect - github.com/golangci/misspell v0.6.0 // indirect - github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/golangci-lint/v2 v2.6.2 // indirect + github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 // indirect + github.com/golangci/misspell v0.7.0 // indirect + github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect - github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect - github.com/gordonklaus/ineffassign v0.1.0 // indirect + github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect + github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect + github.com/gordonklaus/ineffassign v0.2.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.5.0 // indirect github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/gostaticanalysis/nilerr v0.1.2 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/jgautheron/goconst v1.7.1 // indirect + github.com/jgautheron/goconst v1.8.2 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jjti/go-spancheck v0.6.4 // indirect + github.com/jjti/go-spancheck v0.6.5 // indirect github.com/julz/importas v0.2.0 // indirect - github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect + github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect github.com/kisielk/errcheck v1.9.0 // indirect github.com/kkHAIKE/contextcheck v1.1.6 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.14 // indirect + github.com/kulti/thelper v0.7.1 // indirect + github.com/kunwardeep/paralleltest v1.0.15 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.3 // indirect - github.com/ldez/gomoddirectives v0.6.1 // indirect - github.com/ldez/grignotin v0.9.0 // indirect - github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.3 // indirect + github.com/ldez/exptostd v0.4.5 // indirect + github.com/ldez/gomoddirectives v0.7.1 // indirect + github.com/ldez/grignotin v0.10.1 // indirect + github.com/ldez/tagliatelle v0.7.2 // indirect + github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/macabu/inamedparam v0.2.0 // indirect - github.com/maratori/testableexamples v1.0.0 // indirect - github.com/maratori/testpackage v1.1.1 // indirect + github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect + github.com/manuelarte/funcorder v0.5.0 // indirect + github.com/maratori/testableexamples v1.0.1 // indirect + github.com/maratori/testpackage v1.1.2 // indirect github.com/matoous/godox v1.1.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mgechev/revive v1.9.0 // indirect + github.com/mgechev/revive v1.12.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.19.1 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/nunnatsa/ginkgolinter v0.21.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polyfloyd/go-errorlint v1.8.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.4.4 // indirect - github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect + github.com/quasilyte/go-ruleguard v0.4.5 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.23 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect @@ -172,21 +192,19 @@ require ( github.com/ryancurrah/gomodguard v1.4.1 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect - github.com/securego/gosec/v2 v2.22.3 // indirect + github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect + github.com/securego/gosec/v2 v2.22.10 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sivchari/tenv v1.12.1 // indirect - github.com/sonatard/noctx v0.1.0 // indirect + github.com/sonatard/noctx v0.4.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/testify v1.11.1 // indirect - github.com/tdakkota/asciicheck v0.4.1 // indirect - github.com/tetafro/godot v1.5.1 // indirect + github.com/tetafro/godot v1.5.4 // indirect github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect github.com/timonwong/loggercheck v0.11.0 // indirect github.com/tomarrell/wrapcheck/v2 v2.11.0 // indirect @@ -194,31 +212,31 @@ require ( github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect github.com/uudashr/gocognit v1.2.0 // indirect - github.com/uudashr/iface v1.3.1 // indirect + github.com/uudashr/iface v1.4.1 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xen0n/gosmopolitan v1.3.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect - go-simpler.org/musttag v0.13.1 // indirect - go-simpler.org/sloglint v0.11.0 // indirect - go.uber.org/atomic v1.9.0 // indirect + go-simpler.org/musttag v0.14.0 // indirect + go-simpler.org/sloglint v0.11.1 // indirect + go.augendre.info/arangolint v0.3.1 // indirect + go.augendre.info/fatcontext v0.9.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.uber.org/zap v1.24.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect + golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/sync v0.18.0 // indirect golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect golang.org/x/tools v0.39.0 // indirect - golang.org/x/tools/go/expect v0.1.1-deprecated // indirect - golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect - google.golang.org/protobuf v1.36.6 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + google.golang.org/protobuf v1.36.8 // indirect honnef.co/go/tools v0.6.1 // indirect - mvdan.cc/gofumpt v0.8.0 // indirect - mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect + mvdan.cc/gofumpt v0.9.2 // indirect + mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect ) @@ -228,7 +246,7 @@ require ( github.com/danieljoos/wincred v1.2.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -252,7 +270,6 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2 github.com/subosito/gotenv v1.6.0 // indirect - go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.38.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.2 // indirect @@ -263,6 +280,6 @@ require ( ) tool ( - github.com/golangci/golangci-lint/cmd/golangci-lint + github.com/golangci/golangci-lint/v2/cmd/golangci-lint golang.org/x/tools/cmd/goimports ) diff --git a/go.sum b/go.sum index 8d09c805b..a4e5c9be6 100644 --- a/go.sum +++ b/go.sum @@ -36,56 +36,68 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= +codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= +dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= +dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= -github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= -github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= -github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= -github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= -github.com/Antonboom/nilnil v1.1.0/go.mod h1:b7sAlogQjFa1wV8jUW3o4PMzDVFLbTux+xnQdvzdcIE= -github.com/Antonboom/testifylint v1.6.1 h1:6ZSytkFWatT8mwZlmRCHkWz1gPi+q6UBSbieji2Gj/o= -github.com/Antonboom/testifylint v1.6.1/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= +github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= +github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c= +github.com/Abirdcfly/dupword v0.1.7 h1:2j8sInznrje4I0CMisSL6ipEBkeJUJAmK1/lfoNGWrQ= +github.com/Abirdcfly/dupword v0.1.7/go.mod h1:K0DkBeOebJ4VyOICFdppB23Q0YMOgVafM0zYW0n9lF4= +github.com/AdminBenni/iota-mixing v1.0.0 h1:Os6lpjG2dp/AE5fYBPAA1zfa2qMdCAWwPMCgpwKq7wo= +github.com/AdminBenni/iota-mixing v1.0.0/go.mod h1:i4+tpAaB+qMVIV9OK3m4/DAynOd5bQFaOu+2AhtBCNY= +github.com/AlwxSin/noinlineerr v1.0.5 h1:RUjt63wk1AYWTXtVXbSqemlbVTb23JOSRiNsshj7TbY= +github.com/AlwxSin/noinlineerr v1.0.5/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc= +github.com/Antonboom/errname v1.1.1 h1:bllB7mlIbTVzO9jmSWVWLjxTEbGBVQ1Ff/ClQgtPw9Q= +github.com/Antonboom/errname v1.1.1/go.mod h1:gjhe24xoxXp0ScLtHzjiXp0Exi1RFLKJb0bVBtWKCWQ= +github.com/Antonboom/nilnil v1.1.1 h1:9Mdr6BYd8WHCDngQnNVV0b554xyisFioEKi30sksufQ= +github.com/Antonboom/nilnil v1.1.1/go.mod h1:yCyAmSw3doopbOWhJlVci+HuyNRuHJKIv6V2oYQa8II= +github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ= +github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= -github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= -github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= -github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g= +github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/MirrexOne/unqueryvet v1.2.1 h1:M+zdXMq84g+E1YOLa7g7ExN3dWfZQrdDSTCM7gC+m/A= +github.com/MirrexOne/unqueryvet v1.2.1/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= +github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= +github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= -github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= +github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= +github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= +github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= -github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/ashanbrown/forbidigo/v2 v2.3.0 h1:OZZDOchCgsX5gvToVtEBoV2UWbFfI6RKQTir2UZzSxo= +github.com/ashanbrown/forbidigo/v2 v2.3.0/go.mod h1:5p6VmsG5/1xx3E785W9fouMxIOkvY2rRV9nMdWadd6c= +github.com/ashanbrown/makezero/v2 v2.1.0 h1:snuKYMbqosNokUKm+R6/+vOPs8yVAi46La7Ck6QYSaE= +github.com/ashanbrown/makezero/v2 v2.1.0/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -96,6 +108,8 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= +github.com/bombsimon/wsl/v5 v5.3.0 h1:nZWREJFL6U3vgW/B1lfDOigl+tEF6qgs6dGGbFeR0UM= +github.com/bombsimon/wsl/v5 v5.3.0/go.mod h1:Gp8lD04z27wm3FANIUPZycXp+8huVsn0oxc+n4qfV9I= github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= @@ -104,19 +118,27 @@ github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= -github.com/catenacyber/perfsprint v0.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= -github.com/catenacyber/perfsprint v0.9.1/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= -github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= -github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/catenacyber/perfsprint v0.10.0 h1:AZj1mYyxbxLRqmnYOeguZXEQwWOgQGm2wzLI5d7Hl/0= +github.com/catenacyber/perfsprint v0.10.0/go.mod h1:DJTGsi/Zufpuus6XPGJyKOTMELe347o6akPvWG9Zcsc= +github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= +github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= -github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= -github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= +github.com/charithe/durationcheck v0.0.11 h1:g1/EX1eIiKS57NTWsYtHDZ/APfeXKhye1DidBcABctk= +github.com/charithe/durationcheck v0.0.11/go.mod h1:x5iZaixRNl8ctbM+3B2RrPG5t856TxRyVQEnbIEM2X4= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -128,10 +150,14 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/daixiang0/gci v0.13.6 h1:RKuEOSkGpSadkGbvZ6hJ4ddItT3cVZ9Vn9Rybk6xjl8= -github.com/daixiang0/gci v0.13.6/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/daixiang0/gci v0.13.7 h1:+0bG5eK9vlI08J+J/NWGbWPTNiXPG4WhNLJOkSxWITQ= +github.com/daixiang0/gci v0.13.7/go.mod h1:812WVN6JLFY9S6Tv76twqmNqevN0pa3SX3nih0brVzQ= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= +github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= +github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= +github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= +github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -162,10 +188,10 @@ github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sa github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.15 h1:1KF5sXel0HE48zh1/vn0Loiw25A9ApyseLzQuif1mLY= -github.com/ghostiam/protogetter v0.3.15/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= -github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= -github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= +github.com/ghostiam/protogetter v0.3.17 h1:sjGPErP9o7i2Ym+z3LsQzBdLCNaqbYy2iJQPxGXg04Q= +github.com/ghostiam/protogetter v0.3.17/go.mod h1:AivIX1eKA/TcUmzZdzbl+Tb8tjIe8FcyG6JFyemQAH4= +github.com/go-critic/go-critic v0.14.2 h1:PMvP5f+LdR8p6B29npvChUXbD1vrNlKDf60NJtgMBOo= +github.com/go-critic/go-critic v0.14.2/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -175,8 +201,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= @@ -217,8 +243,10 @@ github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE= github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= -github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/godoc-lint/godoc-lint v0.10.1 h1:ZPUVzlDtJfA+P688JfPJPkI/SuzcBr/753yGIk5bOPA= +github.com/godoc-lint/godoc-lint v0.10.1/go.mod h1:KleLcHu/CGSvkjUH2RvZyoK1MBC7pDQg4NxMYLcBBsw= +github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= +github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -251,24 +279,30 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0= +github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E= -github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= -github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= +github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarogrvjO9AfiW3B4U= +github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint v1.64.8 h1:y5TdeVidMtBGG32zgSC7ZXTFNHrsJkDnpO4ItB3Am+I= -github.com/golangci/golangci-lint v1.64.8/go.mod h1:5cEsUQBSr6zi8XI8OjmcY2Xmliqc4iYL7YoPrL+zLJ4= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/golangci-lint/v2 v2.6.2 h1:jkMSVv36JmyTENcEertckvimvjPcD5qxNM7W7qhECvI= +github.com/golangci/golangci-lint/v2 v2.6.2/go.mod h1:fSIMDiBt9kzdpnvvV7GO6iWzyv5uaeZ+iPor+2uRczE= +github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= +github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= +github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= +github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= @@ -283,7 +317,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -297,8 +330,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= +github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -306,18 +339,17 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= -github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk9Nu0TySs= +github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= github.com/gostaticanalysis/comment v1.5.0 h1:X82FLl+TswsUMpMh17srGRuKaaXprTaytmEpgnKIDu8= github.com/gostaticanalysis/comment v1.5.0/go.mod h1:V6eb3gpCv9GNVqb6amXzEUX3jXLVK/AdA+IrAMSqvEc= github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk= github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/nilerr v0.1.2 h1:S6nk8a9N8g062nsx63kUkF6AzbHGw7zzyHMcpu52xQU= +github.com/gostaticanalysis/nilerr v0.1.2/go.mod h1:A19UHhoY3y8ahoL7YKz6sdjDtduwTSI4CsymaC2htPA= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= @@ -341,12 +373,12 @@ github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaB github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= github.com/jedib0t/go-pretty/v6 v6.7.5 h1:9dJSWTJnsXJVVAbvxIFxeHf/JxoJd7GUl5o3UzhtuiM= github.com/jedib0t/go-pretty/v6 v6.7.5/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= -github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= -github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= +github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= +github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -361,8 +393,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= -github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI= -github.com/karamaru-alpha/copyloopvar v1.2.1/go.mod h1:nFmMlFNlClC2BPvNaHMdkirmTJxVCY0lhxBtlfOypMM= +github.com/karamaru-alpha/copyloopvar v1.2.2 h1:yfNQvP9YaGQR7VaWLYcfZUlRP2eo2vhExWKxD/fP6q0= +github.com/karamaru-alpha/copyloopvar v1.2.2/go.mod h1:oY4rGZqZ879JkJMtX3RRkcXRkmUvH0x35ykgaKgsgJY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M= github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= @@ -379,34 +411,40 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= -github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= +github.com/kulti/thelper v0.7.1 h1:fI8QITAoFVLx+y+vSyuLBP+rcVIB8jKooNSCT2EiI98= +github.com/kulti/thelper v0.7.1/go.mod h1:NsMjfQEy6sd+9Kfw8kCP61W1I0nerGSYSFnGaxQkcbs= +github.com/kunwardeep/paralleltest v1.0.15 h1:ZMk4Qt306tHIgKISHWFJAO1IDQJLc6uDyJMLyncOb6w= +github.com/kunwardeep/paralleltest v1.0.15/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.3 h1:Ag1aGiq2epGePuRJhez2mzOpZ8sI9Gimcb4Sb3+pk9Y= -github.com/ldez/exptostd v0.4.3/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= -github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= -github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= -github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= -github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= -github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= -github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k= -github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/exptostd v0.4.5 h1:kv2ZGUVI6VwRfp/+bcQ6Nbx0ghFWcGIKInkG/oFn1aQ= +github.com/ldez/exptostd v0.4.5/go.mod h1:QRjHRMXJrCTIm9WxVNH6VW7oN7KrGSht69bIRwvdFsM= +github.com/ldez/gomoddirectives v0.7.1 h1:FaULkvUIG36hj6chpwa+FdCNGZBsD7/fO+p7CCsM6pE= +github.com/ldez/gomoddirectives v0.7.1/go.mod h1:auDNtakWJR1rC+YX7ar+HmveqXATBAyEK1KYpsIRW/8= +github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o= +github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas= +github.com/ldez/tagliatelle v0.7.2 h1:KuOlL70/fu9paxuxbeqlicJnCspCRjH0x8FW+NfgYUk= +github.com/ldez/tagliatelle v0.7.2/go.mod h1:PtGgm163ZplJfZMZ2sf5nhUT170rSuPgBimoyYtdaSI= +github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= +github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= -github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= -github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0/go.mod h1:z8dFSyXqp+fC6NLDSljRJeNQJJDWnY7RoWFzV3PC6UM= +github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= +github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= +github.com/maratori/testableexamples v1.0.1 h1:HfOQXs+XgfeRBJ+Wz0XfH+FHnoY9TVqL6Fcevpzy4q8= +github.com/maratori/testableexamples v1.0.1/go.mod h1:XE2F/nQs7B9N08JgyRmdGjYVGqxWwClLPCGSQhXQSrQ= +github.com/maratori/testpackage v1.1.2 h1:ffDSh+AgqluCLMXhM19f/cpvQAKygKAJXFl9aUjmbqs= +github.com/maratori/testpackage v1.1.2/go.mod h1:8F24GdVDFW5Ew43Et02jamrVMNXLUNaOynhDssITGfc= github.com/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4= github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= @@ -415,13 +453,12 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgechev/revive v1.9.0 h1:8LaA62XIKrb8lM6VsBSQ92slt/o92z5+hTw3CmrvSrM= -github.com/mgechev/revive v1.9.0/go.mod h1:LAPq3+MgOf7GcL5PlWIkHb0PT7XH4NuC2LdWymhb9Mo= +github.com/mgechev/revive v1.12.0 h1:Q+/kkbbwerrVYPv9d9efaPGmAO/NsxwW/nE6ahpQaCU= +github.com/mgechev/revive v1.12.0/go.mod h1:VXsY2LsTigk8XU9BpZauVLjVrhICMOV3k1lpB3CXrp8= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -434,6 +471,8 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -444,14 +483,12 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= -github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= -github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= -github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/nunnatsa/ginkgolinter v0.21.2 h1:khzWfm2/Br8ZemX8QM1pl72LwM+rMeW6VUbQ4rzh0Po= +github.com/nunnatsa/ginkgolinter v0.21.2/go.mod h1:GItSI5fw7mCGLPmkvGYrr1kEetZe7B593jcyOpyabsY= +github.com/onsi/ginkgo/v2 v2.26.0 h1:1J4Wut1IlYZNEAWIV3ALrT9NfiaGW2cDCJQSFQMs/gE= +github.com/onsi/ginkgo/v2 v2.26.0/go.mod h1:qhEywmzWTBUY88kfO0BRvX4py7scov9yR+Az2oavUzw= +github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -494,10 +531,10 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.4.4 h1:53DncefIeLX3qEpjzlS1lyUmQoUEeOWPFWqaTJq9eAQ= -github.com/quasilyte/go-ruleguard v0.4.4/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard v0.4.5 h1:AGY0tiOT5hJX9BTdx/xBdoCubQUAE2grkqY2lSwvZcA= +github.com/quasilyte/go-ruleguard v0.4.5/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= +github.com/quasilyte/go-ruleguard/dsl v0.3.23 h1:lxjt5B6ZCiBeeNO8/oQsegE6fLeCzuMRoVWSkXC4uvY= +github.com/quasilyte/go-ruleguard/dsl v0.3.23/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= @@ -522,14 +559,16 @@ github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDc github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= -github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4trLRc= -github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= +github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= +github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= +github.com/securego/gosec/v2 v2.22.10 h1:ntbBqdWXnu46DUOXn+R2SvPo3PiJCDugTCgTW2g4tQg= +github.com/securego/gosec/v2 v2.22.10/go.mod h1:9UNjK3tLpv/w2b0+7r82byV43wCJDNtEDQMeS+H/g2w= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -539,10 +578,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= -github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= -github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= +github.com/sonatard/noctx v0.4.0 h1:7MC/5Gg4SQ4lhLYR6mvOP6mQVSxCrdyiExo7atBs27o= +github.com/sonatard/noctx v0.4.0/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= @@ -619,30 +656,22 @@ github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8B github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8= -github.com/tdakkota/asciicheck v0.4.1/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.5.1 h1:PZnjCol4+FqaEzvZg5+O8IY2P3hfY9JzRBNPv1pEDS4= -github.com/tetafro/godot v1.5.1/go.mod h1:cCdPtEndkmqqrhiCfkmxDodMQJ/f3L1BCNskCUZdTwk= +github.com/tetafro/godot v1.5.4 h1:u1ww+gqpRLiIA16yF2PV1CV1n/X3zhyezbNXC3E14Sg= +github.com/tetafro/godot v1.5.4/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= @@ -657,12 +686,14 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= +github.com/uudashr/iface v1.4.1 h1:J16Xl1wyNX9ofhpHmQ9h9gk5rnv2A6lX/2+APLTo0zU= +github.com/uudashr/iface v1.4.1/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xen0n/gosmopolitan v1.3.0 h1:zAZI1zefvo7gcpbCOrPSHJZJYA9ZgLfJqtKzZ5pHqQM= github.com/xen0n/gosmopolitan v1.3.0/go.mod h1:rckfr5T6o4lBtM1ga7mLGKZmLxswUoH1zxHgNXOsEt4= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= @@ -682,25 +713,27 @@ gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.13.1 h1:lw2sJyu7S1X8lc8zWUAdH42y+afdcCnHhWpnkWvd6vU= -go-simpler.org/musttag v0.13.1/go.mod h1:8r450ehpMLQgvpb6sg+hV5Ur47eH6olp/3yEanfG97k= -go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= -go-simpler.org/sloglint v0.11.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= +go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= +go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= +go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= +go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= +go.augendre.info/arangolint v0.3.1 h1:n2E6p8f+zfXSFLa2e2WqFPp4bfvcuRdd50y6cT65pSo= +go.augendre.info/arangolint v0.3.1/go.mod h1:6ZKzEzIZuBQwoSvlKT+qpUfIbBfFCE5gbAoTg0/117g= +go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE= +go.augendre.info/fatcontext v0.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= @@ -728,8 +761,8 @@ golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWB golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 h1:HDjDiATsGqvuqvkDvgJjD1IgPrVekcSXVVE21JwvzGE= +golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -754,9 +787,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= @@ -795,9 +826,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= @@ -873,7 +902,6 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -885,9 +913,7 @@ golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 h1:E2/AqCUMZGgd73TQkxU golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= @@ -900,9 +926,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= @@ -944,7 +968,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -955,19 +978,14 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= @@ -1055,8 +1073,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1073,7 +1091,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= @@ -1099,10 +1116,10 @@ k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOP k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= -mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= -mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= -mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= +mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4= +mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s= +mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI= +mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15/go.mod h1:4M5MMXl2kW6fivUT6yRGpLLPNfuGtU2Z0cPvFquGDYU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/golang-ci.yaml b/golang-ci.yaml index 611e2e172..0a367d55a 100644 --- a/golang-ci.yaml +++ b/golang-ci.yaml @@ -1,95 +1,83 @@ -# This file contains all available configuration options -# with their default values. - -# options for analysis running +version: "2" run: - # default concurrency is a available CPU number concurrency: 4 - - # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 10m -linters-settings: - goimports: - # put imports beginning with prefix after 3rd-party packages; - # it's a comma-separated list of prefixes - local-prefixes: github.com/freiheit-com/nmww - depguard: - rules: - main: - list-mode: lax # Everything is allowed unless it is denied - deny: - - pkg: "github.com/stretchr/testify" - desc: Do not use a testing framework - misspell: - # Correct spellings using locale preferences for US or UK. - # Default is to use a neutral variety of English. - # Setting locale to US will correct the British spelling of 'colour' to 'color'. - locale: US - golint: - min-confidence: 0.8 - gosec: - excludes: - # Suppressions: (see https://github.com/securego/gosec#available-rules for details) - - G104 # "Audit errors not checked" -> which we don't need and is a badly implemented version of errcheck - - G102 # "Bind to all interfaces" -> since this is normal in k8s - - G304 # "File path provided as taint input" -> too many false positives - - G307 # "Deferring unsafe method "Close" on type "io.ReadCloser" -> false positive when calling defer resp.Body.Close() - nakedret: - max-func-lines: 0 - revive: - ignore-generated-header: true - severity: error - # https://github.com/mgechev/revive - rules: - - name: errorf - - name: context-as-argument - - name: error-return - - name: increment-decrement - - name: indent-error-flow - - name: superfluous-else - - name: unused-parameter - - name: unreachable-code - - name: atomic - - name: empty-lines - - name: early-return - gocritic: - enabled-tags: - - performance - - style - - experimental - disabled-checks: - - wrapperFunc - - typeDefFirst - - ifElseChain - - dupImport # https://github.com/go-critic/go-critic/issues/845 linters: enable: - # https://golangci-lint.run/usage/linters/ - # default linters - - gosimple - - govet - - ineffassign - - staticcheck - - typecheck - - unused - # additional linters + - bodyclose + - depguard - errorlint + - forcetypeassert - gochecknoinits - gocritic - - gofmt - - goimports - gosec - misspell - nakedret - revive - - depguard - - bodyclose - sqlclosecheck - wastedassign - - forcetypeassert - - errcheck disable: - noctx # false positive: finds errors with http.NewRequest that dont make sense - unparam # false positives -issues: - exclude-use-default: false + settings: + depguard: + rules: + main: + list-mode: lax + deny: + - pkg: github.com/stretchr/testify + desc: Do not use a testing framework + gocritic: + disabled-checks: + - wrapperFunc + - typeDefFirst + - ifElseChain + - dupImport # https://github.com/go-critic/go-critic/issues/845 + enabled-tags: + - performance + - style + - experimental + gosec: + excludes: + # Suppressions: (see https://github.com/securego/gosec#available-rules for details) + - G104 # "Audit errors not checked" -> which we don't need and is a badly implemented version of errcheck + - G102 # "Bind to all interfaces" -> since this is normal in k8s + - G304 # "File path provided as taint input" -> too many false positives + - G307 # "Deferring unsafe method "Close" on type "io.ReadCloser" -> false positive when calling defer resp.Body.Close() + misspell: + # Correct spellings using locale preferences for US or UK. + # Default is to use a neutral variety of English. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + locale: US + nakedret: + max-func-lines: 0 + revive: + severity: error + # https://github.com/mgechev/revive + rules: + - name: errorf + - name: context-as-argument + - name: error-return + - name: increment-decrement + - name: indent-error-flow + - name: superfluous-else + - name: unused-parameter + - name: unreachable-code + - name: atomic + - name: empty-lines + - name: early-return + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/internal/cmd/affinity-groups/affinity-groups.go b/internal/cmd/affinity-groups/affinity-groups.go index a750b2047..f8fe78433 100644 --- a/internal/cmd/affinity-groups/affinity-groups.go +++ b/internal/cmd/affinity-groups/affinity-groups.go @@ -6,12 +6,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "affinity-group", Short: "Manage server affinity groups", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand( create.NewCmd(params), delete.NewCmd(params), diff --git a/internal/cmd/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go index 311115644..ca5332eb8 100644 --- a/internal/cmd/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Policy string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an affinity groups", @@ -117,7 +118,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, func outputResult(p *print.Printer, model inputModel, resp iaas.AffinityGroup) error { outputFormat := "" if model.GlobalFlagModel != nil { - outputFormat = model.GlobalFlagModel.OutputFormat + outputFormat = model.OutputFormat } return p.OutputResult(outputFormat, resp, func() error { diff --git a/internal/cmd/affinity-groups/create/create_test.go b/internal/cmd/affinity-groups/create/create_test.go index 6876da538..82dd23ef4 100644 --- a/internal/cmd/affinity-groups/create/create_test.go +++ b/internal/cmd/affinity-groups/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -180,7 +181,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.model, tt.response) diff --git a/internal/cmd/affinity-groups/delete/delete.go b/internal/cmd/affinity-groups/delete/delete.go index fdfb68c1a..31df4cb18 100644 --- a/internal/cmd/affinity-groups/delete/delete.go +++ b/internal/cmd/affinity-groups/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ const ( affinityGroupIdArg = "AFFINITY_GROUP" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", affinityGroupIdArg), Short: "Deletes an affinity group", diff --git a/internal/cmd/affinity-groups/delete/delete_test.go b/internal/cmd/affinity-groups/delete/delete_test.go index d66437d2f..b059eb50c 100644 --- a/internal/cmd/affinity-groups/delete/delete_test.go +++ b/internal/cmd/affinity-groups/delete/delete_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -102,7 +103,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/affinity-groups/describe/describe.go b/internal/cmd/affinity-groups/describe/describe.go index 5510a439d..52465a976 100644 --- a/internal/cmd/affinity-groups/describe/describe.go +++ b/internal/cmd/affinity-groups/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ const ( affinityGroupId = "AFFINITY_GROUP_ID" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", affinityGroupId), Short: "Show details of an affinity group", @@ -89,7 +90,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM func outputResult(p *print.Printer, model inputModel, resp iaas.AffinityGroup) error { var outputFormat string if model.GlobalFlagModel != nil { - outputFormat = model.GlobalFlagModel.OutputFormat + outputFormat = model.OutputFormat } return p.OutputResult(outputFormat, resp, func() error { diff --git a/internal/cmd/affinity-groups/describe/describe_test.go b/internal/cmd/affinity-groups/describe/describe_test.go index 01c0d3eac..ac751003b 100644 --- a/internal/cmd/affinity-groups/describe/describe_test.go +++ b/internal/cmd/affinity-groups/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -103,7 +104,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { diff --git a/internal/cmd/affinity-groups/list/list.go b/internal/cmd/affinity-groups/list/list.go index 3752106e0..0a2e3013f 100644 --- a/internal/cmd/affinity-groups/list/list.go +++ b/internal/cmd/affinity-groups/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -26,7 +27,7 @@ type inputModel struct { const limitFlag = "limit" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists affinity groups", @@ -111,7 +112,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, func outputResult(p *print.Printer, model inputModel, items []iaas.AffinityGroup) error { var outputFormat string if model.GlobalFlagModel != nil { - outputFormat = model.GlobalFlagModel.OutputFormat + outputFormat = model.OutputFormat } return p.OutputResult(outputFormat, items, func() error { diff --git a/internal/cmd/affinity-groups/list/list_test.go b/internal/cmd/affinity-groups/list/list_test.go index 5c792a299..432640085 100644 --- a/internal/cmd/affinity-groups/list/list_test.go +++ b/internal/cmd/affinity-groups/list/list_test.go @@ -5,10 +5,11 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -154,7 +155,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.model, tt.response) diff --git a/internal/cmd/auth/activate-service-account/activate_service_account.go b/internal/cmd/auth/activate-service-account/activate_service_account.go index a3cf1ee46..3b87d23f5 100644 --- a/internal/cmd/auth/activate-service-account/activate_service_account.go +++ b/internal/cmd/auth/activate-service-account/activate_service_account.go @@ -4,8 +4,9 @@ import ( "errors" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/viper" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -33,7 +34,7 @@ type inputModel struct { OnlyPrintAccessToken bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "activate-service-account", Short: "Authenticates using a service account", diff --git a/internal/cmd/auth/auth.go b/internal/cmd/auth/auth.go index 7e1c020cf..d54f3fb01 100644 --- a/internal/cmd/auth/auth.go +++ b/internal/cmd/auth/auth.go @@ -5,14 +5,14 @@ import ( getaccesstoken "github.com/stackitcloud/stackit-cli/internal/cmd/auth/get-access-token" "github.com/stackitcloud/stackit-cli/internal/cmd/auth/login" "github.com/stackitcloud/stackit-cli/internal/cmd/auth/logout" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "auth", Short: "Authenticates the STACKIT CLI", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(login.NewCmd(params)) cmd.AddCommand(logout.NewCmd(params)) cmd.AddCommand(activateserviceaccount.NewCmd(params)) diff --git a/internal/cmd/auth/get-access-token/get_access_token.go b/internal/cmd/auth/get-access-token/get_access_token.go index 5ff3da916..a3c1246e6 100644 --- a/internal/cmd/auth/get-access-token/get_access_token.go +++ b/internal/cmd/auth/get-access-token/get_access_token.go @@ -4,8 +4,9 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -18,7 +19,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "get-access-token", Short: "Prints a short-lived access token.", diff --git a/internal/cmd/auth/login/login.go b/internal/cmd/auth/login/login.go index 8740fead7..23efd0a4e 100644 --- a/internal/cmd/auth/login/login.go +++ b/internal/cmd/auth/login/login.go @@ -3,7 +3,8 @@ package login import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -11,7 +12,7 @@ import ( "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "login", Short: "Logs in to the STACKIT CLI", diff --git a/internal/cmd/auth/logout/logout.go b/internal/cmd/auth/logout/logout.go index 4b318b2e7..e5e4f6be8 100644 --- a/internal/cmd/auth/logout/logout.go +++ b/internal/cmd/auth/logout/logout.go @@ -3,7 +3,8 @@ package logout import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -11,7 +12,7 @@ import ( "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "logout", Short: "Logs the user account out of the STACKIT CLI", diff --git a/internal/cmd/beta/alb/alb.go b/internal/cmd/beta/alb/alb.go index fde1da311..62bd90d2b 100644 --- a/internal/cmd/beta/alb/alb.go +++ b/internal/cmd/beta/alb/alb.go @@ -11,15 +11,15 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/quotas" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/template" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "alb", Short: "Manages application loadbalancers", @@ -31,7 +31,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand( list.NewCmd(params), template.NewCmd(params), diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go index 33551e3ac..cf8429d10 100644 --- a/internal/cmd/beta/alb/create/create.go +++ b/internal/cmd/beta/alb/create/create.go @@ -8,8 +8,9 @@ import ( "os" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Configuration *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an application loadbalancer", diff --git a/internal/cmd/beta/alb/create/create_test.go b/internal/cmd/beta/alb/create/create_test.go index a3b7c0725..c99f4a859 100644 --- a/internal/cmd/beta/alb/create/create_test.go +++ b/internal/cmd/beta/alb/create/create_test.go @@ -7,10 +7,11 @@ import ( "log" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -212,7 +213,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/delete/delete.go b/internal/cmd/beta/alb/delete/delete.go index d7dfe1c50..5d0c23ec5 100644 --- a/internal/cmd/beta/alb/delete/delete.go +++ b/internal/cmd/beta/alb/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -25,7 +26,7 @@ type inputModel struct { Name string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", loadbalancerNameArg), Short: "Deletes an application loadbalancer", diff --git a/internal/cmd/beta/alb/describe/describe.go b/internal/cmd/beta/alb/describe/describe.go index bccca2ace..6d4cae785 100644 --- a/internal/cmd/beta/alb/describe/describe.go +++ b/internal/cmd/beta/alb/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -28,7 +29,7 @@ type inputModel struct { Name string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", loadbalancerNameArg), Short: "Describes an application loadbalancer", diff --git a/internal/cmd/beta/alb/describe/describe_test.go b/internal/cmd/beta/alb/describe/describe_test.go index 9132fc5af..9d79acbad 100644 --- a/internal/cmd/beta/alb/describe/describe_test.go +++ b/internal/cmd/beta/alb/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -168,7 +169,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.response); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/list/list.go b/internal/cmd/beta/alb/list/list.go index 292e2e3ae..bfeb711c6 100644 --- a/internal/cmd/beta/alb/list/list.go +++ b/internal/cmd/beta/alb/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ const ( limitFlag = "limit" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists albs", diff --git a/internal/cmd/beta/alb/list/list_test.go b/internal/cmd/beta/alb/list/list_test.go index 5ffc642e2..b579d45a6 100644 --- a/internal/cmd/beta/alb/list/list_test.go +++ b/internal/cmd/beta/alb/list/list_test.go @@ -5,10 +5,11 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -167,7 +168,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.items); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/observability-credentials/add/add.go b/internal/cmd/beta/alb/observability-credentials/add/add.go index 1b430cdf6..039a76ebe 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -29,7 +30,7 @@ type inputModel struct { Password *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "add", Short: "Adds observability credentials to an application load balancer", @@ -69,7 +70,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("add credential: %w", err) } - return outputResult(params.Printer, model.GlobalFlagModel.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/beta/alb/observability-credentials/add/add_test.go b/internal/cmd/beta/alb/observability-credentials/add/add_test.go index fb81d7a34..de16544a6 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add_test.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -166,7 +167,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.item); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete.go b/internal/cmd/beta/alb/observability-credentials/delete/delete.go index 8270d4df0..d27de6d3e 100644 --- a/internal/cmd/beta/alb/observability-credentials/delete/delete.go +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -24,7 +25,7 @@ type inputModel struct { CredentialsRef string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialRefArg), Short: "Deletes credentials", diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go b/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go index 09ecaa532..951846c66 100644 --- a/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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-sdk-go/services/alb" @@ -113,7 +114,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe.go b/internal/cmd/beta/alb/observability-credentials/describe/describe.go index 2ebf96e4a..fe370a10d 100644 --- a/internal/cmd/beta/alb/observability-credentials/describe/describe.go +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -27,7 +28,7 @@ type inputModel struct { CredentialRef string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialRefArg), Short: "Describes observability credentials for the Application Load Balancer", diff --git a/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go b/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go index df4d70fe1..7846a6b21 100644 --- a/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go +++ b/internal/cmd/beta/alb/observability-credentials/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -168,7 +169,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.response); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/observability-credentials/list/list.go b/internal/cmd/beta/alb/observability-credentials/list/list.go index 51347cae2..5c44aae92 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials", diff --git a/internal/cmd/beta/alb/observability-credentials/list/list_test.go b/internal/cmd/beta/alb/observability-credentials/list/list_test.go index e8054a4e8..eacc42dea 100644 --- a/internal/cmd/beta/alb/observability-credentials/list/list_test.go +++ b/internal/cmd/beta/alb/observability-credentials/list/list_test.go @@ -5,7 +5,8 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -180,7 +181,7 @@ func Test_outputResult(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) if err := outputResult(p, tt.args.outputFormat, tt.args.response); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) diff --git a/internal/cmd/beta/alb/observability-credentials/observability-credentials.go b/internal/cmd/beta/alb/observability-credentials/observability-credentials.go index 3d18486ee..0e05ae183 100644 --- a/internal/cmd/beta/alb/observability-credentials/observability-credentials.go +++ b/internal/cmd/beta/alb/observability-credentials/observability-credentials.go @@ -2,17 +2,17 @@ package credentials import ( "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" add "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/add" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/observability-credentials/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "observability-credentials", Short: "Provides functionality for application loadbalancer credentials", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(add.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/beta/alb/observability-credentials/update/update.go b/internal/cmd/beta/alb/observability-credentials/update/update.go index 703fe12a7..222c94559 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -33,7 +34,7 @@ type inputModel struct { CredentialsRef *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", credentialRefArg), Short: "Update credentials", @@ -127,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) inputM func outputResult(p *print.Printer, model inputModel, response *alb.UpdateCredentialsResponse) error { var outputFormat string if model.GlobalFlagModel != nil { - outputFormat = model.GlobalFlagModel.OutputFormat + outputFormat = model.OutputFormat } if response == nil { return fmt.Errorf("no response passed") diff --git a/internal/cmd/beta/alb/observability-credentials/update/update_test.go b/internal/cmd/beta/alb/observability-credentials/update/update_test.go index 1fd029be1..1697fc13a 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update_test.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -128,7 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -218,7 +219,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.item); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/plans/plans.go b/internal/cmd/beta/alb/plans/plans.go index 0724860a1..c38dd9b70 100644 --- a/internal/cmd/beta/alb/plans/plans.go +++ b/internal/cmd/beta/alb/plans/plans.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -22,7 +23,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists the application load balancer plans", diff --git a/internal/cmd/beta/alb/plans/plans_test.go b/internal/cmd/beta/alb/plans/plans_test.go index ebb7ed8f0..c104680e5 100644 --- a/internal/cmd/beta/alb/plans/plans_test.go +++ b/internal/cmd/beta/alb/plans/plans_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -159,7 +160,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.items); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/pool/pool.go b/internal/cmd/beta/alb/pool/pool.go index d40f8733a..f83b7728b 100644 --- a/internal/cmd/beta/alb/pool/pool.go +++ b/internal/cmd/beta/alb/pool/pool.go @@ -2,15 +2,15 @@ package pool import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/pool/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "pool", Short: "Manages target pools for application loadbalancers", @@ -22,6 +22,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(update.NewCmd(params)) } diff --git a/internal/cmd/beta/alb/pool/update/update.go b/internal/cmd/beta/alb/pool/update/update.go index ca294f052..dcc51b7c6 100644 --- a/internal/cmd/beta/alb/pool/update/update.go +++ b/internal/cmd/beta/alb/pool/update/update.go @@ -8,8 +8,9 @@ import ( "os" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { AlbName *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "Updates an application target pool", diff --git a/internal/cmd/beta/alb/pool/update/update_test.go b/internal/cmd/beta/alb/pool/update/update_test.go index 15bc4f4a9..771cf6ce1 100644 --- a/internal/cmd/beta/alb/pool/update/update_test.go +++ b/internal/cmd/beta/alb/pool/update/update_test.go @@ -7,10 +7,11 @@ import ( "log" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -221,7 +222,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/quotas/quotas.go b/internal/cmd/beta/alb/quotas/quotas.go index 3f9a63002..29f1c3bfd 100644 --- a/internal/cmd/beta/alb/quotas/quotas.go +++ b/internal/cmd/beta/alb/quotas/quotas.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -21,7 +22,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "quotas", Short: "Shows the application load balancer quotas", diff --git a/internal/cmd/beta/alb/quotas/quotas_test.go b/internal/cmd/beta/alb/quotas/quotas_test.go index ee63dffcd..80ee324f6 100644 --- a/internal/cmd/beta/alb/quotas/quotas_test.go +++ b/internal/cmd/beta/alb/quotas/quotas_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -157,7 +158,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.response); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/alb/template/template.go b/internal/cmd/beta/alb/template/template.go index a57b83f67..67819b173 100644 --- a/internal/cmd/beta/alb/template/template.go +++ b/internal/cmd/beta/alb/template/template.go @@ -6,9 +6,10 @@ import ( "fmt" "os" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -37,7 +38,7 @@ var ( templatePool string ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "template", Short: "creates configuration templates to use for resource creation", diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go index c1c576f06..5b34fea74 100644 --- a/internal/cmd/beta/alb/update/update.go +++ b/internal/cmd/beta/alb/update/update.go @@ -8,8 +8,9 @@ import ( "os" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { Version *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "Updates an application loadbalancer", diff --git a/internal/cmd/beta/alb/update/update_test.go b/internal/cmd/beta/alb/update/update_test.go index dc8f5986a..d4ccb0788 100644 --- a/internal/cmd/beta/alb/update/update_test.go +++ b/internal/cmd/beta/alb/update/update_test.go @@ -7,10 +7,11 @@ import ( "log" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -215,7 +216,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index a60570613..de4e2f48f 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,11 +3,12 @@ package beta import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -15,7 +16,7 @@ import ( "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "beta", Short: "Contains beta STACKIT CLI commands", @@ -37,7 +38,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(sqlserverflex.NewCmd(params)) cmd.AddCommand(alb.NewCmd(params)) cmd.AddCommand(intake.NewCmd(params)) diff --git a/internal/cmd/beta/intake/intake.go b/internal/cmd/beta/intake/intake.go index 96533f29c..bf298f946 100644 --- a/internal/cmd/beta/intake/intake.go +++ b/internal/cmd/beta/intake/intake.go @@ -3,13 +3,13 @@ package intake import ( "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) // NewCmd creates the 'stackit intake' command -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "intake", Short: "Provides functionality for intake", @@ -21,6 +21,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(runner.NewCmd(params)) } diff --git a/internal/cmd/beta/intake/runner/create/create.go b/internal/cmd/beta/intake/runner/create/create.go index 1a6ed58ec..95b6b4211 100644 --- a/internal/cmd/beta/intake/runner/create/create.go +++ b/internal/cmd/beta/intake/runner/create/create.go @@ -4,11 +4,12 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/intake" "github.com/stackitcloud/stackit-sdk-go/services/intake/wait" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -39,7 +40,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *params.CmdParams) *cobra.Command { +func NewCmd(p *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a new Intake Runner", diff --git a/internal/cmd/beta/intake/runner/create/create_test.go b/internal/cmd/beta/intake/runner/create/create_test.go index 6ddcaa4a1..c4f16995b 100644 --- a/internal/cmd/beta/intake/runner/create/create_test.go +++ b/internal/cmd/beta/intake/runner/create/create_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -282,7 +283,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/intake/runner/delete/delete.go b/internal/cmd/beta/intake/runner/delete/delete.go index e74551a7d..fcb4ae69d 100644 --- a/internal/cmd/beta/intake/runner/delete/delete.go +++ b/internal/cmd/beta/intake/runner/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { } // NewCmd creates a new cobra command for deleting an Intake Runner -func NewCmd(p *params.CmdParams) *cobra.Command { +func NewCmd(p *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", runnerIdArg), Short: "Deletes an Intake Runner", diff --git a/internal/cmd/beta/intake/runner/describe/describe.go b/internal/cmd/beta/intake/runner/describe/describe.go index b5ba12ae7..47eedc386 100644 --- a/internal/cmd/beta/intake/runner/describe/describe.go +++ b/internal/cmd/beta/intake/runner/describe/describe.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/intake" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { RunnerId string } -func NewCmd(p *params.CmdParams) *cobra.Command { +func NewCmd(p *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", runnerIdArg), Short: "Shows details of an Intake Runner", diff --git a/internal/cmd/beta/intake/runner/describe/describe_test.go b/internal/cmd/beta/intake/runner/describe/describe_test.go index 9235ac723..1cb034e04 100644 --- a/internal/cmd/beta/intake/runner/describe/describe_test.go +++ b/internal/cmd/beta/intake/runner/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -181,7 +182,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.runner); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/intake/runner/list/list.go b/internal/cmd/beta/intake/runner/list/list.go index d3df6751f..c9bdc9acd 100644 --- a/internal/cmd/beta/intake/runner/list/list.go +++ b/internal/cmd/beta/intake/runner/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { } // NewCmd creates a new cobra command for listing Intake Runners -func NewCmd(p *params.CmdParams) *cobra.Command { +func NewCmd(p *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Intake Runners", diff --git a/internal/cmd/beta/intake/runner/list/list_test.go b/internal/cmd/beta/intake/runner/list/list_test.go index 582adab2c..bbce39c3e 100644 --- a/internal/cmd/beta/intake/runner/list/list_test.go +++ b/internal/cmd/beta/intake/runner/list/list_test.go @@ -5,11 +5,12 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -186,7 +187,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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, "dummy-projectlabel", tt.args.runners); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/intake/runner/runner.go b/internal/cmd/beta/intake/runner/runner.go index 0708b4ae2..f923d96ff 100644 --- a/internal/cmd/beta/intake/runner/runner.go +++ b/internal/cmd/beta/intake/runner/runner.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake/runner/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "runner", Short: "Provides functionality for Intake Runners", diff --git a/internal/cmd/beta/intake/runner/update/update.go b/internal/cmd/beta/intake/runner/update/update.go index 9ebb4a81e..a5f5bb55a 100644 --- a/internal/cmd/beta/intake/runner/update/update.go +++ b/internal/cmd/beta/intake/runner/update/update.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -43,7 +44,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(p *params.CmdParams) *cobra.Command { +func NewCmd(p *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", runnerIdArg), Short: "Updates an Intake Runner", diff --git a/internal/cmd/beta/intake/runner/update/update_test.go b/internal/cmd/beta/intake/runner/update/update_test.go index 9b4ae7afa..b702ede40 100644 --- a/internal/cmd/beta/intake/runner/update/update_test.go +++ b/internal/cmd/beta/intake/runner/update/update_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -266,7 +267,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/kms/key/create/create.go b/internal/cmd/beta/kms/key/create/create.go index 1d815e638..91c6ab3c9 100644 --- a/internal/cmd/beta/kms/key/create/create.go +++ b/internal/cmd/beta/kms/key/create/create.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" @@ -45,7 +46,7 @@ type inputModel struct { Protection *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a KMS key", diff --git a/internal/cmd/beta/kms/key/create/create_test.go b/internal/cmd/beta/kms/key/create/create_test.go index f6c0a024e..76c04dc6b 100644 --- a/internal/cmd/beta/kms/key/create/create_test.go +++ b/internal/cmd/beta/kms/key/create/create_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -315,7 +316,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.model, tt.key) diff --git a/internal/cmd/beta/kms/key/delete/delete.go b/internal/cmd/beta/kms/key/delete/delete.go index 56ab3059a..5ead9aca5 100644 --- a/internal/cmd/beta/kms/key/delete/delete.go +++ b/internal/cmd/beta/kms/key/delete/delete.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { KeyRingId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", keyIdArg), Short: "Deletes a KMS key", diff --git a/internal/cmd/beta/kms/key/delete/delete_test.go b/internal/cmd/beta/kms/key/delete/delete_test.go index b073b45be..78a2fee98 100644 --- a/internal/cmd/beta/kms/key/delete/delete_test.go +++ b/internal/cmd/beta/kms/key/delete/delete_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -169,7 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -280,7 +281,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.resp) diff --git a/internal/cmd/beta/kms/key/describe/describe.go b/internal/cmd/beta/kms/key/describe/describe.go index 113cf96de..4f036c374 100644 --- a/internal/cmd/beta/kms/key/describe/describe.go +++ b/internal/cmd/beta/kms/key/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { KeyRingID string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", argKeyID), Short: "Describe a KMS key", @@ -74,14 +75,14 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command, args []string) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} } model := &inputModel{ GlobalFlagModel: globalFlags, - KeyID: args[0], + KeyID: inputArgs[0], KeyRingID: flags.FlagToStringValue(p, cmd, flagKeyRingID), } p.DebugInputModel(model) diff --git a/internal/cmd/beta/kms/key/describe/describe_test.go b/internal/cmd/beta/kms/key/describe/describe_test.go index 6abb30a09..6a34e5c74 100644 --- a/internal/cmd/beta/kms/key/describe/describe_test.go +++ b/internal/cmd/beta/kms/key/describe/describe_test.go @@ -7,10 +7,11 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -205,7 +206,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer diff --git a/internal/cmd/beta/kms/key/importKey/importKey.go b/internal/cmd/beta/kms/key/importKey/importKey.go index f491f6eb7..78c70270e 100644 --- a/internal/cmd/beta/kms/key/importKey/importKey.go +++ b/internal/cmd/beta/kms/key/importKey/importKey.go @@ -6,9 +6,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" @@ -38,7 +39,7 @@ type inputModel struct { WrappingKeyId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("import %s", keyIdArg), Short: "Import a KMS key", @@ -109,7 +110,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } // WrappedKey needs to be base64 encoded - var wrappedKey *string = flags.FlagToStringPointer(p, cmd, wrappedKeyFlag) + var wrappedKey = flags.FlagToStringPointer(p, cmd, wrappedKeyFlag) _, err := base64.StdEncoding.DecodeString(*wrappedKey) if err != nil || *wrappedKey == "" { return nil, &cliErr.FlagValidationError{ diff --git a/internal/cmd/beta/kms/key/importKey/importKey_test.go b/internal/cmd/beta/kms/key/importKey/importKey_test.go index 37192e9d1..378f34ea0 100644 --- a/internal/cmd/beta/kms/key/importKey/importKey_test.go +++ b/internal/cmd/beta/kms/key/importKey/importKey_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -228,7 +229,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -350,7 +351,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.keyRingName, tt.keyName, tt.version) diff --git a/internal/cmd/beta/kms/key/key.go b/internal/cmd/beta/kms/key/key.go index b6ff239bc..d1ae57511 100644 --- a/internal/cmd/beta/kms/key/key.go +++ b/internal/cmd/beta/kms/key/key.go @@ -8,14 +8,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/restore" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/key/rotate" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "key", Short: "Manage KMS keys", @@ -27,7 +27,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(importKey.NewCmd(params)) diff --git a/internal/cmd/beta/kms/key/list/list.go b/internal/cmd/beta/kms/key/list/list.go index aa337b5b7..576463689 100644 --- a/internal/cmd/beta/kms/key/list/list.go +++ b/internal/cmd/beta/kms/key/list/list.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { KeyRingId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "List all KMS keys", diff --git a/internal/cmd/beta/kms/key/list/list_test.go b/internal/cmd/beta/kms/key/list/list_test.go index 17d773bd5..74491ae07 100644 --- a/internal/cmd/beta/kms/key/list/list_test.go +++ b/internal/cmd/beta/kms/key/list/list_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -246,7 +247,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.projectId, tt.keyRingId, tt.resp) diff --git a/internal/cmd/beta/kms/key/restore/restore.go b/internal/cmd/beta/kms/key/restore/restore.go index 05494a97a..43164aa89 100644 --- a/internal/cmd/beta/kms/key/restore/restore.go +++ b/internal/cmd/beta/kms/key/restore/restore.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { KeyRingId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("restore %s", keyIdArg), Short: "Restore a key", diff --git a/internal/cmd/beta/kms/key/restore/restore_test.go b/internal/cmd/beta/kms/key/restore/restore_test.go index 69860461d..9c75b8ec0 100644 --- a/internal/cmd/beta/kms/key/restore/restore_test.go +++ b/internal/cmd/beta/kms/key/restore/restore_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -169,7 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -280,7 +281,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.resp) diff --git a/internal/cmd/beta/kms/key/rotate/rotate.go b/internal/cmd/beta/kms/key/rotate/rotate.go index 14e4ff15f..0761554df 100644 --- a/internal/cmd/beta/kms/key/rotate/rotate.go +++ b/internal/cmd/beta/kms/key/rotate/rotate.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { KeyRingId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("rotate %s", keyIdArg), Short: "Rotate a key", diff --git a/internal/cmd/beta/kms/key/rotate/rotate_test.go b/internal/cmd/beta/kms/key/rotate/rotate_test.go index 28d84295e..18965764d 100644 --- a/internal/cmd/beta/kms/key/rotate/rotate_test.go +++ b/internal/cmd/beta/kms/key/rotate/rotate_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -169,7 +170,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -280,7 +281,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.resp) diff --git a/internal/cmd/beta/kms/keyring/create/create.go b/internal/cmd/beta/kms/keyring/create/create.go index b4103e957..6a44529ed 100644 --- a/internal/cmd/beta/kms/keyring/create/create.go +++ b/internal/cmd/beta/kms/keyring/create/create.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" @@ -33,7 +34,7 @@ type inputModel struct { Description string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a KMS key ring", diff --git a/internal/cmd/beta/kms/keyring/create/create_test.go b/internal/cmd/beta/kms/keyring/create/create_test.go index 8cdf81219..c4b307859 100644 --- a/internal/cmd/beta/kms/keyring/create/create_test.go +++ b/internal/cmd/beta/kms/keyring/create/create_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -237,7 +238,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.model, tt.keyRing) diff --git a/internal/cmd/beta/kms/keyring/delete/delete.go b/internal/cmd/beta/kms/keyring/delete/delete.go index 307729745..79c7316ea 100644 --- a/internal/cmd/beta/kms/keyring/delete/delete.go +++ b/internal/cmd/beta/kms/keyring/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { KeyRingId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", keyRingIdArg), Short: "Deletes a KMS key ring", diff --git a/internal/cmd/beta/kms/keyring/delete/delete_test.go b/internal/cmd/beta/kms/keyring/delete/delete_test.go index c53e7d7f0..4881e63e0 100644 --- a/internal/cmd/beta/kms/keyring/delete/delete_test.go +++ b/internal/cmd/beta/kms/keyring/delete/delete_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -132,7 +133,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/beta/kms/keyring/describe/describe.go b/internal/cmd/beta/kms/keyring/describe/describe.go index f9dc11d0a..ed90cee8d 100644 --- a/internal/cmd/beta/kms/keyring/describe/describe.go +++ b/internal/cmd/beta/kms/keyring/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { KeyRingID string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", argKeyRingID), Short: "Describe a KMS key ring", @@ -64,14 +65,14 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func parseInput(p *print.Printer, cmd *cobra.Command, args []string) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} } model := &inputModel{ GlobalFlagModel: globalFlags, - KeyRingID: args[0], + KeyRingID: inputArgs[0], } p.DebugInputModel(model) return model, nil diff --git a/internal/cmd/beta/kms/keyring/describe/describe_test.go b/internal/cmd/beta/kms/keyring/describe/describe_test.go index bdc3caa88..8c0a309f5 100644 --- a/internal/cmd/beta/kms/keyring/describe/describe_test.go +++ b/internal/cmd/beta/kms/keyring/describe/describe_test.go @@ -7,10 +7,11 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -166,7 +167,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer diff --git a/internal/cmd/beta/kms/keyring/keyring.go b/internal/cmd/beta/kms/keyring/keyring.go index f948fae41..8683a6907 100644 --- a/internal/cmd/beta/kms/keyring/keyring.go +++ b/internal/cmd/beta/kms/keyring/keyring.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "keyring", Short: "Manage KMS key rings", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) diff --git a/internal/cmd/beta/kms/keyring/list/list.go b/internal/cmd/beta/kms/keyring/list/list.go index d12b9ae87..240992c43 100644 --- a/internal/cmd/beta/kms/keyring/list/list.go +++ b/internal/cmd/beta/kms/keyring/list/list.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -23,7 +24,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all KMS key rings", diff --git a/internal/cmd/beta/kms/keyring/list/list_test.go b/internal/cmd/beta/kms/keyring/list/list_test.go index d85681c99..d4e74c414 100644 --- a/internal/cmd/beta/kms/keyring/list/list_test.go +++ b/internal/cmd/beta/kms/keyring/list/list_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -217,7 +218,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.projectId, tt.resp) diff --git a/internal/cmd/beta/kms/kms.go b/internal/cmd/beta/kms/kms.go index 8eeb2b0d2..1adfc3004 100644 --- a/internal/cmd/beta/kms/kms.go +++ b/internal/cmd/beta/kms/kms.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/keyring" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "kms", Short: "Provides functionality for KMS", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(keyring.NewCmd(params)) cmd.AddCommand(wrappingkey.NewCmd(params)) cmd.AddCommand(key.NewCmd(params)) diff --git a/internal/cmd/beta/kms/version/destroy/destroy.go b/internal/cmd/beta/kms/version/destroy/destroy.go index 470099c66..b33d5d5b6 100644 --- a/internal/cmd/beta/kms/version/destroy/destroy.go +++ b/internal/cmd/beta/kms/version/destroy/destroy.go @@ -6,9 +6,10 @@ import ( "fmt" "strconv" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { VersionNumber int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("destroy %s", versionNumberArg), Short: "Destroy a key version", diff --git a/internal/cmd/beta/kms/version/destroy/destroy_test.go b/internal/cmd/beta/kms/version/destroy/destroy_test.go index 898d1a084..2dde6cd9b 100644 --- a/internal/cmd/beta/kms/version/destroy/destroy_test.go +++ b/internal/cmd/beta/kms/version/destroy/destroy_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -197,7 +198,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -307,7 +308,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.resp) diff --git a/internal/cmd/beta/kms/version/disable/disable.go b/internal/cmd/beta/kms/version/disable/disable.go index bfb641d56..9260c8e6a 100644 --- a/internal/cmd/beta/kms/version/disable/disable.go +++ b/internal/cmd/beta/kms/version/disable/disable.go @@ -6,9 +6,10 @@ import ( "fmt" "strconv" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { VersionNumber int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disable %s", versionNumberArg), Short: "Disable a key version", diff --git a/internal/cmd/beta/kms/version/disable/disable_test.go b/internal/cmd/beta/kms/version/disable/disable_test.go index 66ec302b8..8108ea4b9 100644 --- a/internal/cmd/beta/kms/version/disable/disable_test.go +++ b/internal/cmd/beta/kms/version/disable/disable_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -197,7 +198,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -308,7 +309,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.resp) diff --git a/internal/cmd/beta/kms/version/enable/enable.go b/internal/cmd/beta/kms/version/enable/enable.go index a2530996c..06d8a85ec 100644 --- a/internal/cmd/beta/kms/version/enable/enable.go +++ b/internal/cmd/beta/kms/version/enable/enable.go @@ -6,9 +6,10 @@ import ( "fmt" "strconv" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { VersionNumber int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("enable %s", versionNumberArg), Short: "Enable a key version", diff --git a/internal/cmd/beta/kms/version/enable/enable_test.go b/internal/cmd/beta/kms/version/enable/enable_test.go index 381f7885a..0cc35d43f 100644 --- a/internal/cmd/beta/kms/version/enable/enable_test.go +++ b/internal/cmd/beta/kms/version/enable/enable_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -197,7 +198,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -308,7 +309,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.resp) diff --git a/internal/cmd/beta/kms/version/list/list.go b/internal/cmd/beta/kms/version/list/list.go index c73b2a949..f9f606ac2 100644 --- a/internal/cmd/beta/kms/version/list/list.go +++ b/internal/cmd/beta/kms/version/list/list.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { KeyId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "List all key versions", diff --git a/internal/cmd/beta/kms/version/list/list_test.go b/internal/cmd/beta/kms/version/list/list_test.go index a1df169ac..e8e97d40c 100644 --- a/internal/cmd/beta/kms/version/list/list_test.go +++ b/internal/cmd/beta/kms/version/list/list_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -270,7 +271,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.projectId, tt.keyId, tt.resp) diff --git a/internal/cmd/beta/kms/version/restore/restore.go b/internal/cmd/beta/kms/version/restore/restore.go index c5b4e7aec..2f5f0882d 100644 --- a/internal/cmd/beta/kms/version/restore/restore.go +++ b/internal/cmd/beta/kms/version/restore/restore.go @@ -6,9 +6,10 @@ import ( "fmt" "strconv" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { VersionNumber int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("restore %s", versionNumberArg), Short: "Restore a key version", diff --git a/internal/cmd/beta/kms/version/restore/restore_test.go b/internal/cmd/beta/kms/version/restore/restore_test.go index ad388135e..7454fc5a5 100644 --- a/internal/cmd/beta/kms/version/restore/restore_test.go +++ b/internal/cmd/beta/kms/version/restore/restore_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -197,7 +198,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -308,7 +309,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.resp) diff --git a/internal/cmd/beta/kms/version/version.go b/internal/cmd/beta/kms/version/version.go index 39c90e5c8..60b642679 100644 --- a/internal/cmd/beta/kms/version/version.go +++ b/internal/cmd/beta/kms/version/version.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version/enable" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/version/restore" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "version", Short: "Manage KMS key versions", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(destroy.NewCmd(params)) cmd.AddCommand(disable.NewCmd(params)) cmd.AddCommand(enable.NewCmd(params)) diff --git a/internal/cmd/beta/kms/wrappingkey/create/create.go b/internal/cmd/beta/kms/wrappingkey/create/create.go index 76d8be6b5..d652da5ac 100644 --- a/internal/cmd/beta/kms/wrappingkey/create/create.go +++ b/internal/cmd/beta/kms/wrappingkey/create/create.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/services/kms/client" @@ -43,7 +44,7 @@ type inputModel struct { Protection *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a KMS wrapping key", diff --git a/internal/cmd/beta/kms/wrappingkey/create/create_test.go b/internal/cmd/beta/kms/wrappingkey/create/create_test.go index 15616c322..2b7d356de 100644 --- a/internal/cmd/beta/kms/wrappingkey/create/create_test.go +++ b/internal/cmd/beta/kms/wrappingkey/create/create_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -306,7 +307,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.model, tt.wrappingKey) diff --git a/internal/cmd/beta/kms/wrappingkey/delete/delete.go b/internal/cmd/beta/kms/wrappingkey/delete/delete.go index 0ade8822f..38b659cdf 100644 --- a/internal/cmd/beta/kms/wrappingkey/delete/delete.go +++ b/internal/cmd/beta/kms/wrappingkey/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { KeyRingId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", wrappingKeyIdArg), Short: "Deletes a KMS wrapping key", diff --git a/internal/cmd/beta/kms/wrappingkey/delete/delete_test.go b/internal/cmd/beta/kms/wrappingkey/delete/delete_test.go index 57be1cbfa..c8d3a2ee2 100644 --- a/internal/cmd/beta/kms/wrappingkey/delete/delete_test.go +++ b/internal/cmd/beta/kms/wrappingkey/delete/delete_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -161,7 +162,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/beta/kms/wrappingkey/describe/describe.go b/internal/cmd/beta/kms/wrappingkey/describe/describe.go index 2c25a288e..f8edb6921 100644 --- a/internal/cmd/beta/kms/wrappingkey/describe/describe.go +++ b/internal/cmd/beta/kms/wrappingkey/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { KeyRingID string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", argWrappingKeyID), Short: "Describe a KMS wrapping key", @@ -74,14 +75,14 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func parseInput(p *print.Printer, cmd *cobra.Command, args []string) (*inputModel, error) { +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} } model := &inputModel{ GlobalFlagModel: globalFlags, - WrappingKeyID: args[0], + WrappingKeyID: inputArgs[0], KeyRingID: flags.FlagToStringValue(p, cmd, flagKeyRingID), } p.DebugInputModel(model) diff --git a/internal/cmd/beta/kms/wrappingkey/describe/describe_test.go b/internal/cmd/beta/kms/wrappingkey/describe/describe_test.go index 9589b33fb..579f27f3d 100644 --- a/internal/cmd/beta/kms/wrappingkey/describe/describe_test.go +++ b/internal/cmd/beta/kms/wrappingkey/describe/describe_test.go @@ -7,10 +7,11 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -198,7 +199,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { var buf bytes.Buffer diff --git a/internal/cmd/beta/kms/wrappingkey/list/list.go b/internal/cmd/beta/kms/wrappingkey/list/list.go index a89babc53..dbb514812 100644 --- a/internal/cmd/beta/kms/wrappingkey/list/list.go +++ b/internal/cmd/beta/kms/wrappingkey/list/list.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { KeyRingId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all KMS wrapping keys", diff --git a/internal/cmd/beta/kms/wrappingkey/list/list_test.go b/internal/cmd/beta/kms/wrappingkey/list/list_test.go index 93eb4b88b..05c571ed3 100644 --- a/internal/cmd/beta/kms/wrappingkey/list/list_test.go +++ b/internal/cmd/beta/kms/wrappingkey/list/list_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/kms" @@ -238,7 +239,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := outputResult(p, tt.outputFormat, tt.keyRingId, tt.resp) diff --git a/internal/cmd/beta/kms/wrappingkey/wrappingkey.go b/internal/cmd/beta/kms/wrappingkey/wrappingkey.go index 168808e37..2aaa14640 100644 --- a/internal/cmd/beta/kms/wrappingkey/wrappingkey.go +++ b/internal/cmd/beta/kms/wrappingkey/wrappingkey.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms/wrappingkey/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "wrapping-key", Short: "Manage KMS wrapping keys", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index 8b20bb219..072c3b91e 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { Owner string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", databaseNameArg), Short: "Creates a SQLServer Flex database", diff --git a/internal/cmd/beta/sqlserverflex/database/create/create_test.go b/internal/cmd/beta/sqlserverflex/database/create/create_test.go index 23001c28c..f33b7623c 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -236,7 +237,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.databaseName, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/database/database.go b/internal/cmd/beta/sqlserverflex/database/database.go index f11cf2bd0..75113d255 100644 --- a/internal/cmd/beta/sqlserverflex/database/database.go +++ b/internal/cmd/beta/sqlserverflex/database/database.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/database/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "database", Short: "Provides functionality for SQLServer Flex databases", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete.go b/internal/cmd/beta/sqlserverflex/database/delete/delete.go index bc19533dc..edfd47f83 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", databaseNameArg), Short: "Deletes a SQLServer Flex database", diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe.go b/internal/cmd/beta/sqlserverflex/database/describe/describe.go index ef4afa8fc..7ad000553 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", databaseNameArg), Short: "Shows details of an SQLServer Flex database", diff --git a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go index b77f11679..2a4bc2b01 100644 --- a/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/database/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -224,7 +225,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/database/list/list.go b/internal/cmd/beta/sqlserverflex/database/list/list.go index 12738a9ab..439b069df 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all SQLServer Flex databases", diff --git a/internal/cmd/beta/sqlserverflex/database/list/list_test.go b/internal/cmd/beta/sqlserverflex/database/list/list_test.go index 36674a923..236f64f78 100644 --- a/internal/cmd/beta/sqlserverflex/database/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/database/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -199,7 +200,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceId, tt.args.projectLabel, tt.args.databases); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 8e349c6bc..04841a4c7 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -5,7 +5,8 @@ import ( "errors" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -64,7 +65,7 @@ type inputModel struct { RetentionDays *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a SQLServer Flex instance", diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go index 40481f963..8168cecc6 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create_test.go @@ -5,10 +5,11 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -480,7 +481,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go index 0fcd25dd5..5e320f039 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a SQLServer Flex instance", diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go index d978bcf97..b1b4f167c 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a SQLServer Flex instance", diff --git a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go index 66676b001..4fb05fb0a 100644 --- a/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/instance/instance.go b/internal/cmd/beta/sqlserverflex/instance/instance.go index 4ed452eb1..9d8784bc7 100644 --- a/internal/cmd/beta/sqlserverflex/instance/instance.go +++ b/internal/cmd/beta/sqlserverflex/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for SQLServer Flex instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list.go b/internal/cmd/beta/sqlserverflex/instance/list/list.go index 27dada066..7fe756750 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all SQLServer Flex instances", diff --git a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go index 4105384df..d730fa056 100644 --- a/internal/cmd/beta/sqlserverflex/instance/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -174,7 +175,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index ec06d020a..019826e3b 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -5,7 +5,8 @@ import ( "errors" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -59,7 +60,7 @@ type inputModel struct { Version *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a SQLServer Flex instance", diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update_test.go b/internal/cmd/beta/sqlserverflex/instance/update/update_test.go index 5db0655ba..894839d93 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update_test.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update_test.go @@ -5,10 +5,11 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -282,7 +283,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -521,7 +522,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/options/options.go b/internal/cmd/beta/sqlserverflex/options/options.go index 9352e53b5..236dab10d 100644 --- a/internal/cmd/beta/sqlserverflex/options/options.go +++ b/internal/cmd/beta/sqlserverflex/options/options.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -86,7 +87,7 @@ type instanceDBCompatibilities struct { DBCompatibilities []sqlserverflex.MssqlDatabaseCompatibility `json:"dbCompatibilities"` } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "options", Short: "Lists SQL Server Flex options", diff --git a/internal/cmd/beta/sqlserverflex/options/options_test.go b/internal/cmd/beta/sqlserverflex/options/options_test.go index 61b24b242..3a43e1668 100644 --- a/internal/cmd/beta/sqlserverflex/options/options_test.go +++ b/internal/cmd/beta/sqlserverflex/options/options_test.go @@ -5,8 +5,9 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -435,7 +436,7 @@ func TestBuildAndExecuteRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) p.Cmd = cmd client := &sqlServerFlexClientMocked{ listFlavorsFails: tt.listFlavorsFails, @@ -507,7 +508,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.flavors, tt.args.versions, tt.args.storages, tt.args.userRoles, tt.args.dbCollations, tt.args.dbCompatibilities); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/sqlserverflex.go b/internal/cmd/beta/sqlserverflex/sqlserverflex.go index 51c93beb8..29404a045 100644 --- a/internal/cmd/beta/sqlserverflex/sqlserverflex.go +++ b/internal/cmd/beta/sqlserverflex/sqlserverflex.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/options" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "sqlserverflex", Short: "Provides functionality for SQLServer Flex", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(database.NewCmd(params)) cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(options.NewCmd(params)) diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 5160873f2..cb77255f9 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a SQLServer Flex user", diff --git a/internal/cmd/beta/sqlserverflex/user/create/create_test.go b/internal/cmd/beta/sqlserverflex/user/create/create_test.go index ad5df9a27..d8e9a8836 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create_test.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -208,7 +209,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete.go b/internal/cmd/beta/sqlserverflex/user/delete/delete.go index 31869cdda..0908a227f 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", userIdArg), Short: "Deletes a SQLServer Flex user", diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe.go b/internal/cmd/beta/sqlserverflex/user/describe/describe.go index 93d97acc4..bdfe47fc1 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", userIdArg), Short: "Shows details of a SQLServer Flex user", diff --git a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go index e67aeb3b9..77123e300 100644 --- a/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go +++ b/internal/cmd/beta/sqlserverflex/user/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -211,7 +212,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/user/list/list.go b/internal/cmd/beta/sqlserverflex/user/list/list.go index c74dc7866..24a216bbd 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all SQLServer Flex users of an instance", diff --git a/internal/cmd/beta/sqlserverflex/user/list/list_test.go b/internal/cmd/beta/sqlserverflex/user/list/list_test.go index 44deacf77..fd7e31df7 100644 --- a/internal/cmd/beta/sqlserverflex/user/list/list_test.go +++ b/internal/cmd/beta/sqlserverflex/user/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -191,7 +192,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.users); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index b56538eec..b27b6e923 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reset-password %s", userIdArg), Short: "Resets the password of a SQLServer Flex user", diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go index b15b7069e..921e39758 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -213,7 +214,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.userLabel, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/beta/sqlserverflex/user/user.go b/internal/cmd/beta/sqlserverflex/user/user.go index 0c83d54e4..572a9ea52 100644 --- a/internal/cmd/beta/sqlserverflex/user/user.go +++ b/internal/cmd/beta/sqlserverflex/user/user.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user/list" resetpassword "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user/reset-password" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "user", Short: "Provides functionality for SQLServer Flex users", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/config/config.go b/internal/cmd/config/config.go index 46b21b96a..3000a8ac1 100644 --- a/internal/cmd/config/config.go +++ b/internal/cmd/config/config.go @@ -3,18 +3,19 @@ package config import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/cmd/config/list" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile" "github.com/stackitcloud/stackit-cli/internal/cmd/config/set" "github.com/stackitcloud/stackit-cli/internal/cmd/config/unset" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "config", Short: "Provides functionality for CLI configuration options", @@ -32,7 +33,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(set.NewCmd(params)) cmd.AddCommand(unset.NewCmd(params)) diff --git a/internal/cmd/config/list/list.go b/internal/cmd/config/list/list.go index 6dbc78e7e..71e115b29 100644 --- a/internal/cmd/config/list/list.go +++ b/internal/cmd/config/list/list.go @@ -4,13 +4,14 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "slices" "sort" "strconv" "strings" "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists the current CLI configuration values", diff --git a/internal/cmd/config/list/list_test.go b/internal/cmd/config/list/list_test.go index cbdab8410..2129c29d9 100644 --- a/internal/cmd/config/list/list_test.go +++ b/internal/cmd/config/list/list_test.go @@ -3,7 +3,7 @@ package list import ( "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/print" ) @@ -26,7 +26,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.configData, tt.args.activeProfile); (err != nil) != tt.wantErr { diff --git a/internal/cmd/config/profile/create/create.go b/internal/cmd/config/profile/create/create.go index 608fe85da..bc7a1790f 100644 --- a/internal/cmd/config/profile/create/create.go +++ b/internal/cmd/config/profile/create/create.go @@ -3,7 +3,7 @@ package create import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" @@ -30,7 +30,7 @@ type inputModel struct { Profile string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", profileArg), Short: "Creates a CLI configuration profile", diff --git a/internal/cmd/config/profile/create/create_test.go b/internal/cmd/config/profile/create/create_test.go index a2edcfe47..eaebaac64 100644 --- a/internal/cmd/config/profile/create/create_test.go +++ b/internal/cmd/config/profile/create/create_test.go @@ -67,7 +67,7 @@ func TestParseInput(t *testing.T) { }, isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.GlobalFlagModel.Verbosity = globalflags.DebugVerbosity + model.Verbosity = globalflags.DebugVerbosity }), }, { diff --git a/internal/cmd/config/profile/delete/delete.go b/internal/cmd/config/profile/delete/delete.go index 98b7bf2e2..631374a84 100644 --- a/internal/cmd/config/profile/delete/delete.go +++ b/internal/cmd/config/profile/delete/delete.go @@ -3,7 +3,7 @@ package delete import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" @@ -25,7 +25,7 @@ type inputModel struct { Profile string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", profileArg), Short: "Delete a CLI configuration profile", diff --git a/internal/cmd/config/profile/delete/delete_test.go b/internal/cmd/config/profile/delete/delete_test.go index e3ea1bf51..2ca839f58 100644 --- a/internal/cmd/config/profile/delete/delete_test.go +++ b/internal/cmd/config/profile/delete/delete_test.go @@ -65,7 +65,7 @@ func TestParseInput(t *testing.T) { }, isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.GlobalFlagModel.Verbosity = globalflags.DebugVerbosity + model.Verbosity = globalflags.DebugVerbosity }), }, { diff --git a/internal/cmd/config/profile/export/export.go b/internal/cmd/config/profile/export/export.go index 9051ea368..631ca975c 100644 --- a/internal/cmd/config/profile/export/export.go +++ b/internal/cmd/config/profile/export/export.go @@ -4,7 +4,8 @@ import ( "fmt" "path/filepath" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { FilePath string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("export %s", profileNameArg), Short: "Exports a CLI configuration profile", diff --git a/internal/cmd/config/profile/import/import.go b/internal/cmd/config/profile/import/import.go index a499f0da0..aede97304 100644 --- a/internal/cmd/config/profile/import/import.go +++ b/internal/cmd/config/profile/import/import.go @@ -2,7 +2,6 @@ package importProfile import ( "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -10,6 +9,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" ) const ( @@ -25,7 +25,7 @@ type inputModel struct { NoSet bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "import", Short: "Imports a CLI configuration profile", diff --git a/internal/cmd/config/profile/list/list.go b/internal/cmd/config/profile/list/list.go index fe90d4619..1707225c1 100644 --- a/internal/cmd/config/profile/list/list.go +++ b/internal/cmd/config/profile/list/list.go @@ -3,7 +3,8 @@ package list import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -19,7 +20,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all CLI configuration profiles", diff --git a/internal/cmd/config/profile/list/list_test.go b/internal/cmd/config/profile/list/list_test.go index 8016b6071..e9d93b147 100644 --- a/internal/cmd/config/profile/list/list_test.go +++ b/internal/cmd/config/profile/list/list_test.go @@ -3,7 +3,8 @@ package list import ( "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" ) @@ -24,7 +25,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.profiles); (err != nil) != tt.wantErr { diff --git a/internal/cmd/config/profile/profile.go b/internal/cmd/config/profile/profile.go index f6ad03ece..ab13f07cc 100644 --- a/internal/cmd/config/profile/profile.go +++ b/internal/cmd/config/profile/profile.go @@ -3,6 +3,8 @@ package profile import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/create" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/export" @@ -10,14 +12,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/list" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/set" "github.com/stackitcloud/stackit-cli/internal/cmd/config/profile/unset" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "profile", Short: "Manage the CLI configuration profiles", @@ -34,7 +35,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(set.NewCmd(params)) cmd.AddCommand(unset.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) diff --git a/internal/cmd/config/profile/set/set.go b/internal/cmd/config/profile/set/set.go index 77101092f..d5436a561 100644 --- a/internal/cmd/config/profile/set/set.go +++ b/internal/cmd/config/profile/set/set.go @@ -3,7 +3,8 @@ package set import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -24,7 +25,7 @@ type inputModel struct { Profile string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("set %s", profileArg), Short: "Set a CLI configuration profile", diff --git a/internal/cmd/config/profile/set/set_test.go b/internal/cmd/config/profile/set/set_test.go index a2ccdbbff..13d23e1be 100644 --- a/internal/cmd/config/profile/set/set_test.go +++ b/internal/cmd/config/profile/set/set_test.go @@ -65,7 +65,7 @@ func TestParseInput(t *testing.T) { }, isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.GlobalFlagModel.Verbosity = globalflags.DebugVerbosity + model.Verbosity = globalflags.DebugVerbosity }), }, { diff --git a/internal/cmd/config/profile/unset/unset.go b/internal/cmd/config/profile/unset/unset.go index 9c7f923cd..d56fcfa14 100644 --- a/internal/cmd/config/profile/unset/unset.go +++ b/internal/cmd/config/profile/unset/unset.go @@ -3,7 +3,8 @@ package unset import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/config" @@ -13,7 +14,7 @@ import ( "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "unset", Short: "Unset the current active CLI configuration profile", diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 7487f8ca3..e6da6ce7c 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -4,7 +4,8 @@ import ( "fmt" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -56,7 +57,7 @@ type inputModel struct { ProjectIdSet bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "set", Short: "Sets CLI configuration options", @@ -238,10 +239,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, // globalflags.Parse uses the flags, and fallsback to config file // To check if projectId was passed, we use the first rather than the second projectIdFromFlag := flags.FlagToStringPointer(p, cmd, globalflags.ProjectIdFlag) - projectIdSet := false - if projectIdFromFlag != nil { - projectIdSet = true - } + projectIdSet := projectIdFromFlag != nil allowedUrlDomainFromFlag := flags.FlagToStringPointer(p, cmd, allowedUrlDomainFlag) allowedUrlDomainFlagValue := flags.FlagToStringValue(p, cmd, allowedUrlDomainFlag) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 359248096..a269e867b 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -3,7 +3,8 @@ package unset import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -93,7 +94,7 @@ type inputModel struct { IntakeCustomEndpoint bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "unset", Short: "Unsets CLI configuration options", diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 12eb2424f..c356af35b 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -309,7 +309,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) for flag, value := range tt.flagValues { stringBool := fmt.Sprintf("%v", value) diff --git a/internal/cmd/curl/curl.go b/internal/cmd/curl/curl.go index 57e823f26..341654dfd 100644 --- a/internal/cmd/curl/curl.go +++ b/internal/cmd/curl/curl.go @@ -11,7 +11,8 @@ import ( "strings" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -46,7 +47,7 @@ type inputModel struct { OutputFile *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("curl %s", urlArg), Short: "Executes an authenticated HTTP request to an endpoint", diff --git a/internal/cmd/curl/curl_test.go b/internal/cmd/curl/curl_test.go index 3fbab3cf4..ce2cd3c37 100644 --- a/internal/cmd/curl/curl_test.go +++ b/internal/cmd/curl/curl_test.go @@ -10,10 +10,11 @@ import ( "strings" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/spf13/viper" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/config" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -217,7 +218,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -448,7 +449,7 @@ func TestOutputResponse(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResponse(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/dns.go b/internal/cmd/dns/dns.go index ccba3b66d..216c02dac 100644 --- a/internal/cmd/dns/dns.go +++ b/internal/cmd/dns/dns.go @@ -3,14 +3,14 @@ package dns import ( recordset "github.com/stackitcloud/stackit-cli/internal/cmd/dns/record-set" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "dns", Short: "Provides functionality for DNS", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(zone.NewCmd(params)) cmd.AddCommand(recordset.NewCmd(params)) } diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 96a5fc8e7..3dcc666e9 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -42,7 +43,7 @@ type inputModel struct { Type dns.CreateRecordSetPayloadTypes } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a DNS record set", diff --git a/internal/cmd/dns/record-set/create/create_test.go b/internal/cmd/dns/record-set/create/create_test.go index b08de66aa..633d7ec60 100644 --- a/internal/cmd/dns/record-set/create/create_test.go +++ b/internal/cmd/dns/record-set/create/create_test.go @@ -6,10 +6,11 @@ import ( "strings" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -349,7 +350,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.zoneLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/record-set/delete/delete.go b/internal/cmd/dns/record-set/delete/delete.go index 4dde11375..dcfa6d300 100644 --- a/internal/cmd/dns/record-set/delete/delete.go +++ b/internal/cmd/dns/record-set/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { RecordSetId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", recordSetIdArg), Short: "Deletes a DNS record set", diff --git a/internal/cmd/dns/record-set/describe/describe.go b/internal/cmd/dns/record-set/describe/describe.go index c84e0ab7a..dabe1d5c1 100644 --- a/internal/cmd/dns/record-set/describe/describe.go +++ b/internal/cmd/dns/record-set/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { RecordSetId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", recordSetIdArg), Short: "Shows details of a DNS record set", diff --git a/internal/cmd/dns/record-set/describe/describe_test.go b/internal/cmd/dns/record-set/describe/describe_test.go index 05d60ebcd..8f7214918 100644 --- a/internal/cmd/dns/record-set/describe/describe_test.go +++ b/internal/cmd/dns/record-set/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -222,7 +223,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.recordSet); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/record-set/list/list.go b/internal/cmd/dns/record-set/list/list.go index 309013a2c..88a7f5324 100644 --- a/internal/cmd/dns/record-set/list/list.go +++ b/internal/cmd/dns/record-set/list/list.go @@ -6,8 +6,9 @@ import ( "math" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -49,7 +50,7 @@ type inputModel struct { PageSize int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists DNS record sets", diff --git a/internal/cmd/dns/record-set/list/list_test.go b/internal/cmd/dns/record-set/list/list_test.go index 67c60a202..af2dc852b 100644 --- a/internal/cmd/dns/record-set/list/list_test.go +++ b/internal/cmd/dns/record-set/list/list_test.go @@ -8,10 +8,11 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -481,7 +482,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.zoneLabel, tt.args.recordSets); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/record-set/record_set.go b/internal/cmd/dns/record-set/record_set.go index d00152da0..548c66ee6 100644 --- a/internal/cmd/dns/record-set/record_set.go +++ b/internal/cmd/dns/record-set/record_set.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/dns/record-set/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/record-set/list" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/record-set/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "record-set", Short: "Provides functionality for DNS record set", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/dns/record-set/update/update.go b/internal/cmd/dns/record-set/update/update.go index 62f01376f..e3df19d91 100644 --- a/internal/cmd/dns/record-set/update/update.go +++ b/internal/cmd/dns/record-set/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -43,7 +44,7 @@ type inputModel struct { Type *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", recordSetIdArg), Short: "Updates a DNS record set", diff --git a/internal/cmd/dns/record-set/update/update_test.go b/internal/cmd/dns/record-set/update/update_test.go index ccb5df9ee..a85c99a12 100644 --- a/internal/cmd/dns/record-set/update/update_test.go +++ b/internal/cmd/dns/record-set/update/update_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -253,7 +253,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index a50b2fd73..0611348f9 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -38,7 +39,7 @@ type inputModel struct { ZoneId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("clone %s", zoneIdArg), Short: "Clones a DNS zone", diff --git a/internal/cmd/dns/zone/clone/clone_test.go b/internal/cmd/dns/zone/clone/clone_test.go index 59d0d13a8..4479eea6e 100644 --- a/internal/cmd/dns/zone/clone/clone_test.go +++ b/internal/cmd/dns/zone/clone/clone_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -244,7 +245,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 0658ceb8b..3454e654d 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -54,7 +55,7 @@ type inputModel struct { ContactEmail *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a DNS zone", diff --git a/internal/cmd/dns/zone/create/create_test.go b/internal/cmd/dns/zone/create/create_test.go index 319147da1..bf26e688a 100644 --- a/internal/cmd/dns/zone/create/create_test.go +++ b/internal/cmd/dns/zone/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -292,7 +293,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/zone/delete/delete.go b/internal/cmd/dns/zone/delete/delete.go index a3c8ce8dc..499ba920a 100644 --- a/internal/cmd/dns/zone/delete/delete.go +++ b/internal/cmd/dns/zone/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ZoneId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", zoneIdArg), Short: "Deletes a DNS zone", diff --git a/internal/cmd/dns/zone/describe/describe.go b/internal/cmd/dns/zone/describe/describe.go index 94ccafde1..51d2fcc8e 100644 --- a/internal/cmd/dns/zone/describe/describe.go +++ b/internal/cmd/dns/zone/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { ZoneId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", zoneIdArg), Short: "Shows details of a DNS zone", diff --git a/internal/cmd/dns/zone/describe/describe_test.go b/internal/cmd/dns/zone/describe/describe_test.go index a205a5cfd..a5704bfed 100644 --- a/internal/cmd/dns/zone/describe/describe_test.go +++ b/internal/cmd/dns/zone/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -195,7 +196,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.zone); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/zone/list/list.go b/internal/cmd/dns/zone/list/list.go index 132a362c7..1a2640fe4 100644 --- a/internal/cmd/dns/zone/list/list.go +++ b/internal/cmd/dns/zone/list/list.go @@ -6,7 +6,8 @@ import ( "math" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -48,7 +49,7 @@ type inputModel struct { PageSize int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists DNS zones", diff --git a/internal/cmd/dns/zone/list/list_test.go b/internal/cmd/dns/zone/list/list_test.go index 14a7082f9..e270d69f7 100644 --- a/internal/cmd/dns/zone/list/list_test.go +++ b/internal/cmd/dns/zone/list/list_test.go @@ -8,10 +8,11 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -475,7 +476,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.zones); (err != nil) != tt.wantErr { diff --git a/internal/cmd/dns/zone/update/update.go b/internal/cmd/dns/zone/update/update.go index 161b0e338..128f1c3f0 100644 --- a/internal/cmd/dns/zone/update/update.go +++ b/internal/cmd/dns/zone/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -51,7 +52,7 @@ type inputModel struct { ContactEmail *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", zoneIdArg), Short: "Updates a DNS zone", diff --git a/internal/cmd/dns/zone/update/update_test.go b/internal/cmd/dns/zone/update/update_test.go index 4610849bd..b537dc2f6 100644 --- a/internal/cmd/dns/zone/update/update_test.go +++ b/internal/cmd/dns/zone/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -245,7 +246,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/dns/zone/zone.go b/internal/cmd/dns/zone/zone.go index b81a143ff..ecfb1240a 100644 --- a/internal/cmd/dns/zone/zone.go +++ b/internal/cmd/dns/zone/zone.go @@ -7,14 +7,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/list" "github.com/stackitcloud/stackit-cli/internal/cmd/dns/zone/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "zone", Short: "Provides functionality for DNS zones", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/git/flavor/flavor.go b/internal/cmd/git/flavor/flavor.go index c6f4c512f..ee1700900 100644 --- a/internal/cmd/git/flavor/flavor.go +++ b/internal/cmd/git/flavor/flavor.go @@ -2,14 +2,14 @@ package flavor import ( "github.com/stackitcloud/stackit-cli/internal/cmd/git/flavor/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "flavor", Short: "Provides functionality for STACKIT Git flavors", @@ -21,7 +21,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand( list.NewCmd(params), ) diff --git a/internal/cmd/git/flavor/list/list.go b/internal/cmd/git/flavor/list/list.go index fddb9bc26..d28448b6c 100644 --- a/internal/cmd/git/flavor/list/list.go +++ b/internal/cmd/git/flavor/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { const limitFlag = "limit" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists instances flavors of STACKIT Git.", diff --git a/internal/cmd/git/flavor/list/list_test.go b/internal/cmd/git/flavor/list/list_test.go index 8c2aca50a..66c4ad264 100644 --- a/internal/cmd/git/flavor/list/list_test.go +++ b/internal/cmd/git/flavor/list/list_test.go @@ -5,10 +5,11 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -190,7 +191,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.flavors); (err != nil) != tt.wantErr { diff --git a/internal/cmd/git/git.go b/internal/cmd/git/git.go index 72605d968..624702686 100644 --- a/internal/cmd/git/git.go +++ b/internal/cmd/git/git.go @@ -3,14 +3,14 @@ package git import ( "github.com/stackitcloud/stackit-cli/internal/cmd/git/flavor" "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "git", Short: "Provides functionality for STACKIT Git", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand( instance.NewCmd(params), flavor.NewCmd(params), diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index f63e7499d..f1323fb49 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Acl []string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates STACKIT Git instance", diff --git a/internal/cmd/git/instance/create/create_test.go b/internal/cmd/git/instance/create/create_test.go index 955e5132f..bde352a95 100644 --- a/internal/cmd/git/instance/create/create_test.go +++ b/internal/cmd/git/instance/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -212,7 +213,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/git/instance/delete/delete.go b/internal/cmd/git/instance/delete/delete.go index 8b5bb7ba1..ae9394c83 100644 --- a/internal/cmd/git/instance/delete/delete.go +++ b/internal/cmd/git/instance/delete/delete.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -28,7 +28,7 @@ type inputModel struct { const instanceIdArg = "INSTANCE_ID" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes STACKIT Git instance", diff --git a/internal/cmd/git/instance/delete/delete_test.go b/internal/cmd/git/instance/delete/delete_test.go index 13609df4e..7b6a47fd9 100644 --- a/internal/cmd/git/instance/delete/delete_test.go +++ b/internal/cmd/git/instance/delete/delete_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -105,7 +106,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/git/instance/describe/describe.go b/internal/cmd/git/instance/describe/describe.go index 2d7948b11..e90dd0905 100644 --- a/internal/cmd/git/instance/describe/describe.go +++ b/internal/cmd/git/instance/describe/describe.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -25,7 +25,7 @@ type inputModel struct { const instanceIdArg = "INSTANCE_ID" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Describes STACKIT Git instance", diff --git a/internal/cmd/git/instance/describe/describe_test.go b/internal/cmd/git/instance/describe/describe_test.go index 5e1825565..6a0260f92 100644 --- a/internal/cmd/git/instance/describe/describe_test.go +++ b/internal/cmd/git/instance/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/git" @@ -119,7 +120,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -216,7 +217,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/git/instance/instance.go b/internal/cmd/git/instance/instance.go index b2d66b43a..bd36a1cbd 100644 --- a/internal/cmd/git/instance/instance.go +++ b/internal/cmd/git/instance/instance.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/git/instance/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for STACKIT Git instances", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand( list.NewCmd(params), describe.NewCmd(params), diff --git a/internal/cmd/git/instance/list/list.go b/internal/cmd/git/instance/list/list.go index 83aa2015b..0f7095199 100644 --- a/internal/cmd/git/instance/list/list.go +++ b/internal/cmd/git/instance/list/list.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -27,7 +27,7 @@ type inputModel struct { const limitFlag = "limit" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all instances of STACKIT Git.", diff --git a/internal/cmd/git/instance/list/list_test.go b/internal/cmd/git/instance/list/list_test.go index 36fa36f10..459165b87 100644 --- a/internal/cmd/git/instance/list/list_test.go +++ b/internal/cmd/git/instance/list/list_test.go @@ -5,10 +5,11 @@ import ( "strconv" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -190,7 +191,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 06a270b11..784c4389f 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -10,8 +10,9 @@ import ( "os" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -82,7 +83,7 @@ type inputModel struct { NoProgressIndicator *bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates images", diff --git a/internal/cmd/image/create/create_test.go b/internal/cmd/image/create/create_test.go index 2b28c7676..aeefdcdaa 100644 --- a/internal/cmd/image/create/create_test.go +++ b/internal/cmd/image/create/create_test.go @@ -6,10 +6,11 @@ import ( "strings" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -391,7 +392,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/image/delete/delete.go b/internal/cmd/image/delete/delete.go index d394c0bfd..ffbbf8714 100644 --- a/internal/cmd/image/delete/delete.go +++ b/internal/cmd/image/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -25,7 +26,7 @@ type inputModel struct { const imageIdArg = "IMAGE_ID" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", imageIdArg), Short: "Deletes an image", diff --git a/internal/cmd/image/delete/delete_test.go b/internal/cmd/image/delete/delete_test.go index cd1179f41..200af7e6c 100644 --- a/internal/cmd/image/delete/delete_test.go +++ b/internal/cmd/image/delete/delete_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -114,7 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/image/describe/describe.go b/internal/cmd/image/describe/describe.go index 516fa9c99..09f9f86dc 100644 --- a/internal/cmd/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -25,7 +26,7 @@ type inputModel struct { const imageIdArg = "IMAGE_ID" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", imageIdArg), Short: "Describes image", diff --git a/internal/cmd/image/describe/describe_test.go b/internal/cmd/image/describe/describe_test.go index 6a76a3200..256ef1c2a 100644 --- a/internal/cmd/image/describe/describe_test.go +++ b/internal/cmd/image/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -129,7 +130,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -226,7 +227,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/image/image.go b/internal/cmd/image/image.go index b722f2b91..65a0cc2a5 100644 --- a/internal/cmd/image/image.go +++ b/internal/cmd/image/image.go @@ -6,15 +6,15 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/image/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/image/list" "github.com/stackitcloud/stackit-cli/internal/cmd/image/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "image", Short: "Manage server images", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand( create.NewCmd(params), list.NewCmd(params), diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index 0ebdf9e95..f30ed8a85 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ const ( limitFlag = "limit" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists images", @@ -142,10 +143,10 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) err for i := range items { item := items[i] var ( - architecture string = "n/a" - os string = "n/a" - distro string = "n/a" - version string = "n/a" + architecture = "n/a" + os = "n/a" + distro = "n/a" + version = "n/a" ) if cfg := item.Config; cfg != nil { if v := cfg.Architecture; v != nil { diff --git a/internal/cmd/image/list/list_test.go b/internal/cmd/image/list/list_test.go index 6dbdb119f..7521d2023 100644 --- a/internal/cmd/image/list/list_test.go +++ b/internal/cmd/image/list/list_test.go @@ -5,7 +5,8 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -213,7 +214,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.items); (err != nil) != tt.wantErr { diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index 799b594b6..7aa3851c0 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -103,7 +104,7 @@ const ( protectedFlag = "protected" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", imageIdArg), Short: "Updates an image", diff --git a/internal/cmd/image/update/update_test.go b/internal/cmd/image/update/update_test.go index 9df1cf99e..9246bd67b 100644 --- a/internal/cmd/image/update/update_test.go +++ b/internal/cmd/image/update/update_test.go @@ -6,7 +6,8 @@ import ( "strings" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -325,7 +326,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } diff --git a/internal/cmd/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go index b7170f539..4ce01cfdf 100644 --- a/internal/cmd/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -29,7 +30,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a key pair", @@ -81,7 +82,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return fmt.Errorf("create key pair: %w", err) } - return outputResult(params.Printer, model.GlobalFlagModel.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, resp) }, } configureFlags(cmd) diff --git a/internal/cmd/key-pair/create/create_test.go b/internal/cmd/key-pair/create/create_test.go index a14818f72..24418d845 100644 --- a/internal/cmd/key-pair/create/create_test.go +++ b/internal/cmd/key-pair/create/create_test.go @@ -5,7 +5,8 @@ import ( "os" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -188,7 +189,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.item); (err != nil) != tt.wantErr { diff --git a/internal/cmd/key-pair/delete/delete.go b/internal/cmd/key-pair/delete/delete.go index 5d6c5cdb7..70d7e9a8f 100644 --- a/internal/cmd/key-pair/delete/delete.go +++ b/internal/cmd/key-pair/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" @@ -24,7 +25,7 @@ type inputModel struct { KeyPairName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", keyPairNameArg), Short: "Deletes a key pair", diff --git a/internal/cmd/key-pair/delete/delete_test.go b/internal/cmd/key-pair/delete/delete_test.go index c5c8dc913..bb45798c9 100644 --- a/internal/cmd/key-pair/delete/delete_test.go +++ b/internal/cmd/key-pair/delete/delete_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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-sdk-go/services/iaas" @@ -97,7 +98,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/key-pair/describe/describe.go b/internal/cmd/key-pair/describe/describe.go index 36addd3b8..40f450949 100644 --- a/internal/cmd/key-pair/describe/describe.go +++ b/internal/cmd/key-pair/describe/describe.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -36,7 +37,7 @@ type inputModel struct { PublicKey bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", keyPairNameArg), Short: "Describes a key pair", diff --git a/internal/cmd/key-pair/describe/describe_test.go b/internal/cmd/key-pair/describe/describe_test.go index 7af2ff2e8..b94ae4ece 100644 --- a/internal/cmd/key-pair/describe/describe_test.go +++ b/internal/cmd/key-pair/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -164,7 +165,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.showOnlyPublicKey, tt.args.keyPair); (err != nil) != tt.wantErr { diff --git a/internal/cmd/key-pair/key-pair.go b/internal/cmd/key-pair/key-pair.go index 44cc1fef8..e435a27df 100644 --- a/internal/cmd/key-pair/key-pair.go +++ b/internal/cmd/key-pair/key-pair.go @@ -2,17 +2,17 @@ package keypair import ( "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/create" "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/list" "github.com/stackitcloud/stackit-cli/internal/cmd/key-pair/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "key-pair", Short: "Provides functionality for SSH key pairs", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/key-pair/list/list.go b/internal/cmd/key-pair/list/list.go index eecec55f0..3820eb038 100644 --- a/internal/cmd/key-pair/list/list.go +++ b/internal/cmd/key-pair/list/list.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -32,7 +33,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all key pairs", diff --git a/internal/cmd/key-pair/list/list_test.go b/internal/cmd/key-pair/list/list_test.go index bc9da640f..2ceb0d426 100644 --- a/internal/cmd/key-pair/list/list_test.go +++ b/internal/cmd/key-pair/list/list_test.go @@ -5,7 +5,8 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -176,7 +177,7 @@ func Test_outputResult(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) if err := outputResult(p, tt.args.outputFormat, tt.args.keyPairs); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) diff --git a/internal/cmd/key-pair/update/update.go b/internal/cmd/key-pair/update/update.go index 10bce6606..450329082 100644 --- a/internal/cmd/key-pair/update/update.go +++ b/internal/cmd/key-pair/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -28,7 +29,7 @@ type inputModel struct { KeyPairName *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", keyPairNameArg), Short: "Updates a key pair", @@ -108,7 +109,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) inputM func outputResult(p *print.Printer, model inputModel, keyPair iaas.Keypair) error { var outputFormat string if model.GlobalFlagModel != nil { - outputFormat = model.GlobalFlagModel.OutputFormat + outputFormat = model.OutputFormat } return p.OutputResult(outputFormat, keyPair, func() error { diff --git a/internal/cmd/key-pair/update/update_test.go b/internal/cmd/key-pair/update/update_test.go index 2f5432deb..7f24c935e 100644 --- a/internal/cmd/key-pair/update/update_test.go +++ b/internal/cmd/key-pair/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -110,7 +111,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -209,7 +210,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.keyPair); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index a6b2adc73..0ebaaee16 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -5,9 +5,10 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/uuid" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ var ( xRequestId = uuid.NewString() ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Load Balancer", diff --git a/internal/cmd/load-balancer/delete/delete.go b/internal/cmd/load-balancer/delete/delete.go index e2cd2b37c..0c43431f1 100644 --- a/internal/cmd/load-balancer/delete/delete.go +++ b/internal/cmd/load-balancer/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { LoadBalancerName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", loadBalancerNameArg), Short: "Deletes a Load Balancer", diff --git a/internal/cmd/load-balancer/describe/describe.go b/internal/cmd/load-balancer/describe/describe.go index 5879fb8f3..5cdffce6a 100644 --- a/internal/cmd/load-balancer/describe/describe.go +++ b/internal/cmd/load-balancer/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { LoadBalancerName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", loadBalancerNameArg), Short: "Shows details of a Load Balancer", diff --git a/internal/cmd/load-balancer/describe/describe_test.go b/internal/cmd/load-balancer/describe/describe_test.go index a7b9a4e36..5dcbfe446 100644 --- a/internal/cmd/load-balancer/describe/describe_test.go +++ b/internal/cmd/load-balancer/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -189,7 +190,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.loadBalancer); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload.go b/internal/cmd/load-balancer/generate-payload/generate_payload.go index b7bfac451..1149ae311 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -110,7 +111,7 @@ var ( } ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "generate-payload", Short: "Generates a payload to create/update a Load Balancer", diff --git a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go index 516d41c92..ca20bc950 100644 --- a/internal/cmd/load-balancer/generate-payload/generate_payload_test.go +++ b/internal/cmd/load-balancer/generate-payload/generate_payload_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -293,7 +294,7 @@ func TestOutputCreateResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputCreateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { @@ -327,7 +328,7 @@ func TestOutputUpdateResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputUpdateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/list/list.go b/internal/cmd/load-balancer/list/list.go index a56de2041..3b14b5ca3 100644 --- a/internal/cmd/load-balancer/list/list.go +++ b/internal/cmd/load-balancer/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Load Balancers", diff --git a/internal/cmd/load-balancer/list/list_test.go b/internal/cmd/load-balancer/list/list_test.go index ee948a6f3..4d6decfa3 100644 --- a/internal/cmd/load-balancer/list/list_test.go +++ b/internal/cmd/load-balancer/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -182,7 +183,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.loadBalancers); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/load_balancer.go b/internal/cmd/load-balancer/load_balancer.go index 4a2876453..25a8f34ae 100644 --- a/internal/cmd/load-balancer/load_balancer.go +++ b/internal/cmd/load-balancer/load_balancer.go @@ -10,7 +10,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/quota" targetpool "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/target-pool" "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -18,7 +18,7 @@ import ( "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "load-balancer", Aliases: []string{"lb"}, @@ -31,7 +31,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index ece99c961..0aa0c8532 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Password *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "add", Short: "Adds observability credentials to Load Balancer", diff --git a/internal/cmd/load-balancer/observability-credentials/add/add_test.go b/internal/cmd/load-balancer/observability-credentials/add/add_test.go index b1e71cf16..f36d7e00c 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add_test.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -193,7 +194,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go index 5a521bb9f..ce2df7311 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -22,7 +23,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "cleanup", Short: "Deletes observability credentials unused by any Load Balancer", diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete.go b/internal/cmd/load-balancer/observability-credentials/delete/delete.go index a26da465f..238a9fcfb 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { CredentialsRef string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsRefArg), Short: "Deletes observability credentials for Load Balancer", diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe.go b/internal/cmd/load-balancer/observability-credentials/describe/describe.go index d0d741a08..68a4af99c 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { CredentialsRef string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsRefArg), Short: "Shows details of observability credentials for Load Balancer", diff --git a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go index 69cfd3bef..1060baeab 100644 --- a/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go +++ b/internal/cmd/load-balancer/observability-credentials/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -200,7 +201,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/observability-credentials/list/list.go b/internal/cmd/load-balancer/observability-credentials/list/list.go index 537edc93f..1b58291a6 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Unused bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists observability credentials for Load Balancer", diff --git a/internal/cmd/load-balancer/observability-credentials/list/list_test.go b/internal/cmd/load-balancer/observability-credentials/list/list_test.go index 475f4bf8f..85b3650fa 100644 --- a/internal/cmd/load-balancer/observability-credentials/list/list_test.go +++ b/internal/cmd/load-balancer/observability-credentials/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" lbUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils" @@ -253,7 +254,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/observability-credentials/observability-credentials.go b/internal/cmd/load-balancer/observability-credentials/observability-credentials.go index 03613a8de..7abc80f62 100644 --- a/internal/cmd/load-balancer/observability-credentials/observability-credentials.go +++ b/internal/cmd/load-balancer/observability-credentials/observability-credentials.go @@ -7,14 +7,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/observability-credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/observability-credentials/list" "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/observability-credentials/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "observability-credentials", Short: "Provides functionality for Load Balancer observability credentials", @@ -27,7 +27,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(add.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/load-balancer/observability-credentials/update/update.go b/internal/cmd/load-balancer/observability-credentials/update/update.go index 29761043e..dfa4e6f1a 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -46,7 +47,7 @@ type inputModel struct { Password *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", credentialsRefArg), Short: "Updates observability credentials for Load Balancer", diff --git a/internal/cmd/load-balancer/quota/quota.go b/internal/cmd/load-balancer/quota/quota.go index 0549fe177..9539612f9 100644 --- a/internal/cmd/load-balancer/quota/quota.go +++ b/internal/cmd/load-balancer/quota/quota.go @@ -5,7 +5,8 @@ import ( "fmt" "strconv" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -21,7 +22,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "quota", Short: "Shows the configured Load Balancer quota", diff --git a/internal/cmd/load-balancer/quota/quota_test.go b/internal/cmd/load-balancer/quota/quota_test.go index 634da62e0..1a3ccae0a 100644 --- a/internal/cmd/load-balancer/quota/quota_test.go +++ b/internal/cmd/load-balancer/quota/quota_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -158,7 +159,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.quota); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target.go b/internal/cmd/load-balancer/target-pool/add-target/add_target.go index 1612628fd..8bd1032ea 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -35,7 +36,7 @@ type inputModel struct { IP string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("add-target %s", ipArg), Short: "Adds a target to a target pool", diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go b/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go index 7d7b1799f..16ebc3096 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -261,7 +262,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { diff --git a/internal/cmd/load-balancer/target-pool/describe/describe.go b/internal/cmd/load-balancer/target-pool/describe/describe.go index 616323663..dadfab47d 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe.go @@ -6,8 +6,9 @@ import ( "strconv" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { LBName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", targetPoolNameArg), Short: "Shows details of a target pool in a Load Balancer", diff --git a/internal/cmd/load-balancer/target-pool/describe/describe_test.go b/internal/cmd/load-balancer/target-pool/describe/describe_test.go index d59a0fe6b..7c1a7535a 100644 --- a/internal/cmd/load-balancer/target-pool/describe/describe_test.go +++ b/internal/cmd/load-balancer/target-pool/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" @@ -137,7 +138,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { @@ -245,7 +246,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.targetPool, tt.args.listener); (err != nil) != tt.wantErr { diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go index 923521b40..c0550ade6 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { IP string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("remove-target %s", ipArg), Short: "Removes a target from a target pool", diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go index 14bb4fadc..e09747421 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -250,7 +251,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { diff --git a/internal/cmd/load-balancer/target-pool/target_pool.go b/internal/cmd/load-balancer/target-pool/target_pool.go index da2e0f7fa..7e40f76e7 100644 --- a/internal/cmd/load-balancer/target-pool/target_pool.go +++ b/internal/cmd/load-balancer/target-pool/target_pool.go @@ -4,14 +4,14 @@ import ( addtarget "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/target-pool/add-target" "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/target-pool/describe" removetarget "github.com/stackitcloud/stackit-cli/internal/cmd/load-balancer/target-pool/remove-target" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "target-pool", Short: "Provides functionality for target pools", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(addtarget.NewCmd(params)) cmd.AddCommand(removetarget.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/load-balancer/update/update.go b/internal/cmd/load-balancer/update/update.go index 47c4e5d80..7a3184e1c 100644 --- a/internal/cmd/load-balancer/update/update.go +++ b/internal/cmd/load-balancer/update/update.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { Payload loadbalancer.UpdateLoadBalancerPayload } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", loadBalancerNameArg), Short: "Updates a Load Balancer", diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 1df3832a2..5c2451e73 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for a LogMe instance", diff --git a/internal/cmd/logme/credentials/create/create_test.go b/internal/cmd/logme/credentials/create/create_test.go index a266eaac7..b2ecffe1f 100644 --- a/internal/cmd/logme/credentials/create/create_test.go +++ b/internal/cmd/logme/credentials/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -191,7 +192,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.showPassword, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/credentials/credentials.go b/internal/cmd/logme/credentials/credentials.go index 9f7cd2d7e..51f821a68 100644 --- a/internal/cmd/logme/credentials/credentials.go +++ b/internal/cmd/logme/credentials/credentials.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/logme/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/credentials/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for LogMe credentials", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/logme/credentials/delete/delete.go b/internal/cmd/logme/credentials/delete/delete.go index 0766f8e5a..3254e6f32 100644 --- a/internal/cmd/logme/credentials/delete/delete.go +++ b/internal/cmd/logme/credentials/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of a LogMe instance", diff --git a/internal/cmd/logme/credentials/describe/describe.go b/internal/cmd/logme/credentials/describe/describe.go index 7ae74bf7d..670b064c0 100644 --- a/internal/cmd/logme/credentials/describe/describe.go +++ b/internal/cmd/logme/credentials/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of a LogMe instance", diff --git a/internal/cmd/logme/credentials/describe/describe_test.go b/internal/cmd/logme/credentials/describe/describe_test.go index 324b92dd6..c2a4c9125 100644 --- a/internal/cmd/logme/credentials/describe/describe_test.go +++ b/internal/cmd/logme/credentials/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -223,7 +224,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/credentials/list/list.go b/internal/cmd/logme/credentials/list/list.go index eda5d8917..ac2660747 100644 --- a/internal/cmd/logme/credentials/list/list.go +++ b/internal/cmd/logme/credentials/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for a LogMe instance", diff --git a/internal/cmd/logme/credentials/list/list_test.go b/internal/cmd/logme/credentials/list/list_test.go index 73a86bad3..30926c183 100644 --- a/internal/cmd/logme/credentials/list/list_test.go +++ b/internal/cmd/logme/credentials/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -202,7 +203,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index fb5ea3e60..f3b1118c1 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -54,7 +55,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a LogMe instance", diff --git a/internal/cmd/logme/instance/create/create_test.go b/internal/cmd/logme/instance/create/create_test.go index 23616f5f8..73558ab91 100644 --- a/internal/cmd/logme/instance/create/create_test.go +++ b/internal/cmd/logme/instance/create/create_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -437,7 +438,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/instance/delete/delete.go b/internal/cmd/logme/instance/delete/delete.go index f606a2cee..f804e3b6d 100644 --- a/internal/cmd/logme/instance/delete/delete.go +++ b/internal/cmd/logme/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a LogMe instance", diff --git a/internal/cmd/logme/instance/describe/describe.go b/internal/cmd/logme/instance/describe/describe.go index 7b73a108c..2c579779c 100644 --- a/internal/cmd/logme/instance/describe/describe.go +++ b/internal/cmd/logme/instance/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a LogMe instance", diff --git a/internal/cmd/logme/instance/describe/describe_test.go b/internal/cmd/logme/instance/describe/describe_test.go index 3e7967085..c20d5814f 100644 --- a/internal/cmd/logme/instance/describe/describe_test.go +++ b/internal/cmd/logme/instance/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/instance/instance.go b/internal/cmd/logme/instance/instance.go index aa86b4f08..184c1b27b 100644 --- a/internal/cmd/logme/instance/instance.go +++ b/internal/cmd/logme/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/logme/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/instance/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for LogMe instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/logme/instance/list/list.go b/internal/cmd/logme/instance/list/list.go index ff5c8c55c..20efce498 100644 --- a/internal/cmd/logme/instance/list/list.go +++ b/internal/cmd/logme/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all LogMe instances", diff --git a/internal/cmd/logme/instance/list/list_test.go b/internal/cmd/logme/instance/list/list_test.go index 10c36c2ba..5104d046a 100644 --- a/internal/cmd/logme/instance/list/list_test.go +++ b/internal/cmd/logme/instance/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -178,7 +179,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/logme/instance/update/update.go b/internal/cmd/logme/instance/update/update.go index 97e016723..6d503a394 100644 --- a/internal/cmd/logme/instance/update/update.go +++ b/internal/cmd/logme/instance/update/update.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -56,7 +57,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a LogMe instance", diff --git a/internal/cmd/logme/instance/update/update_test.go b/internal/cmd/logme/instance/update/update_test.go index dc3518985..8dd59292c 100644 --- a/internal/cmd/logme/instance/update/update_test.go +++ b/internal/cmd/logme/instance/update/update_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -268,7 +269,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/logme/logme.go b/internal/cmd/logme/logme.go index a4e3f4715..a1371d7c1 100644 --- a/internal/cmd/logme/logme.go +++ b/internal/cmd/logme/logme.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/logme/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/logme/plans" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "logme", Short: "Provides functionality for LogMe", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(plans.NewCmd(params)) cmd.AddCommand(credentials.NewCmd(params)) diff --git a/internal/cmd/logme/plans/plans.go b/internal/cmd/logme/plans/plans.go index 227900628..5b1597bf4 100644 --- a/internal/cmd/logme/plans/plans.go +++ b/internal/cmd/logme/plans/plans.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all LogMe service plans", diff --git a/internal/cmd/logme/plans/plans_test.go b/internal/cmd/logme/plans/plans_test.go index 0f93fa3a9..985b0a388 100644 --- a/internal/cmd/logme/plans/plans_test.go +++ b/internal/cmd/logme/plans/plans_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -178,7 +179,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 274b8b740..9ac022e6f 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for a MariaDB instance", diff --git a/internal/cmd/mariadb/credentials/create/create_test.go b/internal/cmd/mariadb/credentials/create/create_test.go index 3ab58f4c3..d89804299 100644 --- a/internal/cmd/mariadb/credentials/create/create_test.go +++ b/internal/cmd/mariadb/credentials/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -192,7 +193,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.showPassword, tt.args.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/credentials/credentials.go b/internal/cmd/mariadb/credentials/credentials.go index e23c3887f..7f216ad4b 100644 --- a/internal/cmd/mariadb/credentials/credentials.go +++ b/internal/cmd/mariadb/credentials/credentials.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/credentials/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for MariaDB credentials", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/mariadb/credentials/delete/delete.go b/internal/cmd/mariadb/credentials/delete/delete.go index 8b8934e36..830ebd840 100644 --- a/internal/cmd/mariadb/credentials/delete/delete.go +++ b/internal/cmd/mariadb/credentials/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of a MariaDB instance", diff --git a/internal/cmd/mariadb/credentials/describe/describe.go b/internal/cmd/mariadb/credentials/describe/describe.go index 121a9228b..368e13e88 100644 --- a/internal/cmd/mariadb/credentials/describe/describe.go +++ b/internal/cmd/mariadb/credentials/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of a MariaDB instance", diff --git a/internal/cmd/mariadb/credentials/describe/describe_test.go b/internal/cmd/mariadb/credentials/describe/describe_test.go index 7f233f5c4..554add42c 100644 --- a/internal/cmd/mariadb/credentials/describe/describe_test.go +++ b/internal/cmd/mariadb/credentials/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -224,7 +225,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/credentials/list/list.go b/internal/cmd/mariadb/credentials/list/list.go index 2ba92d3e0..aa79aadf7 100644 --- a/internal/cmd/mariadb/credentials/list/list.go +++ b/internal/cmd/mariadb/credentials/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for a MariaDB instance", diff --git a/internal/cmd/mariadb/credentials/list/list_test.go b/internal/cmd/mariadb/credentials/list/list_test.go index 7b7b041cb..fbc904da7 100644 --- a/internal/cmd/mariadb/credentials/list/list_test.go +++ b/internal/cmd/mariadb/credentials/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -203,7 +204,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index e55787006..2793da086 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -54,7 +55,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a MariaDB instance", diff --git a/internal/cmd/mariadb/instance/create/create_test.go b/internal/cmd/mariadb/instance/create/create_test.go index 86cfb1daa..8001a4b2a 100644 --- a/internal/cmd/mariadb/instance/create/create_test.go +++ b/internal/cmd/mariadb/instance/create/create_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -438,7 +439,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/instance/delete/delete.go b/internal/cmd/mariadb/instance/delete/delete.go index 2f192e7c3..3e59476f6 100644 --- a/internal/cmd/mariadb/instance/delete/delete.go +++ b/internal/cmd/mariadb/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a MariaDB instance", diff --git a/internal/cmd/mariadb/instance/describe/describe.go b/internal/cmd/mariadb/instance/describe/describe.go index d06c7233c..0757fbe74 100644 --- a/internal/cmd/mariadb/instance/describe/describe.go +++ b/internal/cmd/mariadb/instance/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a MariaDB instance", diff --git a/internal/cmd/mariadb/instance/describe/describe_test.go b/internal/cmd/mariadb/instance/describe/describe_test.go index 4aa17ccc9..d8b5bda20 100644 --- a/internal/cmd/mariadb/instance/describe/describe_test.go +++ b/internal/cmd/mariadb/instance/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -197,7 +198,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/instance/instance.go b/internal/cmd/mariadb/instance/instance.go index 3b16f4864..e46e875f8 100644 --- a/internal/cmd/mariadb/instance/instance.go +++ b/internal/cmd/mariadb/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/instance/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for MariaDB instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/mariadb/instance/list/list.go b/internal/cmd/mariadb/instance/list/list.go index 6bf70a322..5c13db105 100644 --- a/internal/cmd/mariadb/instance/list/list.go +++ b/internal/cmd/mariadb/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all MariaDB instances", diff --git a/internal/cmd/mariadb/instance/list/list_test.go b/internal/cmd/mariadb/instance/list/list_test.go index 092af5002..ff8f033cf 100644 --- a/internal/cmd/mariadb/instance/list/list_test.go +++ b/internal/cmd/mariadb/instance/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -179,7 +180,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mariadb/instance/update/update.go b/internal/cmd/mariadb/instance/update/update.go index bf16d188d..6aa6f701d 100644 --- a/internal/cmd/mariadb/instance/update/update.go +++ b/internal/cmd/mariadb/instance/update/update.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -54,7 +55,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a MariaDB instance", diff --git a/internal/cmd/mariadb/instance/update/update_test.go b/internal/cmd/mariadb/instance/update/update_test.go index 5fb7369c5..d2fba4758 100644 --- a/internal/cmd/mariadb/instance/update/update_test.go +++ b/internal/cmd/mariadb/instance/update/update_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -279,7 +280,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/mariadb/mariadb.go b/internal/cmd/mariadb/mariadb.go index 602949253..5f8c41185 100644 --- a/internal/cmd/mariadb/mariadb.go +++ b/internal/cmd/mariadb/mariadb.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/mariadb/plans" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "mariadb", Short: "Provides functionality for MariaDB", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(plans.NewCmd(params)) cmd.AddCommand(credentials.NewCmd(params)) diff --git a/internal/cmd/mariadb/plans/plans.go b/internal/cmd/mariadb/plans/plans.go index a09b9cb56..5a6d9f017 100644 --- a/internal/cmd/mariadb/plans/plans.go +++ b/internal/cmd/mariadb/plans/plans.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all MariaDB service plans", diff --git a/internal/cmd/mariadb/plans/plans_test.go b/internal/cmd/mariadb/plans/plans_test.go index 411579760..3c8cf58fb 100644 --- a/internal/cmd/mariadb/plans/plans_test.go +++ b/internal/cmd/mariadb/plans/plans_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -179,7 +180,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/backup.go b/internal/cmd/mongodbflex/backup/backup.go index af716446b..e9b3e79d1 100644 --- a/internal/cmd/mongodbflex/backup/backup.go +++ b/internal/cmd/mongodbflex/backup/backup.go @@ -7,14 +7,14 @@ import ( restorejobs "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/backup/restore-jobs" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/backup/schedule" updateschedule "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/backup/update-schedule" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "backup", Short: "Provides functionality for MongoDB Flex instance backups", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(updateschedule.NewCmd(params)) cmd.AddCommand(schedule.NewCmd(params)) cmd.AddCommand(restore.NewCmd(params)) diff --git a/internal/cmd/mongodbflex/backup/describe/describe.go b/internal/cmd/mongodbflex/backup/describe/describe.go index 9f4ebe522..17bbe9b40 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe.go +++ b/internal/cmd/mongodbflex/backup/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { BackupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupIdArg), Short: "Shows details of a backup for a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/backup/describe/describe_test.go b/internal/cmd/mongodbflex/backup/describe/describe_test.go index f83ef4d0a..d621f858b 100644 --- a/internal/cmd/mongodbflex/backup/describe/describe_test.go +++ b/internal/cmd/mongodbflex/backup/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -222,7 +223,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.restoreStatus, tt.args.backup); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/list/list.go b/internal/cmd/mongodbflex/backup/list/list.go index 5287336ed..b75955b7a 100644 --- a/internal/cmd/mongodbflex/backup/list/list.go +++ b/internal/cmd/mongodbflex/backup/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all backups which are available for a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/backup/list/list_test.go b/internal/cmd/mongodbflex/backup/list/list_test.go index a6d13d8e4..253b82936 100644 --- a/internal/cmd/mongodbflex/backup/list/list_test.go +++ b/internal/cmd/mongodbflex/backup/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -217,7 +218,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.backups, tt.args.restoreJobs); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go index c078ed2cd..1822b4583 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "restore-jobs", Short: "Lists all restore jobs which have been run for a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go index 7b6419bbe..816148d5a 100644 --- a/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go +++ b/internal/cmd/mongodbflex/backup/restore-jobs/restore_jobs_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -207,7 +208,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.restoreJobs); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index d853f953b..f7e5feb79 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Timestamp string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "restore", Short: "Restores a MongoDB Flex instance from a backup", diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule.go b/internal/cmd/mongodbflex/backup/schedule/schedule.go index 3a34a9e58..614b42082 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "schedule", Short: "Shows details of the backup schedule and retention policy of a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go index ab81c09e8..a922ca4b6 100644 --- a/internal/cmd/mongodbflex/backup/schedule/schedule_test.go +++ b/internal/cmd/mongodbflex/backup/schedule/schedule_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -183,7 +184,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go index 111ba4281..ce4dce055 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go @@ -5,8 +5,9 @@ import ( "fmt" "strconv" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -47,7 +48,7 @@ type inputModel struct { MonthlySnapshotRetentionMonths *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update-schedule", Short: "Updates the backup schedule and retention policy for a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 39fe64514..6a7c181e6 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -5,8 +5,9 @@ import ( "errors" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -55,7 +56,7 @@ type inputModel struct { Type *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/instance/create/create_test.go b/internal/cmd/mongodbflex/instance/create/create_test.go index 794b5b9fd..acb37784c 100644 --- a/internal/cmd/mongodbflex/instance/create/create_test.go +++ b/internal/cmd/mongodbflex/instance/create/create_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -533,7 +534,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.projectLabel, tt.args.createInstanceResponse); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/instance/delete/delete.go b/internal/cmd/mongodbflex/instance/delete/delete.go index 5ae1da16a..f5316c8fe 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete.go +++ b/internal/cmd/mongodbflex/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/instance/describe/describe.go b/internal/cmd/mongodbflex/instance/describe/describe.go index 7738ec0fd..c20de2606 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe.go +++ b/internal/cmd/mongodbflex/instance/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/instance/describe/describe_test.go b/internal/cmd/mongodbflex/instance/describe/describe_test.go index b63b62933..976e08e7f 100644 --- a/internal/cmd/mongodbflex/instance/describe/describe_test.go +++ b/internal/cmd/mongodbflex/instance/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -200,7 +201,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/instance/instance.go b/internal/cmd/mongodbflex/instance/instance.go index a4cc5b231..ee48a0632 100644 --- a/internal/cmd/mongodbflex/instance/instance.go +++ b/internal/cmd/mongodbflex/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/instance/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for MongoDB Flex instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/mongodbflex/instance/list/list.go b/internal/cmd/mongodbflex/instance/list/list.go index 1a7d398c7..74ac6bcb0 100644 --- a/internal/cmd/mongodbflex/instance/list/list.go +++ b/internal/cmd/mongodbflex/instance/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all MongoDB Flex instances", diff --git a/internal/cmd/mongodbflex/instance/list/list_test.go b/internal/cmd/mongodbflex/instance/list/list_test.go index 7ec79019f..d91c779f1 100644 --- a/internal/cmd/mongodbflex/instance/list/list_test.go +++ b/internal/cmd/mongodbflex/instance/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -184,7 +185,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceList); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index ff1d61c39..fa160df07 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -5,7 +5,8 @@ import ( "errors" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -53,7 +54,7 @@ type inputModel struct { Type *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a MongoDB Flex instance", diff --git a/internal/cmd/mongodbflex/instance/update/update_test.go b/internal/cmd/mongodbflex/instance/update/update_test.go index f9bb2dffa..77df60874 100644 --- a/internal/cmd/mongodbflex/instance/update/update_test.go +++ b/internal/cmd/mongodbflex/instance/update/update_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -287,7 +288,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -624,7 +625,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/mongodbflex.go b/internal/cmd/mongodbflex/mongodbflex.go index 50ba29f78..3376477a3 100644 --- a/internal/cmd/mongodbflex/mongodbflex.go +++ b/internal/cmd/mongodbflex/mongodbflex.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/options" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/user" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "mongodbflex", Short: "Provides functionality for MongoDB Flex", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(user.NewCmd(params)) cmd.AddCommand(options.NewCmd(params)) diff --git a/internal/cmd/mongodbflex/options/options.go b/internal/cmd/mongodbflex/options/options.go index 9d65ea4ef..73febf6cf 100644 --- a/internal/cmd/mongodbflex/options/options.go +++ b/internal/cmd/mongodbflex/options/options.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -45,7 +45,7 @@ type flavorStorages struct { Storages *mongodbflex.ListStoragesResponse `json:"storages"` } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "options", Short: "Lists MongoDB Flex options", diff --git a/internal/cmd/mongodbflex/options/options_test.go b/internal/cmd/mongodbflex/options/options_test.go index 57f549b0b..3b42e4319 100644 --- a/internal/cmd/mongodbflex/options/options_test.go +++ b/internal/cmd/mongodbflex/options/options_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -254,7 +255,7 @@ func TestBuildAndExecuteRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := &print.Printer{} - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) p.Cmd = cmd client := &mongoDBFlexClientMocked{ listFlavorsFails: tt.listFlavorsFails, @@ -369,7 +370,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.inputModel, tt.args.flavors, tt.args.versions, tt.args.storages); (err != nil) != tt.wantErr { @@ -418,7 +419,7 @@ func TestOutputResultAsTable(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResultAsTable(p, tt.args.model, tt.args.options); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index cfeb7b6ba..b1d32aed9 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -38,7 +39,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a MongoDB Flex user", diff --git a/internal/cmd/mongodbflex/user/create/create_test.go b/internal/cmd/mongodbflex/user/create/create_test.go index 7e210559e..e075bd29a 100644 --- a/internal/cmd/mongodbflex/user/create/create_test.go +++ b/internal/cmd/mongodbflex/user/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -235,7 +236,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/delete/delete.go b/internal/cmd/mongodbflex/user/delete/delete.go index b945f5ad3..54f28cdc2 100644 --- a/internal/cmd/mongodbflex/user/delete/delete.go +++ b/internal/cmd/mongodbflex/user/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", userIdArg), Short: "Deletes a MongoDB Flex user", diff --git a/internal/cmd/mongodbflex/user/describe/describe.go b/internal/cmd/mongodbflex/user/describe/describe.go index 5d9a34b3a..038894cfc 100644 --- a/internal/cmd/mongodbflex/user/describe/describe.go +++ b/internal/cmd/mongodbflex/user/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", userIdArg), Short: "Shows details of a MongoDB Flex user", diff --git a/internal/cmd/mongodbflex/user/describe/describe_test.go b/internal/cmd/mongodbflex/user/describe/describe_test.go index 604758d1d..8ba06f13d 100644 --- a/internal/cmd/mongodbflex/user/describe/describe_test.go +++ b/internal/cmd/mongodbflex/user/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -227,7 +228,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceResponseUser); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/list/list.go b/internal/cmd/mongodbflex/user/list/list.go index 94fcfcdd1..57d8530b1 100644 --- a/internal/cmd/mongodbflex/user/list/list.go +++ b/internal/cmd/mongodbflex/user/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all MongoDB Flex users of an instance", diff --git a/internal/cmd/mongodbflex/user/list/list_test.go b/internal/cmd/mongodbflex/user/list/list_test.go index d480ed651..aa7b42dd6 100644 --- a/internal/cmd/mongodbflex/user/list/list_test.go +++ b/internal/cmd/mongodbflex/user/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -201,7 +202,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.users); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index cc0fb810d..e92c189db 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reset-password %s", userIdArg), Short: "Resets the password of a MongoDB Flex user", diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go index 0836c789e..75a467eb9 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -229,7 +230,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.userLabel, tt.args.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/mongodbflex/user/update/update.go b/internal/cmd/mongodbflex/user/update/update.go index a8fcfee3e..caa91c059 100644 --- a/internal/cmd/mongodbflex/user/update/update.go +++ b/internal/cmd/mongodbflex/user/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -36,7 +37,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", userIdArg), Short: "Updates a MongoDB Flex user", diff --git a/internal/cmd/mongodbflex/user/user.go b/internal/cmd/mongodbflex/user/user.go index 0e0600ed6..ed76dffbf 100644 --- a/internal/cmd/mongodbflex/user/user.go +++ b/internal/cmd/mongodbflex/user/user.go @@ -7,14 +7,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/user/list" resetpassword "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/user/reset-password" "github.com/stackitcloud/stackit-cli/internal/cmd/mongodbflex/user/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "user", Short: "Provides functionality for MongoDB Flex users", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index 7268d0a2d..15e9b8192 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -6,7 +6,8 @@ import ( "os" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -70,7 +71,7 @@ type NetworkAreaResponses struct { RegionalArea *iaas.RegionalArea `json:"regional_area"` } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/create/create_test.go b/internal/cmd/network-area/create/create_test.go index 9bfadd260..b903ccbba 100644 --- a/internal/cmd/network-area/create/create_test.go +++ b/internal/cmd/network-area/create/create_test.go @@ -6,7 +6,8 @@ import ( "strings" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -375,7 +376,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.orgLabel, tt.args.responses); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/delete/delete.go b/internal/cmd/network-area/delete/delete.go index 0e42d5883..becf4524c 100644 --- a/internal/cmd/network-area/delete/delete.go +++ b/internal/cmd/network-area/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -34,7 +35,7 @@ type inputModel struct { AreaId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", areaIdArg), Short: "Deletes a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/describe/describe.go b/internal/cmd/network-area/describe/describe.go index 4fdf257c5..f51fa40a5 100644 --- a/internal/cmd/network-area/describe/describe.go +++ b/internal/cmd/network-area/describe/describe.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -34,7 +35,7 @@ type inputModel struct { ShowAttachedProjects bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", areaIdArg), Short: "Shows details of a STACKIT Network Area", diff --git a/internal/cmd/network-area/describe/describe_test.go b/internal/cmd/network-area/describe/describe_test.go index 70e63e145..d4cf7379c 100644 --- a/internal/cmd/network-area/describe/describe_test.go +++ b/internal/cmd/network-area/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -208,7 +209,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networkArea, tt.args.attachedProjects); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/list/list.go b/internal/cmd/network-area/list/list.go index e37822602..a7688648e 100644 --- a/internal/cmd/network-area/list/list.go +++ b/internal/cmd/network-area/list/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + rmClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/resourcemanager/client" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all STACKIT Network Areas (SNA) of an organization", diff --git a/internal/cmd/network-area/list/list_test.go b/internal/cmd/network-area/list/list_test.go index 41c51e380..2524bb8c8 100644 --- a/internal/cmd/network-area/list/list_test.go +++ b/internal/cmd/network-area/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networkAreas); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go index 33610c045..a77852fb3 100644 --- a/internal/cmd/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -31,7 +32,7 @@ type inputModel struct { NetworkRange *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a network range in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/network-range/create/create_test.go b/internal/cmd/network-area/network-range/create/create_test.go index e5b01e224..913e66b60 100644 --- a/internal/cmd/network-area/network-range/create/create_test.go +++ b/internal/cmd/network-area/network-range/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -212,7 +213,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networkAreaLabel, tt.args.networkRange); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/network-range/delete/delete.go b/internal/cmd/network-area/network-range/delete/delete.go index 4d3a94c5d..82e697109 100644 --- a/internal/cmd/network-area/network-range/delete/delete.go +++ b/internal/cmd/network-area/network-range/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -32,7 +33,7 @@ type inputModel struct { NetworkRangeId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", networkRangeIdArg), Short: "Deletes a network range in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/network-range/delete/delete_test.go b/internal/cmd/network-area/network-range/delete/delete_test.go index 79c1ad52c..a087681a8 100644 --- a/internal/cmd/network-area/network-range/delete/delete_test.go +++ b/internal/cmd/network-area/network-range/delete/delete_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -164,7 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/network-area/network-range/describe/describe.go b/internal/cmd/network-area/network-range/describe/describe.go index ee13560b9..1abd718b9 100644 --- a/internal/cmd/network-area/network-range/describe/describe.go +++ b/internal/cmd/network-area/network-range/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -32,7 +33,7 @@ type inputModel struct { NetworkRangeId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", networkRangeIdArg), Short: "Shows details of a network range in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/network-range/describe/describe_test.go b/internal/cmd/network-area/network-range/describe/describe_test.go index 6e519fef8..ede21b094 100644 --- a/internal/cmd/network-area/network-range/describe/describe_test.go +++ b/internal/cmd/network-area/network-range/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -165,7 +166,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -268,7 +269,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networkRange); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/network-range/list/list.go b/internal/cmd/network-area/network-range/list/list.go index 2fec7b330..42d57c669 100644 --- a/internal/cmd/network-area/network-range/list/list.go +++ b/internal/cmd/network-area/network-range/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { NetworkAreaId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all network ranges in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/network-range/list/list_test.go b/internal/cmd/network-area/network-range/list/list_test.go index 67044ee06..80ab8a7c4 100644 --- a/internal/cmd/network-area/network-range/list/list_test.go +++ b/internal/cmd/network-area/network-range/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -213,7 +214,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networkRanges); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/network-range/network_range.go b/internal/cmd/network-area/network-range/network_range.go index 1c52227a8..adf53b654 100644 --- a/internal/cmd/network-area/network-range/network_range.go +++ b/internal/cmd/network-area/network-range/network_range.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/network-range/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network-range", Aliases: []string{"range"}, @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/network-area/network_area.go b/internal/cmd/network-area/network_area.go index 637a7af0e..ff09d229e 100644 --- a/internal/cmd/network-area/network_area.go +++ b/internal/cmd/network-area/network_area.go @@ -9,14 +9,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network-area", Short: "Provides functionality for STACKIT Network Area (SNA)", @@ -28,7 +28,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/network-area/region/create/create.go b/internal/cmd/network-area/region/create/create.go index a4cda53d6..4adf5cee9 100644 --- a/internal/cmd/network-area/region/create/create.go +++ b/internal/cmd/network-area/region/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -44,7 +45,7 @@ type inputModel struct { IPv4TransferNetwork string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a new regional configuration for a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/region/create/create_test.go b/internal/cmd/network-area/region/create/create_test.go index 1f8cacef2..cf92c59c3 100644 --- a/internal/cmd/network-area/region/create/create_test.go +++ b/internal/cmd/network-area/region/create/create_test.go @@ -6,10 +6,11 @@ import ( "strings" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -296,7 +297,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.region, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/region/delete/delete.go b/internal/cmd/network-area/region/delete/delete.go index 37f1f8bb0..ff31aeaa2 100644 --- a/internal/cmd/network-area/region/delete/delete.go +++ b/internal/cmd/network-area/region/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { NetworkAreaId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Short: "Deletes a regional configuration for a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/region/describe/describe.go b/internal/cmd/network-area/region/describe/describe.go index 71e4f5c31..131d0f031 100644 --- a/internal/cmd/network-area/region/describe/describe.go +++ b/internal/cmd/network-area/region/describe/describe.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { NetworkAreaId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "describe", Short: "Describes a regional configuration for a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/region/describe/describe_test.go b/internal/cmd/network-area/region/describe/describe_test.go index 7d06c1794..ea4beee77 100644 --- a/internal/cmd/network-area/region/describe/describe_test.go +++ b/internal/cmd/network-area/region/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -203,7 +204,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.region, tt.args.areaId, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/region/list/list.go b/internal/cmd/network-area/region/list/list.go index 44149c9af..c74f79848 100644 --- a/internal/cmd/network-area/region/list/list.go +++ b/internal/cmd/network-area/region/list/list.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -30,7 +31,7 @@ type inputModel struct { NetworkAreaId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all configured regions for a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/region/list/list_test.go b/internal/cmd/network-area/region/list/list_test.go index bb7b3f15b..f3cbc6ec8 100644 --- a/internal/cmd/network-area/region/list/list_test.go +++ b/internal/cmd/network-area/region/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -210,7 +211,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/region/region.go b/internal/cmd/network-area/region/region.go index 99edcace2..d21eaa106 100644 --- a/internal/cmd/network-area/region/region.go +++ b/internal/cmd/network-area/region/region.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region/list" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/region/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "region", Short: "Provides functionality for regional configuration of STACKIT Network Area (SNA)", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/network-area/region/update/update.go b/internal/cmd/network-area/region/update/update.go index 9018cb175..1d1f64bf7 100644 --- a/internal/cmd/network-area/region/update/update.go +++ b/internal/cmd/network-area/region/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -37,7 +38,7 @@ type inputModel struct { IPv4MinPrefixLength *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "Updates a existing regional configuration for a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/region/update/update_test.go b/internal/cmd/network-area/region/update/update_test.go index 73482555d..90535d384 100644 --- a/internal/cmd/network-area/region/update/update_test.go +++ b/internal/cmd/network-area/region/update/update_test.go @@ -6,10 +6,11 @@ import ( "strings" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -254,7 +255,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.region, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index c8950144e..d0ad72a2b 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -6,7 +6,8 @@ import ( "net" "os" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -58,7 +59,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a static route in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/route/create/create_test.go b/internal/cmd/network-area/route/create/create_test.go index b3d577b80..497c31a66 100644 --- a/internal/cmd/network-area/route/create/create_test.go +++ b/internal/cmd/network-area/route/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -287,7 +288,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networkAreaLabel, tt.args.route); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/route/delete/delete.go b/internal/cmd/network-area/route/delete/delete.go index b888fb6d5..6292f3cd7 100644 --- a/internal/cmd/network-area/route/delete/delete.go +++ b/internal/cmd/network-area/route/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -32,7 +33,7 @@ type inputModel struct { RouteId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", routeIdArg), Short: "Deletes a static route in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/route/delete/delete_test.go b/internal/cmd/network-area/route/delete/delete_test.go index d34c268a7..6352be04a 100644 --- a/internal/cmd/network-area/route/delete/delete_test.go +++ b/internal/cmd/network-area/route/delete/delete_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -164,7 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/network-area/route/describe/describe.go b/internal/cmd/network-area/route/describe/describe.go index b650e5964..2a7e7e4f1 100644 --- a/internal/cmd/network-area/route/describe/describe.go +++ b/internal/cmd/network-area/route/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -33,7 +34,7 @@ type inputModel struct { RouteId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", routeIdArg), Short: "Shows details of a static route in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/route/describe/describe_test.go b/internal/cmd/network-area/route/describe/describe_test.go index 67345ccae..3923e2b26 100644 --- a/internal/cmd/network-area/route/describe/describe_test.go +++ b/internal/cmd/network-area/route/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -164,7 +165,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -267,7 +268,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.route); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/route/list/list.go b/internal/cmd/network-area/route/list/list.go index 9ea4f6159..d85ac49db 100644 --- a/internal/cmd/network-area/route/list/list.go +++ b/internal/cmd/network-area/route/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { NetworkAreaId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all static routes in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/route/list/list_test.go b/internal/cmd/network-area/route/list/list_test.go index 365249370..f40f9bafe 100644 --- a/internal/cmd/network-area/route/list/list_test.go +++ b/internal/cmd/network-area/route/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -231,7 +232,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.routes); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/route/routes.go b/internal/cmd/network-area/route/routes.go index 1769f349e..f6d2b3656 100644 --- a/internal/cmd/network-area/route/routes.go +++ b/internal/cmd/network-area/route/routes.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/list" "github.com/stackitcloud/stackit-cli/internal/cmd/network-area/route/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "route", Short: "Provides functionality for static routes in STACKIT Network Areas", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/network-area/route/update/update.go b/internal/cmd/network-area/route/update/update.go index 92ca244a9..c20c86601 100644 --- a/internal/cmd/network-area/route/update/update.go +++ b/internal/cmd/network-area/route/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", routeIdArg), Short: "Updates a static route in a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/route/update/update_test.go b/internal/cmd/network-area/route/update/update_test.go index da6c6e03a..855d36513 100644 --- a/internal/cmd/network-area/route/update/update_test.go +++ b/internal/cmd/network-area/route/update/update_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -197,7 +198,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -301,7 +302,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networkAreaLabel, tt.args.route); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-area/update/update.go b/internal/cmd/network-area/update/update.go index 20f426d89..71d9bd899 100644 --- a/internal/cmd/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -6,7 +6,8 @@ import ( "os" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -63,7 +64,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", areaIdArg), Short: "Updates a STACKIT Network Area (SNA)", diff --git a/internal/cmd/network-area/update/update_test.go b/internal/cmd/network-area/update/update_test.go index b46b66aab..e6963c929 100644 --- a/internal/cmd/network-area/update/update_test.go +++ b/internal/cmd/network-area/update/update_test.go @@ -6,7 +6,8 @@ import ( "strings" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -232,7 +233,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -372,7 +373,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.responses); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index ad945e81d..c660bb561 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -5,8 +5,9 @@ import ( "fmt" "regexp" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -48,7 +49,7 @@ type inputModel struct { SecurityGroups *[]string // = 36 characters + regex ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a network interface", diff --git a/internal/cmd/network-interface/create/create_test.go b/internal/cmd/network-interface/create/create_test.go index fd584b84e..5ebe70d2b 100644 --- a/internal/cmd/network-interface/create/create_test.go +++ b/internal/cmd/network-interface/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -49,7 +50,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st } func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { - var allowedAddresses []iaas.AllowedAddressesInner = []iaas.AllowedAddressesInner{ + var allowedAddresses = []iaas.AllowedAddressesInner{ iaas.StringAsAllowedAddressesInner(utils.Ptr("1.1.1.1")), iaas.StringAsAllowedAddressesInner(utils.Ptr("8.8.8.8")), iaas.StringAsAllowedAddressesInner(utils.Ptr("9.9.9.9")), @@ -87,7 +88,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateNicRequest)) iaas.ApiCre } func fixturePayload(mods ...func(payload *iaas.CreateNicPayload)) iaas.CreateNicPayload { - var allowedAddresses []iaas.AllowedAddressesInner = []iaas.AllowedAddressesInner{ + var allowedAddresses = []iaas.AllowedAddressesInner{ iaas.StringAsAllowedAddressesInner(utils.Ptr("1.1.1.1")), iaas.StringAsAllowedAddressesInner(utils.Ptr("8.8.8.8")), iaas.StringAsAllowedAddressesInner(utils.Ptr("9.9.9.9")), @@ -256,7 +257,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.projectId, tt.args.nic); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-interface/delete/delete.go b/internal/cmd/network-interface/delete/delete.go index c5d9d61e0..8db2f2376 100644 --- a/internal/cmd/network-interface/delete/delete.go +++ b/internal/cmd/network-interface/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -28,7 +29,7 @@ type inputModel struct { NicId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", nicIdArg), Short: "Deletes a network interface", diff --git a/internal/cmd/network-interface/delete/delete_test.go b/internal/cmd/network-interface/delete/delete_test.go index c0170eab1..e541c34a7 100644 --- a/internal/cmd/network-interface/delete/delete_test.go +++ b/internal/cmd/network-interface/delete/delete_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -127,7 +128,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/network-interface/describe/describe.go b/internal/cmd/network-interface/describe/describe.go index 128c333fa..52a47532a 100644 --- a/internal/cmd/network-interface/describe/describe.go +++ b/internal/cmd/network-interface/describe/describe.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { NicId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", nicIdArg), Short: "Describes a network interface", diff --git a/internal/cmd/network-interface/describe/describe_test.go b/internal/cmd/network-interface/describe/describe_test.go index 2f802bf0e..be6d7f317 100644 --- a/internal/cmd/network-interface/describe/describe_test.go +++ b/internal/cmd/network-interface/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -127,7 +128,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -230,7 +231,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.nic); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-interface/list/list.go b/internal/cmd/network-interface/list/list.go index 23fe3aa4d..21c41a260 100644 --- a/internal/cmd/network-interface/list/list.go +++ b/internal/cmd/network-interface/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { NetworkId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all network interfaces of a network", diff --git a/internal/cmd/network-interface/list/list_test.go b/internal/cmd/network-interface/list/list_test.go index 56eb5435d..d04c1d9b7 100644 --- a/internal/cmd/network-interface/list/list_test.go +++ b/internal/cmd/network-interface/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -192,7 +193,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.nics); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network-interface/network-interface.go b/internal/cmd/network-interface/network-interface.go index f9bbca3fe..d9cb6214d 100644 --- a/internal/cmd/network-interface/network-interface.go +++ b/internal/cmd/network-interface/network-interface.go @@ -7,12 +7,12 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/list" "github.com/stackitcloud/stackit-cli/internal/cmd/network-interface/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network-interface", Short: "Provides functionality for network interfaces", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(update.NewCmd(params)) diff --git a/internal/cmd/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go index 3b1902bb4..283083698 100644 --- a/internal/cmd/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -5,8 +5,9 @@ import ( "fmt" "regexp" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -46,7 +47,7 @@ type inputModel struct { SecurityGroups *[]string // = 36 characters + regex ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", nicIdArg), Short: "Updates a network interface", diff --git a/internal/cmd/network-interface/update/update_test.go b/internal/cmd/network-interface/update/update_test.go index 3f1382dab..7eba7d62d 100644 --- a/internal/cmd/network-interface/update/update_test.go +++ b/internal/cmd/network-interface/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -57,7 +58,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st } func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { - var allowedAddresses []iaas.AllowedAddressesInner = []iaas.AllowedAddressesInner{ + var allowedAddresses = []iaas.AllowedAddressesInner{ iaas.StringAsAllowedAddressesInner(utils.Ptr("1.1.1.1")), iaas.StringAsAllowedAddressesInner(utils.Ptr("8.8.8.8")), iaas.StringAsAllowedAddressesInner(utils.Ptr("9.9.9.9")), @@ -94,7 +95,7 @@ func fixtureRequest(mods ...func(request *iaas.ApiUpdateNicRequest)) iaas.ApiUpd } func fixturePayload(mods ...func(payload *iaas.UpdateNicPayload)) iaas.UpdateNicPayload { - var allowedAddresses []iaas.AllowedAddressesInner = []iaas.AllowedAddressesInner{ + var allowedAddresses = []iaas.AllowedAddressesInner{ iaas.StringAsAllowedAddressesInner(utils.Ptr("1.1.1.1")), iaas.StringAsAllowedAddressesInner(utils.Ptr("8.8.8.8")), iaas.StringAsAllowedAddressesInner(utils.Ptr("9.9.9.9")), @@ -219,7 +220,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -323,7 +324,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.projectId, tt.args.nic); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index 9877e4477..4a2098191 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -54,7 +55,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a network", @@ -288,15 +289,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli } } - routed := true - if model.NonRouted { - routed = false - } - payload := iaas.CreateNetworkPayload{ Name: model.Name, Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), - Routed: &routed, + Routed: utils.Ptr(!model.NonRouted), Ipv4: ipv4Network, Ipv6: ipv6Network, } diff --git a/internal/cmd/network/create/create_test.go b/internal/cmd/network/create/create_test.go index a73f7d07a..dbb2ea6d3 100644 --- a/internal/cmd/network/create/create_test.go +++ b/internal/cmd/network/create/create_test.go @@ -6,7 +6,8 @@ import ( "strings" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -634,7 +635,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.projectLabel, tt.args.network); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network/delete/delete.go b/internal/cmd/network/delete/delete.go index e101edf0a..4cb4410be 100644 --- a/internal/cmd/network/delete/delete.go +++ b/internal/cmd/network/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { NetworkId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", networkIdArg), Short: "Deletes a network", diff --git a/internal/cmd/network/describe/describe.go b/internal/cmd/network/describe/describe.go index c7f0d08bc..ab81a8c48 100644 --- a/internal/cmd/network/describe/describe.go +++ b/internal/cmd/network/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { NetworkId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", networkIdArg), Short: "Shows details of a network", diff --git a/internal/cmd/network/describe/describe_test.go b/internal/cmd/network/describe/describe_test.go index 5a9015489..14fa618e4 100644 --- a/internal/cmd/network/describe/describe_test.go +++ b/internal/cmd/network/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.network); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network/list/list.go b/internal/cmd/network/list/list.go index e92ab31cc..3b1fabea5 100644 --- a/internal/cmd/network/list/list.go +++ b/internal/cmd/network/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all networks of a project", diff --git a/internal/cmd/network/list/list_test.go b/internal/cmd/network/list/list_test.go index d753ab11d..67e90a2b4 100644 --- a/internal/cmd/network/list/list_test.go +++ b/internal/cmd/network/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -198,7 +199,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.networks); (err != nil) != tt.wantErr { diff --git a/internal/cmd/network/network.go b/internal/cmd/network/network.go index 5fbd7e77b..eb7c6ece7 100644 --- a/internal/cmd/network/network.go +++ b/internal/cmd/network/network.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/network/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/network/list" "github.com/stackitcloud/stackit-cli/internal/cmd/network/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network", Short: "Provides functionality for networks", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/network/update/update.go b/internal/cmd/network/update/update.go index b1891fd34..6a752b5e1 100644 --- a/internal/cmd/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -47,7 +48,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", networkIdArg), Short: "Updates a network", diff --git a/internal/cmd/network/update/update_test.go b/internal/cmd/network/update/update_test.go index 236fbcd8b..87b533c0a 100644 --- a/internal/cmd/network/update/update_test.go +++ b/internal/cmd/network/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -245,7 +246,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/object-storage/bucket/bucket.go b/internal/cmd/object-storage/bucket/bucket.go index 62d928e54..0f8ab39a3 100644 --- a/internal/cmd/object-storage/bucket/bucket.go +++ b/internal/cmd/object-storage/bucket/bucket.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/bucket/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/bucket/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/bucket/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "bucket", Short: "Provides functionality for Object Storage buckets", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index 8d2c6f942..a3409a6a5 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { BucketName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", bucketNameArg), Short: "Creates an Object Storage bucket", diff --git a/internal/cmd/object-storage/bucket/create/create_test.go b/internal/cmd/object-storage/bucket/create/create_test.go index 976dab8a0..da4fcb9cf 100644 --- a/internal/cmd/object-storage/bucket/create/create_test.go +++ b/internal/cmd/object-storage/bucket/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.bucketName, tt.args.createBucketResponse); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/bucket/delete/delete.go b/internal/cmd/object-storage/bucket/delete/delete.go index eb47d1bd7..010aa121e 100644 --- a/internal/cmd/object-storage/bucket/delete/delete.go +++ b/internal/cmd/object-storage/bucket/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { BucketName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", bucketNameArg), Short: "Deletes an Object Storage bucket", diff --git a/internal/cmd/object-storage/bucket/describe/describe.go b/internal/cmd/object-storage/bucket/describe/describe.go index 99fa3e52d..a2a3ceedb 100644 --- a/internal/cmd/object-storage/bucket/describe/describe.go +++ b/internal/cmd/object-storage/bucket/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { BucketName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", bucketNameArg), Short: "Shows details of an Object Storage bucket", diff --git a/internal/cmd/object-storage/bucket/describe/describe_test.go b/internal/cmd/object-storage/bucket/describe/describe_test.go index a55f90bc1..106844ed2 100644 --- a/internal/cmd/object-storage/bucket/describe/describe_test.go +++ b/internal/cmd/object-storage/bucket/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -194,7 +195,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.bucket); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/bucket/list/list.go b/internal/cmd/object-storage/bucket/list/list.go index 595b095b9..ff01c60d6 100644 --- a/internal/cmd/object-storage/bucket/list/list.go +++ b/internal/cmd/object-storage/bucket/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Object Storage buckets", diff --git a/internal/cmd/object-storage/bucket/list/list_test.go b/internal/cmd/object-storage/bucket/list/list_test.go index 93b467433..47be7605e 100644 --- a/internal/cmd/object-storage/bucket/list/list_test.go +++ b/internal/cmd/object-storage/bucket/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -174,7 +175,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.buckets); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index b4f8a850c..2081d3550 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { CredentialsGroupName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a credentials group to hold Object Storage access credentials", diff --git a/internal/cmd/object-storage/credentials-group/create/create_test.go b/internal/cmd/object-storage/credentials-group/create/create_test.go index 307876137..2823fc5da 100644 --- a/internal/cmd/object-storage/credentials-group/create/create_test.go +++ b/internal/cmd/object-storage/credentials-group/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -190,7 +191,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.createCredentialsGroupResponse); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/credentials-group/credentials_group.go b/internal/cmd/object-storage/credentials-group/credentials_group.go index 9b9d05129..e9ce52dbd 100644 --- a/internal/cmd/object-storage/credentials-group/credentials_group.go +++ b/internal/cmd/object-storage/credentials-group/credentials_group.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group/create" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials-group", Short: "Provides functionality for Object Storage credentials group", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) diff --git a/internal/cmd/object-storage/credentials-group/delete/delete.go b/internal/cmd/object-storage/credentials-group/delete/delete.go index 6a328b875..aad80623e 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { CredentialsGroupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsGroupIdArg), Short: "Deletes a credentials group that holds Object Storage access credentials", diff --git a/internal/cmd/object-storage/credentials-group/list/list.go b/internal/cmd/object-storage/credentials-group/list/list.go index cbad3cba1..f422ad6d3 100644 --- a/internal/cmd/object-storage/credentials-group/list/list.go +++ b/internal/cmd/object-storage/credentials-group/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials groups that hold Object Storage access credentials", diff --git a/internal/cmd/object-storage/credentials-group/list/list_test.go b/internal/cmd/object-storage/credentials-group/list/list_test.go index 2415108c4..cbbbb1a89 100644 --- a/internal/cmd/object-storage/credentials-group/list/list_test.go +++ b/internal/cmd/object-storage/credentials-group/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -181,7 +182,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentialsGroups); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index e7f9fdcfc..ef75cac78 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -5,8 +5,9 @@ import ( "fmt" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { HidePassword bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for an Object Storage credentials group", diff --git a/internal/cmd/object-storage/credentials/create/create_test.go b/internal/cmd/object-storage/credentials/create/create_test.go index f351a4d3e..46f0e2e18 100644 --- a/internal/cmd/object-storage/credentials/create/create_test.go +++ b/internal/cmd/object-storage/credentials/create/create_test.go @@ -5,7 +5,8 @@ import ( "testing" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -241,7 +242,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentialsGroupLabel, tt.args.createAccessKeyResponse); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/credentials/credentials.go b/internal/cmd/object-storage/credentials/credentials.go index 8654a6734..4a271019e 100644 --- a/internal/cmd/object-storage/credentials/credentials.go +++ b/internal/cmd/object-storage/credentials/credentials.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials/create" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for Object Storage credentials", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) diff --git a/internal/cmd/object-storage/credentials/delete/delete.go b/internal/cmd/object-storage/credentials/delete/delete.go index 5cab91f49..c8f1c63d8 100644 --- a/internal/cmd/object-storage/credentials/delete/delete.go +++ b/internal/cmd/object-storage/credentials/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of an Object Storage credentials group", diff --git a/internal/cmd/object-storage/credentials/list/list.go b/internal/cmd/object-storage/credentials/list/list.go index 522459440..f1ef8c155 100644 --- a/internal/cmd/object-storage/credentials/list/list.go +++ b/internal/cmd/object-storage/credentials/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials for an Object Storage credentials group", diff --git a/internal/cmd/object-storage/credentials/list/list_test.go b/internal/cmd/object-storage/credentials/list/list_test.go index 8e6469b18..ba6967c84 100644 --- a/internal/cmd/object-storage/credentials/list/list_test.go +++ b/internal/cmd/object-storage/credentials/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -206,7 +207,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentialsGroupLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/object-storage/disable/disable.go b/internal/cmd/object-storage/disable/disable.go index 12a0f16de..0272151f4 100644 --- a/internal/cmd/object-storage/disable/disable.go +++ b/internal/cmd/object-storage/disable/disable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -21,7 +22,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "disable", Short: "Disables Object Storage for a project", diff --git a/internal/cmd/object-storage/enable/enable.go b/internal/cmd/object-storage/enable/enable.go index e6a1ade29..c135a1212 100644 --- a/internal/cmd/object-storage/enable/enable.go +++ b/internal/cmd/object-storage/enable/enable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -21,7 +22,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "enable", Short: "Enables Object Storage for a project", diff --git a/internal/cmd/object-storage/object_storage.go b/internal/cmd/object-storage/object_storage.go index 2adfb7001..88358e0d8 100644 --- a/internal/cmd/object-storage/object_storage.go +++ b/internal/cmd/object-storage/object_storage.go @@ -6,14 +6,14 @@ import ( credentialsGroup "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/credentials-group" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/disable" "github.com/stackitcloud/stackit-cli/internal/cmd/object-storage/enable" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "object-storage", Short: "Provides functionality for Object Storage", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(bucket.NewCmd(params)) cmd.AddCommand(disable.NewCmd(params)) cmd.AddCommand(enable.NewCmd(params)) diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index f9cd2feb4..a3ef3f615 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for an Observability instance.", diff --git a/internal/cmd/observability/credentials/create/create_test.go b/internal/cmd/observability/credentials/create/create_test.go index 43ba6f271..c00d81989 100644 --- a/internal/cmd/observability/credentials/create/create_test.go +++ b/internal/cmd/observability/credentials/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -189,7 +190,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/credentials/credentials.go b/internal/cmd/observability/credentials/credentials.go index c4aa1e396..2c40cc3d2 100644 --- a/internal/cmd/observability/credentials/credentials.go +++ b/internal/cmd/observability/credentials/credentials.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/create" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/credentials/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for Observability credentials", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) diff --git a/internal/cmd/observability/credentials/delete/delete.go b/internal/cmd/observability/credentials/delete/delete.go index eeb00d2b9..86617ab82 100644 --- a/internal/cmd/observability/credentials/delete/delete.go +++ b/internal/cmd/observability/credentials/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { Username string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", usernameArg), Short: "Deletes credentials of an Observability instance", diff --git a/internal/cmd/observability/credentials/list/list.go b/internal/cmd/observability/credentials/list/list.go index 5e7e7a3ad..f26af68de 100644 --- a/internal/cmd/observability/credentials/list/list.go +++ b/internal/cmd/observability/credentials/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists the usernames of all credentials for an Observability instance", diff --git a/internal/cmd/observability/credentials/list/list_test.go b/internal/cmd/observability/credentials/list/list_test.go index ceed7952d..f2ed00e46 100644 --- a/internal/cmd/observability/credentials/list/list_test.go +++ b/internal/cmd/observability/credentials/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -203,7 +204,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/grafana/describe/describe.go b/internal/cmd/observability/grafana/describe/describe.go index 225bc18ef..674104a9b 100644 --- a/internal/cmd/observability/grafana/describe/describe.go +++ b/internal/cmd/observability/grafana/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of the Grafana configuration of an Observability instance", diff --git a/internal/cmd/observability/grafana/describe/describe_test.go b/internal/cmd/observability/grafana/describe/describe_test.go index d84af41cb..c1aeb443d 100644 --- a/internal/cmd/observability/grafana/describe/describe_test.go +++ b/internal/cmd/observability/grafana/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -170,7 +171,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -323,7 +324,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.showPassword, tt.args.grafanaConfig, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/grafana/grafana.go b/internal/cmd/observability/grafana/grafana.go index 000da5eac..7ba2a996f 100644 --- a/internal/cmd/observability/grafana/grafana.go +++ b/internal/cmd/observability/grafana/grafana.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/describe" publicreadaccess "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access" singlesignon "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "grafana", Short: "Provides functionality for the Grafana configuration of Observability instances", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(publicreadaccess.NewCmd(params)) cmd.AddCommand(singlesignon.NewCmd(params)) diff --git a/internal/cmd/observability/grafana/public-read-access/disable/disable.go b/internal/cmd/observability/grafana/public-read-access/disable/disable.go index bfb42108c..4f63f776f 100644 --- a/internal/cmd/observability/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disable %s", instanceIdArg), Short: "Disables public read access for Grafana on Observability instances", diff --git a/internal/cmd/observability/grafana/public-read-access/enable/enable.go b/internal/cmd/observability/grafana/public-read-access/enable/enable.go index b868c0535..87a79cfd8 100644 --- a/internal/cmd/observability/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("enable %s", instanceIdArg), Short: "Enables public read access for Grafana on Observability instances", diff --git a/internal/cmd/observability/grafana/public-read-access/public_read_access.go b/internal/cmd/observability/grafana/public-read-access/public_read_access.go index 94c27eb36..bf45ec5df 100644 --- a/internal/cmd/observability/grafana/public-read-access/public_read_access.go +++ b/internal/cmd/observability/grafana/public-read-access/public_read_access.go @@ -3,16 +3,17 @@ package publicreadaccess import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access/disable" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/public-read-access/enable" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "public-read-access", Short: "Enable or disable public read access for Grafana in Observability instances", @@ -27,7 +28,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(enable.NewCmd(params)) cmd.AddCommand(disable.NewCmd(params)) } diff --git a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go index a26977645..806bd02d0 100644 --- a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disable %s", instanceIdArg), Short: "Disables single sign-on for Grafana on Observability instances", diff --git a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go index f95812d80..fa8f7f6de 100644 --- a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("enable %s", instanceIdArg), Short: "Enables single sign-on for Grafana on Observability instances", diff --git a/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go b/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go index c4a73ada2..293066b8f 100644 --- a/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go +++ b/internal/cmd/observability/grafana/single-sign-on/single_sign_on.go @@ -3,16 +3,17 @@ package singlesignon import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on/disable" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/grafana/single-sign-on/enable" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "single-sign-on", Aliases: []string{"sso"}, @@ -28,7 +29,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(enable.NewCmd(params)) cmd.AddCommand(disable.NewCmd(params)) } diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 84e8b1b6b..23c4bc51a 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -5,7 +5,8 @@ import ( "errors" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -37,7 +38,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an Observability instance", diff --git a/internal/cmd/observability/instance/create/create_test.go b/internal/cmd/observability/instance/create/create_test.go index 382cbeb0a..5aac98b82 100644 --- a/internal/cmd/observability/instance/create/create_test.go +++ b/internal/cmd/observability/instance/create/create_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -325,7 +326,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/instance/delete/delete.go b/internal/cmd/observability/instance/delete/delete.go index 165c74f05..b06179e6c 100644 --- a/internal/cmd/observability/instance/delete/delete.go +++ b/internal/cmd/observability/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes an Observability instance", diff --git a/internal/cmd/observability/instance/describe/describe.go b/internal/cmd/observability/instance/describe/describe.go index ad204b74e..e9e4a256a 100644 --- a/internal/cmd/observability/instance/describe/describe.go +++ b/internal/cmd/observability/instance/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of an Observability instance", diff --git a/internal/cmd/observability/instance/describe/describe_test.go b/internal/cmd/observability/instance/describe/describe_test.go index 1aa4cc756..dd1c07d42 100644 --- a/internal/cmd/observability/instance/describe/describe_test.go +++ b/internal/cmd/observability/instance/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/instance/instance.go b/internal/cmd/observability/instance/instance.go index 47a84edf6..955ae39ec 100644 --- a/internal/cmd/observability/instance/instance.go +++ b/internal/cmd/observability/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for Observability instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(update.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/observability/instance/list/list.go b/internal/cmd/observability/instance/list/list.go index ff124b8fb..2d31e348c 100644 --- a/internal/cmd/observability/instance/list/list.go +++ b/internal/cmd/observability/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Observability instances", diff --git a/internal/cmd/observability/instance/list/list_test.go b/internal/cmd/observability/instance/list/list_test.go index f4c1b20b7..456dbfb20 100644 --- a/internal/cmd/observability/instance/list/list_test.go +++ b/internal/cmd/observability/instance/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -179,7 +180,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/instance/update/update.go b/internal/cmd/observability/instance/update/update.go index d4ae51392..c97eb98ba 100644 --- a/internal/cmd/observability/instance/update/update.go +++ b/internal/cmd/observability/instance/update/update.go @@ -5,7 +5,8 @@ import ( "errors" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -39,7 +40,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates an Observability instance", diff --git a/internal/cmd/observability/observability.go b/internal/cmd/observability/observability.go index 136f29637..66345691a 100644 --- a/internal/cmd/observability/observability.go +++ b/internal/cmd/observability/observability.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/plans" scrapeconfig "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "observability", Short: "Provides functionality for Observability", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(grafana.NewCmd(params)) cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(credentials.NewCmd(params)) diff --git a/internal/cmd/observability/plans/plans.go b/internal/cmd/observability/plans/plans.go index 322bebb0d..5ef3952ed 100644 --- a/internal/cmd/observability/plans/plans.go +++ b/internal/cmd/observability/plans/plans.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all Observability service plans", diff --git a/internal/cmd/observability/plans/plans_test.go b/internal/cmd/observability/plans/plans_test.go index 36026aecf..65fb129d3 100644 --- a/internal/cmd/observability/plans/plans_test.go +++ b/internal/cmd/observability/plans/plans_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -179,7 +180,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go index 43ff12a8f..c4e8a4dac 100644 --- a/internal/cmd/observability/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { Payload *observability.CreateScrapeConfigPayload } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a scrape configuration for an Observability instance", diff --git a/internal/cmd/observability/scrape-config/delete/delete.go b/internal/cmd/observability/scrape-config/delete/delete.go index 5ec7e3931..ceae80ac5 100644 --- a/internal/cmd/observability/scrape-config/delete/delete.go +++ b/internal/cmd/observability/scrape-config/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", jobNameArg), Short: "Deletes a scrape configuration from an Observability instance", diff --git a/internal/cmd/observability/scrape-config/describe/describe.go b/internal/cmd/observability/scrape-config/describe/describe.go index 1558edbbc..91dc0d064 100644 --- a/internal/cmd/observability/scrape-config/describe/describe.go +++ b/internal/cmd/observability/scrape-config/describe/describe.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", jobNameArg), Short: "Shows details of a scrape configuration from an Observability instance", diff --git a/internal/cmd/observability/scrape-config/describe/describe_test.go b/internal/cmd/observability/scrape-config/describe/describe_test.go index d975ba82c..5f4326b33 100644 --- a/internal/cmd/observability/scrape-config/describe/describe_test.go +++ b/internal/cmd/observability/scrape-config/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -258,7 +259,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.config); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go index 5476fbd94..e891d728e 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/fileutils" @@ -32,7 +33,7 @@ type inputModel struct { FilePath *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "generate-payload", Short: "Generates a payload to create/update scrape configurations for an Observability instance ", diff --git a/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go index 07be71444..81d3138e3 100644 --- a/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go +++ b/internal/cmd/observability/scrape-config/generate-payload/generate_payload_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -232,7 +233,7 @@ func TestOutputCreateResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputCreateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { @@ -266,7 +267,7 @@ func TestOutputUpdateResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputUpdateResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/scrape-config/list/list.go b/internal/cmd/observability/scrape-config/list/list.go index 1002a87d8..faab36b0a 100644 --- a/internal/cmd/observability/scrape-config/list/list.go +++ b/internal/cmd/observability/scrape-config/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all scrape configurations of an Observability instance", diff --git a/internal/cmd/observability/scrape-config/list/list_test.go b/internal/cmd/observability/scrape-config/list/list_test.go index 371944178..6d4569d71 100644 --- a/internal/cmd/observability/scrape-config/list/list_test.go +++ b/internal/cmd/observability/scrape-config/list/list_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -204,7 +205,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.configs); (err != nil) != tt.wantErr { diff --git a/internal/cmd/observability/scrape-config/scrape_config.go b/internal/cmd/observability/scrape-config/scrape_config.go index d0934ff3b..b45cff386 100644 --- a/internal/cmd/observability/scrape-config/scrape_config.go +++ b/internal/cmd/observability/scrape-config/scrape_config.go @@ -7,14 +7,14 @@ import ( generatepayload "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/generate-payload" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/list" "github.com/stackitcloud/stackit-cli/internal/cmd/observability/scrape-config/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "scrape-config", Short: "Provides functionality for scrape configurations in Observability", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(generatepayload.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/observability/scrape-config/update/update.go b/internal/cmd/observability/scrape-config/update/update.go index ab39ea9e0..3556e6620 100644 --- a/internal/cmd/observability/scrape-config/update/update.go +++ b/internal/cmd/observability/scrape-config/update/update.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { Payload observability.UpdateScrapeConfigPayload } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", jobNameArg), Short: "Updates a scrape configuration of an Observability instance", diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index c74347c51..f44215219 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for an OpenSearch instance", diff --git a/internal/cmd/opensearch/credentials/create/create_test.go b/internal/cmd/opensearch/credentials/create/create_test.go index 9b9057414..0c768de74 100644 --- a/internal/cmd/opensearch/credentials/create/create_test.go +++ b/internal/cmd/opensearch/credentials/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -233,7 +234,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.showPassword, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/credentials/credentials.go b/internal/cmd/opensearch/credentials/credentials.go index 3e1c17ba8..e9c878d02 100644 --- a/internal/cmd/opensearch/credentials/credentials.go +++ b/internal/cmd/opensearch/credentials/credentials.go @@ -5,14 +5,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/credentials/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for OpenSearch credentials", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/opensearch/credentials/delete/delete.go b/internal/cmd/opensearch/credentials/delete/delete.go index c513cb55e..d8b57c185 100644 --- a/internal/cmd/opensearch/credentials/delete/delete.go +++ b/internal/cmd/opensearch/credentials/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of an OpenSearch instance", diff --git a/internal/cmd/opensearch/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index 2acf9188a..17ddd78f9 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of an OpenSearch instance", diff --git a/internal/cmd/opensearch/credentials/describe/describe_test.go b/internal/cmd/opensearch/credentials/describe/describe_test.go index f9b43012d..254912869 100644 --- a/internal/cmd/opensearch/credentials/describe/describe_test.go +++ b/internal/cmd/opensearch/credentials/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -221,7 +222,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index 7a086385b..05f4e8ef8 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for an OpenSearch instance", diff --git a/internal/cmd/opensearch/credentials/list/list_test.go b/internal/cmd/opensearch/credentials/list/list_test.go index ee376658f..514606b9e 100644 --- a/internal/cmd/opensearch/credentials/list/list_test.go +++ b/internal/cmd/opensearch/credentials/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -202,7 +203,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index 826c6990f..91fe825c8 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -56,7 +57,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an OpenSearch instance", diff --git a/internal/cmd/opensearch/instance/create/create_test.go b/internal/cmd/opensearch/instance/create/create_test.go index 9d14e0bd4..27822b653 100644 --- a/internal/cmd/opensearch/instance/create/create_test.go +++ b/internal/cmd/opensearch/instance/create/create_test.go @@ -5,9 +5,10 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -453,7 +454,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/instance/delete/delete.go b/internal/cmd/opensearch/instance/delete/delete.go index 7d5996c6b..31983b4a5 100644 --- a/internal/cmd/opensearch/instance/delete/delete.go +++ b/internal/cmd/opensearch/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes an OpenSearch instance", diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index 44aa6cb82..663ce82de 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of an OpenSearch instance", diff --git a/internal/cmd/opensearch/instance/describe/describe_test.go b/internal/cmd/opensearch/instance/describe/describe_test.go index 633d7da44..a90f5d142 100644 --- a/internal/cmd/opensearch/instance/describe/describe_test.go +++ b/internal/cmd/opensearch/instance/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -194,7 +195,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/instance/instance.go b/internal/cmd/opensearch/instance/instance.go index 05d92bbc6..d8f58a668 100644 --- a/internal/cmd/opensearch/instance/instance.go +++ b/internal/cmd/opensearch/instance/instance.go @@ -6,14 +6,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/instance/update" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for OpenSearch instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index a6c57bc29..0dacbcf6d 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all OpenSearch instances", diff --git a/internal/cmd/opensearch/instance/list/list_test.go b/internal/cmd/opensearch/instance/list/list_test.go index 15f772725..910c0fab3 100644 --- a/internal/cmd/opensearch/instance/list/list_test.go +++ b/internal/cmd/opensearch/instance/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -178,7 +179,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/opensearch/instance/update/update.go b/internal/cmd/opensearch/instance/update/update.go index 3b1114780..fab2792f0 100644 --- a/internal/cmd/opensearch/instance/update/update.go +++ b/internal/cmd/opensearch/instance/update/update.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -57,7 +58,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates an OpenSearch instance", diff --git a/internal/cmd/opensearch/instance/update/update_test.go b/internal/cmd/opensearch/instance/update/update_test.go index 934088f02..3d7b291d2 100644 --- a/internal/cmd/opensearch/instance/update/update_test.go +++ b/internal/cmd/opensearch/instance/update/update_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -293,7 +294,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/opensearch/opensearch.go b/internal/cmd/opensearch/opensearch.go index 766065ed2..96d02fd3e 100644 --- a/internal/cmd/opensearch/opensearch.go +++ b/internal/cmd/opensearch/opensearch.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch/plans" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "opensearch", Short: "Provides functionality for OpenSearch", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(plans.NewCmd(params)) cmd.AddCommand(credentials.NewCmd(params)) diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index 5ba348f99..3f644c000 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all OpenSearch service plans", diff --git a/internal/cmd/opensearch/plans/plans_test.go b/internal/cmd/opensearch/plans/plans_test.go index 093e129fd..aedcd19b3 100644 --- a/internal/cmd/opensearch/plans/plans_test.go +++ b/internal/cmd/opensearch/plans/plans_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -178,7 +179,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/organization/member/add/add.go b/internal/cmd/organization/member/add/add.go index 297e64c33..f41eaa06d 100644 --- a/internal/cmd/organization/member/add/add.go +++ b/internal/cmd/organization/member/add/add.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -33,7 +34,7 @@ type inputModel struct { Role *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("add %s", subjectArg), Short: "Adds a member to an organization", diff --git a/internal/cmd/organization/member/list/list.go b/internal/cmd/organization/member/list/list.go index d4989bc76..7e17796c6 100644 --- a/internal/cmd/organization/member/list/list.go +++ b/internal/cmd/organization/member/list/list.go @@ -5,8 +5,9 @@ import ( "fmt" "sort" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -37,7 +38,7 @@ type inputModel struct { SortBy string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists members of an organization", @@ -159,9 +160,10 @@ func outputResult(p *print.Printer, outputFormat, sortBy string, members []autho table.AddRow(utils.PtrString(m.Subject), utils.PtrString(m.Role)) } - if sortBy == "subject" { + switch sortBy { + case "subject": table.EnableAutoMergeOnColumns(1) - } else if sortBy == "role" { + case "role": table.EnableAutoMergeOnColumns(2) } diff --git a/internal/cmd/organization/member/list/list_test.go b/internal/cmd/organization/member/list/list_test.go index 37f13746b..675cbd787 100644 --- a/internal/cmd/organization/member/list/list_test.go +++ b/internal/cmd/organization/member/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -198,7 +199,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.sortBy, tt.args.members); (err != nil) != tt.wantErr { diff --git a/internal/cmd/organization/member/member.go b/internal/cmd/organization/member/member.go index fe2b67e5d..bc4a8b200 100644 --- a/internal/cmd/organization/member/member.go +++ b/internal/cmd/organization/member/member.go @@ -4,14 +4,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/organization/member/add" "github.com/stackitcloud/stackit-cli/internal/cmd/organization/member/list" "github.com/stackitcloud/stackit-cli/internal/cmd/organization/member/remove" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "member", Short: "Manages organization members", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(add.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(remove.NewCmd(params)) diff --git a/internal/cmd/organization/member/remove/remove.go b/internal/cmd/organization/member/remove/remove.go index f79075bdb..f0d5ee13c 100644 --- a/internal/cmd/organization/member/remove/remove.go +++ b/internal/cmd/organization/member/remove/remove.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -36,7 +37,7 @@ type inputModel struct { Force bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("remove %s", subjectArg), Short: "Removes a member from an organization", diff --git a/internal/cmd/organization/organization.go b/internal/cmd/organization/organization.go index e7d1376b5..7a68177b7 100644 --- a/internal/cmd/organization/organization.go +++ b/internal/cmd/organization/organization.go @@ -3,16 +3,17 @@ package organization import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/cmd/organization/member" "github.com/stackitcloud/stackit-cli/internal/cmd/organization/role" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "organization", Short: "Manages organizations", @@ -27,7 +28,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(member.NewCmd(params)) cmd.AddCommand(role.NewCmd(params)) } diff --git a/internal/cmd/organization/role/list/list.go b/internal/cmd/organization/role/list/list.go index 9603d0212..bb59b28c5 100644 --- a/internal/cmd/organization/role/list/list.go +++ b/internal/cmd/organization/role/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists roles and permissions of an organization", diff --git a/internal/cmd/organization/role/list/list_test.go b/internal/cmd/organization/role/list/list_test.go index 7e2dcb518..5396717d0 100644 --- a/internal/cmd/organization/role/list/list_test.go +++ b/internal/cmd/organization/role/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -160,7 +161,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputRolesResult(p, tt.args.outputFormat, tt.args.roles); (err != nil) != tt.wantErr { diff --git a/internal/cmd/organization/role/role.go b/internal/cmd/organization/role/role.go index 286783661..d3146aca8 100644 --- a/internal/cmd/organization/role/role.go +++ b/internal/cmd/organization/role/role.go @@ -2,14 +2,14 @@ package role import ( "github.com/stackitcloud/stackit-cli/internal/cmd/organization/role/list" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "role", Short: "Manages organization roles", @@ -21,6 +21,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/postgresflex/backup/backup.go b/internal/cmd/postgresflex/backup/backup.go index bac6c4a72..f6ad7c518 100644 --- a/internal/cmd/postgresflex/backup/backup.go +++ b/internal/cmd/postgresflex/backup/backup.go @@ -1,17 +1,17 @@ package backup import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/backup/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/backup/list" updateschedule "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/backup/update-schedule" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "backup", Short: "Provides functionality for PostgreSQL Flex instance backups", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(updateschedule.NewCmd(params)) diff --git a/internal/cmd/postgresflex/backup/describe/describe.go b/internal/cmd/postgresflex/backup/describe/describe.go index 930bf334a..891b78888 100644 --- a/internal/cmd/postgresflex/backup/describe/describe.go +++ b/internal/cmd/postgresflex/backup/describe/describe.go @@ -5,8 +5,9 @@ import ( "fmt" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { BackupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupIdArg), Short: "Shows details of a backup for a PostgreSQL Flex instance", diff --git a/internal/cmd/postgresflex/backup/describe/describe_test.go b/internal/cmd/postgresflex/backup/describe/describe_test.go index 6e47eabb0..cd44d829e 100644 --- a/internal/cmd/postgresflex/backup/describe/describe_test.go +++ b/internal/cmd/postgresflex/backup/describe/describe_test.go @@ -5,10 +5,11 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -263,7 +264,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/backup/list/list.go b/internal/cmd/postgresflex/backup/list/list.go index cfd5718d5..004159b2b 100644 --- a/internal/cmd/postgresflex/backup/list/list.go +++ b/internal/cmd/postgresflex/backup/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -37,7 +38,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all backups which are available for a PostgreSQL Flex instance", @@ -77,10 +78,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command { req := buildRequest(ctx, model, apiClient) resp, err := req.Execute() if err != nil { - return fmt.Errorf("get backups for PostgreSQL Flex instance %q: %w\n", instanceLabel, err) + return fmt.Errorf("get backups for PostgreSQL Flex instance %q: %w", instanceLabel, err) } if resp.Items == nil || len(*resp.Items) == 0 { - cmd.Printf("No backups found for instance %q\n", instanceLabel) + params.Printer.Outputf("No backups found for instance %q", instanceLabel) return nil } backups := *resp.Items diff --git a/internal/cmd/postgresflex/backup/list/list_test.go b/internal/cmd/postgresflex/backup/list/list_test.go index 4ac63c37c..39c9d8f53 100644 --- a/internal/cmd/postgresflex/backup/list/list_test.go +++ b/internal/cmd/postgresflex/backup/list/list_test.go @@ -5,12 +5,13 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "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" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -209,7 +210,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go index 9d8bf59fc..5e954322e 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { BackupSchedule *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update-schedule", Short: "Updates backup schedule for a PostgreSQL Flex instance", diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index 10da911bb..9c72a9874 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -39,7 +40,7 @@ type inputModel struct { RecoveryDate *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("clone %s", instanceIdArg), Short: "Clones a PostgreSQL Flex instance", diff --git a/internal/cmd/postgresflex/instance/clone/clone_test.go b/internal/cmd/postgresflex/instance/clone/clone_test.go index 5f2a60189..657670aa2 100644 --- a/internal/cmd/postgresflex/instance/clone/clone_test.go +++ b/internal/cmd/postgresflex/instance/clone/clone_test.go @@ -6,10 +6,11 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -508,7 +509,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 1e3172a3b..de9106998 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -5,7 +5,8 @@ import ( "errors" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -56,7 +57,7 @@ type inputModel struct { Type *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a PostgreSQL Flex instance", diff --git a/internal/cmd/postgresflex/instance/create/create_test.go b/internal/cmd/postgresflex/instance/create/create_test.go index 09b6b2311..f3fa498c2 100644 --- a/internal/cmd/postgresflex/instance/create/create_test.go +++ b/internal/cmd/postgresflex/instance/create/create_test.go @@ -5,10 +5,11 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -503,7 +504,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/postgresflex/instance/delete/delete.go b/internal/cmd/postgresflex/instance/delete/delete.go index 5b8cbbd91..56401d564 100644 --- a/internal/cmd/postgresflex/instance/delete/delete.go +++ b/internal/cmd/postgresflex/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { ForceDelete bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a PostgreSQL Flex instance", diff --git a/internal/cmd/postgresflex/instance/describe/describe.go b/internal/cmd/postgresflex/instance/describe/describe.go index a9480e74e..a50f3f167 100644 --- a/internal/cmd/postgresflex/instance/describe/describe.go +++ b/internal/cmd/postgresflex/instance/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a PostgreSQL Flex instance", diff --git a/internal/cmd/postgresflex/instance/describe/describe_test.go b/internal/cmd/postgresflex/instance/describe/describe_test.go index 9331b81d4..80ce6c262 100644 --- a/internal/cmd/postgresflex/instance/describe/describe_test.go +++ b/internal/cmd/postgresflex/instance/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -214,7 +215,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/instance/instance.go b/internal/cmd/postgresflex/instance/instance.go index f43979195..5beba3e48 100644 --- a/internal/cmd/postgresflex/instance/instance.go +++ b/internal/cmd/postgresflex/instance/instance.go @@ -1,7 +1,6 @@ package instance import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/clone" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/create" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/delete" @@ -9,12 +8,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for PostgreSQL Flex instances", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/postgresflex/instance/list/list.go b/internal/cmd/postgresflex/instance/list/list.go index 148a31d46..2b20dc3e2 100644 --- a/internal/cmd/postgresflex/instance/list/list.go +++ b/internal/cmd/postgresflex/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all PostgreSQL Flex instances", diff --git a/internal/cmd/postgresflex/instance/list/list_test.go b/internal/cmd/postgresflex/instance/list/list_test.go index c8c2d8a7a..dfde2729a 100644 --- a/internal/cmd/postgresflex/instance/list/list_test.go +++ b/internal/cmd/postgresflex/instance/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -179,7 +180,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index f2784645c..9eef70391 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -5,7 +5,8 @@ import ( "errors" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -53,7 +54,7 @@ type inputModel struct { Type *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a PostgreSQL Flex instance", diff --git a/internal/cmd/postgresflex/instance/update/update_test.go b/internal/cmd/postgresflex/instance/update/update_test.go index 0c4ed96b6..1402996f7 100644 --- a/internal/cmd/postgresflex/instance/update/update_test.go +++ b/internal/cmd/postgresflex/instance/update/update_test.go @@ -5,10 +5,11 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -283,7 +284,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -621,7 +622,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/options/options.go b/internal/cmd/postgresflex/options/options.go index d5afbbbf5..ad57495d3 100644 --- a/internal/cmd/postgresflex/options/options.go +++ b/internal/cmd/postgresflex/options/options.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -46,7 +46,7 @@ type flavorStorages struct { Storages *postgresflex.ListStoragesResponse `json:"storages"` } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "options", Short: "Lists PostgreSQL Flex options", diff --git a/internal/cmd/postgresflex/options/options_test.go b/internal/cmd/postgresflex/options/options_test.go index 4f7f5c67f..bd47b14ba 100644 --- a/internal/cmd/postgresflex/options/options_test.go +++ b/internal/cmd/postgresflex/options/options_test.go @@ -5,8 +5,9 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -262,7 +263,7 @@ func TestBuildAndExecuteRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := &print.Printer{} - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) p.Cmd = cmd client := &postgresFlexClientMocked{ listFlavorsFails: tt.listFlavorsFails, @@ -332,7 +333,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.flavors, tt.args.versions, tt.args.storages); (err != nil) != tt.wantErr { diff --git a/internal/cmd/postgresflex/postgresflex.go b/internal/cmd/postgresflex/postgresflex.go index 3a86086c2..536584f2f 100644 --- a/internal/cmd/postgresflex/postgresflex.go +++ b/internal/cmd/postgresflex/postgresflex.go @@ -1,18 +1,18 @@ package postgresflex import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/backup" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/options" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "postgresflex", Aliases: []string{"postgresqlflex"}, @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(user.NewCmd(params)) cmd.AddCommand(options.NewCmd(params)) diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 73682a34a..7623ba786 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a PostgreSQL Flex user", diff --git a/internal/cmd/postgresflex/user/create/create_test.go b/internal/cmd/postgresflex/user/create/create_test.go index bbd08e214..2ab611d42 100644 --- a/internal/cmd/postgresflex/user/create/create_test.go +++ b/internal/cmd/postgresflex/user/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -219,7 +220,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/user/delete/delete.go b/internal/cmd/postgresflex/user/delete/delete.go index 38b20dbfe..219798121 100644 --- a/internal/cmd/postgresflex/user/delete/delete.go +++ b/internal/cmd/postgresflex/user/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", userIdArg), Short: "Deletes a PostgreSQL Flex user", diff --git a/internal/cmd/postgresflex/user/describe/describe.go b/internal/cmd/postgresflex/user/describe/describe.go index c0f3f450d..01ab5fce1 100644 --- a/internal/cmd/postgresflex/user/describe/describe.go +++ b/internal/cmd/postgresflex/user/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", userIdArg), Short: "Shows details of a PostgreSQL Flex user", diff --git a/internal/cmd/postgresflex/user/describe/describe_test.go b/internal/cmd/postgresflex/user/describe/describe_test.go index ad6a2377f..92b83cc99 100644 --- a/internal/cmd/postgresflex/user/describe/describe_test.go +++ b/internal/cmd/postgresflex/user/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -214,7 +215,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/user/list/list.go b/internal/cmd/postgresflex/user/list/list.go index 420619f46..a8dc23773 100644 --- a/internal/cmd/postgresflex/user/list/list.go +++ b/internal/cmd/postgresflex/user/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all PostgreSQL Flex users of an instance", diff --git a/internal/cmd/postgresflex/user/list/list_test.go b/internal/cmd/postgresflex/user/list/list_test.go index 8985f945f..2695296c7 100644 --- a/internal/cmd/postgresflex/user/list/list_test.go +++ b/internal/cmd/postgresflex/user/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -183,7 +184,7 @@ func Test_outputResult(t *testing.T) { }}}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index 0a69b4c94..3c78d191f 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reset-password %s", userIdArg), Short: "Resets the password of a PostgreSQL Flex user", diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go index 51572b406..920c78b93 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password_test.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -215,7 +216,7 @@ func Test_outputResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/postgresflex/user/update/update.go b/internal/cmd/postgresflex/user/update/update.go index c8b24f1d3..3ebb2231f 100644 --- a/internal/cmd/postgresflex/user/update/update.go +++ b/internal/cmd/postgresflex/user/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { Roles *[]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", userIdArg), Short: "Updates a PostgreSQL Flex user", diff --git a/internal/cmd/postgresflex/user/user.go b/internal/cmd/postgresflex/user/user.go index af9d371ef..ce566f5b7 100644 --- a/internal/cmd/postgresflex/user/user.go +++ b/internal/cmd/postgresflex/user/user.go @@ -1,7 +1,6 @@ package user import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/create" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/describe" @@ -9,12 +8,13 @@ import ( resetpassword "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/reset-password" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex/user/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "user", Short: "Provides functionality for PostgreSQL Flex users", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index c70e58e92..e00210b71 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -5,7 +5,8 @@ import ( "fmt" "regexp" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -40,7 +41,7 @@ type inputModel struct { NetworkAreaId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a STACKIT project", diff --git a/internal/cmd/project/create/create_test.go b/internal/cmd/project/create/create_test.go index 3503b0b68..095469298 100644 --- a/internal/cmd/project/create/create_test.go +++ b/internal/cmd/project/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -330,7 +331,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/project/delete/delete.go b/internal/cmd/project/delete/delete.go index eff9d2615..314fb621e 100644 --- a/internal/cmd/project/delete/delete.go +++ b/internal/cmd/project/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -21,7 +22,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Short: "Deletes a STACKIT project", diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index b1db718bf..52dc280b3 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -30,7 +31,7 @@ type inputModel struct { IncludeParents bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "describe", Short: "Shows details of a STACKIT project", @@ -86,7 +87,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" && projectId == "" { - return nil, fmt.Errorf("Project ID needs to be provided either as an argument or as a flag") + return nil, fmt.Errorf("project ID needs to be provided either as an argument or as a flag") } if projectId == "" { diff --git a/internal/cmd/project/describe/describe_test.go b/internal/cmd/project/describe/describe_test.go index 2afd90610..b5f3ddcff 100644 --- a/internal/cmd/project/describe/describe_test.go +++ b/internal/cmd/project/describe/describe_test.go @@ -5,10 +5,11 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -193,7 +194,7 @@ func Test_outputResult(t *testing.T) { }, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.project); (err != nil) != tt.wantErr { diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index fe7f8503a..d4ef99b63 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -5,8 +5,9 @@ import ( "fmt" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -42,7 +43,7 @@ type inputModel struct { PageSize int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists STACKIT projects", diff --git a/internal/cmd/project/list/list_test.go b/internal/cmd/project/list/list_test.go index baf7fed6d..8050a0f27 100644 --- a/internal/cmd/project/list/list_test.go +++ b/internal/cmd/project/list/list_test.go @@ -9,12 +9,13 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "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" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -486,7 +487,7 @@ func Test_outputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/cmd/project/member/add/add.go b/internal/cmd/project/member/add/add.go index f8491a6de..d08437440 100644 --- a/internal/cmd/project/member/add/add.go +++ b/internal/cmd/project/member/add/add.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -34,7 +35,7 @@ type inputModel struct { Role *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("add %s", subjectArg), Short: "Adds a member to a project", @@ -119,7 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *authorization.APIClient) authorization.ApiAddMembersRequest { - req := apiClient.AddMembers(ctx, model.GlobalFlagModel.ProjectId) + req := apiClient.AddMembers(ctx, model.ProjectId) req = req.AddMembersPayload(authorization.AddMembersPayload{ Members: utils.Ptr([]authorization.Member{ { diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index 04d141e3b..66df41524 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -5,8 +5,9 @@ import ( "fmt" "sort" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { SortBy string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists members of a project", @@ -129,7 +130,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *authorization.APIClient) authorization.ApiListMembersRequest { - req := apiClient.ListMembers(ctx, projectResourceType, model.GlobalFlagModel.ProjectId) + req := apiClient.ListMembers(ctx, projectResourceType, model.ProjectId) if model.Subject != nil { req = req.Subject(*model.Subject) } @@ -164,9 +165,10 @@ func outputResult(p *print.Printer, model inputModel, members []authorization.Me table.AddRow(utils.PtrString(m.Subject), utils.PtrString(m.Role)) } - if model.SortBy == "subject" { + switch model.SortBy { + case "subject": table.EnableAutoMergeOnColumns(1) - } else if model.SortBy == "role" { + case "role": table.EnableAutoMergeOnColumns(2) } diff --git a/internal/cmd/project/member/list/list_test.go b/internal/cmd/project/member/list/list_test.go index 14167c407..af050ba78 100644 --- a/internal/cmd/project/member/list/list_test.go +++ b/internal/cmd/project/member/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -201,7 +202,7 @@ func Test_outputResult(t *testing.T) { false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.members); (err != nil) != tt.wantErr { diff --git a/internal/cmd/project/member/member.go b/internal/cmd/project/member/member.go index cef271820..4b247e877 100644 --- a/internal/cmd/project/member/member.go +++ b/internal/cmd/project/member/member.go @@ -1,17 +1,17 @@ package member import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/project/member/add" "github.com/stackitcloud/stackit-cli/internal/cmd/project/member/list" "github.com/stackitcloud/stackit-cli/internal/cmd/project/member/remove" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "member", Short: "Manages project members", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(add.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(remove.NewCmd(params)) diff --git a/internal/cmd/project/member/remove/remove.go b/internal/cmd/project/member/remove/remove.go index 20bf7ee3c..8b7089283 100644 --- a/internal/cmd/project/member/remove/remove.go +++ b/internal/cmd/project/member/remove/remove.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -36,7 +37,7 @@ type inputModel struct { Force bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("remove %s", subjectArg), Short: "Removes a member from a project", @@ -127,7 +128,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *authorization.APIClient) authorization.ApiRemoveMembersRequest { - req := apiClient.RemoveMembers(ctx, model.GlobalFlagModel.ProjectId) + req := apiClient.RemoveMembers(ctx, model.ProjectId) payload := authorization.RemoveMembersPayload{ Members: utils.Ptr([]authorization.Member{ { diff --git a/internal/cmd/project/project.go b/internal/cmd/project/project.go index f888fbbc5..c1a04db9a 100644 --- a/internal/cmd/project/project.go +++ b/internal/cmd/project/project.go @@ -3,7 +3,8 @@ package project import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/cmd/project/create" "github.com/stackitcloud/stackit-cli/internal/cmd/project/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/project/describe" @@ -17,7 +18,7 @@ import ( "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "project", Short: "Manages projects", @@ -32,7 +33,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(update.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/project/role/list/list.go b/internal/cmd/project/role/list/list.go index a2d65e21d..7be67dc6b 100644 --- a/internal/cmd/project/role/list/list.go +++ b/internal/cmd/project/role/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists roles and permissions of a project", @@ -118,7 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *authorization.APIClient) authorization.ApiListRolesRequest { - return apiClient.ListRoles(ctx, projectResourceType, model.GlobalFlagModel.ProjectId) + return apiClient.ListRoles(ctx, projectResourceType, model.ProjectId) } func outputRolesResult(p *print.Printer, outputFormat string, roles []authorization.Role) error { diff --git a/internal/cmd/project/role/list/list_test.go b/internal/cmd/project/role/list/list_test.go index 66f51f7df..3bc59db9a 100644 --- a/internal/cmd/project/role/list/list_test.go +++ b/internal/cmd/project/role/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -157,7 +158,7 @@ func Test_outputRolesResult(t *testing.T) { }}, false}, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputRolesResult(p, tt.args.outputFormat, tt.args.roles); (err != nil) != tt.wantErr { diff --git a/internal/cmd/project/role/role.go b/internal/cmd/project/role/role.go index bb0781f08..1c4c119a9 100644 --- a/internal/cmd/project/role/role.go +++ b/internal/cmd/project/role/role.go @@ -1,15 +1,15 @@ package role import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/project/role/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "role", Short: "Manages project roles", @@ -21,6 +21,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/project/update/update.go b/internal/cmd/project/update/update.go index 7523ff5e1..37e799a36 100644 --- a/internal/cmd/project/update/update.go +++ b/internal/cmd/project/update/update.go @@ -5,7 +5,8 @@ import ( "fmt" "regexp" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -36,7 +37,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "Updates a STACKIT project", diff --git a/internal/cmd/public-ip/associate/associate.go b/internal/cmd/public-ip/associate/associate.go index ec2ac72c3..a3ed8cc0e 100644 --- a/internal/cmd/public-ip/associate/associate.go +++ b/internal/cmd/public-ip/associate/associate.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { AssociatedResourceId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("associate %s", publicIpIdArg), Short: "Associates a Public IP with a network interface or a virtual IP", diff --git a/internal/cmd/public-ip/associate/associate_test.go b/internal/cmd/public-ip/associate/associate_test.go index 18084731d..8d40c1a6a 100644 --- a/internal/cmd/public-ip/associate/associate_test.go +++ b/internal/cmd/public-ip/associate/associate_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -171,7 +172,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index 872a95057..a467529d9 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Public IP", diff --git a/internal/cmd/public-ip/create/create_test.go b/internal/cmd/public-ip/create/create_test.go index 3602a422b..a4d0a4b23 100644 --- a/internal/cmd/public-ip/create/create_test.go +++ b/internal/cmd/public-ip/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -201,7 +202,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.publicIp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/public-ip/delete/delete.go b/internal/cmd/public-ip/delete/delete.go index f5f8e340a..4cbcd1094 100644 --- a/internal/cmd/public-ip/delete/delete.go +++ b/internal/cmd/public-ip/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", publicIpIdArg), Short: "Deletes a Public IP", diff --git a/internal/cmd/public-ip/describe/describe.go b/internal/cmd/public-ip/describe/describe.go index 94ff1a5c9..fbcc2b15b 100644 --- a/internal/cmd/public-ip/describe/describe.go +++ b/internal/cmd/public-ip/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", publicIpIdArg), Short: "Shows details of a Public IP", diff --git a/internal/cmd/public-ip/describe/describe_test.go b/internal/cmd/public-ip/describe/describe_test.go index 581eb0496..d140e36bf 100644 --- a/internal/cmd/public-ip/describe/describe_test.go +++ b/internal/cmd/public-ip/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -193,7 +194,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.publicIp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/public-ip/disassociate/disassociate.go b/internal/cmd/public-ip/disassociate/disassociate.go index 3a54d40cb..69a5dc77d 100644 --- a/internal/cmd/public-ip/disassociate/disassociate.go +++ b/internal/cmd/public-ip/disassociate/disassociate.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("disassociate %s", publicIpIdArg), Short: "Disassociates a Public IP from a network interface or a virtual IP", diff --git a/internal/cmd/public-ip/disassociate/disassociate_test.go b/internal/cmd/public-ip/disassociate/disassociate_test.go index 1edc96014..41c8d26e8 100644 --- a/internal/cmd/public-ip/disassociate/disassociate_test.go +++ b/internal/cmd/public-ip/disassociate/disassociate_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/google/go-cmp/cmp" @@ -143,7 +144,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/public-ip/list/list.go b/internal/cmd/public-ip/list/list.go index ec95cb0c6..b2acfff92 100644 --- a/internal/cmd/public-ip/list/list.go +++ b/internal/cmd/public-ip/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Public IPs of a project", diff --git a/internal/cmd/public-ip/list/list_test.go b/internal/cmd/public-ip/list/list_test.go index 2256ed99c..9a10067d9 100644 --- a/internal/cmd/public-ip/list/list_test.go +++ b/internal/cmd/public-ip/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -189,7 +190,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.publicIps); (err != nil) != tt.wantErr { diff --git a/internal/cmd/public-ip/public-ip.go b/internal/cmd/public-ip/public-ip.go index d16565288..77a4e3a2b 100644 --- a/internal/cmd/public-ip/public-ip.go +++ b/internal/cmd/public-ip/public-ip.go @@ -1,7 +1,6 @@ package publicip import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/associate" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/create" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/delete" @@ -11,12 +10,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/ranges" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "public-ip", Short: "Provides functionality for public IPs", @@ -28,7 +28,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/public-ip/ranges/list/list.go b/internal/cmd/public-ip/ranges/list/list.go index 7188146f6..918cb2041 100644 --- a/internal/cmd/public-ip/ranges/list/list.go +++ b/internal/cmd/public-ip/ranges/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all STACKIT public-ip ranges", diff --git a/internal/cmd/public-ip/ranges/list/list_test.go b/internal/cmd/public-ip/ranges/list/list_test.go index 20af8f19f..9a50dfeb1 100644 --- a/internal/cmd/public-ip/ranges/list/list_test.go +++ b/internal/cmd/public-ip/ranges/list/list_test.go @@ -3,10 +3,11 @@ package list import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -180,7 +181,7 @@ func TestOutputResult(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) err := outputResult(p, tt.outputFormat, tt.publicIpRanges) if (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) diff --git a/internal/cmd/public-ip/ranges/ranges.go b/internal/cmd/public-ip/ranges/ranges.go index 8d616ac5a..5978bbbb1 100644 --- a/internal/cmd/public-ip/ranges/ranges.go +++ b/internal/cmd/public-ip/ranges/ranges.go @@ -1,15 +1,15 @@ package ranges import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/ranges/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "ranges", Short: "Provides functionality for STACKIT public-ip ranges", @@ -21,6 +21,6 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go index c4498a032..df2687a76 100644 --- a/internal/cmd/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -4,10 +4,10 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -31,7 +31,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", publicIpIdArg), Short: "Updates a Public IP", @@ -103,7 +103,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu labels := flags.FlagToStringToStringPointer(p, cmd, labelFlag) if labels == nil { - return nil, &errors.EmptyUpdateError{} + return nil, &cliErr.EmptyUpdateError{} } model := inputModel{ diff --git a/internal/cmd/public-ip/update/update_test.go b/internal/cmd/public-ip/update/update_test.go index bf987a524..36514978f 100644 --- a/internal/cmd/public-ip/update/update_test.go +++ b/internal/cmd/public-ip/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -151,7 +152,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/quota/list/list.go b/internal/cmd/quota/list/list.go index f61151f24..d16da37d0 100644 --- a/internal/cmd/quota/list/list.go +++ b/internal/cmd/quota/list/list.go @@ -5,8 +5,9 @@ import ( "fmt" "strconv" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -22,7 +23,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists quotas", diff --git a/internal/cmd/quota/list/list_test.go b/internal/cmd/quota/list/list_test.go index 358749384..b508a5c94 100644 --- a/internal/cmd/quota/list/list_test.go +++ b/internal/cmd/quota/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -160,7 +161,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.quotas); (err != nil) != tt.wantErr { diff --git a/internal/cmd/quota/quota.go b/internal/cmd/quota/quota.go index ff323e97e..ed65097d2 100644 --- a/internal/cmd/quota/quota.go +++ b/internal/cmd/quota/quota.go @@ -1,16 +1,16 @@ package quota import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/quota/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "quota", Short: "Manage server quotas", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand( list.NewCmd(params), ) diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index 9f22b594a..9c43e2ca1 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for a RabbitMQ instance", diff --git a/internal/cmd/rabbitmq/credentials/create/create_test.go b/internal/cmd/rabbitmq/credentials/create/create_test.go index b36306cd8..3286d4931 100644 --- a/internal/cmd/rabbitmq/credentials/create/create_test.go +++ b/internal/cmd/rabbitmq/credentials/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -205,7 +206,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/credentials/credentials.go b/internal/cmd/rabbitmq/credentials/credentials.go index 80c06fb8e..2f7c435e2 100644 --- a/internal/cmd/rabbitmq/credentials/credentials.go +++ b/internal/cmd/rabbitmq/credentials/credentials.go @@ -1,18 +1,18 @@ package credentials import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials/create" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for RabbitMQ credentials", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/rabbitmq/credentials/delete/delete.go b/internal/cmd/rabbitmq/credentials/delete/delete.go index 20f868ddc..7dcd75143 100644 --- a/internal/cmd/rabbitmq/credentials/delete/delete.go +++ b/internal/cmd/rabbitmq/credentials/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of a RabbitMQ instance", diff --git a/internal/cmd/rabbitmq/credentials/describe/describe.go b/internal/cmd/rabbitmq/credentials/describe/describe.go index fb8d5ea6a..e17a39f73 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of a RabbitMQ instance", diff --git a/internal/cmd/rabbitmq/credentials/describe/describe_test.go b/internal/cmd/rabbitmq/credentials/describe/describe_test.go index 0a466858c..b92353fb9 100644 --- a/internal/cmd/rabbitmq/credentials/describe/describe_test.go +++ b/internal/cmd/rabbitmq/credentials/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -223,7 +224,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/credentials/list/list.go b/internal/cmd/rabbitmq/credentials/list/list.go index fd6921b8a..218b4a97f 100644 --- a/internal/cmd/rabbitmq/credentials/list/list.go +++ b/internal/cmd/rabbitmq/credentials/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for a RabbitMQ instance", diff --git a/internal/cmd/rabbitmq/credentials/list/list_test.go b/internal/cmd/rabbitmq/credentials/list/list_test.go index 86e36c0aa..d2593b39b 100644 --- a/internal/cmd/rabbitmq/credentials/list/list_test.go +++ b/internal/cmd/rabbitmq/credentials/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -197,7 +198,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index 143264140..2778e082a 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -56,7 +57,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a RabbitMQ instance", diff --git a/internal/cmd/rabbitmq/instance/create/create_test.go b/internal/cmd/rabbitmq/instance/create/create_test.go index c76fa6af3..8a267ca2a 100644 --- a/internal/cmd/rabbitmq/instance/create/create_test.go +++ b/internal/cmd/rabbitmq/instance/create/create_test.go @@ -5,12 +5,13 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "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" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -458,7 +459,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/instance/delete/delete.go b/internal/cmd/rabbitmq/instance/delete/delete.go index 69f955ed5..8be4dacfb 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete.go +++ b/internal/cmd/rabbitmq/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a RabbitMQ instance", diff --git a/internal/cmd/rabbitmq/instance/describe/describe.go b/internal/cmd/rabbitmq/instance/describe/describe.go index 60ca0bad3..8385bfe7e 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe.go +++ b/internal/cmd/rabbitmq/instance/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a RabbitMQ instance", diff --git a/internal/cmd/rabbitmq/instance/describe/describe_test.go b/internal/cmd/rabbitmq/instance/describe/describe_test.go index b2e2d2a95..c92834466 100644 --- a/internal/cmd/rabbitmq/instance/describe/describe_test.go +++ b/internal/cmd/rabbitmq/instance/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -203,7 +204,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/instance/instance.go b/internal/cmd/rabbitmq/instance/instance.go index 2ad311846..fcbc2b7d9 100644 --- a/internal/cmd/rabbitmq/instance/instance.go +++ b/internal/cmd/rabbitmq/instance/instance.go @@ -1,19 +1,19 @@ package instance import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/create" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for RabbitMQ instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/rabbitmq/instance/list/list.go b/internal/cmd/rabbitmq/instance/list/list.go index 2bf032e8c..715f6fa45 100644 --- a/internal/cmd/rabbitmq/instance/list/list.go +++ b/internal/cmd/rabbitmq/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all RabbitMQ instances", diff --git a/internal/cmd/rabbitmq/instance/list/list_test.go b/internal/cmd/rabbitmq/instance/list/list_test.go index 4f9a0ab7d..18bfa1817 100644 --- a/internal/cmd/rabbitmq/instance/list/list_test.go +++ b/internal/cmd/rabbitmq/instance/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -173,7 +174,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/instance/update/update.go b/internal/cmd/rabbitmq/instance/update/update.go index 792e82681..f2a87e12b 100644 --- a/internal/cmd/rabbitmq/instance/update/update.go +++ b/internal/cmd/rabbitmq/instance/update/update.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -57,7 +58,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a RabbitMQ instance", diff --git a/internal/cmd/rabbitmq/instance/update/update_test.go b/internal/cmd/rabbitmq/instance/update/update_test.go index 11198d9a6..2120ac96d 100644 --- a/internal/cmd/rabbitmq/instance/update/update_test.go +++ b/internal/cmd/rabbitmq/instance/update/update_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -293,7 +294,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/rabbitmq/plans/plans.go b/internal/cmd/rabbitmq/plans/plans.go index d62474125..cc9cc3e1b 100644 --- a/internal/cmd/rabbitmq/plans/plans.go +++ b/internal/cmd/rabbitmq/plans/plans.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all RabbitMQ service plans", diff --git a/internal/cmd/rabbitmq/plans/plans_test.go b/internal/cmd/rabbitmq/plans/plans_test.go index 486369731..f98191e88 100644 --- a/internal/cmd/rabbitmq/plans/plans_test.go +++ b/internal/cmd/rabbitmq/plans/plans_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -173,7 +174,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/rabbitmq/rabbitmq.go b/internal/cmd/rabbitmq/rabbitmq.go index 9dc5b76a3..23099b758 100644 --- a/internal/cmd/rabbitmq/rabbitmq.go +++ b/internal/cmd/rabbitmq/rabbitmq.go @@ -1,17 +1,17 @@ package rabbitmq import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/rabbitmq/plans" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "rabbitmq", Short: "Provides functionality for RabbitMQ", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(plans.NewCmd(params)) cmd.AddCommand(credentials.NewCmd(params)) diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index 2b8e011da..c7793c1c7 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { ShowPassword bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates credentials for a Redis instance", diff --git a/internal/cmd/redis/credentials/create/create_test.go b/internal/cmd/redis/credentials/create/create_test.go index fc968ce32..79d571121 100644 --- a/internal/cmd/redis/credentials/create/create_test.go +++ b/internal/cmd/redis/credentials/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -187,7 +188,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/credentials/credentials.go b/internal/cmd/redis/credentials/credentials.go index d1d8a4d7a..41a7b4f92 100644 --- a/internal/cmd/redis/credentials/credentials.go +++ b/internal/cmd/redis/credentials/credentials.go @@ -1,18 +1,18 @@ package credentials import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials/create" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for Redis credentials", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/redis/credentials/delete/delete.go b/internal/cmd/redis/credentials/delete/delete.go index 34d0a12ac..2209c45b1 100644 --- a/internal/cmd/redis/credentials/delete/delete.go +++ b/internal/cmd/redis/credentials/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", credentialsIdArg), Short: "Deletes credentials of a Redis instance", diff --git a/internal/cmd/redis/credentials/describe/describe.go b/internal/cmd/redis/credentials/describe/describe.go index 36ada5448..115f23f4b 100644 --- a/internal/cmd/redis/credentials/describe/describe.go +++ b/internal/cmd/redis/credentials/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { CredentialsId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", credentialsIdArg), Short: "Shows details of credentials of a Redis instance", diff --git a/internal/cmd/redis/credentials/describe/describe_test.go b/internal/cmd/redis/credentials/describe/describe_test.go index b98c36631..7ee94e50c 100644 --- a/internal/cmd/redis/credentials/describe/describe_test.go +++ b/internal/cmd/redis/credentials/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -222,7 +223,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/credentials/list/list.go b/internal/cmd/redis/credentials/list/list.go index 8f2dc6945..332ef35e0 100644 --- a/internal/cmd/redis/credentials/list/list.go +++ b/internal/cmd/redis/credentials/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all credentials' IDs for a Redis instance", diff --git a/internal/cmd/redis/credentials/list/list_test.go b/internal/cmd/redis/credentials/list/list_test.go index cd986c587..fdf207e55 100644 --- a/internal/cmd/redis/credentials/list/list_test.go +++ b/internal/cmd/redis/credentials/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -198,7 +199,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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, "dummy-instance-label", tt.args.credentials); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index d5a410d35..f6b4d050c 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -54,7 +55,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Redis instance", diff --git a/internal/cmd/redis/instance/create/create_test.go b/internal/cmd/redis/instance/create/create_test.go index 6316e50b6..cc6baaeed 100644 --- a/internal/cmd/redis/instance/create/create_test.go +++ b/internal/cmd/redis/instance/create/create_test.go @@ -5,10 +5,11 @@ import ( "fmt" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -443,7 +444,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/instance/delete/delete.go b/internal/cmd/redis/instance/delete/delete.go index c6d3f271b..1b314ea33 100644 --- a/internal/cmd/redis/instance/delete/delete.go +++ b/internal/cmd/redis/instance/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a Redis instance", diff --git a/internal/cmd/redis/instance/describe/describe.go b/internal/cmd/redis/instance/describe/describe.go index 36e6d7b76..aaa003478 100644 --- a/internal/cmd/redis/instance/describe/describe.go +++ b/internal/cmd/redis/instance/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a Redis instance", diff --git a/internal/cmd/redis/instance/describe/describe_test.go b/internal/cmd/redis/instance/describe/describe_test.go index 9c1bf4e39..16a99ab65 100644 --- a/internal/cmd/redis/instance/describe/describe_test.go +++ b/internal/cmd/redis/instance/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -206,7 +207,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/instance/instance.go b/internal/cmd/redis/instance/instance.go index a45e6bd96..82cbe63cd 100644 --- a/internal/cmd/redis/instance/instance.go +++ b/internal/cmd/redis/instance/instance.go @@ -1,19 +1,19 @@ package instance import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/create" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for Redis instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/redis/instance/list/list.go b/internal/cmd/redis/instance/list/list.go index 571004f47..2051f471e 100644 --- a/internal/cmd/redis/instance/list/list.go +++ b/internal/cmd/redis/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Redis instances", diff --git a/internal/cmd/redis/instance/list/list_test.go b/internal/cmd/redis/instance/list/list_test.go index fea12c21f..81053ecdd 100644 --- a/internal/cmd/redis/instance/list/list_test.go +++ b/internal/cmd/redis/instance/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -173,7 +174,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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, "dummy-project-label", tt.args.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/instance/update/update.go b/internal/cmd/redis/instance/update/update.go index 5b254072e..98b192ad6 100644 --- a/internal/cmd/redis/instance/update/update.go +++ b/internal/cmd/redis/instance/update/update.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -54,7 +55,7 @@ type inputModel struct { PlanId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a Redis instance", diff --git a/internal/cmd/redis/instance/update/update_test.go b/internal/cmd/redis/instance/update/update_test.go index 7c5df24d5..c4bfedb8c 100644 --- a/internal/cmd/redis/instance/update/update_test.go +++ b/internal/cmd/redis/instance/update/update_test.go @@ -5,7 +5,8 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -279,7 +280,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/redis/plans/plans.go b/internal/cmd/redis/plans/plans.go index 83125b63a..f7ecfe5cf 100644 --- a/internal/cmd/redis/plans/plans.go +++ b/internal/cmd/redis/plans/plans.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "plans", Short: "Lists all Redis service plans", diff --git a/internal/cmd/redis/plans/plans_test.go b/internal/cmd/redis/plans/plans_test.go index 919b8d01f..a18048cd6 100644 --- a/internal/cmd/redis/plans/plans_test.go +++ b/internal/cmd/redis/plans/plans_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -173,7 +174,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.plans); (err != nil) != tt.wantErr { diff --git a/internal/cmd/redis/redis.go b/internal/cmd/redis/redis.go index 4a45e9c33..e0716339b 100644 --- a/internal/cmd/redis/redis.go +++ b/internal/cmd/redis/redis.go @@ -1,17 +1,17 @@ package redis import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/redis/plans" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "redis", Short: "Provides functionality for Redis", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(plans.NewCmd(params)) cmd.AddCommand(credentials.NewCmd(params)) diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 4e0ac6ea9..33b38ebfa 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -6,6 +6,8 @@ import ( "strings" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + affinityGroups "github.com/stackitcloud/stackit-cli/internal/cmd/affinity-groups" "github.com/stackitcloud/stackit-cli/internal/cmd/auth" "github.com/stackitcloud/stackit-cli/internal/cmd/beta" @@ -26,7 +28,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/observability" "github.com/stackitcloud/stackit-cli/internal/cmd/opensearch" "github.com/stackitcloud/stackit-cli/internal/cmd/organization" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/postgresflex" "github.com/stackitcloud/stackit-cli/internal/cmd/project" publicip "github.com/stackitcloud/stackit-cli/internal/cmd/public-ip" @@ -116,7 +117,7 @@ func NewRootCmd(version, date string, p *print.Printer) *cobra.Command { err := configureFlags(cmd) cobra.CheckErr(err) - addSubcommands(cmd, ¶ms.CmdParams{ + addSubcommands(cmd, &types.CmdParams{ Printer: p, CliVersion: version, }) @@ -159,7 +160,7 @@ func configureFlags(cmd *cobra.Command) error { return nil } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(auth.NewCmd(params)) cmd.AddCommand(configCmd.NewCmd(params)) cmd.AddCommand(beta.NewCmd(params)) diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index 8f5401d9a..abc0bb5f2 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Acls *[]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Secrets Manager instance", diff --git a/internal/cmd/secrets-manager/instance/create/create_test.go b/internal/cmd/secrets-manager/instance/create/create_test.go index 641767b53..4cef0d887 100644 --- a/internal/cmd/secrets-manager/instance/create/create_test.go +++ b/internal/cmd/secrets-manager/instance/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -285,7 +286,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceId, tt.args.instance); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/instance/delete/delete.go b/internal/cmd/secrets-manager/instance/delete/delete.go index 2432c5a5e..ec8148e34 100644 --- a/internal/cmd/secrets-manager/instance/delete/delete.go +++ b/internal/cmd/secrets-manager/instance/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", instanceIdArg), Short: "Deletes a Secrets Manager instance", diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index ed12cb1b0..bbd162bff 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { InstanceId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", instanceIdArg), Short: "Shows details of a Secrets Manager instance", diff --git a/internal/cmd/secrets-manager/instance/describe/describe_test.go b/internal/cmd/secrets-manager/instance/describe/describe_test.go index 25ee15d66..c1e3e0bb7 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe_test.go +++ b/internal/cmd/secrets-manager/instance/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -248,7 +249,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instance, tt.args.aclList); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/instance/instance.go b/internal/cmd/secrets-manager/instance/instance.go index 5617aeddc..8edeb55fc 100644 --- a/internal/cmd/secrets-manager/instance/instance.go +++ b/internal/cmd/secrets-manager/instance/instance.go @@ -1,19 +1,19 @@ package instance import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/create" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/list" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "instance", Short: "Provides functionality for Secrets Manager instances", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/secrets-manager/instance/list/list.go b/internal/cmd/secrets-manager/instance/list/list.go index 9cd6b24ad..e32f99ed0 100644 --- a/internal/cmd/secrets-manager/instance/list/list.go +++ b/internal/cmd/secrets-manager/instance/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Secrets Manager instances", diff --git a/internal/cmd/secrets-manager/instance/list/list_test.go b/internal/cmd/secrets-manager/instance/list/list_test.go index 2b416584d..fa1cc496a 100644 --- a/internal/cmd/secrets-manager/instance/list/list_test.go +++ b/internal/cmd/secrets-manager/instance/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -189,7 +190,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instances); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/instance/update/update.go b/internal/cmd/secrets-manager/instance/update/update.go index d3caca348..c3cfb5956 100644 --- a/internal/cmd/secrets-manager/instance/update/update.go +++ b/internal/cmd/secrets-manager/instance/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -33,7 +34,7 @@ type inputModel struct { Acls *[]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", instanceIdArg), Short: "Updates a Secrets Manager instance", diff --git a/internal/cmd/secrets-manager/instance/update/update_test.go b/internal/cmd/secrets-manager/instance/update/update_test.go index 1a60db361..24e14d1fb 100644 --- a/internal/cmd/secrets-manager/instance/update/update_test.go +++ b/internal/cmd/secrets-manager/instance/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -199,7 +200,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/secrets-manager/secrets_manager.go b/internal/cmd/secrets-manager/secrets_manager.go index 35745dfde..eb5632c4f 100644 --- a/internal/cmd/secrets-manager/secrets_manager.go +++ b/internal/cmd/secrets-manager/secrets_manager.go @@ -1,16 +1,16 @@ package secretsmanager import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "secrets-manager", Short: "Provides functionality for Secrets Manager", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(instance.NewCmd(params)) cmd.AddCommand(user.NewCmd(params)) } diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index 153bb5035..eba0d736b 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { Write *bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Secrets Manager user", diff --git a/internal/cmd/secrets-manager/user/create/create_test.go b/internal/cmd/secrets-manager/user/create/create_test.go index bbc606f1e..256a1f29a 100644 --- a/internal/cmd/secrets-manager/user/create/create_test.go +++ b/internal/cmd/secrets-manager/user/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -212,7 +213,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.instanceLabel, tt.args.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/user/delete/delete.go b/internal/cmd/secrets-manager/user/delete/delete.go index fb1972dbf..e2ad75eb5 100644 --- a/internal/cmd/secrets-manager/user/delete/delete.go +++ b/internal/cmd/secrets-manager/user/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", userIdArg), Short: "Deletes a Secrets Manager user", diff --git a/internal/cmd/secrets-manager/user/describe/describe.go b/internal/cmd/secrets-manager/user/describe/describe.go index 9a2a30280..5a658385c 100644 --- a/internal/cmd/secrets-manager/user/describe/describe.go +++ b/internal/cmd/secrets-manager/user/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { UserId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", userIdArg), Short: "Shows details of a Secrets Manager user", diff --git a/internal/cmd/secrets-manager/user/describe/describe_test.go b/internal/cmd/secrets-manager/user/describe/describe_test.go index f65790dfe..c267fe143 100644 --- a/internal/cmd/secrets-manager/user/describe/describe_test.go +++ b/internal/cmd/secrets-manager/user/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -223,7 +224,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.user); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/user/list/list.go b/internal/cmd/secrets-manager/user/list/list.go index 249b0cee5..9b601d47a 100644 --- a/internal/cmd/secrets-manager/user/list/list.go +++ b/internal/cmd/secrets-manager/user/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all Secrets Manager users", diff --git a/internal/cmd/secrets-manager/user/list/list_test.go b/internal/cmd/secrets-manager/user/list/list_test.go index cd395dc64..30ce25955 100644 --- a/internal/cmd/secrets-manager/user/list/list_test.go +++ b/internal/cmd/secrets-manager/user/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.users); (err != nil) != tt.wantErr { diff --git a/internal/cmd/secrets-manager/user/update/update.go b/internal/cmd/secrets-manager/user/update/update.go index c41c59b35..31a8e5a6e 100644 --- a/internal/cmd/secrets-manager/user/update/update.go +++ b/internal/cmd/secrets-manager/user/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -36,7 +37,7 @@ type inputModel struct { DisableWrite *bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", userIdArg), Short: "Updates the write privileges Secrets Manager user", diff --git a/internal/cmd/secrets-manager/user/update/update_test.go b/internal/cmd/secrets-manager/user/update/update_test.go index 5ae24676b..830bacdfd 100644 --- a/internal/cmd/secrets-manager/user/update/update_test.go +++ b/internal/cmd/secrets-manager/user/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -190,7 +191,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/secrets-manager/user/user.go b/internal/cmd/secrets-manager/user/user.go index ae4e1c90f..738426858 100644 --- a/internal/cmd/secrets-manager/user/user.go +++ b/internal/cmd/secrets-manager/user/user.go @@ -2,10 +2,10 @@ package user import ( "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" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user/create" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user/describe" @@ -13,7 +13,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user/update" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "user", Short: "Provides functionality for Secrets Manager users", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index fd10a585d..b5e7143a2 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Stateful *bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates security groups", diff --git a/internal/cmd/security-group/create/create_test.go b/internal/cmd/security-group/create/create_test.go index 9b6d8f92c..b025e7419 100644 --- a/internal/cmd/security-group/create/create_test.go +++ b/internal/cmd/security-group/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -256,7 +257,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.name, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/delete/delete.go b/internal/cmd/security-group/delete/delete.go index 506dce800..37c0b283c 100644 --- a/internal/cmd/security-group/delete/delete.go +++ b/internal/cmd/security-group/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -25,7 +26,7 @@ type inputModel struct { const groupIdArg = "GROUP_ID" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", groupIdArg), Short: "Deletes a security group", diff --git a/internal/cmd/security-group/delete/delete_test.go b/internal/cmd/security-group/delete/delete_test.go index e29d614e6..0416a41fe 100644 --- a/internal/cmd/security-group/delete/delete_test.go +++ b/internal/cmd/security-group/delete/delete_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -114,7 +115,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/security-group/describe/describe.go b/internal/cmd/security-group/describe/describe.go index 6d8d615b0..485c2f10d 100644 --- a/internal/cmd/security-group/describe/describe.go +++ b/internal/cmd/security-group/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -26,7 +27,7 @@ type inputModel struct { const groupIdArg = "GROUP_ID" -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", groupIdArg), Short: "Describes security groups", diff --git a/internal/cmd/security-group/describe/describe_test.go b/internal/cmd/security-group/describe/describe_test.go index 1c6f15431..9342e946e 100644 --- a/internal/cmd/security-group/describe/describe_test.go +++ b/internal/cmd/security-group/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -128,7 +129,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } @@ -225,7 +226,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/list/list.go b/internal/cmd/security-group/list/list.go index 159995162..a368152a6 100644 --- a/internal/cmd/security-group/list/list.go +++ b/internal/cmd/security-group/list/list.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ const ( labelSelectorFlag = "label-selector" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists security groups", diff --git a/internal/cmd/security-group/list/list_test.go b/internal/cmd/security-group/list/list_test.go index 7e5515059..22c588604 100644 --- a/internal/cmd/security-group/list/list_test.go +++ b/internal/cmd/security-group/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -196,7 +197,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.items); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go index 9c87570f3..5e08c09b0 100644 --- a/internal/cmd/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -51,7 +52,7 @@ type inputModel struct { ProtocolName *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a security group rule", diff --git a/internal/cmd/security-group/rule/create/create_test.go b/internal/cmd/security-group/rule/create/create_test.go index 4088823e4..5099c7ca3 100644 --- a/internal/cmd/security-group/rule/create/create_test.go +++ b/internal/cmd/security-group/rule/create/create_test.go @@ -4,12 +4,13 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "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" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -324,7 +325,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.securityGroupName, tt.args.securityGroupRule); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/rule/delete/delete.go b/internal/cmd/security-group/rule/delete/delete.go index f0426854b..722142f9d 100644 --- a/internal/cmd/security-group/rule/delete/delete.go +++ b/internal/cmd/security-group/rule/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { SecurityGroupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", securityGroupRuleIdArg), Short: "Deletes a security group rule", diff --git a/internal/cmd/security-group/rule/delete/delete_test.go b/internal/cmd/security-group/rule/delete/delete_test.go index 9f78a7e1a..0d6a9b4cb 100644 --- a/internal/cmd/security-group/rule/delete/delete_test.go +++ b/internal/cmd/security-group/rule/delete/delete_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -159,7 +160,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/security-group/rule/describe/describe.go b/internal/cmd/security-group/rule/describe/describe.go index 12d6edece..82486d989 100644 --- a/internal/cmd/security-group/rule/describe/describe.go +++ b/internal/cmd/security-group/rule/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { SecurityGroupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", securityGroupRuleIdArg), Short: "Shows details of a security group rule", diff --git a/internal/cmd/security-group/rule/describe/describe_test.go b/internal/cmd/security-group/rule/describe/describe_test.go index 357457705..f1af54485 100644 --- a/internal/cmd/security-group/rule/describe/describe_test.go +++ b/internal/cmd/security-group/rule/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -227,7 +228,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.securityGroupRule); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/rule/list/list.go b/internal/cmd/security-group/rule/list/list.go index 7ddb33c7a..1d39e5ed8 100644 --- a/internal/cmd/security-group/rule/list/list.go +++ b/internal/cmd/security-group/rule/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { SecurityGroupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all security group rules in a security group of a project", diff --git a/internal/cmd/security-group/rule/list/list_test.go b/internal/cmd/security-group/rule/list/list_test.go index 92ba77801..166b58e58 100644 --- a/internal/cmd/security-group/rule/list/list_test.go +++ b/internal/cmd/security-group/rule/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -198,7 +199,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.securityGroupRules); (err != nil) != tt.wantErr { diff --git a/internal/cmd/security-group/rule/security_group_rule.go b/internal/cmd/security-group/rule/security_group_rule.go index 75f394384..fda58dd87 100644 --- a/internal/cmd/security-group/rule/security_group_rule.go +++ b/internal/cmd/security-group/rule/security_group_rule.go @@ -1,18 +1,18 @@ package rule import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/create" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "rule", Short: "Provides functionality for security group rules", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/security-group/security_group.go b/internal/cmd/security-group/security_group.go index 952da976c..ef613d054 100644 --- a/internal/cmd/security-group/security_group.go +++ b/internal/cmd/security-group/security_group.go @@ -1,7 +1,6 @@ package security_group import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/create" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/describe" @@ -9,13 +8,14 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/rule" "github.com/stackitcloud/stackit-cli/internal/cmd/security-group/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "security-group", Short: "Manage security groups", @@ -27,7 +27,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand( rule.NewCmd(params), create.NewCmd(params), diff --git a/internal/cmd/security-group/update/update.go b/internal/cmd/security-group/update/update.go index c9e255929..5a5039fa9 100644 --- a/internal/cmd/security-group/update/update.go +++ b/internal/cmd/security-group/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ const ( labelsArg = "labels" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", groupNameArg), Short: "Updates a security group", diff --git a/internal/cmd/security-group/update/update_test.go b/internal/cmd/security-group/update/update_test.go index 081875080..115cdb32c 100644 --- a/internal/cmd/security-group/update/update_test.go +++ b/internal/cmd/security-group/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -214,7 +215,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) if err := globalflags.Configure(cmd.Flags()); err != nil { t.Errorf("cannot configure global flags: %v", err) } diff --git a/internal/cmd/server/backup/backup.go b/internal/cmd/server/backup/backup.go index e29887143..77d290a42 100644 --- a/internal/cmd/server/backup/backup.go +++ b/internal/cmd/server/backup/backup.go @@ -1,7 +1,6 @@ package backup import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/create" del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/describe" @@ -12,12 +11,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule" volumebackup "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "backup", Short: "Provides functionality for server backups", @@ -29,7 +29,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(enable.NewCmd(params)) cmd.AddCommand(disable.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index 4ee1b42a4..c2ab4b028 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -39,7 +40,7 @@ type inputModel struct { BackupVolumeIds []string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server Backup.", diff --git a/internal/cmd/server/backup/create/create_test.go b/internal/cmd/server/backup/create/create_test.go index 9f7799a7f..07d305320 100644 --- a/internal/cmd/server/backup/create/create_test.go +++ b/internal/cmd/server/backup/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -192,7 +193,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/delete/delete.go b/internal/cmd/server/backup/delete/delete.go index f89a451b1..e4cb8118d 100644 --- a/internal/cmd/server/backup/delete/delete.go +++ b/internal/cmd/server/backup/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", backupIdArg), Short: "Deletes a Server Backup.", diff --git a/internal/cmd/server/backup/describe/describe.go b/internal/cmd/server/backup/describe/describe.go index 5289a31d4..b303028c3 100644 --- a/internal/cmd/server/backup/describe/describe.go +++ b/internal/cmd/server/backup/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strconv" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { BackupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupIdArg), Short: "Shows details of a Server Backup", diff --git a/internal/cmd/server/backup/describe/describe_test.go b/internal/cmd/server/backup/describe/describe_test.go index 2e3c10af2..1550a9c4e 100644 --- a/internal/cmd/server/backup/describe/describe_test.go +++ b/internal/cmd/server/backup/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -191,7 +192,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.backup); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go index 7fc57c79b..a9cc28ac4 100644 --- a/internal/cmd/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "disable", Short: "Disables Server Backup service", diff --git a/internal/cmd/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go index 369434d55..419d54076 100644 --- a/internal/cmd/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "enable", Short: "Enables Server Backup service", diff --git a/internal/cmd/server/backup/list/list.go b/internal/cmd/server/backup/list/list.go index 0e9856d4f..7f60f6a70 100644 --- a/internal/cmd/server/backup/list/list.go +++ b/internal/cmd/server/backup/list/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server backups", diff --git a/internal/cmd/server/backup/list/list_test.go b/internal/cmd/server/backup/list/list_test.go index a265c6779..a316ee0c4 100644 --- a/internal/cmd/server/backup/list/list_test.go +++ b/internal/cmd/server/backup/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -178,7 +179,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.backups); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/restore/restore.go b/internal/cmd/server/backup/restore/restore.go index ffca1ca53..8d3899dd5 100644 --- a/internal/cmd/server/backup/restore/restore.go +++ b/internal/cmd/server/backup/restore/restore.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -35,7 +36,7 @@ type inputModel struct { BackupVolumeIds []string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("restore %s", backupIdArg), Short: "Restores a Server Backup.", diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index 415f58a8f..9f113f0e6 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -47,7 +48,7 @@ type inputModel struct { BackupVolumeIds []string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server Backup Schedule", diff --git a/internal/cmd/server/backup/schedule/create/create_test.go b/internal/cmd/server/backup/schedule/create/create_test.go index 5f4d51733..548a93bd4 100644 --- a/internal/cmd/server/backup/schedule/create/create_test.go +++ b/internal/cmd/server/backup/schedule/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -202,7 +203,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/schedule/delete/delete.go b/internal/cmd/server/backup/schedule/delete/delete.go index 344ad02c0..498f7cacd 100644 --- a/internal/cmd/server/backup/schedule/delete/delete.go +++ b/internal/cmd/server/backup/schedule/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", scheduleIdArg), Short: "Deletes a Server Backup Schedule", diff --git a/internal/cmd/server/backup/schedule/describe/describe.go b/internal/cmd/server/backup/schedule/describe/describe.go index 4b5b7079f..a4e3b1f21 100644 --- a/internal/cmd/server/backup/schedule/describe/describe.go +++ b/internal/cmd/server/backup/schedule/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { BackupScheduleId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupScheduleIdArg), Short: "Shows details of a Server Backup Schedule", diff --git a/internal/cmd/server/backup/schedule/describe/describe_test.go b/internal/cmd/server/backup/schedule/describe/describe_test.go index 5d1f51e3a..e5808e545 100644 --- a/internal/cmd/server/backup/schedule/describe/describe_test.go +++ b/internal/cmd/server/backup/schedule/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -218,7 +219,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.schedule); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/schedule/list/list.go b/internal/cmd/server/backup/schedule/list/list.go index 3111ea55f..58f8f7ac9 100644 --- a/internal/cmd/server/backup/schedule/list/list.go +++ b/internal/cmd/server/backup/schedule/list/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server backup schedules", diff --git a/internal/cmd/server/backup/schedule/list/list_test.go b/internal/cmd/server/backup/schedule/list/list_test.go index 2234b0397..9c08b0f5d 100644 --- a/internal/cmd/server/backup/schedule/list/list_test.go +++ b/internal/cmd/server/backup/schedule/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -189,7 +190,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.schedules); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/schedule/schedule.go b/internal/cmd/server/backup/schedule/schedule.go index 1ce797c4f..fd93c4cde 100644 --- a/internal/cmd/server/backup/schedule/schedule.go +++ b/internal/cmd/server/backup/schedule/schedule.go @@ -1,19 +1,19 @@ package schedule import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/create" del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/schedule/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "schedule", Short: "Provides functionality for Server Backup Schedule", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) diff --git a/internal/cmd/server/backup/schedule/update/update.go b/internal/cmd/server/backup/schedule/update/update.go index 6d9d2aa69..3a54a12eb 100644 --- a/internal/cmd/server/backup/schedule/update/update.go +++ b/internal/cmd/server/backup/schedule/update/update.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -47,7 +48,7 @@ type inputModel struct { BackupVolumeIds []string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", scheduleIdArg), Short: "Updates a Server Backup Schedule", diff --git a/internal/cmd/server/backup/schedule/update/update_test.go b/internal/cmd/server/backup/schedule/update/update_test.go index 263a9188a..fc42794a0 100644 --- a/internal/cmd/server/backup/schedule/update/update_test.go +++ b/internal/cmd/server/backup/schedule/update/update_test.go @@ -5,7 +5,8 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -184,7 +185,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -296,7 +297,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/backup/volume-backup/delete/delete.go b/internal/cmd/server/backup/volume-backup/delete/delete.go index fc3cbced4..f13d85633 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", volumeBackupIdArg), Short: "Deletes a Server Volume Backup.", diff --git a/internal/cmd/server/backup/volume-backup/restore/restore.go b/internal/cmd/server/backup/volume-backup/restore/restore.go index d29b21681..676b5135e 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { RestoreVolumeId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("restore %s", volumeBackupIdArg), Short: "Restore a Server Volume Backup to a volume.", diff --git a/internal/cmd/server/backup/volume-backup/volumebackup.go b/internal/cmd/server/backup/volume-backup/volumebackup.go index e0d3b6d62..5bdf0f72d 100644 --- a/internal/cmd/server/backup/volume-backup/volumebackup.go +++ b/internal/cmd/server/backup/volume-backup/volumebackup.go @@ -1,16 +1,16 @@ package volumebackup import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" del "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup/volume-backup/restore" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "volume-backup", Short: "Provides functionality for Server Backup Volume Backups", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(del.NewCmd(params)) cmd.AddCommand(restore.NewCmd(params)) } diff --git a/internal/cmd/server/command/command.go b/internal/cmd/server/command/command.go index e6c2d79a8..ccd8978fd 100644 --- a/internal/cmd/server/command/command.go +++ b/internal/cmd/server/command/command.go @@ -1,18 +1,18 @@ package command import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/create" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "command", Short: "Provides functionality for Server Command", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index a95838116..1937f4e28 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Params *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server Command", diff --git a/internal/cmd/server/command/create/create_test.go b/internal/cmd/server/command/create/create_test.go index cb2368d6f..5b19bf508 100644 --- a/internal/cmd/server/command/create/create_test.go +++ b/internal/cmd/server/command/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -187,7 +188,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/describe/describe.go b/internal/cmd/server/command/describe/describe.go index c734cd137..8ca9b6aa3 100644 --- a/internal/cmd/server/command/describe/describe.go +++ b/internal/cmd/server/command/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { CommandId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", commandIdArg), Short: "Shows details of a Server Command", diff --git a/internal/cmd/server/command/describe/describe_test.go b/internal/cmd/server/command/describe/describe_test.go index 89689817d..5ad83715a 100644 --- a/internal/cmd/server/command/describe/describe_test.go +++ b/internal/cmd/server/command/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -216,7 +217,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.command); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/list/list.go b/internal/cmd/server/command/list/list.go index 052f13766..e5607abd0 100644 --- a/internal/cmd/server/command/list/list.go +++ b/internal/cmd/server/command/list/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server commands", diff --git a/internal/cmd/server/command/list/list_test.go b/internal/cmd/server/command/list/list_test.go index 9af1dfc05..bb806598d 100644 --- a/internal/cmd/server/command/list/list_test.go +++ b/internal/cmd/server/command/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -172,7 +173,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.commands); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/template/describe/describe.go b/internal/cmd/server/command/template/describe/describe.go index 120040660..a70ee5ae2 100644 --- a/internal/cmd/server/command/template/describe/describe.go +++ b/internal/cmd/server/command/template/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { CommandTemplateName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", commandTemplateNameArg), Short: "Shows details of a Server Command Template", diff --git a/internal/cmd/server/command/template/describe/describe_test.go b/internal/cmd/server/command/template/describe/describe_test.go index 45cbe627a..aaa90096a 100644 --- a/internal/cmd/server/command/template/describe/describe_test.go +++ b/internal/cmd/server/command/template/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -216,7 +217,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.commandTemplate); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/template/list/list.go b/internal/cmd/server/command/template/list/list.go index ffd76ac24..723772b45 100644 --- a/internal/cmd/server/command/template/list/list.go +++ b/internal/cmd/server/command/template/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server command templates", diff --git a/internal/cmd/server/command/template/list/list_test.go b/internal/cmd/server/command/template/list/list_test.go index 9255b13fe..df57cce22 100644 --- a/internal/cmd/server/command/template/list/list_test.go +++ b/internal/cmd/server/command/template/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -171,7 +172,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.templates); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/command/template/template.go b/internal/cmd/server/command/template/template.go index 6b41f434b..5607fa5c4 100644 --- a/internal/cmd/server/command/template/template.go +++ b/internal/cmd/server/command/template/template.go @@ -1,16 +1,16 @@ package template import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command/template/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "template", Short: "Provides functionality for Server Command Template", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/server/console/console.go b/internal/cmd/server/console/console.go index ea363c540..23e7f5c10 100644 --- a/internal/cmd/server/console/console.go +++ b/internal/cmd/server/console/console.go @@ -5,7 +5,8 @@ import ( "fmt" "net/url" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("console %s", serverIdArg), Short: "Gets a URL for server remote console", diff --git a/internal/cmd/server/console/console_test.go b/internal/cmd/server/console/console_test.go index a449d49bc..6fa46ba1b 100644 --- a/internal/cmd/server/console/console_test.go +++ b/internal/cmd/server/console/console_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -193,7 +194,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.serverUrl); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index afd46385c..841f21d1d 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -64,7 +65,7 @@ type inputModel struct { Volumes *[]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a server", diff --git a/internal/cmd/server/create/create_test.go b/internal/cmd/server/create/create_test.go index 1270eed51..521b80922 100644 --- a/internal/cmd/server/create/create_test.go +++ b/internal/cmd/server/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -403,7 +404,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.server); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/deallocate/deallocate.go b/internal/cmd/server/deallocate/deallocate.go index b55da54b2..9c8d7971c 100644 --- a/internal/cmd/server/deallocate/deallocate.go +++ b/internal/cmd/server/deallocate/deallocate.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("deallocate %s", serverIdArg), Short: "Deallocates an existing server", diff --git a/internal/cmd/server/delete/delete.go b/internal/cmd/server/delete/delete.go index 1a63f5ae1..85c264b5e 100644 --- a/internal/cmd/server/delete/delete.go +++ b/internal/cmd/server/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", serverIdArg), Short: "Deletes a server", diff --git a/internal/cmd/server/describe/describe.go b/internal/cmd/server/describe/describe.go index 3058cd465..f13e6f5c8 100644 --- a/internal/cmd/server/describe/describe.go +++ b/internal/cmd/server/describe/describe.go @@ -6,7 +6,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", serverIdArg), Short: "Shows details of a server", diff --git a/internal/cmd/server/describe/describe_test.go b/internal/cmd/server/describe/describe_test.go index af975d7c6..0b835a8da 100644 --- a/internal/cmd/server/describe/describe_test.go +++ b/internal/cmd/server/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -202,7 +203,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.server); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/list/list.go b/internal/cmd/server/list/list.go index 98faf6365..54c058dc0 100644 --- a/internal/cmd/server/list/list.go +++ b/internal/cmd/server/list/list.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all servers of a project", diff --git a/internal/cmd/server/list/list_test.go b/internal/cmd/server/list/list_test.go index f23efc370..4eb3a78cf 100644 --- a/internal/cmd/server/list/list_test.go +++ b/internal/cmd/server/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -190,7 +191,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.servers); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/log/log.go b/internal/cmd/server/log/log.go index 6b6a59f67..a211a44c1 100644 --- a/internal/cmd/server/log/log.go +++ b/internal/cmd/server/log/log.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { Length *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("log %s", serverIdArg), Short: "Gets server console log", diff --git a/internal/cmd/server/log/log_test.go b/internal/cmd/server/log/log_test.go index e9c0c657a..87375530f 100644 --- a/internal/cmd/server/log/log_test.go +++ b/internal/cmd/server/log/log_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -199,7 +200,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.log); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/machine-type/describe/describe.go b/internal/cmd/server/machine-type/describe/describe.go index 2fbdae1de..d496d5a83 100644 --- a/internal/cmd/server/machine-type/describe/describe.go +++ b/internal/cmd/server/machine-type/describe/describe.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { MachineType string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", machineTypeArg), Short: "Shows details of a server machine type", diff --git a/internal/cmd/server/machine-type/describe/describe_test.go b/internal/cmd/server/machine-type/describe/describe_test.go index f423455f6..4343f6fb6 100644 --- a/internal/cmd/server/machine-type/describe/describe_test.go +++ b/internal/cmd/server/machine-type/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -181,7 +182,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.machineType); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/machine-type/list/list.go b/internal/cmd/server/machine-type/list/list.go index db88e7be5..9dc3aad50 100644 --- a/internal/cmd/server/machine-type/list/list.go +++ b/internal/cmd/server/machine-type/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ const ( limitFlag = "limit" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Get list of all machine types available in a project", diff --git a/internal/cmd/server/machine-type/list/list_test.go b/internal/cmd/server/machine-type/list/list_test.go index 55b5c3c4a..8b07ca64c 100644 --- a/internal/cmd/server/machine-type/list/list_test.go +++ b/internal/cmd/server/machine-type/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -175,7 +176,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.machineTypes); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/machine-type/machine-type.go b/internal/cmd/server/machine-type/machine-type.go index 9482a6143..ee4e2ae54 100644 --- a/internal/cmd/server/machine-type/machine-type.go +++ b/internal/cmd/server/machine-type/machine-type.go @@ -1,16 +1,16 @@ package machinetype import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/machine-type/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/machine-type/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "machine-type", Short: "Provides functionality for server machine types available inside a project", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/server/network-interface/attach/attach.go b/internal/cmd/server/network-interface/attach/attach.go index 639c070a0..3e98a366e 100644 --- a/internal/cmd/server/network-interface/attach/attach.go +++ b/internal/cmd/server/network-interface/attach/attach.go @@ -4,10 +4,10 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -36,7 +36,7 @@ type inputModel struct { Create *bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "attach", Short: "Attaches a network interface to a server", @@ -134,7 +134,7 @@ func configureFlags(cmd *cobra.Command) { func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } // if create is not provided then network-interface-id is needed diff --git a/internal/cmd/server/network-interface/detach/detach.go b/internal/cmd/server/network-interface/detach/detach.go index 287b715f4..1e8babe16 100644 --- a/internal/cmd/server/network-interface/detach/detach.go +++ b/internal/cmd/server/network-interface/detach/detach.go @@ -4,10 +4,10 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" - "github.com/stackitcloud/stackit-cli/internal/pkg/errors" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -36,7 +36,7 @@ type inputModel struct { Delete *bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "detach", Short: "Detaches a network interface from a server", @@ -136,7 +136,7 @@ func configureFlags(cmd *cobra.Command) { func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) if globalFlags.ProjectId == "" { - return nil, &errors.ProjectIdError{} + return nil, &cliErr.ProjectIdError{} } // if delete is not provided then network-interface-id is needed diff --git a/internal/cmd/server/network-interface/list/list.go b/internal/cmd/server/network-interface/list/list.go index a63095dd6..607798a89 100644 --- a/internal/cmd/server/network-interface/list/list.go +++ b/internal/cmd/server/network-interface/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all attached network interfaces of a server", diff --git a/internal/cmd/server/network-interface/list/list_test.go b/internal/cmd/server/network-interface/list/list_test.go index 3c93f92c3..27f411166 100644 --- a/internal/cmd/server/network-interface/list/list_test.go +++ b/internal/cmd/server/network-interface/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -204,7 +205,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverId, tt.args.serverNics); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/network-interface/network-interface.go b/internal/cmd/server/network-interface/network-interface.go index 998ee07d3..2496def12 100644 --- a/internal/cmd/server/network-interface/network-interface.go +++ b/internal/cmd/server/network-interface/network-interface.go @@ -1,17 +1,17 @@ package networkinterface import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/attach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/detach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/network-interface/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "network-interface", Short: "Allows attaching/detaching network interfaces to servers", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(attach.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(detach.NewCmd(params)) diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index 1c8bddf44..eac250845 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { MaintenanceWindow int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server os-update.", diff --git a/internal/cmd/server/os-update/create/create_test.go b/internal/cmd/server/os-update/create/create_test.go index 073ea1db6..c95f62de3 100644 --- a/internal/cmd/server/os-update/create/create_test.go +++ b/internal/cmd/server/os-update/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -190,7 +191,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/describe/describe.go b/internal/cmd/server/os-update/describe/describe.go index 5686ff5be..026cec137 100644 --- a/internal/cmd/server/os-update/describe/describe.go +++ b/internal/cmd/server/os-update/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { UpdateId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", updateIdArg), Short: "Shows details of a Server os-update", diff --git a/internal/cmd/server/os-update/describe/describe_test.go b/internal/cmd/server/os-update/describe/describe_test.go index 32dfa4334..646b5ac87 100644 --- a/internal/cmd/server/os-update/describe/describe_test.go +++ b/internal/cmd/server/os-update/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -186,7 +187,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.update); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go index 81086b85f..c0cc0bb8d 100644 --- a/internal/cmd/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "disable", Short: "Disables server os-update service", diff --git a/internal/cmd/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go index c2538aa0f..5e25334bb 100644 --- a/internal/cmd/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "enable", Short: "Enables Server os-update service", diff --git a/internal/cmd/server/os-update/list/list.go b/internal/cmd/server/os-update/list/list.go index 94112f256..7ff61504e 100644 --- a/internal/cmd/server/os-update/list/list.go +++ b/internal/cmd/server/os-update/list/list.go @@ -5,7 +5,8 @@ import ( "fmt" "strconv" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server os-updates", diff --git a/internal/cmd/server/os-update/list/list_test.go b/internal/cmd/server/os-update/list/list_test.go index 541ad0567..99cf70484 100644 --- a/internal/cmd/server/os-update/list/list_test.go +++ b/internal/cmd/server/os-update/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -172,7 +173,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.updates); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/os-update.go b/internal/cmd/server/os-update/os-update.go index 516d7ce06..53abb7893 100644 --- a/internal/cmd/server/os-update/os-update.go +++ b/internal/cmd/server/os-update/os-update.go @@ -1,7 +1,6 @@ package osupdate import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/create" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/disable" @@ -9,12 +8,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "os-update", Short: "Provides functionality for managed server updates", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index b9c1e3a1a..446859534 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -42,7 +43,7 @@ type inputModel struct { MaintenanceWindow int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a Server os-update Schedule", diff --git a/internal/cmd/server/os-update/schedule/create/create_test.go b/internal/cmd/server/os-update/schedule/create/create_test.go index c944e63e7..1e29f4f30 100644 --- a/internal/cmd/server/os-update/schedule/create/create_test.go +++ b/internal/cmd/server/os-update/schedule/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -197,7 +198,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/schedule/delete/delete.go b/internal/cmd/server/os-update/schedule/delete/delete.go index f97ee0ec6..de1d19d3e 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete.go +++ b/internal/cmd/server/os-update/schedule/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", scheduleIdArg), Short: "Deletes a Server os-update Schedule", diff --git a/internal/cmd/server/os-update/schedule/describe/describe.go b/internal/cmd/server/os-update/schedule/describe/describe.go index c7e9a9e93..4e68b04bd 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe.go +++ b/internal/cmd/server/os-update/schedule/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { ScheduleId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", scheduleIdArg), Short: "Shows details of a Server os-update Schedule", diff --git a/internal/cmd/server/os-update/schedule/describe/describe_test.go b/internal/cmd/server/os-update/schedule/describe/describe_test.go index 1f938f1de..0904ac5b5 100644 --- a/internal/cmd/server/os-update/schedule/describe/describe_test.go +++ b/internal/cmd/server/os-update/schedule/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -186,7 +187,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.schedule); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/schedule/list/list.go b/internal/cmd/server/os-update/schedule/list/list.go index 4047fba6d..0e300e547 100644 --- a/internal/cmd/server/os-update/schedule/list/list.go +++ b/internal/cmd/server/os-update/schedule/list/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + iaasClient "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server os-update schedules", diff --git a/internal/cmd/server/os-update/schedule/list/list_test.go b/internal/cmd/server/os-update/schedule/list/list_test.go index f39c88508..5f4fceebc 100644 --- a/internal/cmd/server/os-update/schedule/list/list_test.go +++ b/internal/cmd/server/os-update/schedule/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -172,7 +173,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.schedules); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/os-update/schedule/schedule.go b/internal/cmd/server/os-update/schedule/schedule.go index 3ffeb36ea..d3ccd6b63 100644 --- a/internal/cmd/server/os-update/schedule/schedule.go +++ b/internal/cmd/server/os-update/schedule/schedule.go @@ -1,19 +1,19 @@ package schedule import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/create" del "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/os-update/schedule/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "schedule", Short: "Provides functionality for Server os-update Schedule", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) diff --git a/internal/cmd/server/os-update/schedule/update/update.go b/internal/cmd/server/os-update/schedule/update/update.go index 78570839e..59ca210b1 100644 --- a/internal/cmd/server/os-update/schedule/update/update.go +++ b/internal/cmd/server/os-update/schedule/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -42,7 +43,7 @@ type inputModel struct { MaintenanceWindow *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", scheduleIdArg), Short: "Updates a Server os-update Schedule", diff --git a/internal/cmd/server/os-update/schedule/update/update_test.go b/internal/cmd/server/os-update/schedule/update/update_test.go index a19c77958..e3cf7c7ab 100644 --- a/internal/cmd/server/os-update/schedule/update/update_test.go +++ b/internal/cmd/server/os-update/schedule/update/update_test.go @@ -5,7 +5,8 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -174,7 +175,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -286,7 +287,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.resp); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/public-ip/attach/attach.go b/internal/cmd/server/public-ip/attach/attach.go index 3f76d8852..52ef99867 100644 --- a/internal/cmd/server/public-ip/attach/attach.go +++ b/internal/cmd/server/public-ip/attach/attach.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("attach %s", publicIpIdArg), Short: "Attaches a public IP to a server", diff --git a/internal/cmd/server/public-ip/attach/attach_test.go b/internal/cmd/server/public-ip/attach/attach_test.go index 3f0e10763..4aef71f1f 100644 --- a/internal/cmd/server/public-ip/attach/attach_test.go +++ b/internal/cmd/server/public-ip/attach/attach_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -151,7 +152,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/public-ip/detach/detach.go b/internal/cmd/server/public-ip/detach/detach.go index ecf43cba5..adfa2ad47 100644 --- a/internal/cmd/server/public-ip/detach/detach.go +++ b/internal/cmd/server/public-ip/detach/detach.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { PublicIpId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("detach %s", publicIpIdArg), Short: "Detaches a public IP from a server", diff --git a/internal/cmd/server/public-ip/detach/detach_test.go b/internal/cmd/server/public-ip/detach/detach_test.go index ccea98e12..99251eae0 100644 --- a/internal/cmd/server/public-ip/detach/detach_test.go +++ b/internal/cmd/server/public-ip/detach/detach_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -150,7 +151,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/public-ip/public_ip.go b/internal/cmd/server/public-ip/public_ip.go index 494993ce8..db04a0a67 100644 --- a/internal/cmd/server/public-ip/public_ip.go +++ b/internal/cmd/server/public-ip/public_ip.go @@ -1,16 +1,16 @@ package publicip import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/public-ip/attach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/public-ip/detach" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "public-ip", Short: "Allows attaching/detaching public IPs to servers", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(attach.NewCmd(params)) cmd.AddCommand(detach.NewCmd(params)) } diff --git a/internal/cmd/server/reboot/reboot.go b/internal/cmd/server/reboot/reboot.go index ed13d02ce..4f4b3e268 100644 --- a/internal/cmd/server/reboot/reboot.go +++ b/internal/cmd/server/reboot/reboot.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { HardReboot bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reboot %s", serverIdArg), Short: "Reboots a server", diff --git a/internal/cmd/server/rescue/rescue.go b/internal/cmd/server/rescue/rescue.go index 3ae4f99b5..746fbadc4 100644 --- a/internal/cmd/server/rescue/rescue.go +++ b/internal/cmd/server/rescue/rescue.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { ImageId *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("rescue %s", serverIdArg), Short: "Rescues an existing server", diff --git a/internal/cmd/server/resize/resize.go b/internal/cmd/server/resize/resize.go index 329d5a6b4..495098b40 100644 --- a/internal/cmd/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { MachineType *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("resize %s", serverIdArg), Short: "Resizes the server to the given machine type", diff --git a/internal/cmd/server/server.go b/internal/cmd/server/server.go index ac3101b41..e671fda2b 100644 --- a/internal/cmd/server/server.go +++ b/internal/cmd/server/server.go @@ -1,7 +1,6 @@ package server import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/backup" "github.com/stackitcloud/stackit-cli/internal/cmd/server/command" "github.com/stackitcloud/stackit-cli/internal/cmd/server/console" @@ -24,6 +23,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/server/unrescue" "github.com/stackitcloud/stackit-cli/internal/cmd/server/update" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -31,7 +31,7 @@ import ( "github.com/spf13/cobra" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "server", Short: "Provides functionality for servers", @@ -43,7 +43,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(backup.NewCmd(params)) cmd.AddCommand(command.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 5644ee45f..1bf853199 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { ServiceAccMail string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("attach %s", serviceAccMailArg), Short: "Attach a service account to a server", diff --git a/internal/cmd/server/service-account/attach/attach_test.go b/internal/cmd/server/service-account/attach/attach_test.go index 0edf073b4..b34109960 100644 --- a/internal/cmd/server/service-account/attach/attach_test.go +++ b/internal/cmd/server/service-account/attach/attach_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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-sdk-go/services/iaas" @@ -151,7 +152,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -249,7 +250,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serviceAccMail, tt.args.serverLabel, tt.args.serviceAccounts); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 59966f6d5..ab9fbbe03 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { ServiceAccMail string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("detach %s", serviceAccMailArg), Short: "Detach a service account from a server", diff --git a/internal/cmd/server/service-account/detach/detach_test.go b/internal/cmd/server/service-account/detach/detach_test.go index a1e6c89cd..0867408f1 100644 --- a/internal/cmd/server/service-account/detach/detach_test.go +++ b/internal/cmd/server/service-account/detach/detach_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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-sdk-go/services/iaas" @@ -151,7 +152,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -249,7 +250,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serviceAccMail, tt.args.serverLabel, tt.args.service); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/service-account/list/list.go b/internal/cmd/server/service-account/list/list.go index 95773fc6e..a8188b65b 100644 --- a/internal/cmd/server/service-account/list/list.go +++ b/internal/cmd/server/service-account/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "List all attached service accounts for a server", diff --git a/internal/cmd/server/service-account/list/list_test.go b/internal/cmd/server/service-account/list/list_test.go index a58d5e671..a239a9392 100644 --- a/internal/cmd/server/service-account/list/list_test.go +++ b/internal/cmd/server/service-account/list/list_test.go @@ -5,7 +5,8 @@ import ( "strconv" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -217,7 +218,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverId, tt.args.serverName, tt.args.serviceAccounts); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/service-account/service-account.go b/internal/cmd/server/service-account/service-account.go index b9455c563..6bb4576ba 100644 --- a/internal/cmd/server/service-account/service-account.go +++ b/internal/cmd/server/service-account/service-account.go @@ -2,8 +2,8 @@ package serviceaccount import ( "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/attach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/detach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/service-account/list" @@ -11,7 +11,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "service-account", Short: "Allows attaching/detaching service accounts to servers", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(attach.NewCmd(params)) cmd.AddCommand(detach.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) diff --git a/internal/cmd/server/start/start.go b/internal/cmd/server/start/start.go index e025e2890..3dc23ff31 100644 --- a/internal/cmd/server/start/start.go +++ b/internal/cmd/server/start/start.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("start %s", serverIdArg), Short: "Starts an existing server or allocates the server if deallocated", diff --git a/internal/cmd/server/stop/stop.go b/internal/cmd/server/stop/stop.go index 958127da7..07a8008c3 100644 --- a/internal/cmd/server/stop/stop.go +++ b/internal/cmd/server/stop/stop.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("stop %s", serverIdArg), Short: "Stops an existing server", diff --git a/internal/cmd/server/unrescue/unrescue.go b/internal/cmd/server/unrescue/unrescue.go index 6f433ebeb..e65d13d6e 100644 --- a/internal/cmd/server/unrescue/unrescue.go +++ b/internal/cmd/server/unrescue/unrescue.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -29,7 +30,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("unrescue %s", serverIdArg), Short: "Unrescues an existing server", diff --git a/internal/cmd/server/update/update.go b/internal/cmd/server/update/update.go index f8b404794..76973b91c 100644 --- a/internal/cmd/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", serverIdArg), Short: "Updates a server", diff --git a/internal/cmd/server/update/update_test.go b/internal/cmd/server/update/update_test.go index d13d32c87..7aea4f1c1 100644 --- a/internal/cmd/server/update/update_test.go +++ b/internal/cmd/server/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -178,7 +179,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -275,7 +276,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.server); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go index 65a631ddf..f8bf74a2f 100644 --- a/internal/cmd/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { DeleteOnTermination *bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("attach %s", volumeIdArg), Short: "Attaches a volume to a server", diff --git a/internal/cmd/server/volume/attach/attach_test.go b/internal/cmd/server/volume/attach/attach_test.go index 2f3ed3e69..69bffcfee 100644 --- a/internal/cmd/server/volume/attach/attach_test.go +++ b/internal/cmd/server/volume/attach/attach_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -177,7 +178,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -275,7 +276,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.volumeLabel, tt.args.serverLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/describe/describe.go b/internal/cmd/server/volume/describe/describe.go index 4c0288851..385b585bf 100644 --- a/internal/cmd/server/volume/describe/describe.go +++ b/internal/cmd/server/volume/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { VolumeId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", volumeIdArg), Short: "Describes a server volume attachment", diff --git a/internal/cmd/server/volume/describe/describe_test.go b/internal/cmd/server/volume/describe/describe_test.go index 3d6634075..2e88ae1c4 100644 --- a/internal/cmd/server/volume/describe/describe_test.go +++ b/internal/cmd/server/volume/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -151,7 +152,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -249,7 +250,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.volumeLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/detach/detach.go b/internal/cmd/server/volume/detach/detach.go index 5c271b8fe..7ae8dee8e 100644 --- a/internal/cmd/server/volume/detach/detach.go +++ b/internal/cmd/server/volume/detach/detach.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { VolumeId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("detach %s", volumeIdArg), Short: "Detaches a volume from a server", diff --git a/internal/cmd/server/volume/detach/detach_test.go b/internal/cmd/server/volume/detach/detach_test.go index e9ebecb32..a9b5843b1 100644 --- a/internal/cmd/server/volume/detach/detach_test.go +++ b/internal/cmd/server/volume/detach/detach_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -150,7 +151,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/server/volume/list/list.go b/internal/cmd/server/volume/list/list.go index 4dddab072..10df56261 100644 --- a/internal/cmd/server/volume/list/list.go +++ b/internal/cmd/server/volume/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { ServerId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all server volumes", diff --git a/internal/cmd/server/volume/list/list_test.go b/internal/cmd/server/volume/list/list_test.go index 82e73dff8..ea65dc2cb 100644 --- a/internal/cmd/server/volume/list/list_test.go +++ b/internal/cmd/server/volume/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -187,7 +188,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serverLabel, tt.args.volumeNames, tt.args.volumes); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go index 12c7e66ee..b3faf2d2f 100644 --- a/internal/cmd/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { DeleteOnTermination *bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", volumeIdArg), Short: "Updates an attached volume of a server", diff --git a/internal/cmd/server/volume/update/update_test.go b/internal/cmd/server/volume/update/update_test.go index a15d5e810..532b37d5a 100644 --- a/internal/cmd/server/volume/update/update_test.go +++ b/internal/cmd/server/volume/update/update_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -176,7 +177,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -274,7 +275,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.volumeLabel, tt.args.serverLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/server/volume/volume.go b/internal/cmd/server/volume/volume.go index 15dd14ef7..444ef040b 100644 --- a/internal/cmd/server/volume/volume.go +++ b/internal/cmd/server/volume/volume.go @@ -1,19 +1,19 @@ package volume import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/attach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/detach" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/list" "github.com/stackitcloud/stackit-cli/internal/cmd/server/volume/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "volume", Short: "Provides functionality for server volumes", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(attach.NewCmd(params)) cmd.AddCommand(detach.NewCmd(params)) cmd.AddCommand(update.NewCmd(params)) diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index 73618ca1f..aca5c8133 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { Name *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a service account", diff --git a/internal/cmd/service-account/create/create_test.go b/internal/cmd/service-account/create/create_test.go index 2f95584f8..5418822eb 100644 --- a/internal/cmd/service-account/create/create_test.go +++ b/internal/cmd/service-account/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -177,7 +178,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serviceAccount); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/delete/delete.go b/internal/cmd/service-account/delete/delete.go index ad0a9dc45..ff843534d 100644 --- a/internal/cmd/service-account/delete/delete.go +++ b/internal/cmd/service-account/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -25,7 +26,7 @@ type inputModel struct { Email string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", emailArg), Short: "Deletes a service account", diff --git a/internal/cmd/service-account/get-jwks/get_jwks.go b/internal/cmd/service-account/get-jwks/get_jwks.go index a99655c1c..340df926f 100644 --- a/internal/cmd/service-account/get-jwks/get_jwks.go +++ b/internal/cmd/service-account/get-jwks/get_jwks.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -23,7 +24,7 @@ type inputModel struct { Email string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("get-jwks %s", emailArg), Short: "Shows the JWKS for a service account", diff --git a/internal/cmd/service-account/get-jwks/get_jwks_test.go b/internal/cmd/service-account/get-jwks/get_jwks_test.go index c418ffb22..cd1ed4435 100644 --- a/internal/cmd/service-account/get-jwks/get_jwks_test.go +++ b/internal/cmd/service-account/get-jwks/get_jwks_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -70,7 +71,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -169,7 +170,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serviceAccounts); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/key/create/create.go b/internal/cmd/service-account/key/create/create.go index e23d11cc8..6af133cdc 100644 --- a/internal/cmd/service-account/key/create/create.go +++ b/internal/cmd/service-account/key/create/create.go @@ -6,7 +6,8 @@ import ( "fmt" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -34,7 +35,7 @@ type inputModel struct { PublicKey *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a service account key", diff --git a/internal/cmd/service-account/key/delete/delete.go b/internal/cmd/service-account/key/delete/delete.go index 61c551652..b6ff682d8 100644 --- a/internal/cmd/service-account/key/delete/delete.go +++ b/internal/cmd/service-account/key/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { KeyId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", keyIdArg), Short: "Deletes a service account key", diff --git a/internal/cmd/service-account/key/describe/describe.go b/internal/cmd/service-account/key/describe/describe.go index 8fdc2d7c1..84fb62dd8 100644 --- a/internal/cmd/service-account/key/describe/describe.go +++ b/internal/cmd/service-account/key/describe/describe.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -32,7 +33,7 @@ type inputModel struct { KeyId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", keyIdArg), Short: "Shows details of a service account key", diff --git a/internal/cmd/service-account/key/describe/describe_test.go b/internal/cmd/service-account/key/describe/describe_test.go index 38a7af958..5884f4ce4 100644 --- a/internal/cmd/service-account/key/describe/describe_test.go +++ b/internal/cmd/service-account/key/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -208,7 +209,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.key); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/key/key.go b/internal/cmd/service-account/key/key.go index b91d31b6a..36d982f4e 100644 --- a/internal/cmd/service-account/key/key.go +++ b/internal/cmd/service-account/key/key.go @@ -1,19 +1,19 @@ package key import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/create" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/list" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/key/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "key", Short: "Provides functionality for service account keys", @@ -25,7 +25,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/service-account/key/list/list.go b/internal/cmd/service-account/key/list/list.go index bd7184caa..e450ef021 100644 --- a/internal/cmd/service-account/key/list/list.go +++ b/internal/cmd/service-account/key/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all service account keys", diff --git a/internal/cmd/service-account/key/list/list_test.go b/internal/cmd/service-account/key/list/list_test.go index 845c5cae9..043b1b522 100644 --- a/internal/cmd/service-account/key/list/list_test.go +++ b/internal/cmd/service-account/key/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -189,7 +190,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.keys); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/key/update/update.go b/internal/cmd/service-account/key/update/update.go index ff3387965..fd5d3383a 100644 --- a/internal/cmd/service-account/key/update/update.go +++ b/internal/cmd/service-account/key/update/update.go @@ -6,7 +6,8 @@ import ( "fmt" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -39,7 +40,7 @@ type inputModel struct { Deactivate bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", keyIdArg), Short: "Updates a service account key", diff --git a/internal/cmd/service-account/list/list.go b/internal/cmd/service-account/list/list.go index 7dcd16322..f444e83b3 100644 --- a/internal/cmd/service-account/list/list.go +++ b/internal/cmd/service-account/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all service accounts", diff --git a/internal/cmd/service-account/list/list_test.go b/internal/cmd/service-account/list/list_test.go index f6bcc47ec..051d78044 100644 --- a/internal/cmd/service-account/list/list_test.go +++ b/internal/cmd/service-account/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -179,7 +180,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serviceAccounts); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/service_account.go b/internal/cmd/service-account/service_account.go index 9c2462bfa..856be2fba 100644 --- a/internal/cmd/service-account/service_account.go +++ b/internal/cmd/service-account/service_account.go @@ -1,7 +1,6 @@ package serviceaccount import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/create" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/delete" getjwks "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/get-jwks" @@ -9,12 +8,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/list" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/token" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "service-account", Short: "Provides functionality for service accounts", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index d01da3a99..ea0b1f39d 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { TTLDays *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates an access token for a service account", diff --git a/internal/cmd/service-account/token/create/create_test.go b/internal/cmd/service-account/token/create/create_test.go index a7935e1a7..3dfc4340b 100644 --- a/internal/cmd/service-account/token/create/create_test.go +++ b/internal/cmd/service-account/token/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -183,7 +184,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.serviceAccountEmail, tt.args.token); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/token/list/list.go b/internal/cmd/service-account/token/list/list.go index 7e8f6e12d..436d599f6 100644 --- a/internal/cmd/service-account/token/list/list.go +++ b/internal/cmd/service-account/token/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists access tokens of a service account", diff --git a/internal/cmd/service-account/token/list/list_test.go b/internal/cmd/service-account/token/list/list_test.go index c4cbcf9df..1410b275a 100644 --- a/internal/cmd/service-account/token/list/list_test.go +++ b/internal/cmd/service-account/token/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -189,7 +190,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.tokensMetadata); (err != nil) != tt.wantErr { diff --git a/internal/cmd/service-account/token/revoke/revoke.go b/internal/cmd/service-account/token/revoke/revoke.go index a3bd60f3a..ee3c05a81 100644 --- a/internal/cmd/service-account/token/revoke/revoke.go +++ b/internal/cmd/service-account/token/revoke/revoke.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -30,7 +31,7 @@ type inputModel struct { TokenId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("revoke %s", tokenIdArg), Short: "Revokes an access token of a service account", diff --git a/internal/cmd/service-account/token/token.go b/internal/cmd/service-account/token/token.go index ce4b4eac6..5faeff394 100644 --- a/internal/cmd/service-account/token/token.go +++ b/internal/cmd/service-account/token/token.go @@ -1,17 +1,17 @@ package token import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/token/create" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/token/list" "github.com/stackitcloud/stackit-cli/internal/cmd/service-account/token/revoke" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "token", Short: "Provides functionality for service account tokens", @@ -23,7 +23,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(revoke.NewCmd(params)) diff --git a/internal/cmd/ske/cluster/cluster.go b/internal/cmd/ske/cluster/cluster.go index 87994c2fa..e4dd6bcbb 100644 --- a/internal/cmd/ske/cluster/cluster.go +++ b/internal/cmd/ske/cluster/cluster.go @@ -1,7 +1,6 @@ package cluster import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/create" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/describe" @@ -13,12 +12,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/update" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster/wakeup" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "cluster", Short: "Provides functionality for SKE cluster", @@ -30,7 +30,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(generatepayload.NewCmd(params)) cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index f1874fb65..18113539b 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -5,8 +5,9 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -36,7 +37,7 @@ type inputModel struct { Payload *ske.CreateOrUpdateClusterPayload } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", clusterNameArg), Short: "Creates a SKE cluster", diff --git a/internal/cmd/ske/cluster/create/create_test.go b/internal/cmd/ske/cluster/create/create_test.go index b8bb55557..99392a63d 100644 --- a/internal/cmd/ske/cluster/create/create_test.go +++ b/internal/cmd/ske/cluster/create/create_test.go @@ -6,9 +6,10 @@ import ( "testing" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -295,7 +296,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.projectLabel, tt.args.cluster); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/delete/delete.go b/internal/cmd/ske/cluster/delete/delete.go index d0ebb34fe..fc8b70978 100644 --- a/internal/cmd/ske/cluster/delete/delete.go +++ b/internal/cmd/ske/cluster/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { ClusterName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", clusterNameArg), Short: "Deletes a SKE cluster", diff --git a/internal/cmd/ske/cluster/describe/describe.go b/internal/cmd/ske/cluster/describe/describe.go index 7bbf9ac6b..3e94fa9d9 100644 --- a/internal/cmd/ske/cluster/describe/describe.go +++ b/internal/cmd/ske/cluster/describe/describe.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { ClusterName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", clusterNameArg), Short: "Shows details of a SKE cluster", diff --git a/internal/cmd/ske/cluster/describe/describe_test.go b/internal/cmd/ske/cluster/describe/describe_test.go index da85e7af3..3049998fe 100644 --- a/internal/cmd/ske/cluster/describe/describe_test.go +++ b/internal/cmd/ske/cluster/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -369,7 +370,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.cluster); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload.go b/internal/cmd/ske/cluster/generate-payload/generate_payload.go index e7fcbe234..5afa14cf8 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { FilePath *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "generate-payload", Short: "Generates a payload to create/update SKE clusters", diff --git a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go index 415f83359..97f0aa013 100644 --- a/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go +++ b/internal/cmd/ske/cluster/generate-payload/generate_payload_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -201,7 +202,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.filePath, tt.args.payload); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/hibernate/hibernate.go b/internal/cmd/ske/cluster/hibernate/hibernate.go index 1ee7aff06..ce4c416e5 100644 --- a/internal/cmd/ske/cluster/hibernate/hibernate.go +++ b/internal/cmd/ske/cluster/hibernate/hibernate.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { ClusterName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("hibernate %s", clusterNameArg), Short: "Trigger hibernate for a SKE cluster", diff --git a/internal/cmd/ske/cluster/list/list.go b/internal/cmd/ske/cluster/list/list.go index 33e93389a..b1fa9f024 100644 --- a/internal/cmd/ske/cluster/list/list.go +++ b/internal/cmd/ske/cluster/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { Limit *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all SKE clusters", diff --git a/internal/cmd/ske/cluster/list/list_test.go b/internal/cmd/ske/cluster/list/list_test.go index a2d8f4d44..2b123dba0 100644 --- a/internal/cmd/ske/cluster/list/list_test.go +++ b/internal/cmd/ske/cluster/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -183,7 +184,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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, "dummy-projectlabel", tt.args.clusters); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/maintenance/maintenance.go b/internal/cmd/ske/cluster/maintenance/maintenance.go index bad6c37f4..cc3c1ab1d 100644 --- a/internal/cmd/ske/cluster/maintenance/maintenance.go +++ b/internal/cmd/ske/cluster/maintenance/maintenance.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -27,7 +28,7 @@ type inputModel struct { ClusterName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("maintenance %s", clusterNameArg), Short: "Trigger maintenance for a SKE cluster", diff --git a/internal/cmd/ske/cluster/reconcile/reconcile.go b/internal/cmd/ske/cluster/reconcile/reconcile.go index 719ebeb44..0108ae568 100644 --- a/internal/cmd/ske/cluster/reconcile/reconcile.go +++ b/internal/cmd/ske/cluster/reconcile/reconcile.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { ClusterName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("reconcile %s", clusterNameArg), Short: "Trigger reconcile for a SKE cluster", diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index 81187ccd4..e59fa9990 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -33,7 +34,7 @@ type inputModel struct { Payload ske.CreateOrUpdateClusterPayload } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", clusterNameArg), Short: "Updates a SKE cluster", diff --git a/internal/cmd/ske/cluster/update/update_test.go b/internal/cmd/ske/cluster/update/update_test.go index 8285af7e1..e4a28fb91 100644 --- a/internal/cmd/ske/cluster/update/update_test.go +++ b/internal/cmd/ske/cluster/update/update_test.go @@ -6,7 +6,8 @@ import ( "testing" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -282,7 +283,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.async, tt.args.clusterName, tt.args.cluster); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/cluster/wakeup/wakeup.go b/internal/cmd/ske/cluster/wakeup/wakeup.go index 950dbf3b1..64b0e5ccf 100644 --- a/internal/cmd/ske/cluster/wakeup/wakeup.go +++ b/internal/cmd/ske/cluster/wakeup/wakeup.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -26,7 +27,7 @@ type inputModel struct { ClusterName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("wakeup %s", clusterNameArg), Short: "Trigger wakeup from hibernation for a SKE cluster", diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go index f4a1fcc5b..d9970b539 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { ClusterName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("complete-rotation %s", clusterNameArg), Short: "Completes the rotation of the credentials associated to a SKE cluster", diff --git a/internal/cmd/ske/credentials/credentials.go b/internal/cmd/ske/credentials/credentials.go index 2770f349a..13218d2fa 100644 --- a/internal/cmd/ske/credentials/credentials.go +++ b/internal/cmd/ske/credentials/credentials.go @@ -1,16 +1,16 @@ package credentials import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" completerotation "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials/complete-rotation" startrotation "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials/start-rotation" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "credentials", Short: "Provides functionality for SKE credentials", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(startrotation.NewCmd(params)) cmd.AddCommand(completerotation.NewCmd(params)) } diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation.go b/internal/cmd/ske/credentials/start-rotation/start_rotation.go index ea65650ea..91af511fd 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -27,7 +28,7 @@ type inputModel struct { ClusterName string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("start-rotation %s", clusterNameArg), Short: "Starts the rotation of the credentials associated to a SKE cluster", diff --git a/internal/cmd/ske/describe/describe.go b/internal/cmd/ske/describe/describe.go index c1804fc9a..414525335 100644 --- a/internal/cmd/ske/describe/describe.go +++ b/internal/cmd/ske/describe/describe.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -22,7 +23,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "describe", Short: "Shows overall details regarding SKE", diff --git a/internal/cmd/ske/describe/describe_test.go b/internal/cmd/ske/describe/describe_test.go index 3a0283a6c..53dd3afc8 100644 --- a/internal/cmd/ske/describe/describe_test.go +++ b/internal/cmd/ske/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" serviceEnablementUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/service-enablement/utils" @@ -159,7 +160,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.project, tt.args.projectId); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index f9eb1ac3b..cd2dc87db 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -24,7 +25,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "disable", Short: "Disables SKE for a project", diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index 9d9783dd2..411140edc 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -24,7 +25,7 @@ type inputModel struct { *globalflags.GlobalFlagModel } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "enable", Short: "Enables SKE for a project", diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index 86b282cfa..725c53636 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -5,8 +5,9 @@ import ( "encoding/json" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/goccy/go-yaml" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -41,7 +42,7 @@ type inputModel struct { Overwrite bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", clusterNameArg), Short: "Creates or update a kubeconfig for a SKE cluster", diff --git a/internal/cmd/ske/kubeconfig/create/create_test.go b/internal/cmd/ske/kubeconfig/create/create_test.go index 5c7b25e58..f8e826064 100644 --- a/internal/cmd/ske/kubeconfig/create/create_test.go +++ b/internal/cmd/ske/kubeconfig/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -283,7 +284,7 @@ func Test_outputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.clusterName, tt.args.kubeconfigPath, tt.args.respKubeconfig, tt.args.respLogin); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/kubeconfig/kubeconfig.go b/internal/cmd/ske/kubeconfig/kubeconfig.go index ad5482dbe..e1fb827c2 100644 --- a/internal/cmd/ske/kubeconfig/kubeconfig.go +++ b/internal/cmd/ske/kubeconfig/kubeconfig.go @@ -1,16 +1,16 @@ package kubeconfig import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/kubeconfig/create" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/kubeconfig/login" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "kubeconfig", Short: "Provides functionality for SKE kubeconfig", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(login.NewCmd(params)) } diff --git a/internal/cmd/ske/kubeconfig/login/login.go b/internal/cmd/ske/kubeconfig/login/login.go index e51f69c63..68775aed3 100644 --- a/internal/cmd/ske/kubeconfig/login/login.go +++ b/internal/cmd/ske/kubeconfig/login/login.go @@ -12,7 +12,8 @@ import ( "strconv" "time" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/cache" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "k8s.io/client-go/rest" @@ -36,7 +37,7 @@ const ( refreshBeforeDuration = 15 * time.Minute // 15 min ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "login", Short: "Login plugin for kubernetes clients", diff --git a/internal/cmd/ske/options/options.go b/internal/cmd/ske/options/options.go index 5da30e803..21f04d028 100644 --- a/internal/cmd/ske/options/options.go +++ b/internal/cmd/ske/options/options.go @@ -7,8 +7,9 @@ import ( "strings" "time" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/flags" @@ -37,7 +38,7 @@ type inputModel struct { VolumeTypes bool } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "options", Short: "Lists SKE provider options", @@ -272,13 +273,13 @@ func buildMachineImagesTable(resp *ske.ProviderOptions) tables.Table { } func buildMachineTypesTable(resp *ske.ProviderOptions) tables.Table { - types := *resp.MachineTypes + machineTypes := *resp.MachineTypes table := tables.NewTable() table.SetTitle("Machine Types") table.SetHeader("TYPE", "CPU", "MEMORY") - for i := range types { - t := types[i] + for i := range machineTypes { + t := machineTypes[i] table.AddRow( utils.PtrString(t.Name), utils.PtrString(t.Cpu), @@ -289,13 +290,13 @@ func buildMachineTypesTable(resp *ske.ProviderOptions) tables.Table { } func buildVolumeTypesTable(resp *ske.ProviderOptions) tables.Table { - types := *resp.VolumeTypes + volumeTypes := *resp.VolumeTypes table := tables.NewTable() table.SetTitle("Volume Types") table.SetHeader("TYPE") - for i := range types { - z := types[i] + for i := range volumeTypes { + z := volumeTypes[i] table.AddRow(utils.PtrString(z.Name)) } return table diff --git a/internal/cmd/ske/options/options_test.go b/internal/cmd/ske/options/options_test.go index 1627f3709..43f58c5b4 100644 --- a/internal/cmd/ske/options/options_test.go +++ b/internal/cmd/ske/options/options_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -211,7 +212,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.options); (err != nil) != tt.wantErr { @@ -244,7 +245,7 @@ func TestOutputResultAsTable(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := outputResultAsTable(p, tt.args.options); (err != nil) != tt.wantErr { diff --git a/internal/cmd/ske/ske.go b/internal/cmd/ske/ske.go index e782119db..3c052fa71 100644 --- a/internal/cmd/ske/ske.go +++ b/internal/cmd/ske/ske.go @@ -1,7 +1,6 @@ package ske import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/cluster" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/credentials" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/describe" @@ -10,12 +9,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/ske/kubeconfig" "github.com/stackitcloud/stackit-cli/internal/cmd/ske/options" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "ske", Short: "Provides functionality for SKE", @@ -27,7 +27,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(cluster.NewCmd(params)) cmd.AddCommand(credentials.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/volume/backup/backup.go b/internal/cmd/volume/backup/backup.go index b7cf8b37b..271336ba2 100644 --- a/internal/cmd/volume/backup/backup.go +++ b/internal/cmd/volume/backup/backup.go @@ -1,7 +1,6 @@ package backup import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/create" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/describe" @@ -9,12 +8,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/restore" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "backup", Short: "Provides functionality for volume backups", @@ -26,7 +26,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) cmd.AddCommand(update.NewCmd(params)) diff --git a/internal/cmd/volume/backup/create/create.go b/internal/cmd/volume/backup/create/create.go index 316efc520..3673b6ac8 100644 --- a/internal/cmd/volume/backup/create/create.go +++ b/internal/cmd/volume/backup/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -39,7 +40,7 @@ type inputModel struct { Labels map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a backup from a specific source", @@ -77,14 +78,16 @@ func NewCmd(params *params.CmdParams) *cobra.Command { // Get source name for label (use ID if name not available) sourceLabel := model.SourceID - if model.SourceType == "volume" { + + switch model.SourceType { + case "volume": name, err := iaasutils.GetVolumeName(ctx, apiClient, model.ProjectId, model.Region, model.SourceID) if err != nil { params.Printer.Debug(print.ErrorLevel, "get volume name: %v", err) } else if name != "" { sourceLabel = name } - } else if model.SourceType == "snapshot" { + case "snapshot": name, err := iaasutils.GetSnapshotName(ctx, apiClient, model.ProjectId, model.Region, model.SourceID) if err != nil { params.Printer.Debug(print.ErrorLevel, "get snapshot name: %v", err) diff --git a/internal/cmd/volume/backup/create/create_test.go b/internal/cmd/volume/backup/create/create_test.go index 3f4e64d15..3b7d432e6 100644 --- a/internal/cmd/volume/backup/create/create_test.go +++ b/internal/cmd/volume/backup/create/create_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -263,7 +264,7 @@ func TestOutputResult(t *testing.T) { } p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) p.Cmd = cmd for _, tt := range tests { diff --git a/internal/cmd/volume/backup/delete/delete.go b/internal/cmd/volume/backup/delete/delete.go index b439f0d6d..e8e2ce676 100644 --- a/internal/cmd/volume/backup/delete/delete.go +++ b/internal/cmd/volume/backup/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { BackupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", backupIdArg), Short: "Deletes a backup", diff --git a/internal/cmd/volume/backup/describe/describe.go b/internal/cmd/volume/backup/describe/describe.go index 3f95fe355..c8c1b66d1 100644 --- a/internal/cmd/volume/backup/describe/describe.go +++ b/internal/cmd/volume/backup/describe/describe.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { BackupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", backupIdArg), Short: "Describes a backup", diff --git a/internal/cmd/volume/backup/describe/describe_test.go b/internal/cmd/volume/backup/describe/describe_test.go index 1ba033cb2..8ffe6e03e 100644 --- a/internal/cmd/volume/backup/describe/describe_test.go +++ b/internal/cmd/volume/backup/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -174,7 +175,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.backup); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/backup/list/list.go b/internal/cmd/volume/backup/list/list.go index 825a6793e..c434b3df5 100644 --- a/internal/cmd/volume/backup/list/list.go +++ b/internal/cmd/volume/backup/list/list.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all backups", diff --git a/internal/cmd/volume/backup/list/list_test.go b/internal/cmd/volume/backup/list/list_test.go index 3734dc1f7..0722dd90d 100644 --- a/internal/cmd/volume/backup/list/list_test.go +++ b/internal/cmd/volume/backup/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -189,7 +190,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.backups); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/backup/restore/restore.go b/internal/cmd/volume/backup/restore/restore.go index 3922c4ae8..29239a7fe 100644 --- a/internal/cmd/volume/backup/restore/restore.go +++ b/internal/cmd/volume/backup/restore/restore.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { BackupId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("restore %s", backupIdArg), Short: "Restores a backup", diff --git a/internal/cmd/volume/backup/update/update.go b/internal/cmd/volume/backup/update/update.go index 920ef6667..02fe3703a 100644 --- a/internal/cmd/volume/backup/update/update.go +++ b/internal/cmd/volume/backup/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Labels map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", backupIdArg), Short: "Updates a backup", diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index a9b624c67..8b3a536a5 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -44,7 +45,7 @@ type inputModel struct { SourceType *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a volume", diff --git a/internal/cmd/volume/create/create_test.go b/internal/cmd/volume/create/create_test.go index dde4f7893..9628fd508 100644 --- a/internal/cmd/volume/create/create_test.go +++ b/internal/cmd/volume/create/create_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -280,7 +281,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.model, tt.args.projectLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go index 58d47c8ae..f6550714c 100644 --- a/internal/cmd/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { VolumeId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", volumeIdArg), Short: "Deletes a volume", diff --git a/internal/cmd/volume/describe/describe.go b/internal/cmd/volume/describe/describe.go index 0683ae255..8ff8dbfab 100644 --- a/internal/cmd/volume/describe/describe.go +++ b/internal/cmd/volume/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { VolumeId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", volumeIdArg), Short: "Shows details of a volume", diff --git a/internal/cmd/volume/describe/describe_test.go b/internal/cmd/volume/describe/describe_test.go index 9396645d4..eb595b37e 100644 --- a/internal/cmd/volume/describe/describe_test.go +++ b/internal/cmd/volume/describe/describe_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -199,7 +200,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/list/list.go b/internal/cmd/volume/list/list.go index 586f8b721..5d82bad1a 100644 --- a/internal/cmd/volume/list/list.go +++ b/internal/cmd/volume/list/list.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -30,7 +31,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all volumes of a project", diff --git a/internal/cmd/volume/list/list_test.go b/internal/cmd/volume/list/list_test.go index 4fdeab7b2..d81ee310f 100644 --- a/internal/cmd/volume/list/list_test.go +++ b/internal/cmd/volume/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -195,7 +196,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.volumes); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/performance-class/describe/describe.go b/internal/cmd/volume/performance-class/describe/describe.go index 324609ada..23c763e84 100644 --- a/internal/cmd/volume/performance-class/describe/describe.go +++ b/internal/cmd/volume/performance-class/describe/describe.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -28,7 +29,7 @@ type inputModel struct { VolumePerformanceClass string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", volumePerformanceClassArg), Short: "Shows details of a volume performance class", diff --git a/internal/cmd/volume/performance-class/describe/describe_test.go b/internal/cmd/volume/performance-class/describe/describe_test.go index 269dae052..d24d96eaf 100644 --- a/internal/cmd/volume/performance-class/describe/describe_test.go +++ b/internal/cmd/volume/performance-class/describe/describe_test.go @@ -4,12 +4,13 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "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" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-sdk-go/services/iaas" @@ -194,7 +195,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.performanceClass); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/performance-class/list/list.go b/internal/cmd/volume/performance-class/list/list.go index 46ef6574b..7062011aa 100644 --- a/internal/cmd/volume/performance-class/list/list.go +++ b/internal/cmd/volume/performance-class/list/list.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -31,7 +32,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all volume performance classes for a project", diff --git a/internal/cmd/volume/performance-class/list/list_test.go b/internal/cmd/volume/performance-class/list/list_test.go index 7bbd048f0..53004a31b 100644 --- a/internal/cmd/volume/performance-class/list/list_test.go +++ b/internal/cmd/volume/performance-class/list/list_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -195,7 +196,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.performanceClasses); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/performance-class/performance_class.go b/internal/cmd/volume/performance-class/performance_class.go index 6ed86618a..dd00fe2d6 100644 --- a/internal/cmd/volume/performance-class/performance_class.go +++ b/internal/cmd/volume/performance-class/performance_class.go @@ -1,16 +1,16 @@ package performanceclass import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/performance-class/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/performance-class/list" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "performance-class", Short: "Provides functionality for volume performance classes available inside a project", @@ -22,7 +22,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(describe.NewCmd(params)) cmd.AddCommand(list.NewCmd(params)) } diff --git a/internal/cmd/volume/resize/resize.go b/internal/cmd/volume/resize/resize.go index 58be4800d..7bcc40dc0 100644 --- a/internal/cmd/volume/resize/resize.go +++ b/internal/cmd/volume/resize/resize.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -31,7 +32,7 @@ type inputModel struct { Size *int64 } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("resize %s", volumeIdArg), Short: "Resizes a volume", diff --git a/internal/cmd/volume/resize/resize_test.go b/internal/cmd/volume/resize/resize_test.go index 094cb7864..a45ecb6ea 100644 --- a/internal/cmd/volume/resize/resize_test.go +++ b/internal/cmd/volume/resize/resize_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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/utils" @@ -158,7 +159,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/volume/snapshot/create/create.go b/internal/cmd/volume/snapshot/create/create.go index a49b89da4..29dd2894c 100644 --- a/internal/cmd/volume/snapshot/create/create.go +++ b/internal/cmd/volume/snapshot/create/create.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -35,7 +36,7 @@ type inputModel struct { Labels map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Creates a snapshot from a volume", diff --git a/internal/cmd/volume/snapshot/delete/delete.go b/internal/cmd/volume/snapshot/delete/delete.go index a94ef6bf1..c4c06b34d 100644 --- a/internal/cmd/volume/snapshot/delete/delete.go +++ b/internal/cmd/volume/snapshot/delete/delete.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -29,7 +30,7 @@ type inputModel struct { SnapshotId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete %s", snapshotIdArg), Short: "Deletes a snapshot", diff --git a/internal/cmd/volume/snapshot/describe/describe.go b/internal/cmd/volume/snapshot/describe/describe.go index 17ed41c88..c87336496 100644 --- a/internal/cmd/volume/snapshot/describe/describe.go +++ b/internal/cmd/volume/snapshot/describe/describe.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -28,7 +29,7 @@ type inputModel struct { SnapshotId string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe %s", snapshotIdArg), Short: "Describes a snapshot", diff --git a/internal/cmd/volume/snapshot/describe/describe_test.go b/internal/cmd/volume/snapshot/describe/describe_test.go index ff1e25aec..046e19f24 100644 --- a/internal/cmd/volume/snapshot/describe/describe_test.go +++ b/internal/cmd/volume/snapshot/describe/describe_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -199,7 +200,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.snapshot); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/snapshot/list/list.go b/internal/cmd/volume/snapshot/list/list.go index ce8052287..70b97edf2 100644 --- a/internal/cmd/volume/snapshot/list/list.go +++ b/internal/cmd/volume/snapshot/list/list.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { LabelSelector *string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "Lists all snapshots", diff --git a/internal/cmd/volume/snapshot/list/list_test.go b/internal/cmd/volume/snapshot/list/list_test.go index 5e9c8b0c8..ff2d86383 100644 --- a/internal/cmd/volume/snapshot/list/list_test.go +++ b/internal/cmd/volume/snapshot/list/list_test.go @@ -4,7 +4,8 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" + "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" @@ -217,7 +218,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.snapshots); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/snapshot/snapshot.go b/internal/cmd/volume/snapshot/snapshot.go index 9656b1465..579233ca9 100644 --- a/internal/cmd/volume/snapshot/snapshot.go +++ b/internal/cmd/volume/snapshot/snapshot.go @@ -2,17 +2,17 @@ package snapshot import ( "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/create" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/delete" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/describe" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/list" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot/update" "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "snapshot", Short: "Provides functionality for snapshots", @@ -24,7 +24,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/cmd/volume/snapshot/update/update.go b/internal/cmd/volume/snapshot/update/update.go index 766c33b34..b43072bce 100644 --- a/internal/cmd/volume/snapshot/update/update.go +++ b/internal/cmd/volume/snapshot/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -32,7 +33,7 @@ type inputModel struct { Labels map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", snapshotIdArg), Short: "Updates a snapshot", diff --git a/internal/cmd/volume/update/update.go b/internal/cmd/volume/update/update.go index 55e2e2a70..194a70db3 100644 --- a/internal/cmd/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -34,7 +35,7 @@ type inputModel struct { Labels *map[string]string } -func NewCmd(params *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update %s", volumeIdArg), Short: "Updates a volume", diff --git a/internal/cmd/volume/update/update_test.go b/internal/cmd/volume/update/update_test.go index 6b890a82c..0f34841aa 100644 --- a/internal/cmd/volume/update/update_test.go +++ b/internal/cmd/volume/update/update_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -182,7 +183,7 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { p := print.NewPrinter() - cmd := NewCmd(¶ms.CmdParams{Printer: p}) + cmd := NewCmd(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) @@ -286,7 +287,7 @@ func TestOutputResult(t *testing.T) { }, } p := print.NewPrinter() - p.Cmd = NewCmd(¶ms.CmdParams{Printer: p}) + 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.volumeLabel, tt.args.volume); (err != nil) != tt.wantErr { diff --git a/internal/cmd/volume/volume.go b/internal/cmd/volume/volume.go index 8da9cbd13..a6967a9ae 100644 --- a/internal/cmd/volume/volume.go +++ b/internal/cmd/volume/volume.go @@ -1,7 +1,6 @@ package volume import ( - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/backup" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/create" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/delete" @@ -12,12 +11,13 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/volume/snapshot" "github.com/stackitcloud/stackit-cli/internal/cmd/volume/update" "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 *params.CmdParams) *cobra.Command { +func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: "volume", Short: "Provides functionality for volumes", @@ -29,7 +29,7 @@ func NewCmd(params *params.CmdParams) *cobra.Command { return cmd } -func addSubcommands(cmd *cobra.Command, params *params.CmdParams) { +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(create.NewCmd(params)) cmd.AddCommand(delete.NewCmd(params)) cmd.AddCommand(describe.NewCmd(params)) diff --git a/internal/pkg/projectname/project_name.go b/internal/pkg/projectname/project_name.go index 84381a8c6..b2c77117f 100644 --- a/internal/pkg/projectname/project_name.go +++ b/internal/pkg/projectname/project_name.go @@ -42,7 +42,7 @@ func GetProjectName(ctx context.Context, p *print.Printer, cliVersion string, cm // If project ID is set in config, we store the project name in config // (So next time we can just pull it from there) - if !(isProjectIdSetInFlags(p, cmd) || isProjectIdSetInEnvVar()) { + if !isProjectIdSetInFlags(p, cmd) && !isProjectIdSetInEnvVar() { viper.Set(config.ProjectNameKey, projectName) err = config.Write() if err != nil { @@ -61,10 +61,7 @@ func useProjectNameFromConfig(p *print.Printer, cmd *cobra.Command) bool { projectIdSetInFlags := isProjectIdSetInFlags(p, cmd) projectIdSetInEnv := isProjectIdSetInEnvVar() projectName := viper.GetString(config.ProjectNameKey) - projectNameSet := false - if projectName != "" { - projectNameSet = true - } + projectNameSet := projectName != "" return !projectIdSetInFlags && !projectIdSetInEnv && projectNameSet } @@ -73,10 +70,7 @@ func isProjectIdSetInFlags(p *print.Printer, cmd *cobra.Command) bool { // viper.GetString uses the flags, and fallsback to config file // To check if projectId was passed, we use the first rather than the second projectIdFromFlag := flags.FlagToStringPointer(p, cmd, globalflags.ProjectIdFlag) - projectIdSetInFlag := false - if projectIdFromFlag != nil { - projectIdSetInFlag = true - } + projectIdSetInFlag := projectIdFromFlag != nil return projectIdSetInFlag } diff --git a/internal/pkg/testutils/testutils.go b/internal/pkg/testutils/testutils.go index 8f970fd0a..f9ac93524 100644 --- a/internal/pkg/testutils/testutils.go +++ b/internal/pkg/testutils/testutils.go @@ -3,23 +3,24 @@ package testutils import ( "testing" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/google/go-cmp/cmp" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-cli/internal/cmd/params" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/print" ) // TestParseInput centralizes the logic to test a combination of inputs (arguments, flags) for a cobra command -func TestParseInput[T any](t *testing.T, cmdFactory func(*params.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, isValid bool) { +func TestParseInput[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, isValid bool) { TestParseInputWithAdditionalFlags(t, cmdFactory, parseInputFunc, expectedModel, argValues, flagValues, map[string][]string{}, isValid) } // TestParseInputWithAdditionalFlags centralizes the logic to test a combination of inputs (arguments, flags) for a cobra command. // It allows to pass multiple instances of a single flag to the cobra command using the `additionalFlagValues` parameter. -func TestParseInputWithAdditionalFlags[T any](t *testing.T, cmdFactory func(*params.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, additionalFlagValues map[string][]string, isValid bool) { +func TestParseInputWithAdditionalFlags[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, additionalFlagValues map[string][]string, isValid bool) { p := print.NewPrinter() - cmd := cmdFactory(¶ms.CmdParams{Printer: p}) + cmd := cmdFactory(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) if err != nil { t.Fatalf("configure global flags: %v", err) diff --git a/internal/cmd/params/cmd_params.go b/internal/pkg/types/cmd_params.go similarity index 90% rename from internal/cmd/params/cmd_params.go rename to internal/pkg/types/cmd_params.go index 572c80706..e221ac7bb 100644 --- a/internal/cmd/params/cmd_params.go +++ b/internal/pkg/types/cmd_params.go @@ -1,4 +1,4 @@ -package params +package types import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" From 5870218b4fb08889bffc098700b7781d5eb4be8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 08:32:00 +0100 Subject: [PATCH 551/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex (#1149) Bumps [github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex](https://github.com/stackitcloud/stackit-sdk-go) from 1.3.3 to 1.3.4. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/runcommand/v1.3.3...services/serverbackup/v1.3.4) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex dependency-version: 1.3.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bae42f51f..a480fd168 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.3 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.30.0 golang.org/x/oauth2 v0.33.0 diff --git a/go.sum b/go.sum index a4e5c9be6..735375a28 100644 --- a/go.sum +++ b/go.sum @@ -650,8 +650,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 h1:zcfL github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3/go.mod h1:icu5WtsZ8c57/pUrXeFLmZu29Qhwr/rsjTkVRWJYTqY= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 h1:bQk5qKid5Kv3fZ2miWlS5Dvo+cW90hbePaxOyWF67EE= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0/go.mod h1:/Ujlw+qo6RgKm69dD8y6MgmJFcUmrHjuJPO6VFoQX9U= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.3 h1:TFefEGGxvcI7euqyosbLS/zSEOy+3JMGOirW3vNj/84= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.3/go.mod h1:Jsry+gfhuXv2P0ldfa48BaL605NhDjdQMgaoV8czlbo= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 h1:IUhMJH9fQ+CaMas+5bbnrH7m1Hadf1vWoUtu9KeAEFM= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4/go.mod h1:fd13ANCU/Pye8uDd/6E0I605+6PYfHuVIQpPEK2Ph6c= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From a686b9fdff144f8e899656556f93ccfc7708f794 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 07:40:36 +0000 Subject: [PATCH 552/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serverbackup (#1150) Bumps [github.com/stackitcloud/stackit-sdk-go/services/serverbackup](https://github.com/stackitcloud/stackit-sdk-go) from 1.3.3 to 1.3.4. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/runcommand/v1.3.3...services/serverbackup/v1.3.4) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/serverbackup dependency-version: 1.3.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a480fd168..cbd8c6062 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 diff --git a/go.sum b/go.sum index 735375a28..9357799e2 100644 --- a/go.sum +++ b/go.sum @@ -640,8 +640,8 @@ github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 h1:Jts49V7XvLL github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2/go.mod h1:hV1rmsyb3jlL5kWO+flhtXTbm5EM9vU+BJsV4U/YEUU= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp742W6AgleV2eEXrJFZ7ai9rXu9V1Lkmir0drI= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2/go.mod h1:xm0ARtIbfzmqw8e8qThtrYdHHEkpuYvKt13SZGBoWSE= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3 h1:LONKouoyrgDfu4Tu152YFjd5cw3SoG8P7PHdd8tsBOU= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.3/go.mod h1:mCiDOqMHQKM9cFs5/GULaYz6Ni0QA2TTMQZJcj4GFUE= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 h1:lOlg8zYL2nwMi1JxDYW2p8LL4cSB3eoOjlqPHioDWU0= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4/go.mod h1:MBlzqmewliF1LKeOBdOuT+aQrtc3y7p1Kd1fWkjecKQ= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 h1:ubaIeflBZ70evMhU5Xl4NzzDUTk0Z309jnv18OikXgs= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2/go.mod h1:NH6dyKSkJ0WezDgIpXr5PkhSGUXJvwEFcsQmeGScDs8= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 h1:+S5yPftGLH99ByzDCwzdI927bvKOKMQxMkd/tuPeQTE= From 3eabca4e6ad68d0682e1768f44f32b2daa0ff003 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 07:50:22 +0000 Subject: [PATCH 553/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mariadb (#1151) Bumps [github.com/stackitcloud/stackit-sdk-go/services/mariadb](https://github.com/stackitcloud/stackit-sdk-go) from 0.25.2 to 0.25.3. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/logme/v0.25.2...services/logme/v0.25.3) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/mariadb dependency-version: 0.25.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cbd8c6062..53fe6a5c5 100644 --- a/go.mod +++ b/go.mod @@ -264,7 +264,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 - github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.2 + github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 diff --git a/go.sum b/go.sum index 9357799e2..3626f57ab 100644 --- a/go.sum +++ b/go.sum @@ -618,8 +618,8 @@ github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 h1:BHNjq4+Os github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1/go.mod h1:sTV6ylmBoMOrOxUED8Ebts4a1PaJSPLtmNh5m+s5fus= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 h1:g3xzRqwul8W638gOKTZRAnnQuMhYqaliuz/A8BcfjhU= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2/go.mod h1:OlGmMlXKp33ZYpUm9TqaLYf8SdzhDW5uBKcbgq1zXOk= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.2 h1:SfRbw3DxvDnZF2q6D9xfSy8EKHyrG5TgLMP0qRW8r9o= -github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.2/go.mod h1:VmXwRQHZsGUjGWdLf8d2WhKNyuPi5+JgCAF/meOp4DE= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOwjKMWpKl0nrqiq7psTf4NJv0IKgwTkc= +github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3/go.mod h1:TMl5WcpjzUiAlLWaxMKbu9ysDzFziSPgg4xLxj9jjfY= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 h1:tGa+NcjNKTWvChN+0OMdLomb9Jod4MmY6YAiPTJMgfo= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3/go.mod h1:ciuOzwN5GcqplRy95fXRaS44dFmhfNxvmzTl/ALwV/k= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 h1:I9B/zUU7R74xuH/ztcPrDIuMp2KV3QQMjeE7lFudboM= From 0e90fb5966cadc91651b33c1292e79bf0452edcd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 09:01:37 +0100 Subject: [PATCH 554/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/redis (#1152) Bumps [github.com/stackitcloud/stackit-sdk-go/services/redis](https://github.com/stackitcloud/stackit-sdk-go) from 0.25.2 to 0.25.3. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/logme/v0.25.2...services/logme/v0.25.3) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/redis dependency-version: 0.25.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 53fe6a5c5..f1fe41ecd 100644 --- a/go.mod +++ b/go.mod @@ -268,7 +268,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 - github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2 + github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 github.com/subosito/gotenv v1.6.0 // indirect golang.org/x/sys v0.38.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 3626f57ab..1f35fc7d2 100644 --- a/go.sum +++ b/go.sum @@ -632,8 +632,8 @@ github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1/go.mod h1:hyhw+I19NtjKmRLcUkY4boaTxnYSPFGbpn4RxvGqH2s= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 h1:Ww0baLTiZha4H1thfEEsDq+O0Ce0hNhdbkJ5eDdGEoE= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2/go.mod h1:lPz9iQ3kLvpzPR7jt6P1VJyjSumo2+D1i3RkjFGpVTI= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2 h1:VWx+u5b9r+HEm2rCtGlS7OFKl6Fnqe6s2xyCBA3IbM8= -github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.2/go.mod h1:fg1pAqju7q5A696aiok2L4SHZIjZCCiBCpsm7FrQZMA= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 h1:AcJSIEu1QCzRughJLzVjRP5ICop0DkvV2TgFb9LS7/c= +github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3/go.mod h1:DLXqpz1WhmOergfOLMJ4pybozz33ysOZNIO7fv9Wtfc= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 h1:KDa5sy6NSzMOXaf4a9skxOm8oUoleI45fLbD3ww7qsc= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1/go.mod h1:+k3iHkWpehO+FLC5WsW7eGhYdNjDklYqRcpIxQBLbZg= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 h1:Jts49V7XvLLr7MwI9o5Mo0NW3iUVVt8DtqNqRDt6ags= From bddbc7b7440d70265481d463e9233cc542bcf952 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 8 Dec 2025 09:17:57 +0100 Subject: [PATCH 555/619] chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.7.2 (#1154) Co-authored-by: Renovate Bot --- go.mod | 18 +++++++++--------- go.sum | 40 ++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/go.mod b/go.mod index f1fe41ecd..df5f75555 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/BurntSushi/toml v1.5.0 // indirect github.com/Djarvur/go-err113 v0.1.1 // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect - github.com/MirrexOne/unqueryvet v1.2.1 // indirect + github.com/MirrexOne/unqueryvet v1.3.0 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect github.com/alecthomas/chroma/v2 v2.20.0 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect @@ -87,7 +87,7 @@ require ( github.com/breml/errchkjson v0.4.1 // indirect github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect - github.com/catenacyber/perfsprint v0.10.0 // indirect + github.com/catenacyber/perfsprint v0.10.1 // indirect github.com/ccojocar/zxcvbn-go v1.0.4 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charithe/durationcheck v0.0.11 // indirect @@ -119,14 +119,14 @@ require ( github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/godoc-lint/godoc-lint v0.10.1 // indirect + github.com/godoc-lint/godoc-lint v0.10.2 // indirect github.com/gofrs/flock v0.13.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect github.com/golangci/go-printf-func-name v0.1.1 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golangci-lint/v2 v2.6.2 // indirect + github.com/golangci/golangci-lint/v2 v2.7.2 // indirect github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 // indirect github.com/golangci/misspell v0.7.0 // indirect github.com/golangci/plugin-module-register v0.1.2 // indirect @@ -139,7 +139,7 @@ require ( github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect github.com/gostaticanalysis/nilerr v0.1.2 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/jgautheron/goconst v1.8.2 // indirect @@ -167,7 +167,7 @@ require ( github.com/matoous/godox v1.1.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mgechev/revive v1.12.0 // indirect + github.com/mgechev/revive v1.13.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect github.com/muesli/termenv v0.16.0 // indirect @@ -195,19 +195,19 @@ require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect - github.com/securego/gosec/v2 v2.22.10 // indirect + github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/sonatard/noctx v0.4.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect - github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect + github.com/stbenjam/no-sprintf-host-port v0.3.1 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/testify v1.11.1 // indirect github.com/tetafro/godot v1.5.4 // indirect github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect github.com/timonwong/loggercheck v0.11.0 // indirect - github.com/tomarrell/wrapcheck/v2 v2.11.0 // indirect + github.com/tomarrell/wrapcheck/v2 v2.12.0 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect diff --git a/go.sum b/go.sum index 1f35fc7d2..9ac8e9379 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,8 @@ github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/MirrexOne/unqueryvet v1.2.1 h1:M+zdXMq84g+E1YOLa7g7ExN3dWfZQrdDSTCM7gC+m/A= -github.com/MirrexOne/unqueryvet v1.2.1/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= +github.com/MirrexOne/unqueryvet v1.3.0 h1:5slWSomgqpYU4zFuZ3NNOfOUxVPlXFDBPAVasZOGlAY= +github.com/MirrexOne/unqueryvet v1.3.0/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= @@ -118,8 +118,8 @@ github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= -github.com/catenacyber/perfsprint v0.10.0 h1:AZj1mYyxbxLRqmnYOeguZXEQwWOgQGm2wzLI5d7Hl/0= -github.com/catenacyber/perfsprint v0.10.0/go.mod h1:DJTGsi/Zufpuus6XPGJyKOTMELe347o6akPvWG9Zcsc= +github.com/catenacyber/perfsprint v0.10.1 h1:u7Riei30bk46XsG8nknMhKLXG9BcXz3+3tl/WpKm0PQ= +github.com/catenacyber/perfsprint v0.10.1/go.mod h1:DJTGsi/Zufpuus6XPGJyKOTMELe347o6akPvWG9Zcsc= github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -243,8 +243,8 @@ github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE= github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godoc-lint/godoc-lint v0.10.1 h1:ZPUVzlDtJfA+P688JfPJPkI/SuzcBr/753yGIk5bOPA= -github.com/godoc-lint/godoc-lint v0.10.1/go.mod h1:KleLcHu/CGSvkjUH2RvZyoK1MBC7pDQg4NxMYLcBBsw= +github.com/godoc-lint/godoc-lint v0.10.2 h1:dksNgK+zebnVlj4Fx83CRnCmPO0qRat/9xfFsir1nfg= +github.com/godoc-lint/godoc-lint v0.10.2/go.mod h1:KleLcHu/CGSvkjUH2RvZyoK1MBC7pDQg4NxMYLcBBsw= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -289,8 +289,8 @@ github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarog github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint/v2 v2.6.2 h1:jkMSVv36JmyTENcEertckvimvjPcD5qxNM7W7qhECvI= -github.com/golangci/golangci-lint/v2 v2.6.2/go.mod h1:fSIMDiBt9kzdpnvvV7GO6iWzyv5uaeZ+iPor+2uRczE= +github.com/golangci/golangci-lint/v2 v2.7.2 h1:AhBC+YeEueec4AGlIbvPym5C70Thx0JykIqXbdIXWx0= +github.com/golangci/golangci-lint/v2 v2.7.2/go.mod h1:pDijleoBu7e8sejMqyZ3L5n6geqe+cVvOAz2QImqqVc= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= @@ -358,8 +358,8 @@ github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1T github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -457,8 +457,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgechev/revive v1.12.0 h1:Q+/kkbbwerrVYPv9d9efaPGmAO/NsxwW/nE6ahpQaCU= -github.com/mgechev/revive v1.12.0/go.mod h1:VXsY2LsTigk8XU9BpZauVLjVrhICMOV3k1lpB3CXrp8= +github.com/mgechev/revive v1.13.0 h1:yFbEVliCVKRXY8UgwEO7EOYNopvjb1BFbmYqm9hZjBM= +github.com/mgechev/revive v1.13.0/go.mod h1:efJfeBVCX2JUumNQ7dtOLDja+QKj9mYGgEZA7rt5u+0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -485,8 +485,8 @@ github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/nunnatsa/ginkgolinter v0.21.2 h1:khzWfm2/Br8ZemX8QM1pl72LwM+rMeW6VUbQ4rzh0Po= github.com/nunnatsa/ginkgolinter v0.21.2/go.mod h1:GItSI5fw7mCGLPmkvGYrr1kEetZe7B593jcyOpyabsY= -github.com/onsi/ginkgo/v2 v2.26.0 h1:1J4Wut1IlYZNEAWIV3ALrT9NfiaGW2cDCJQSFQMs/gE= -github.com/onsi/ginkgo/v2 v2.26.0/go.mod h1:qhEywmzWTBUY88kfO0BRvX4py7scov9yR+Az2oavUzw= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= @@ -565,8 +565,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= -github.com/securego/gosec/v2 v2.22.10 h1:ntbBqdWXnu46DUOXn+R2SvPo3PiJCDugTCgTW2g4tQg= -github.com/securego/gosec/v2 v2.22.10/go.mod h1:9UNjK3tLpv/w2b0+7r82byV43wCJDNtEDQMeS+H/g2w= +github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7 h1:rZg6IGn0ySYZwCX8LHwZoYm03JhG/cVAJJ3O+u3Vclo= +github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7/go.mod h1:9sr22NZO5Kfh7unW/xZxkGYTmj2484/fCiE54gw7UTY= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -652,8 +652,8 @@ github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 h1:bQk5qKid5Kv3fZ2miW github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0/go.mod h1:/Ujlw+qo6RgKm69dD8y6MgmJFcUmrHjuJPO6VFoQX9U= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 h1:IUhMJH9fQ+CaMas+5bbnrH7m1Hadf1vWoUtu9KeAEFM= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4/go.mod h1:fd13ANCU/Pye8uDd/6E0I605+6PYfHuVIQpPEK2Ph6c= -github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= -github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= +github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g= +github.com/stbenjam/no-sprintf-host-port v0.3.1/go.mod h1:ODbZesTCHMVKthBHskvUUexdcNHAQRXk9NpSsL8p/HQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -676,8 +676,8 @@ github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= -github.com/tomarrell/wrapcheck/v2 v2.11.0 h1:BJSt36snX9+4WTIXeJ7nvHBQBcm1h2SjQMSlmQ6aFSU= -github.com/tomarrell/wrapcheck/v2 v2.11.0/go.mod h1:wFL9pDWDAbXhhPZZt+nG8Fu+h29TtnZ2MW6Lx4BRXIU= +github.com/tomarrell/wrapcheck/v2 v2.12.0 h1:H/qQ1aNWz/eeIhxKAFvkfIA+N7YDvq6TWVFL27Of9is= +github.com/tomarrell/wrapcheck/v2 v2.12.0/go.mod h1:AQhQuZd0p7b6rfW+vUwHm5OMCGgp63moQ9Qr/0BpIWo= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= From 2989931c14ab971d1ee6d87ce59ba63aa699b3b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 09:37:51 +0100 Subject: [PATCH 556/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/postgresflex (#1153) Bumps [github.com/stackitcloud/stackit-sdk-go/services/postgresflex](https://github.com/stackitcloud/stackit-sdk-go) from 1.2.1 to 1.3.2. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/cdn/v1.2.1...services/cdn/v1.3.2) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/postgresflex dependency-version: 1.3.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- internal/cmd/postgresflex/instance/update/update.go | 4 ++-- internal/cmd/postgresflex/instance/update/update_test.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index df5f75555..3b305393e 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 - github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 + github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 diff --git a/go.sum b/go.sum index 9ac8e9379..2caab5731 100644 --- a/go.sum +++ b/go.sum @@ -628,8 +628,8 @@ github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 h1:zk+47Gh github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1/go.mod h1:vapb/sJqbHlf+c7pZWdE9GqrbyI8wesGvUc9o7oJ1Xk= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 h1:J9WP0lBoqmaQF/OjDw4MwDUbmhwlNBTi9zHdwsXJ3ug= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2/go.mod h1:QenOJF1LD39d/arGFGZFCzHoQuwF6VuWCvS8CbdoMBw= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1 h1:K8vXele3U6b5urcSIpq21EkVblWfPDY3eMPSuQ48TkI= -github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.2.1/go.mod h1:hyhw+I19NtjKmRLcUkY4boaTxnYSPFGbpn4RxvGqH2s= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 h1:uQIpj0phDRGrV78/vhtULwxaO2cBdHwqZcFKYUrH1Hs= +github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2/go.mod h1:rPwdDiCx0eZ+yKiy6Wo6uv76LuCgFlQxkomvun1c740= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 h1:Ww0baLTiZha4H1thfEEsDq+O0Ce0hNhdbkJ5eDdGEoE= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2/go.mod h1:lPz9iQ3kLvpzPR7jt6P1VJyjSumo2+D1i3RkjFGpVTI= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 h1:AcJSIEu1QCzRughJLzVjRP5ICop0DkvV2TgFb9LS7/c= diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 9eef70391..821d10b1c 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -264,9 +264,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl payloadAcl = &postgresflex.ACL{Items: model.ACL} } - var payloadStorage *postgresflex.Storage + var payloadStorage *postgresflex.StorageUpdate if model.StorageClass != nil || model.StorageSize != nil { - payloadStorage = &postgresflex.Storage{ + payloadStorage = &postgresflex.StorageUpdate{ Class: model.StorageClass, Size: model.StorageSize, } diff --git a/internal/cmd/postgresflex/instance/update/update_test.go b/internal/cmd/postgresflex/instance/update/update_test.go index 1402996f7..17cfb46c8 100644 --- a/internal/cmd/postgresflex/instance/update/update_test.go +++ b/internal/cmd/postgresflex/instance/update/update_test.go @@ -427,7 +427,7 @@ func TestBuildRequest(t *testing.T) { }, expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId). PartialUpdateInstancePayload(postgresflex.PartialUpdateInstancePayload{ - Storage: &postgresflex.Storage{ + Storage: &postgresflex.StorageUpdate{ Class: utils.Ptr("class"), }, }), @@ -455,7 +455,7 @@ func TestBuildRequest(t *testing.T) { }, expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId). PartialUpdateInstancePayload(postgresflex.PartialUpdateInstancePayload{ - Storage: &postgresflex.Storage{ + Storage: &postgresflex.StorageUpdate{ Class: utils.Ptr("class"), Size: utils.Ptr(int64(10)), }, From 0c5b30e6b12403687119540dae09accf5fa5440a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:15:57 +0100 Subject: [PATCH 557/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/iaas (#1156) Bumps [github.com/stackitcloud/stackit-sdk-go/services/iaas](https://github.com/stackitcloud/stackit-sdk-go) from 1.2.2 to 1.2.4. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/iaas/v1.2.2...services/iaas/v1.2.4) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/iaas dependency-version: 1.2.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3b305393e..0b1123ee0 100644 --- a/go.mod +++ b/go.mod @@ -20,12 +20,12 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 + github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 - github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 + github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 diff --git a/go.sum b/go.sum index 2caab5731..7f1c195b0 100644 --- a/go.sum +++ b/go.sum @@ -608,8 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 h1:x1i5rqhEVuUPq5M0e github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2/go.mod h1:nOdpHeRWeiPlioOGovHzLpojlilbxAxoXsAy+TiOpw4= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0 h1:fWAjxvf5D1jc1hvziGxJq68RO4pDXBUAPVrIumHb5mw= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0/go.mod h1:HgScss2f+/k/wDxcsM1K8SzLgDso/EZyhoJC2eZ+tFA= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2 h1:afGHMCqBM/E/FPUvbfSTFb9ddI+eDm2a7DpWPCkxMzs= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.2/go.mod h1:/DlO7+cOqyYKROIxkBYIUdMoEfFevkVXhsShglxyUOQ= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 h1:OpPPLUIpObDYmqJr+8aRq/J+YD663nhl3t1Fft2cIzQ= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4/go.mod h1:6+5+RCDfU7eQN3+/SGdOtx7Bq9dEa2FrHz/jflgY1M4= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 h1:KwjR5L+IoUbRYS8k3dyqHgtBUuq8cqRPrUrzzZSSnRI= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0/go.mod h1:Nea8wkoPGvcjKCsjfbAB3pE3kA7oZLi+Zk9hUtunjRI= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EGbsmSX9CLFp3nBcWV8JAeTz4p8= @@ -634,8 +634,8 @@ github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 h1:Ww0baLTiZha4 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2/go.mod h1:lPz9iQ3kLvpzPR7jt6P1VJyjSumo2+D1i3RkjFGpVTI= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 h1:AcJSIEu1QCzRughJLzVjRP5ICop0DkvV2TgFb9LS7/c= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3/go.mod h1:DLXqpz1WhmOergfOLMJ4pybozz33ysOZNIO7fv9Wtfc= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1 h1:KDa5sy6NSzMOXaf4a9skxOm8oUoleI45fLbD3ww7qsc= -github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.1/go.mod h1:+k3iHkWpehO+FLC5WsW7eGhYdNjDklYqRcpIxQBLbZg= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 h1:VDIXOvRNmSYMeF0qQ2+w4/ez04YutVDz73hSMuuOJ54= +github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2/go.mod h1:9zyEzPL4DnmU/SHq+SuMWTSO5BPxM1Z4g8Fp28n00ds= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 h1:Jts49V7XvLLr7MwI9o5Mo0NW3iUVVt8DtqNqRDt6ags= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2/go.mod h1:hV1rmsyb3jlL5kWO+flhtXTbm5EM9vU+BJsV4U/YEUU= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp742W6AgleV2eEXrJFZ7ai9rXu9V1Lkmir0drI= From 79eda982909311d107f1383f32f9cee1e7b83fbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 10:24:43 +0000 Subject: [PATCH 558/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serverupdate (#1157) Bumps [github.com/stackitcloud/stackit-sdk-go/services/serverupdate](https://github.com/stackitcloud/stackit-sdk-go) from 1.2.2 to 1.2.3. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/iaas/v1.2.2...services/iaas/v1.2.3) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/serverupdate dependency-version: 1.2.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0b1123ee0..aa432e36a 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 - github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 + github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 diff --git a/go.sum b/go.sum index 7f1c195b0..c427617ce 100644 --- a/go.sum +++ b/go.sum @@ -642,8 +642,8 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2/go.mod h1:xm0ARtIbfzmqw8e8qThtrYdHHEkpuYvKt13SZGBoWSE= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 h1:lOlg8zYL2nwMi1JxDYW2p8LL4cSB3eoOjlqPHioDWU0= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4/go.mod h1:MBlzqmewliF1LKeOBdOuT+aQrtc3y7p1Kd1fWkjecKQ= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2 h1:ubaIeflBZ70evMhU5Xl4NzzDUTk0Z309jnv18OikXgs= -github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.2/go.mod h1:NH6dyKSkJ0WezDgIpXr5PkhSGUXJvwEFcsQmeGScDs8= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 h1:1gLKXD91qOYUpackMuu0PdRwrm2Z8vFK+k8H7SF0xbg= +github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3/go.mod h1:V34YusCRsq/3bJ/HxUk0wslLjVWWE/QVe70AZ+XrDPE= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 h1:+S5yPftGLH99ByzDCwzdI927bvKOKMQxMkd/tuPeQTE= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2/go.mod h1:gaHXopzXPDP1AmquUVhMmz9opAr2QYVBL0XbBdPtB7s= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 h1:zcfL+rpQZWXZazL8w8DqXYxGbIOInaUc155BWTshNRA= From 1f50702b3789224de852ad9219d08585b395b052 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:47:10 +0100 Subject: [PATCH 559/619] chore(deps): update module golang.org/x/tools to v0.40.0 (#1161) Co-authored-by: Renovate Bot --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index aa432e36a..4b4fc2719 100644 --- a/go.mod +++ b/go.mod @@ -35,16 +35,16 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.30.0 + golang.org/x/mod v0.31.0 golang.org/x/oauth2 v0.33.0 - golang.org/x/term v0.37.0 - golang.org/x/text v0.31.0 + golang.org/x/term v0.38.0 + golang.org/x/text v0.32.0 k8s.io/apimachinery v0.34.2 k8s.io/client-go v0.34.2 ) require ( - golang.org/x/net v0.47.0 // indirect + golang.org/x/net v0.48.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -230,9 +230,9 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect - golang.org/x/tools v0.39.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc // indirect + golang.org/x/tools v0.40.0 // indirect google.golang.org/protobuf v1.36.8 // indirect honnef.co/go/tools v0.6.1 // indirect mvdan.cc/gofumpt v0.9.2 // indirect @@ -270,7 +270,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 github.com/subosito/gotenv v1.6.0 // indirect - golang.org/x/sys v0.38.0 // indirect + golang.org/x/sys v0.39.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index c427617ce..508d403b1 100644 --- a/go.sum +++ b/go.sum @@ -790,8 +790,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= -golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -830,8 +830,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -855,8 +855,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -907,18 +907,18 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 h1:E2/AqCUMZGgd73TQkxUMcMla25GB9i/5HOdLr+uH7Vo= -golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc h1:bH6xUXay0AIFMElXG2rQ4uiE+7ncwtiOdPfYK1NK2XA= +golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -929,8 +929,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -988,8 +988,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= From 1cd50456e7152453a658aecb89394e209cd6295e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:59:58 +0100 Subject: [PATCH 560/619] fix(deps): update module golang.org/x/oauth2 to v0.34.0 (#1163) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4b4fc2719..e40c4e5b4 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.31.0 - golang.org/x/oauth2 v0.33.0 + golang.org/x/oauth2 v0.34.0 golang.org/x/term v0.38.0 golang.org/x/text v0.32.0 k8s.io/apimachinery v0.34.2 diff --git a/go.sum b/go.sum index 508d403b1..42577307c 100644 --- a/go.sum +++ b/go.sum @@ -838,8 +838,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= -golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 11be379a7bfe9c1341b0eaa75a4bfe45f16f9fe0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:09:31 +0000 Subject: [PATCH 561/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/git (#1158) Bumps [github.com/stackitcloud/stackit-sdk-go/services/git](https://github.com/stackitcloud/stackit-sdk-go) from 0.10.0 to 0.10.1. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/core/v0.10.0...core/v0.10.1) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/git dependency-version: 0.10.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e40c4e5b4..1c5db4e36 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 - github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 diff --git a/go.sum b/go.sum index 42577307c..c3c76201d 100644 --- a/go.sum +++ b/go.sum @@ -606,8 +606,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 h1:6Buzw5C github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0/go.mod h1:40XVgsSOcVCjoIAsbSycDh8Ikp2y88AdAeqwqIIHvZE= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 h1:x1i5rqhEVuUPq5M0eb68ZD2KL1C8OFD8RG2sWMQGL6o= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2/go.mod h1:nOdpHeRWeiPlioOGovHzLpojlilbxAxoXsAy+TiOpw4= -github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0 h1:fWAjxvf5D1jc1hvziGxJq68RO4pDXBUAPVrIumHb5mw= -github.com/stackitcloud/stackit-sdk-go/services/git v0.10.0/go.mod h1:HgScss2f+/k/wDxcsM1K8SzLgDso/EZyhoJC2eZ+tFA= +github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjUZg5qprXG5rDmPnM6dsvplMk/vg= +github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1/go.mod h1:3nTaj8IGjNNGYUD2CpuXkXwc5c4giTUmoPggFhjVFxo= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 h1:OpPPLUIpObDYmqJr+8aRq/J+YD663nhl3t1Fft2cIzQ= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4/go.mod h1:6+5+RCDfU7eQN3+/SGdOtx7Bq9dEa2FrHz/jflgY1M4= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 h1:KwjR5L+IoUbRYS8k3dyqHgtBUuq8cqRPrUrzzZSSnRI= From 7caa3019322adb336dafcbdbc315f096bfc68b31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:18:58 +0000 Subject: [PATCH 562/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/objectstorage (#1159) Bumps [github.com/stackitcloud/stackit-sdk-go/services/objectstorage](https://github.com/stackitcloud/stackit-sdk-go) from 1.4.1 to 1.4.2. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/ske/v1.4.1...services/objectstorage/v1.4.2) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/objectstorage dependency-version: 1.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1c5db4e36..90ffd9630 100644 --- a/go.mod +++ b/go.mod @@ -265,7 +265,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 - github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 + github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 diff --git a/go.sum b/go.sum index c3c76201d..58877a6f0 100644 --- a/go.sum +++ b/go.sum @@ -622,8 +622,8 @@ github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOw github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3/go.mod h1:TMl5WcpjzUiAlLWaxMKbu9ysDzFziSPgg4xLxj9jjfY= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 h1:tGa+NcjNKTWvChN+0OMdLomb9Jod4MmY6YAiPTJMgfo= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3/go.mod h1:ciuOzwN5GcqplRy95fXRaS44dFmhfNxvmzTl/ALwV/k= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1 h1:I9B/zUU7R74xuH/ztcPrDIuMp2KV3QQMjeE7lFudboM= -github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.1/go.mod h1:h4aX5tyTQoO6KLrugkvfkqgKTjIzh7e4q9N92kT5OBs= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 h1:nsC6oA1whA4ibxEuD+0Osngmnpz8dLdV6bv+9jYP4Eo= +github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2/go.mod h1:WA6QlAAQ8aaw81W0VSVoDrxOfchGkdtmn2jQL/ub/50= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 h1:zk+47GhutK2ajO4Yiek0laGm2PdXvY8BvFZc8yHFnSE= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1/go.mod h1:vapb/sJqbHlf+c7pZWdE9GqrbyI8wesGvUc9o7oJ1Xk= github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 h1:J9WP0lBoqmaQF/OjDw4MwDUbmhwlNBTi9zHdwsXJ3ug= From 2c0fa1401a41639fa75e2b5faba3f929566d4e23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:28:36 +0000 Subject: [PATCH 563/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/rabbitmq (#1160) Bumps [github.com/stackitcloud/stackit-sdk-go/services/rabbitmq](https://github.com/stackitcloud/stackit-sdk-go) from 0.25.2 to 0.25.3. - [Release notes](https://github.com/stackitcloud/stackit-sdk-go/releases) - [Changelog](https://github.com/stackitcloud/stackit-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/stackitcloud/stackit-sdk-go/compare/services/logme/v0.25.2...services/logme/v0.25.3) --- updated-dependencies: - dependency-name: github.com/stackitcloud/stackit-sdk-go/services/rabbitmq dependency-version: 0.25.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 90ffd9630..a2b22022e 100644 --- a/go.mod +++ b/go.mod @@ -267,7 +267,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 - github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 + github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 github.com/subosito/gotenv v1.6.0 // indirect golang.org/x/sys v0.39.0 // indirect diff --git a/go.sum b/go.sum index 58877a6f0..4e5a48809 100644 --- a/go.sum +++ b/go.sum @@ -630,8 +630,8 @@ github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 h1:J9WP0lBoqm github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2/go.mod h1:QenOJF1LD39d/arGFGZFCzHoQuwF6VuWCvS8CbdoMBw= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 h1:uQIpj0phDRGrV78/vhtULwxaO2cBdHwqZcFKYUrH1Hs= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2/go.mod h1:rPwdDiCx0eZ+yKiy6Wo6uv76LuCgFlQxkomvun1c740= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2 h1:Ww0baLTiZha4H1thfEEsDq+O0Ce0hNhdbkJ5eDdGEoE= -github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.2/go.mod h1:lPz9iQ3kLvpzPR7jt6P1VJyjSumo2+D1i3RkjFGpVTI= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.3 h1:a9XjDC01il+3IDQIDgg5qcJBYcsu5rrTJyMfJZPyvCg= +github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.3/go.mod h1:tjbSLF5+5JFx+qNazqhakqfPlCZPzque9R4XqRZzTRc= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 h1:AcJSIEu1QCzRughJLzVjRP5ICop0DkvV2TgFb9LS7/c= github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3/go.mod h1:DLXqpz1WhmOergfOLMJ4pybozz33ysOZNIO7fv9Wtfc= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 h1:VDIXOvRNmSYMeF0qQ2+w4/ez04YutVDz73hSMuuOJ54= From 2bdaa5b918ab4b0688aaf0401e61594be13f45e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6kce=20G=C3=B6k=20Klingel?= <161626272+GokceGK@users.noreply.github.com> Date: Tue, 9 Dec 2025 15:21:38 +0100 Subject: [PATCH 564/619] chore(docs): update links to new STACKIT docs (#1167) --- AUTHENTICATION.md | 6 +++--- README.md | 2 +- docs/stackit_beta_sqlserverflex_user_create.md | 2 +- docs/stackit_server_create.md | 2 +- docs/stackit_server_resize.md | 2 +- docs/stackit_ske_credentials_complete-rotation.md | 2 +- docs/stackit_ske_credentials_start-rotation.md | 2 +- internal/cmd/beta/sqlserverflex/user/create/create.go | 2 +- internal/cmd/server/create/create.go | 2 +- internal/cmd/server/resize/resize.go | 2 +- .../ske/credentials/complete-rotation/complete_rotation.go | 2 +- .../cmd/ske/credentials/start-rotation/start_rotation.go | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/AUTHENTICATION.md b/AUTHENTICATION.md index 1cf3003f8..7da16657f 100644 --- a/AUTHENTICATION.md +++ b/AUTHENTICATION.md @@ -4,7 +4,7 @@ This document describes how you can configure authentication for the STACKIT CLI ## Service account -You can use a [service account](https://docs.stackit.cloud/stackit/en/service-accounts-134415819.html) to authenticate to the STACKIT CLI. +You can use a [service account](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/) to authenticate to the STACKIT CLI. The CLI will search for service account credentials similarly to the [STACKIT SDK](https://github.com/stackitcloud/stackit-sdk-go) and [STACKIT Terraform Provider](https://github.com/stackitcloud/terraform-provider-stackit), so if you have already set up your environment for those tools, you can just run: ```bash @@ -47,14 +47,14 @@ To use the key flow, you need to have a service account key, which must have an When creating the service account key, a new RSA key-pair can be created automatically, which will be included in the service account key. This will make it much easier to configure the key flow authentication in the CLI, by just providing the service account key. -**Optionally**, you can provide your own private key when creating the service account key, which will then require you to also provide it explicitly to the CLI, additionally to the service account key. Check the STACKIT Knowledge Base for an [example of how to create your own key-pair](https://docs.stackit.cloud/stackit/en/usage-of-the-service-account-keys-in-stackit-175112464.html#UsageoftheserviceaccountkeysinSTACKIT-CreatinganRSAkey-pair). +**Optionally**, you can provide your own private key when creating the service account key, which will then require you to also provide it explicitly to the CLI, additionally to the service account key. Check the STACKIT Docs for an [example of how to create your own key-pair](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-keys/). To configure the key flow, follow this steps: 1. Create a service account key: - In the CLI, run `stackit service-account key create --email ` -- As an alternative, use the [STACKIT Portal](https://portal.stackit.cloud/): go to the `Service Accounts` tab, choose a `Service Account` and go to `Service Account Keys` to create a key. For more details, see [Create a service account key](https://docs.stackit.cloud/stackit/en/create-a-service-account-key-175112456.html) +- As an alternative, use the [STACKIT Portal](https://portal.stackit.cloud/): go to the `Service Accounts` tab, choose a `Service Account` and go to `Service Account Keys` to create a key. For more details, see [Create a service account key](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-keys/) 2. Save the content of the service account key by copying it and saving it in a JSON file. diff --git a/README.md b/README.md index 56fa01bcf..8c66fa532 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,6 @@ Apache 2.0 - [STACKIT](https://www.stackit.de/en/) -- [STACKIT Knowledge Base](https://docs.stackit.cloud/stackit/en/knowledge-base-85301704.html) +- [STACKIT Docs](https://docs.stackit.cloud/) - [STACKIT Terraform Provider](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs) diff --git a/docs/stackit_beta_sqlserverflex_user_create.md b/docs/stackit_beta_sqlserverflex_user_create.md index f1cf9dbbe..47aa6a5e3 100644 --- a/docs/stackit_beta_sqlserverflex_user_create.md +++ b/docs/stackit_beta_sqlserverflex_user_create.md @@ -9,7 +9,7 @@ Creates a SQLServer Flex user for an instance. The password is only visible upon creation and cannot be retrieved later. Alternatively, you can reset the password and access the new one by running: $ stackit beta sqlserverflex user reset-password USER_ID --instance-id INSTANCE_ID -Please refer to https://docs.stackit.cloud/stackit/en/creating-logins-and-users-in-sqlserver-flex-instances-210862358.html for additional information. +Please refer to https://docs.stackit.cloud/products/databases/sqlserver-flex/how-tos/create-logins-and-users-in-sqlserver-flex-instances/ for additional information. The allowed user roles for your instance can be obtained by running: $ stackit beta sqlserverflex options --user-roles --instance-id INSTANCE_ID diff --git a/docs/stackit_server_create.md b/docs/stackit_server_create.md index 27412840a..c1c4e9b21 100644 --- a/docs/stackit_server_create.md +++ b/docs/stackit_server_create.md @@ -55,7 +55,7 @@ stackit server create [flags] --image-id string The image ID to be used for an ephemeral disk on the server. Either 'image-id' or 'boot-volume-...' flags are required --keypair-name string The name of the SSH keypair used during the server creation --labels stringToString Labels are key-value string pairs which can be attached to a server. E.g. '--labels key1=value1,key2=value2,...' (default []) - --machine-type string Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html + --machine-type string Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/products/compute-engine/server/basics/machine-types/ -n, --name string Server name --network-id string ID of the network for the initial networking setup for the server creation --network-interface-ids strings List of network interface IDs for the initial networking setup for the server creation diff --git a/docs/stackit_server_resize.md b/docs/stackit_server_resize.md index c91335432..bbcb239f5 100644 --- a/docs/stackit_server_resize.md +++ b/docs/stackit_server_resize.md @@ -21,7 +21,7 @@ stackit server resize SERVER_ID [flags] ``` -h, --help Help for "stackit server resize" - --machine-type string Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html + --machine-type string Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/products/compute-engine/server/basics/machine-types/ ``` ### Options inherited from parent commands diff --git a/docs/stackit_ske_credentials_complete-rotation.md b/docs/stackit_ske_credentials_complete-rotation.md index 12536dba5..7df00136f 100644 --- a/docs/stackit_ske_credentials_complete-rotation.md +++ b/docs/stackit_ske_credentials_complete-rotation.md @@ -14,7 +14,7 @@ To ensure continued access to the Kubernetes cluster, please update your kubecon If you haven't, please start the process by running: $ stackit ske credentials start-rotation my-cluster -For more information, visit: https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html +For more information, visit: https://docs.stackit.cloud/products/runtime/kubernetes-engine/how-tos/rotate-ske-credentials/ ``` stackit ske credentials complete-rotation CLUSTER_NAME [flags] diff --git a/docs/stackit_ske_credentials_start-rotation.md b/docs/stackit_ske_credentials_start-rotation.md index aa8160adf..05200a386 100644 --- a/docs/stackit_ske_credentials_start-rotation.md +++ b/docs/stackit_ske_credentials_start-rotation.md @@ -18,7 +18,7 @@ After completing the rotation of credentials, you can generate a new kubeconfig $ stackit ske kubeconfig create my-cluster Complete the rotation by running: $ stackit ske credentials complete-rotation my-cluster -For more information, visit: https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html +For more information, visit: https://docs.stackit.cloud/products/runtime/kubernetes-engine/how-tos/rotate-ske-credentials/ ``` stackit ske credentials start-rotation CLUSTER_NAME [flags] diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index cb77255f9..5a818be70 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -43,7 +43,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { "The password is only visible upon creation and cannot be retrieved later.", "Alternatively, you can reset the password and access the new one by running:", " $ stackit beta sqlserverflex user reset-password USER_ID --instance-id INSTANCE_ID", - "Please refer to https://docs.stackit.cloud/stackit/en/creating-logins-and-users-in-sqlserver-flex-instances-210862358.html for additional information.", + "Please refer to https://docs.stackit.cloud/products/databases/sqlserver-flex/how-tos/create-logins-and-users-in-sqlserver-flex-instances/ for additional information.", "The allowed user roles for your instance can be obtained by running:", " $ stackit beta sqlserverflex options --user-roles --instance-id INSTANCE_ID", ), diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 841f21d1d..86f0af5dc 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -164,7 +164,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(nameFlag, "n", "", "Server name") - cmd.Flags().String(machineTypeFlag, "", "Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html") + cmd.Flags().String(machineTypeFlag, "", "Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/products/compute-engine/server/basics/machine-types/") cmd.Flags().String(affinityGroupFlag, "", "The affinity group the server is assigned to") cmd.Flags().String(availabilityZoneFlag, "", "The availability zone of the server") cmd.Flags().String(bootVolumeSourceIdFlag, "", "ID of the source object of boot volume. It can be either an image or volume ID") diff --git a/internal/cmd/server/resize/resize.go b/internal/cmd/server/resize/resize.go index 495098b40..d2a7836a2 100644 --- a/internal/cmd/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -107,7 +107,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } func configureFlags(cmd *cobra.Command) { - cmd.Flags().String(machineTypeFlag, "", "Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html") + cmd.Flags().String(machineTypeFlag, "", "Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/products/compute-engine/server/basics/machine-types/") err := flags.MarkFlagsRequired(cmd, machineTypeFlag) cobra.CheckErr(err) diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go index d9970b539..5fc0f81bb 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go @@ -41,7 +41,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { " $ stackit ske kubeconfig create my-cluster", "If you haven't, please start the process by running:", " $ stackit ske credentials start-rotation my-cluster", - "For more information, visit: https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html", + "For more information, visit: https://docs.stackit.cloud/products/runtime/kubernetes-engine/how-tos/rotate-ske-credentials/", ), Args: args.SingleArg(clusterNameArg, nil), Example: examples.Build( diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation.go b/internal/cmd/ske/credentials/start-rotation/start_rotation.go index 91af511fd..fa239775a 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation.go @@ -45,7 +45,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { " $ stackit ske kubeconfig create my-cluster", "Complete the rotation by running:", " $ stackit ske credentials complete-rotation my-cluster", - "For more information, visit: https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html", + "For more information, visit: https://docs.stackit.cloud/products/runtime/kubernetes-engine/how-tos/rotate-ske-credentials/", ), Args: args.SingleArg(clusterNameArg, nil), Example: examples.Build( From aead8fd4c94dab91cf1a53e1477732c0c9b1bb03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:25:23 +0100 Subject: [PATCH 565/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/logme (#1172) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a2b22022e..5a5b5fc02 100644 --- a/go.mod +++ b/go.mod @@ -263,7 +263,7 @@ require ( github.com/spf13/cast v1.10.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 - github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 + github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 diff --git a/go.sum b/go.sum index 4e5a48809..479880ed1 100644 --- a/go.sum +++ b/go.sum @@ -616,8 +616,8 @@ github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EG github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1/go.mod h1:Wh1NKX5ZI0FuIdYavOYu0Cjh0yA3S9rlm4j5g0vuPVI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 h1:BHNjq4+OsmVrGu1KBOv0dh/++nwysyINtAUTxNFz2Uo= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1/go.mod h1:sTV6ylmBoMOrOxUED8Ebts4a1PaJSPLtmNh5m+s5fus= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2 h1:g3xzRqwul8W638gOKTZRAnnQuMhYqaliuz/A8BcfjhU= -github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.2/go.mod h1:OlGmMlXKp33ZYpUm9TqaLYf8SdzhDW5uBKcbgq1zXOk= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+FtFDYOm1kv/gJrGBZLjhVOXJOuYfFY= +github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3/go.mod h1:305j9bvzJ+3c4csOw4SUfLSSxRbkpL0osbvqMI89FeM= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOwjKMWpKl0nrqiq7psTf4NJv0IKgwTkc= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3/go.mod h1:TMl5WcpjzUiAlLWaxMKbu9ysDzFziSPgg4xLxj9jjfY= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 h1:tGa+NcjNKTWvChN+0OMdLomb9Jod4MmY6YAiPTJMgfo= From f9d5b221f8c81f8337fe210c7848dbd48bb6820b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 10:34:00 +0000 Subject: [PATCH 566/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/ske (#1171) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5a5b5fc02..1053f4244 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 - github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.31.0 diff --git a/go.sum b/go.sum index 479880ed1..be8359a3e 100644 --- a/go.sum +++ b/go.sum @@ -648,8 +648,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 h1:+S5yPf github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2/go.mod h1:gaHXopzXPDP1AmquUVhMmz9opAr2QYVBL0XbBdPtB7s= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 h1:zcfL+rpQZWXZazL8w8DqXYxGbIOInaUc155BWTshNRA= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3/go.mod h1:icu5WtsZ8c57/pUrXeFLmZu29Qhwr/rsjTkVRWJYTqY= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0 h1:bQk5qKid5Kv3fZ2miWlS5Dvo+cW90hbePaxOyWF67EE= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.0/go.mod h1:/Ujlw+qo6RgKm69dD8y6MgmJFcUmrHjuJPO6VFoQX9U= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 h1:HVlBylGwXVR3qDUGwUMqofAcLEawRaWSgeYXbyAcN1E= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1/go.mod h1:NzcTU5GGlUF6Lys3Ra7ylRj4ZKxJr3f/29/yoE5tjPI= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 h1:IUhMJH9fQ+CaMas+5bbnrH7m1Hadf1vWoUtu9KeAEFM= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4/go.mod h1:fd13ANCU/Pye8uDd/6E0I605+6PYfHuVIQpPEK2Ph6c= github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g= From 037122d98779bd99a955fc0000adfdbae662b16d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 10:43:53 +0000 Subject: [PATCH 567/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/dns (#1170) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1053f4244..eb88f4938 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.20.1 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 - github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 + github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 diff --git a/go.sum b/go.sum index be8359a3e..d60cfb652 100644 --- a/go.sum +++ b/go.sum @@ -604,8 +604,8 @@ github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 h1:x7ndqw6yaOw+TmThNe github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2/go.mod h1:wbPNu6e5r/5xhzznCKbC7fEJahrAOb89gmaIm+0w2/s= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 h1:6Buzw5CuPb5ixdMHx4tKjmsQkMn0Hpj0xJ+aNDimKnk= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0/go.mod h1:40XVgsSOcVCjoIAsbSycDh8Ikp2y88AdAeqwqIIHvZE= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2 h1:x1i5rqhEVuUPq5M0eb68ZD2KL1C8OFD8RG2sWMQGL6o= -github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.2/go.mod h1:nOdpHeRWeiPlioOGovHzLpojlilbxAxoXsAy+TiOpw4= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= +github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3/go.mod h1:BNiIZkDqwSV1LkWDjMKxVb9pxQ/HMIsXJ0AQ8pFoAo4= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjUZg5qprXG5rDmPnM6dsvplMk/vg= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1/go.mod h1:3nTaj8IGjNNGYUD2CpuXkXwc5c4giTUmoPggFhjVFxo= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 h1:OpPPLUIpObDYmqJr+8aRq/J+YD663nhl3t1Fft2cIzQ= From 74a682d0d3b0adb099265c00932d752aacc4cb70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:55:43 +0100 Subject: [PATCH 568/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/runcommand (#1168) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eb88f4938..316f757f0 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 - github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 + github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 diff --git a/go.sum b/go.sum index d60cfb652..835d79925 100644 --- a/go.sum +++ b/go.sum @@ -636,8 +636,8 @@ github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 h1:AcJSIEu1QCzRugh github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3/go.mod h1:DLXqpz1WhmOergfOLMJ4pybozz33ysOZNIO7fv9Wtfc= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 h1:VDIXOvRNmSYMeF0qQ2+w4/ez04YutVDz73hSMuuOJ54= github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2/go.mod h1:9zyEzPL4DnmU/SHq+SuMWTSO5BPxM1Z4g8Fp28n00ds= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2 h1:Jts49V7XvLLr7MwI9o5Mo0NW3iUVVt8DtqNqRDt6ags= -github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.2/go.mod h1:hV1rmsyb3jlL5kWO+flhtXTbm5EM9vU+BJsV4U/YEUU= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 h1:ShK5AFExNRAVUMsbeoVQhCxb7GpNSmzq15jJuaBUSFo= +github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3/go.mod h1:P1uhYJpSvhUXTnTGSEZqWf97J2+1Z6VuVwmUOlnhiwI= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp742W6AgleV2eEXrJFZ7ai9rXu9V1Lkmir0drI= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2/go.mod h1:xm0ARtIbfzmqw8e8qThtrYdHHEkpuYvKt13SZGBoWSE= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 h1:lOlg8zYL2nwMi1JxDYW2p8LL4cSB3eoOjlqPHioDWU0= From f15e9666ddce0f566fb01d85c943a144902151ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:04:42 +0000 Subject: [PATCH 569/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/alb (#1169) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 316f757f0..1bb0cbb95 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.20.1 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 diff --git a/go.sum b/go.sum index 835d79925..c3c0b6b82 100644 --- a/go.sum +++ b/go.sum @@ -600,8 +600,8 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98edvw2Cd3DcnkepncP3M= github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2 h1:x7ndqw6yaOw+TmThNeAkI+eN9vK5hWgjIJlFZrYPREo= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.2/go.mod h1:wbPNu6e5r/5xhzznCKbC7fEJahrAOb89gmaIm+0w2/s= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3 h1:DqRtyuIb34/x9C3/sT7Uz5xrD0TQOL3ERnDOS1gst4E= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 h1:6Buzw5CuPb5ixdMHx4tKjmsQkMn0Hpj0xJ+aNDimKnk= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0/go.mod h1:40XVgsSOcVCjoIAsbSycDh8Ikp2y88AdAeqwqIIHvZE= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= From 43a57652b984022169e84e9e8b5eae8fc0e7bf8a Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 15 Dec 2025 12:13:42 +0100 Subject: [PATCH 570/619] fix(deps): update module github.com/jedib0t/go-pretty/v6 to v6.7.7 (#1174) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1bb0cbb95..d29cdb085 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.7.5 + github.com/jedib0t/go-pretty/v6 v6.7.7 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.2 diff --git a/go.sum b/go.sum index c3c0b6b82..ac62b2c33 100644 --- a/go.sum +++ b/go.sum @@ -371,8 +371,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.7.5 h1:9dJSWTJnsXJVVAbvxIFxeHf/JxoJd7GUl5o3UzhtuiM= -github.com/jedib0t/go-pretty/v6 v6.7.5/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.7.7 h1:Y1Id3lJ3k4UB8uwWWy3l8EVFnUlx5chR5+VbsofPNX0= +github.com/jedib0t/go-pretty/v6 v6.7.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From ac6919d3426a848c04fd29f6c275fcc3b29e80a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:36:30 +0100 Subject: [PATCH 571/619] chore(deps): bump actions/upload-artifact from 5 to 6 (#1181) --- .github/workflows/ci.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 48e304976..67954c08f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -36,7 +36,7 @@ jobs: run: make test - name: Archive code coverage results - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} path: ${{ env.CODE_COVERAGE_FILE_NAME }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 108d24521..3cd5f7d9d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -90,7 +90,7 @@ jobs: rm -f "$GPG_KEY_PATH" - name: Upload artifacts to workflow - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: goreleaser-dist-temp path: dist From f27c598a05d744d26c86bb94d5c585c461e8f8bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 08:42:53 +0000 Subject: [PATCH 572/619] chore(deps): bump actions/download-artifact from 6 to 7 (#1180) --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3cd5f7d9d..e9377a728 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -110,7 +110,7 @@ jobs: # use the artifacts from the "goreleaser" job - name: Download artifacts from workflow - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: goreleaser-dist-temp path: dist @@ -147,7 +147,7 @@ jobs: uses: actions/checkout@v6 - name: Download artifacts from workflow - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: goreleaser-dist-temp path: dist From 9660efb0de49658cd41c32dfb9e805fddf34f784 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 08:51:56 +0000 Subject: [PATCH 573/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/secretsmanager (#1179) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d29cdb085..174813580 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.3 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 diff --git a/go.sum b/go.sum index ac62b2c33..372d4dd28 100644 --- a/go.sum +++ b/go.sum @@ -638,8 +638,8 @@ github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 h1:VDIXO github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2/go.mod h1:9zyEzPL4DnmU/SHq+SuMWTSO5BPxM1Z4g8Fp28n00ds= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 h1:ShK5AFExNRAVUMsbeoVQhCxb7GpNSmzq15jJuaBUSFo= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3/go.mod h1:P1uhYJpSvhUXTnTGSEZqWf97J2+1Z6VuVwmUOlnhiwI= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2 h1:z7ZJtp742W6AgleV2eEXrJFZ7ai9rXu9V1Lkmir0drI= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.2/go.mod h1:xm0ARtIbfzmqw8e8qThtrYdHHEkpuYvKt13SZGBoWSE= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.3 h1:9DZDISle23rdgWH8YBBujCWnEqUOQ9RAh6/G8wEHb3w= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.3/go.mod h1:dMBt/b/LXfXTDLQTCW6PRhBlbl41q7XS+5mAyBezSJk= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 h1:lOlg8zYL2nwMi1JxDYW2p8LL4cSB3eoOjlqPHioDWU0= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4/go.mod h1:MBlzqmewliF1LKeOBdOuT+aQrtc3y7p1Kd1fWkjecKQ= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 h1:1gLKXD91qOYUpackMuu0PdRwrm2Z8vFK+k8H7SF0xbg= From d821c09e87c451c10cae21c51541a1518317920c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 10:27:21 +0100 Subject: [PATCH 574/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex (#1178) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 174813580..2804f40cd 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 diff --git a/go.sum b/go.sum index 372d4dd28..01af6c3cf 100644 --- a/go.sum +++ b/go.sum @@ -620,8 +620,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+Ft github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3/go.mod h1:305j9bvzJ+3c4csOw4SUfLSSxRbkpL0osbvqMI89FeM= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOwjKMWpKl0nrqiq7psTf4NJv0IKgwTkc= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3/go.mod h1:TMl5WcpjzUiAlLWaxMKbu9ysDzFziSPgg4xLxj9jjfY= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3 h1:tGa+NcjNKTWvChN+0OMdLomb9Jod4MmY6YAiPTJMgfo= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.3/go.mod h1:ciuOzwN5GcqplRy95fXRaS44dFmhfNxvmzTl/ALwV/k= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4 h1:4LA0Mw7Y8swLRQBvQ/JRv1fUSlnrIHilWklX4v3SZ0A= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4/go.mod h1:G/UD3tzPzzu79MiFWUYqogxdLMB+YArNHR6Yqz7Cqr0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 h1:nsC6oA1whA4ibxEuD+0Osngmnpz8dLdV6bv+9jYP4Eo= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2/go.mod h1:WA6QlAAQ8aaw81W0VSVoDrxOfchGkdtmn2jQL/ub/50= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 h1:zk+47GhutK2ajO4Yiek0laGm2PdXvY8BvFZc8yHFnSE= From 4a046e63ec6b0f1e35422e1f37a2bb943ea7b473 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:37:11 +0000 Subject: [PATCH 575/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/authorization (#1176) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2804f40cd..5648f7990 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.20.1 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 diff --git a/go.sum b/go.sum index 01af6c3cf..599e04f4a 100644 --- a/go.sum +++ b/go.sum @@ -602,8 +602,8 @@ github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98e github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3 h1:DqRtyuIb34/x9C3/sT7Uz5xrD0TQOL3ERnDOS1gst4E= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0 h1:6Buzw5CuPb5ixdMHx4tKjmsQkMn0Hpj0xJ+aNDimKnk= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.0/go.mod h1:40XVgsSOcVCjoIAsbSycDh8Ikp2y88AdAeqwqIIHvZE= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.1 h1:Z7K6CfjbWSAzFbAXFzxefRBap/dujpK2TZgJqBUZ8NQ= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.1/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3/go.mod h1:BNiIZkDqwSV1LkWDjMKxVb9pxQ/HMIsXJ0AQ8pFoAo4= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjUZg5qprXG5rDmPnM6dsvplMk/vg= From 1e87acb9ab6f99c9f5509dac356f455150a61ba3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 10:52:33 +0100 Subject: [PATCH 576/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/intake (#1177) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5648f7990..bb0b97338 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 - github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 + github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 diff --git a/go.sum b/go.sum index 599e04f4a..ad9680c84 100644 --- a/go.sum +++ b/go.sum @@ -610,8 +610,8 @@ github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjU github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1/go.mod h1:3nTaj8IGjNNGYUD2CpuXkXwc5c4giTUmoPggFhjVFxo= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 h1:OpPPLUIpObDYmqJr+8aRq/J+YD663nhl3t1Fft2cIzQ= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4/go.mod h1:6+5+RCDfU7eQN3+/SGdOtx7Bq9dEa2FrHz/jflgY1M4= -github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0 h1:KwjR5L+IoUbRYS8k3dyqHgtBUuq8cqRPrUrzzZSSnRI= -github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.0/go.mod h1:Nea8wkoPGvcjKCsjfbAB3pE3kA7oZLi+Zk9hUtunjRI= +github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 h1:WCSuqD6AoOD/D8u+YU3brMhQwYZYxu809o3uW5SH4HA= +github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1/go.mod h1:qq6rNvOuSQ1HDZie8gy4Wzso+a9DrgOODNPyKeBljK4= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EGbsmSX9CLFp3nBcWV8JAeTz4p8= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1/go.mod h1:Wh1NKX5ZI0FuIdYavOYu0Cjh0yA3S9rlm4j5g0vuPVI= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 h1:BHNjq4+OsmVrGu1KBOv0dh/++nwysyINtAUTxNFz2Uo= From ea693eec30aaa9663683af43093071fbf73d863f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 10:01:22 +0000 Subject: [PATCH 577/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/opensearch (#1175) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bb0b97338..15675e785 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.3 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 diff --git a/go.sum b/go.sum index ad9680c84..e48119717 100644 --- a/go.sum +++ b/go.sum @@ -626,8 +626,8 @@ github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 h1:nsC6oA1w github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2/go.mod h1:WA6QlAAQ8aaw81W0VSVoDrxOfchGkdtmn2jQL/ub/50= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 h1:zk+47GhutK2ajO4Yiek0laGm2PdXvY8BvFZc8yHFnSE= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1/go.mod h1:vapb/sJqbHlf+c7pZWdE9GqrbyI8wesGvUc9o7oJ1Xk= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2 h1:J9WP0lBoqmaQF/OjDw4MwDUbmhwlNBTi9zHdwsXJ3ug= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.2/go.mod h1:QenOJF1LD39d/arGFGZFCzHoQuwF6VuWCvS8CbdoMBw= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.3 h1:CAgu3Wsmo8pA1/VWqnqLftMn7X26uDs5zctTci4WG7A= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.3/go.mod h1:VC3vqIQIDN+8SAzhlMdrK4eXeiSaNE1JtjIGFzpgiRI= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 h1:uQIpj0phDRGrV78/vhtULwxaO2cBdHwqZcFKYUrH1Hs= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2/go.mod h1:rPwdDiCx0eZ+yKiy6Wo6uv76LuCgFlQxkomvun1c740= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.3 h1:a9XjDC01il+3IDQIDgg5qcJBYcsu5rrTJyMfJZPyvCg= From 1535eec6c385d45fd8160487aa024d55f210a93b Mon Sep 17 00:00:00 2001 From: Jorge Turrado Ferrero Date: Wed, 17 Dec 2025 12:04:46 +0100 Subject: [PATCH 578/619] feat: max_age is set during auth request to limit user session (#1134) relates to STACKITCLI-294 --- docs/stackit_config_set.md | 2 +- docs/stackit_config_unset.md | 2 +- .../config/profile/import/template/profile.json | 2 +- internal/cmd/config/set/set.go | 2 +- internal/pkg/auth/auth.go | 14 +++++++++++--- internal/pkg/auth/user_login.go | 7 ++++++- internal/pkg/config/config.go | 2 +- internal/pkg/config/template/test_profile.json | 2 +- 8 files changed, 23 insertions(+), 10 deletions(-) diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 1b4549617..13050384f 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -55,7 +55,7 @@ stackit config set [flags] --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API --service-account-custom-endpoint string Service Account API base URL, used in calls to this API --service-enablement-custom-endpoint string Service Enablement API base URL, used in calls to this API - --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) + --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s --ske-custom-endpoint string SKE API base URL, used in calls to this API --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API --token-custom-endpoint string Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication. diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index cfe34ab0b..88b5b3bd8 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -56,7 +56,7 @@ stackit config unset [flags] --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL --service-account-custom-endpoint Service Account API base URL. If unset, uses the default base URL --service-enablement-custom-endpoint Service Enablement API base URL. If unset, uses the default base URL - --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h + --session-time-limit Maximum time before authentication is required again. If unset, defaults to 12h --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL --token-custom-endpoint Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication. diff --git a/internal/cmd/config/profile/import/template/profile.json b/internal/cmd/config/profile/import/template/profile.json index ab56ce66b..dbc0bad02 100644 --- a/internal/cmd/config/profile/import/template/profile.json +++ b/internal/cmd/config/profile/import/template/profile.json @@ -25,7 +25,7 @@ "serverbackup_custom_endpoint": "", "service_account_custom_endpoint": "", "service_enablement_custom_endpoint": "", - "session_time_limit": "2h", + "session_time_limit": "12h", "ske_custom_endpoint": "", "sqlserverflex_custom_endpoint": "", "token_custom_endpoint": "", diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index e6da6ce7c..b23fbba9b 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -135,7 +135,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e } func configureFlags(cmd *cobra.Command) { - cmd.Flags().String(sessionTimeLimitFlag, "", "Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect)") + cmd.Flags().String(sessionTimeLimitFlag, "", "Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s") cmd.Flags().String(identityProviderCustomWellKnownConfigurationFlag, "", "Identity Provider well-known OpenID configuration URL, used for user authentication") cmd.Flags().String(identityProviderCustomClientIdFlag, "", "Identity Provider client ID, used for user authentication") cmd.Flags().String(allowedUrlDomainFlag, "", `Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command`) diff --git a/internal/pkg/auth/auth.go b/internal/pkg/auth/auth.go index ea549a2cb..dd56536d3 100644 --- a/internal/pkg/auth/auth.go +++ b/internal/pkg/auth/auth.go @@ -110,15 +110,23 @@ func GetAccessToken() (string, error) { func getStartingSessionExpiresAtUnix() (string, error) { sessionStart := time.Now() - sessionTimeLimitString := viper.GetString(config.SessionTimeLimitKey) - sessionTimeLimit, err := time.ParseDuration(sessionTimeLimitString) + sessionTimeLimit, err := getSessionExpiration() if err != nil { - return "", fmt.Errorf("parse session time limit \"%s\": %w", sessionTimeLimitString, err) + return "", err } sessionExpiresAt := sessionStart.Add(sessionTimeLimit) return strconv.FormatInt(sessionExpiresAt.Unix(), 10), nil } +func getSessionExpiration() (time.Duration, error) { + sessionTimeLimitString := viper.GetString(config.SessionTimeLimitKey) + duration, err := time.ParseDuration(sessionTimeLimitString) + if err != nil { + return 0, fmt.Errorf("parse session time limit \"%s\": %w", sessionTimeLimitString, err) + } + return duration, nil +} + func getEmailFromToken(token string) (string, error) { // We can safely use ParseUnverified because we are not authenticating the user at this point, // We are parsing the token just to get the service account e-mail diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index c01dbccba..054c74c89 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -121,8 +121,13 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { // Initialize the code verifier codeVerifier := oauth2.GenerateVerifier() + // Generate max age based on the session time limit + maxSessionDuration, err := getSessionExpiration() + if err != nil { + return err + } // Construct the authorization URL - authorizationURL := conf.AuthCodeURL("", oauth2.S256ChallengeOption(codeVerifier)) + authorizationURL := conf.AuthCodeURL("", oauth2.S256ChallengeOption(codeVerifier), oauth2.SetAuthURLParam("max_age", fmt.Sprintf("%d", int64(maxSessionDuration.Seconds())))) // Start a web server to listen on a callback URL mux := http.NewServeMux() diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 89cc4decb..68ca2ee8c 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -55,7 +55,7 @@ const ( AsyncDefault = false RegionDefault = "eu01" - SessionTimeLimitDefault = "2h" + SessionTimeLimitDefault = "12h" AllowedUrlDomainDefault = "stackit.cloud" ) diff --git a/internal/pkg/config/template/test_profile.json b/internal/pkg/config/template/test_profile.json index ab56ce66b..dbc0bad02 100644 --- a/internal/pkg/config/template/test_profile.json +++ b/internal/pkg/config/template/test_profile.json @@ -25,7 +25,7 @@ "serverbackup_custom_endpoint": "", "service_account_custom_endpoint": "", "service_enablement_custom_endpoint": "", - "session_time_limit": "2h", + "session_time_limit": "12h", "ske_custom_endpoint": "", "sqlserverflex_custom_endpoint": "", "token_custom_endpoint": "", From ae0838d911d382c5701c9058caabdca9ecb7566b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:30:52 +0100 Subject: [PATCH 579/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/iaas (#1189) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 15675e785..125052932 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 - github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 + github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.3 diff --git a/go.sum b/go.sum index e48119717..979212ba4 100644 --- a/go.sum +++ b/go.sum @@ -608,8 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwi github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3/go.mod h1:BNiIZkDqwSV1LkWDjMKxVb9pxQ/HMIsXJ0AQ8pFoAo4= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjUZg5qprXG5rDmPnM6dsvplMk/vg= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1/go.mod h1:3nTaj8IGjNNGYUD2CpuXkXwc5c4giTUmoPggFhjVFxo= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4 h1:OpPPLUIpObDYmqJr+8aRq/J+YD663nhl3t1Fft2cIzQ= -github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.4/go.mod h1:6+5+RCDfU7eQN3+/SGdOtx7Bq9dEa2FrHz/jflgY1M4= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 h1:U/x0tc487X9msMS5yZYjrBAAKrCx87Trmt0kh8JiARA= +github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0/go.mod h1:6+5+RCDfU7eQN3+/SGdOtx7Bq9dEa2FrHz/jflgY1M4= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 h1:WCSuqD6AoOD/D8u+YU3brMhQwYZYxu809o3uW5SH4HA= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1/go.mod h1:qq6rNvOuSQ1HDZie8gy4Wzso+a9DrgOODNPyKeBljK4= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EGbsmSX9CLFp3nBcWV8JAeTz4p8= From f7bb29bd4e980cb024f69e4c3cb8ce475e9cc7ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 15:43:53 +0000 Subject: [PATCH 580/619] chore(deps): bump renovatebot/github-action from 44.0.5 to 44.2.0 (#1182) --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index d9eddd18a..d0c4954cf 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Self-hosted Renovate - uses: renovatebot/github-action@v44.0.5 + uses: renovatebot/github-action@v44.2.0 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From d3695f514a884bc7a63ef92d5aba4c9383293fc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:01:05 +0000 Subject: [PATCH 581/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serviceaccount (#1185) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 125052932..7d761aa94 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.3 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 - github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 + github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 diff --git a/go.sum b/go.sum index 979212ba4..927d3f4fd 100644 --- a/go.sum +++ b/go.sum @@ -644,8 +644,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 h1:lOlg8zYL2 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4/go.mod h1:MBlzqmewliF1LKeOBdOuT+aQrtc3y7p1Kd1fWkjecKQ= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 h1:1gLKXD91qOYUpackMuu0PdRwrm2Z8vFK+k8H7SF0xbg= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3/go.mod h1:V34YusCRsq/3bJ/HxUk0wslLjVWWE/QVe70AZ+XrDPE= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2 h1:+S5yPftGLH99ByzDCwzdI927bvKOKMQxMkd/tuPeQTE= -github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.2/go.mod h1:gaHXopzXPDP1AmquUVhMmz9opAr2QYVBL0XbBdPtB7s= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 h1:XV3pPXpdvQjR5Z90FFutU4iqCHfejDYQAL840Y4ztLM= +github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3/go.mod h1:YNJJ1jwBWjEdLH6vECuzoslJY9jQThIvDvTa30J3D0U= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 h1:zcfL+rpQZWXZazL8w8DqXYxGbIOInaUc155BWTshNRA= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3/go.mod h1:icu5WtsZ8c57/pUrXeFLmZu29Qhwr/rsjTkVRWJYTqY= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 h1:HVlBylGwXVR3qDUGwUMqofAcLEawRaWSgeYXbyAcN1E= From 81edb2db36295ee97aaf415a3237da86f5ac3e71 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:13:09 +0100 Subject: [PATCH 582/619] fix(deps): update module github.com/goccy/go-yaml to v1.19.1 (#1191) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7d761aa94..2e8b75395 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.0 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.19.0 + github.com/goccy/go-yaml v1.19.1 github.com/golang-jwt/jwt/v5 v5.3.0 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 927d3f4fd..434c5f67c 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUW github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE= -github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.19.1 h1:3rG3+v8pkhRqoQ/88NYNMHYVGYztCOCIZ7UQhu7H+NE= +github.com/goccy/go-yaml v1.19.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godoc-lint/godoc-lint v0.10.2 h1:dksNgK+zebnVlj4Fx83CRnCmPO0qRat/9xfFsir1nfg= From d84c7a42bf431ca789776e543a3676cf7786b37a Mon Sep 17 00:00:00 2001 From: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:30:26 +0100 Subject: [PATCH 583/619] feat: add label to ignore stale (#1193) --- .github/workflows/stale.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index f5e745a71..894da7025 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -11,6 +11,7 @@ on: env: DAYS_BEFORE_PR_STALE: 7 DAYS_BEFORE_PR_CLOSE: 7 + EXEMPT_PR_LABELS: "ignore-stale" permissions: issues: write @@ -30,6 +31,7 @@ jobs: close-pr-message: "This PR was closed automatically because it has been stalled for ${{ env.DAYS_BEFORE_PR_CLOSE }} days with no activity. Feel free to re-open it at any time." days-before-pr-stale: ${{ env.DAYS_BEFORE_PR_STALE }} days-before-pr-close: ${{ env.DAYS_BEFORE_PR_CLOSE }} + exempt-pr-labels: ${{ env.EXEMPT_PR_LABELS }} # never mark issues as stale or close them days-before-issue-stale: -1 days-before-issue-close: -1 From 2e3dac3330893c22b74aa04d0b26b77951a0c6ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:27:15 +0000 Subject: [PATCH 584/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serviceenablement (#1188) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2e8b75395..e1331561e 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 - github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 + github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 github.com/zalando/go-keyring v0.2.6 diff --git a/go.sum b/go.sum index 434c5f67c..4c65f767c 100644 --- a/go.sum +++ b/go.sum @@ -646,8 +646,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 h1:1gLKXD91q github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3/go.mod h1:V34YusCRsq/3bJ/HxUk0wslLjVWWE/QVe70AZ+XrDPE= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 h1:XV3pPXpdvQjR5Z90FFutU4iqCHfejDYQAL840Y4ztLM= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3/go.mod h1:YNJJ1jwBWjEdLH6vECuzoslJY9jQThIvDvTa30J3D0U= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3 h1:zcfL+rpQZWXZazL8w8DqXYxGbIOInaUc155BWTshNRA= -github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.3/go.mod h1:icu5WtsZ8c57/pUrXeFLmZu29Qhwr/rsjTkVRWJYTqY= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4 h1:h4aSfJPMBBcXrG/BZiLLZRvvGJesRdll4bLP7jetuKA= +github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4/go.mod h1:Iv+svIxk5baXnvrEdvVl5JZri6a3H/2OrQDlRWmUFMI= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 h1:HVlBylGwXVR3qDUGwUMqofAcLEawRaWSgeYXbyAcN1E= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1/go.mod h1:NzcTU5GGlUF6Lys3Ra7ylRj4ZKxJr3f/29/yoE5tjPI= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 h1:IUhMJH9fQ+CaMas+5bbnrH7m1Hadf1vWoUtu9KeAEFM= From 9f5e2e5e8a4874c3751870525947949d3c8e99c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 13:41:14 +0100 Subject: [PATCH 585/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/kms (#1187) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e1331561e..fd6c3faba 100644 --- a/go.mod +++ b/go.mod @@ -261,7 +261,7 @@ require ( github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 + github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 diff --git a/go.sum b/go.sum index 4c65f767c..f39fa6d47 100644 --- a/go.sum +++ b/go.sum @@ -612,8 +612,8 @@ github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 h1:U/x0tc487X9msMS5y github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0/go.mod h1:6+5+RCDfU7eQN3+/SGdOtx7Bq9dEa2FrHz/jflgY1M4= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 h1:WCSuqD6AoOD/D8u+YU3brMhQwYZYxu809o3uW5SH4HA= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1/go.mod h1:qq6rNvOuSQ1HDZie8gy4Wzso+a9DrgOODNPyKeBljK4= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1 h1:F/2qLBATi0nDjKR8EGbsmSX9CLFp3nBcWV8JAeTz4p8= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.1/go.mod h1:Wh1NKX5ZI0FuIdYavOYu0Cjh0yA3S9rlm4j5g0vuPVI= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2 h1:YsgqwU+qc+AL5yOaXIb/Va3ANAjXDnSJtIflZ6EeM0w= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2/go.mod h1:sHMFoYvVrkRZcH13DkLvp48nW+ssRVVVuwqJHDGpa5M= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 h1:BHNjq4+OsmVrGu1KBOv0dh/++nwysyINtAUTxNFz2Uo= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1/go.mod h1:sTV6ylmBoMOrOxUED8Ebts4a1PaJSPLtmNh5m+s5fus= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+FtFDYOm1kv/gJrGBZLjhVOXJOuYfFY= From d536b0c22f50862e613cb0e294c22387dc3f763e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 12:50:42 +0000 Subject: [PATCH 586/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/loadbalancer (#1194) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fd6c3faba..249261c95 100644 --- a/go.mod +++ b/go.mod @@ -262,7 +262,7 @@ require ( github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2 - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 diff --git a/go.sum b/go.sum index f39fa6d47..ae0c06e51 100644 --- a/go.sum +++ b/go.sum @@ -614,8 +614,8 @@ github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 h1:WCSuqD6AoOD/D8u github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1/go.mod h1:qq6rNvOuSQ1HDZie8gy4Wzso+a9DrgOODNPyKeBljK4= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2 h1:YsgqwU+qc+AL5yOaXIb/Va3ANAjXDnSJtIflZ6EeM0w= github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2/go.mod h1:sHMFoYvVrkRZcH13DkLvp48nW+ssRVVVuwqJHDGpa5M= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1 h1:BHNjq4+OsmVrGu1KBOv0dh/++nwysyINtAUTxNFz2Uo= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.1/go.mod h1:sTV6ylmBoMOrOxUED8Ebts4a1PaJSPLtmNh5m+s5fus= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2 h1:DwwRMzvnKWTbfmLvq2xe+mYhv5fA1AwWdQGznI05sGc= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2/go.mod h1:dYmNdSNDKUG+E0SwuFWu+c8CuMBF/l6w1bdzAHxQao0= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+FtFDYOm1kv/gJrGBZLjhVOXJOuYfFY= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3/go.mod h1:305j9bvzJ+3c4csOw4SUfLSSxRbkpL0osbvqMI89FeM= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOwjKMWpKl0nrqiq7psTf4NJv0IKgwTkc= From 09164393b28063b9f0e11619a68df7111b51fcce Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Fri, 19 Dec 2025 14:36:00 +0100 Subject: [PATCH 587/619] feat(sfs): Onboard sfs commands (#1197) - export-policy - performance-class - resource-pool - share - snapshot Signed-off-by: Alexander Dahmen --- docs/stackit_beta.md | 1 + docs/stackit_beta_sfs.md | 38 ++ docs/stackit_beta_sfs_export-policy.md | 38 ++ docs/stackit_beta_sfs_export-policy_create.md | 45 +++ docs/stackit_beta_sfs_export-policy_delete.md | 40 ++ ...stackit_beta_sfs_export-policy_describe.md | 40 ++ docs/stackit_beta_sfs_export-policy_list.md | 44 +++ docs/stackit_beta_sfs_export-policy_update.md | 45 +++ docs/stackit_beta_sfs_performance-class.md | 34 ++ ...stackit_beta_sfs_performance-class_list.md | 40 ++ docs/stackit_beta_sfs_resource-pool.md | 38 ++ docs/stackit_beta_sfs_resource-pool_create.md | 58 +++ docs/stackit_beta_sfs_resource-pool_delete.md | 40 ++ ...stackit_beta_sfs_resource-pool_describe.md | 40 ++ docs/stackit_beta_sfs_resource-pool_list.md | 47 +++ docs/stackit_beta_sfs_resource-pool_update.md | 56 +++ docs/stackit_beta_sfs_share.md | 38 ++ docs/stackit_beta_sfs_share_create.md | 47 +++ docs/stackit_beta_sfs_share_delete.md | 41 ++ docs/stackit_beta_sfs_share_describe.md | 41 ++ docs/stackit_beta_sfs_share_list.md | 45 +++ docs/stackit_beta_sfs_share_update.md | 46 +++ docs/stackit_beta_sfs_snapshot.md | 37 ++ docs/stackit_beta_sfs_snapshot_create.md | 46 +++ docs/stackit_beta_sfs_snapshot_delete.md | 41 ++ docs/stackit_beta_sfs_snapshot_describe.md | 41 ++ docs/stackit_beta_sfs_snapshot_list.md | 42 ++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 2 + internal/cmd/beta/beta.go | 2 + .../beta/sfs/export-policy/create/create.go | 151 ++++++++ .../sfs/export-policy/create/create_test.go | 212 ++++++++++ .../beta/sfs/export-policy/delete/delete.go | 100 +++++ .../sfs/export-policy/delete/delete_test.go | 174 +++++++++ .../sfs/export-policy/describe/describe.go | 151 ++++++++ .../export-policy/describe/describe_test.go | 221 +++++++++++ .../beta/sfs/export-policy/export-policy.go | 33 ++ .../cmd/beta/sfs/export-policy/list/list.go | 147 +++++++ .../beta/sfs/export-policy/list/list_test.go | 176 +++++++++ .../test-files/rules-example.json | 14 + .../beta/sfs/export-policy/update/update.go | 172 +++++++++ .../sfs/export-policy/update/update_test.go | 251 ++++++++++++ .../beta/sfs/performance-class/list/list.go | 110 ++++++ .../sfs/performance-class/list/list_test.go | 170 +++++++++ .../performance-class/performance_class.go | 26 ++ .../beta/sfs/resource-pool/create/create.go | 184 +++++++++ .../sfs/resource-pool/create/create_test.go | 295 ++++++++++++++ .../beta/sfs/resource-pool/delete/delete.go | 120 ++++++ .../sfs/resource-pool/delete/delete_test.go | 209 ++++++++++ .../sfs/resource-pool/describe/describe.go | 152 ++++++++ .../resource-pool/describe/describe_test.go | 211 ++++++++++ .../cmd/beta/sfs/resource-pool/list/list.go | 153 ++++++++ .../beta/sfs/resource-pool/list/list_test.go | 199 ++++++++++ .../beta/sfs/resource-pool/resource_pool.go | 34 ++ .../beta/sfs/resource-pool/update/update.go | 179 +++++++++ .../sfs/resource-pool/update/update_test.go | 361 ++++++++++++++++++ internal/cmd/beta/sfs/sfs.go | 34 ++ internal/cmd/beta/sfs/share/create/create.go | 181 +++++++++ .../cmd/beta/sfs/share/create/create_test.go | 207 ++++++++++ internal/cmd/beta/sfs/share/delete/delete.go | 134 +++++++ .../cmd/beta/sfs/share/delete/delete_test.go | 186 +++++++++ .../cmd/beta/sfs/share/describe/describe.go | 191 +++++++++ .../beta/sfs/share/describe/describe_test.go | 233 +++++++++++ internal/cmd/beta/sfs/share/list/list.go | 158 ++++++++ internal/cmd/beta/sfs/share/list/list_test.go | 207 ++++++++++ internal/cmd/beta/sfs/share/share.go | 34 ++ internal/cmd/beta/sfs/share/update/update.go | 181 +++++++++ .../cmd/beta/sfs/share/update/update_test.go | 266 +++++++++++++ .../cmd/beta/sfs/snapshot/create/create.go | 142 +++++++ .../beta/sfs/snapshot/create/create_test.go | 218 +++++++++++ .../cmd/beta/sfs/snapshot/delete/delete.go | 114 ++++++ .../beta/sfs/snapshot/delete/delete_test.go | 188 +++++++++ .../beta/sfs/snapshot/describe/describe.go | 129 +++++++ .../sfs/snapshot/describe/describe_test.go | 233 +++++++++++ internal/cmd/beta/sfs/snapshot/list/list.go | 148 +++++++ .../cmd/beta/sfs/snapshot/list/list_test.go | 173 +++++++++ internal/cmd/beta/sfs/snapshot/snapshot.go | 32 ++ .../profile/import/template/profile.json | 1 + internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 13 + internal/pkg/config/config.go | 1 + .../pkg/config/template/test_profile.json | 1 + internal/pkg/services/sfs/client/client.go | 14 + internal/pkg/services/sfs/utils/utils.go | 47 +++ internal/pkg/services/sfs/utils/utils_test.go | 206 ++++++++++ internal/pkg/testutils/options.go | 16 + internal/pkg/testutils/testutils.go | 15 +- 90 files changed, 9034 insertions(+), 1 deletion(-) create mode 100644 docs/stackit_beta_sfs.md create mode 100644 docs/stackit_beta_sfs_export-policy.md create mode 100644 docs/stackit_beta_sfs_export-policy_create.md create mode 100644 docs/stackit_beta_sfs_export-policy_delete.md create mode 100644 docs/stackit_beta_sfs_export-policy_describe.md create mode 100644 docs/stackit_beta_sfs_export-policy_list.md create mode 100644 docs/stackit_beta_sfs_export-policy_update.md create mode 100644 docs/stackit_beta_sfs_performance-class.md create mode 100644 docs/stackit_beta_sfs_performance-class_list.md create mode 100644 docs/stackit_beta_sfs_resource-pool.md create mode 100644 docs/stackit_beta_sfs_resource-pool_create.md create mode 100644 docs/stackit_beta_sfs_resource-pool_delete.md create mode 100644 docs/stackit_beta_sfs_resource-pool_describe.md create mode 100644 docs/stackit_beta_sfs_resource-pool_list.md create mode 100644 docs/stackit_beta_sfs_resource-pool_update.md create mode 100644 docs/stackit_beta_sfs_share.md create mode 100644 docs/stackit_beta_sfs_share_create.md create mode 100644 docs/stackit_beta_sfs_share_delete.md create mode 100644 docs/stackit_beta_sfs_share_describe.md create mode 100644 docs/stackit_beta_sfs_share_list.md create mode 100644 docs/stackit_beta_sfs_share_update.md create mode 100644 docs/stackit_beta_sfs_snapshot.md create mode 100644 docs/stackit_beta_sfs_snapshot_create.md create mode 100644 docs/stackit_beta_sfs_snapshot_delete.md create mode 100644 docs/stackit_beta_sfs_snapshot_describe.md create mode 100644 docs/stackit_beta_sfs_snapshot_list.md create mode 100644 internal/cmd/beta/sfs/export-policy/create/create.go create mode 100644 internal/cmd/beta/sfs/export-policy/create/create_test.go create mode 100644 internal/cmd/beta/sfs/export-policy/delete/delete.go create mode 100644 internal/cmd/beta/sfs/export-policy/delete/delete_test.go create mode 100644 internal/cmd/beta/sfs/export-policy/describe/describe.go create mode 100644 internal/cmd/beta/sfs/export-policy/describe/describe_test.go create mode 100644 internal/cmd/beta/sfs/export-policy/export-policy.go create mode 100644 internal/cmd/beta/sfs/export-policy/list/list.go create mode 100644 internal/cmd/beta/sfs/export-policy/list/list_test.go create mode 100644 internal/cmd/beta/sfs/export-policy/test-files/rules-example.json create mode 100644 internal/cmd/beta/sfs/export-policy/update/update.go create mode 100644 internal/cmd/beta/sfs/export-policy/update/update_test.go create mode 100644 internal/cmd/beta/sfs/performance-class/list/list.go create mode 100644 internal/cmd/beta/sfs/performance-class/list/list_test.go create mode 100644 internal/cmd/beta/sfs/performance-class/performance_class.go create mode 100644 internal/cmd/beta/sfs/resource-pool/create/create.go create mode 100644 internal/cmd/beta/sfs/resource-pool/create/create_test.go create mode 100644 internal/cmd/beta/sfs/resource-pool/delete/delete.go create mode 100644 internal/cmd/beta/sfs/resource-pool/delete/delete_test.go create mode 100644 internal/cmd/beta/sfs/resource-pool/describe/describe.go create mode 100644 internal/cmd/beta/sfs/resource-pool/describe/describe_test.go create mode 100644 internal/cmd/beta/sfs/resource-pool/list/list.go create mode 100644 internal/cmd/beta/sfs/resource-pool/list/list_test.go create mode 100644 internal/cmd/beta/sfs/resource-pool/resource_pool.go create mode 100644 internal/cmd/beta/sfs/resource-pool/update/update.go create mode 100644 internal/cmd/beta/sfs/resource-pool/update/update_test.go create mode 100644 internal/cmd/beta/sfs/sfs.go create mode 100644 internal/cmd/beta/sfs/share/create/create.go create mode 100644 internal/cmd/beta/sfs/share/create/create_test.go create mode 100644 internal/cmd/beta/sfs/share/delete/delete.go create mode 100644 internal/cmd/beta/sfs/share/delete/delete_test.go create mode 100644 internal/cmd/beta/sfs/share/describe/describe.go create mode 100644 internal/cmd/beta/sfs/share/describe/describe_test.go create mode 100644 internal/cmd/beta/sfs/share/list/list.go create mode 100644 internal/cmd/beta/sfs/share/list/list_test.go create mode 100644 internal/cmd/beta/sfs/share/share.go create mode 100644 internal/cmd/beta/sfs/share/update/update.go create mode 100644 internal/cmd/beta/sfs/share/update/update_test.go create mode 100644 internal/cmd/beta/sfs/snapshot/create/create.go create mode 100644 internal/cmd/beta/sfs/snapshot/create/create_test.go create mode 100644 internal/cmd/beta/sfs/snapshot/delete/delete.go create mode 100644 internal/cmd/beta/sfs/snapshot/delete/delete_test.go create mode 100644 internal/cmd/beta/sfs/snapshot/describe/describe.go create mode 100644 internal/cmd/beta/sfs/snapshot/describe/describe_test.go create mode 100644 internal/cmd/beta/sfs/snapshot/list/list.go create mode 100644 internal/cmd/beta/sfs/snapshot/list/list_test.go create mode 100644 internal/cmd/beta/sfs/snapshot/snapshot.go create mode 100644 internal/pkg/services/sfs/client/client.go create mode 100644 internal/pkg/services/sfs/utils/utils.go create mode 100644 internal/pkg/services/sfs/utils/utils_test.go create mode 100644 internal/pkg/testutils/options.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index c099db5b3..fab1825e5 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -44,5 +44,6 @@ stackit beta [flags] * [stackit beta alb](./stackit_beta_alb.md) - Manages application loadbalancers * [stackit beta intake](./stackit_beta_intake.md) - Provides functionality for intake * [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS +* [stackit beta sfs](./stackit_beta_sfs.md) - Provides functionality for SFS (stackit file storage) * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_sfs.md b/docs/stackit_beta_sfs.md new file mode 100644 index 000000000..7067bb52b --- /dev/null +++ b/docs/stackit_beta_sfs.md @@ -0,0 +1,38 @@ +## stackit beta sfs + +Provides functionality for SFS (stackit file storage) + +### Synopsis + +Provides functionality for SFS (stackit file storage). + +``` +stackit beta sfs [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta sfs export-policy](./stackit_beta_sfs_export-policy.md) - Provides functionality for SFS export policies +* [stackit beta sfs performance-class](./stackit_beta_sfs_performance-class.md) - Provides functionality for SFS performance classes +* [stackit beta sfs resource-pool](./stackit_beta_sfs_resource-pool.md) - Provides functionality for SFS resource pools +* [stackit beta sfs share](./stackit_beta_sfs_share.md) - Provides functionality for SFS shares +* [stackit beta sfs snapshot](./stackit_beta_sfs_snapshot.md) - Provides functionality for SFS snapshots + diff --git a/docs/stackit_beta_sfs_export-policy.md b/docs/stackit_beta_sfs_export-policy.md new file mode 100644 index 000000000..eaad44e74 --- /dev/null +++ b/docs/stackit_beta_sfs_export-policy.md @@ -0,0 +1,38 @@ +## stackit beta sfs export-policy + +Provides functionality for SFS export policies + +### Synopsis + +Provides functionality for SFS export policies. + +``` +stackit beta sfs export-policy [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs export-policy" +``` + +### 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 beta sfs](./stackit_beta_sfs.md) - Provides functionality for SFS (stackit file storage) +* [stackit beta sfs export-policy create](./stackit_beta_sfs_export-policy_create.md) - Creates a export policy +* [stackit beta sfs export-policy delete](./stackit_beta_sfs_export-policy_delete.md) - Deletes a export policy +* [stackit beta sfs export-policy describe](./stackit_beta_sfs_export-policy_describe.md) - Shows details of a export policy +* [stackit beta sfs export-policy list](./stackit_beta_sfs_export-policy_list.md) - Lists all export policies of a project +* [stackit beta sfs export-policy update](./stackit_beta_sfs_export-policy_update.md) - Updates a export policy + diff --git a/docs/stackit_beta_sfs_export-policy_create.md b/docs/stackit_beta_sfs_export-policy_create.md new file mode 100644 index 000000000..87198e9c4 --- /dev/null +++ b/docs/stackit_beta_sfs_export-policy_create.md @@ -0,0 +1,45 @@ +## stackit beta sfs export-policy create + +Creates a export policy + +### Synopsis + +Creates a export policy. + +``` +stackit beta sfs export-policy create [flags] +``` + +### Examples + +``` + Create a new export policy with name "EXPORT_POLICY_NAME" + $ stackit beta sfs export-policy create --name EXPORT_POLICY_NAME + + Create a new export policy with name "EXPORT_POLICY_NAME" and rules from file "./rules.json" + $ stackit beta sfs export-policy create --name EXPORT_POLICY_NAME --rules @./rules.json +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs export-policy create" + --name string Export policy name + --rules string Rules of the export policy (format: json) +``` + +### 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 beta sfs export-policy](./stackit_beta_sfs_export-policy.md) - Provides functionality for SFS export policies + diff --git a/docs/stackit_beta_sfs_export-policy_delete.md b/docs/stackit_beta_sfs_export-policy_delete.md new file mode 100644 index 000000000..af95dfa5f --- /dev/null +++ b/docs/stackit_beta_sfs_export-policy_delete.md @@ -0,0 +1,40 @@ +## stackit beta sfs export-policy delete + +Deletes a export policy + +### Synopsis + +Deletes a export policy. + +``` +stackit beta sfs export-policy delete EXPORT_POLICY_ID [flags] +``` + +### Examples + +``` + Delete a export policy with ID "xxx" + $ stackit beta sfs export-policy delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs export-policy delete" +``` + +### 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 beta sfs export-policy](./stackit_beta_sfs_export-policy.md) - Provides functionality for SFS export policies + diff --git a/docs/stackit_beta_sfs_export-policy_describe.md b/docs/stackit_beta_sfs_export-policy_describe.md new file mode 100644 index 000000000..79b314f38 --- /dev/null +++ b/docs/stackit_beta_sfs_export-policy_describe.md @@ -0,0 +1,40 @@ +## stackit beta sfs export-policy describe + +Shows details of a export policy + +### Synopsis + +Shows details of a export policy. + +``` +stackit beta sfs export-policy describe EXPORT_POLICY_ID [flags] +``` + +### Examples + +``` + Describe a export policy with ID "xxx" + $ stackit beta sfs export-policy describe xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs export-policy 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 beta sfs export-policy](./stackit_beta_sfs_export-policy.md) - Provides functionality for SFS export policies + diff --git a/docs/stackit_beta_sfs_export-policy_list.md b/docs/stackit_beta_sfs_export-policy_list.md new file mode 100644 index 000000000..0611395c7 --- /dev/null +++ b/docs/stackit_beta_sfs_export-policy_list.md @@ -0,0 +1,44 @@ +## stackit beta sfs export-policy list + +Lists all export policies of a project + +### Synopsis + +Lists all export policies of a project. + +``` +stackit beta sfs export-policy list [flags] +``` + +### Examples + +``` + List all export policies + $ stackit beta sfs export-policy list + + List up to 10 export policies + $ stackit beta sfs export-policy list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs export-policy list" + --limit int Maximum number of entries to list +``` + +### 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 beta sfs export-policy](./stackit_beta_sfs_export-policy.md) - Provides functionality for SFS export policies + diff --git a/docs/stackit_beta_sfs_export-policy_update.md b/docs/stackit_beta_sfs_export-policy_update.md new file mode 100644 index 000000000..99bdec9d7 --- /dev/null +++ b/docs/stackit_beta_sfs_export-policy_update.md @@ -0,0 +1,45 @@ +## stackit beta sfs export-policy update + +Updates a export policy + +### Synopsis + +Updates a export policy. + +``` +stackit beta sfs export-policy update EXPORT_POLICY_ID [flags] +``` + +### Examples + +``` + Update a export policy with ID "xxx" and with rules from file "./rules.json" + $ stackit beta sfs export-policy update xxx --rules @./rules.json + + Update a export policy with ID "xxx" and remove the rules + $ stackit beta sfs export-policy update XXX --remove-rules +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs export-policy update" + --remove-rules Remove the export policy rules + --rules string Rules of the export policy +``` + +### 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 beta sfs export-policy](./stackit_beta_sfs_export-policy.md) - Provides functionality for SFS export policies + diff --git a/docs/stackit_beta_sfs_performance-class.md b/docs/stackit_beta_sfs_performance-class.md new file mode 100644 index 000000000..31b10d31c --- /dev/null +++ b/docs/stackit_beta_sfs_performance-class.md @@ -0,0 +1,34 @@ +## stackit beta sfs performance-class + +Provides functionality for SFS performance classes + +### Synopsis + +Provides functionality for SFS performance classes. + +``` +stackit beta sfs performance-class [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs performance-class" +``` + +### 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 beta sfs](./stackit_beta_sfs.md) - Provides functionality for SFS (stackit file storage) +* [stackit beta sfs performance-class list](./stackit_beta_sfs_performance-class_list.md) - Lists all performances classes available + diff --git a/docs/stackit_beta_sfs_performance-class_list.md b/docs/stackit_beta_sfs_performance-class_list.md new file mode 100644 index 000000000..14c264a8a --- /dev/null +++ b/docs/stackit_beta_sfs_performance-class_list.md @@ -0,0 +1,40 @@ +## stackit beta sfs performance-class list + +Lists all performances classes available + +### Synopsis + +Lists all performances classes available. + +``` +stackit beta sfs performance-class list [flags] +``` + +### Examples + +``` + List all performances classes + $ stackit beta sfs performance-class list +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs performance-class list" +``` + +### 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 beta sfs performance-class](./stackit_beta_sfs_performance-class.md) - Provides functionality for SFS performance classes + diff --git a/docs/stackit_beta_sfs_resource-pool.md b/docs/stackit_beta_sfs_resource-pool.md new file mode 100644 index 000000000..d719f18e2 --- /dev/null +++ b/docs/stackit_beta_sfs_resource-pool.md @@ -0,0 +1,38 @@ +## stackit beta sfs resource-pool + +Provides functionality for SFS resource pools + +### Synopsis + +Provides functionality for SFS resource pools. + +``` +stackit beta sfs resource-pool [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs resource-pool" +``` + +### 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 beta sfs](./stackit_beta_sfs.md) - Provides functionality for SFS (stackit file storage) +* [stackit beta sfs resource-pool create](./stackit_beta_sfs_resource-pool_create.md) - Creates a SFS resource pool +* [stackit beta sfs resource-pool delete](./stackit_beta_sfs_resource-pool_delete.md) - Deletes a SFS resource pool +* [stackit beta sfs resource-pool describe](./stackit_beta_sfs_resource-pool_describe.md) - Shows details of a SFS resource pool +* [stackit beta sfs resource-pool list](./stackit_beta_sfs_resource-pool_list.md) - Lists all SFS resource pools +* [stackit beta sfs resource-pool update](./stackit_beta_sfs_resource-pool_update.md) - Updates a SFS resource pool + diff --git a/docs/stackit_beta_sfs_resource-pool_create.md b/docs/stackit_beta_sfs_resource-pool_create.md new file mode 100644 index 000000000..334864945 --- /dev/null +++ b/docs/stackit_beta_sfs_resource-pool_create.md @@ -0,0 +1,58 @@ +## stackit beta sfs resource-pool create + +Creates a SFS resource pool + +### Synopsis + +Creates a SFS resource pool. + +The available performance class values can be obtained by running: + $ stackit beta sfs performance-class list + +``` +stackit beta sfs resource-pool create [flags] +``` + +### Examples + +``` + Create a SFS resource pool + $ stackit beta sfs resource-pool create --availability-zone eu01-m --ip-acl 10.88.135.144/28 --performance-class Standard --size 500 --name resource-pool-01 + + Create a SFS resource pool, allow only a single IP which can mount the resource pool + $ stackit beta sfs resource-pool create --availability-zone eu01-m --ip-acl 250.81.87.224/32 --performance-class Standard --size 500 --name resource-pool-01 + + Create a SFS resource pool, allow multiple IP ACL which can mount the resource pool + $ stackit beta sfs resource-pool create --availability-zone eu01-m --ip-acl "10.88.135.144/28,250.81.87.224/32" --performance-class Standard --size 500 --name resource-pool-01 + + Create a SFS resource pool with visible snapshots + $ stackit beta sfs resource-pool create --availability-zone eu01-m --ip-acl 10.88.135.144/28 --performance-class Standard --size 500 --name resource-pool-01 --snapshots-visible +``` + +### Options + +``` + --availability-zone string Availability zone + -h, --help Help for "stackit beta sfs resource-pool create" + --ip-acl strings List of network addresses in the form
, e.g. 192.168.10.0/24 that can mount the resource pool readonly (default []) + --name string Name + --performance-class string Performance class + --size int Size of the pool in Gigabytes + --snapshots-visible Set snapshots visible and accessible to users +``` + +### 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 beta sfs resource-pool](./stackit_beta_sfs_resource-pool.md) - Provides functionality for SFS resource pools + diff --git a/docs/stackit_beta_sfs_resource-pool_delete.md b/docs/stackit_beta_sfs_resource-pool_delete.md new file mode 100644 index 000000000..97c52a8ae --- /dev/null +++ b/docs/stackit_beta_sfs_resource-pool_delete.md @@ -0,0 +1,40 @@ +## stackit beta sfs resource-pool delete + +Deletes a SFS resource pool + +### Synopsis + +Deletes a SFS resource pool. + +``` +stackit beta sfs resource-pool delete [flags] +``` + +### Examples + +``` + Delete the SFS resource pool with ID "xxx" + $ stackit beta sfs resource-pool delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs resource-pool delete" +``` + +### 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 beta sfs resource-pool](./stackit_beta_sfs_resource-pool.md) - Provides functionality for SFS resource pools + diff --git a/docs/stackit_beta_sfs_resource-pool_describe.md b/docs/stackit_beta_sfs_resource-pool_describe.md new file mode 100644 index 000000000..9b04e42bb --- /dev/null +++ b/docs/stackit_beta_sfs_resource-pool_describe.md @@ -0,0 +1,40 @@ +## stackit beta sfs resource-pool describe + +Shows details of a SFS resource pool + +### Synopsis + +Shows details of a SFS resource pool. + +``` +stackit beta sfs resource-pool describe [flags] +``` + +### Examples + +``` + Describe the SFS resource pool with ID "xxx" + $ stackit beta sfs resource-pool describe xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs resource-pool 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 beta sfs resource-pool](./stackit_beta_sfs_resource-pool.md) - Provides functionality for SFS resource pools + diff --git a/docs/stackit_beta_sfs_resource-pool_list.md b/docs/stackit_beta_sfs_resource-pool_list.md new file mode 100644 index 000000000..103d9cc47 --- /dev/null +++ b/docs/stackit_beta_sfs_resource-pool_list.md @@ -0,0 +1,47 @@ +## stackit beta sfs resource-pool list + +Lists all SFS resource pools + +### Synopsis + +Lists all SFS resource pools. + +``` +stackit beta sfs resource-pool list [flags] +``` + +### Examples + +``` + List all SFS resource pools + $ stackit beta sfs resource-pool list + + List all SFS resource pools for another region than the default one + $ stackit beta sfs resource-pool list --region eu01 + + List up to 10 SFS resource pools + $ stackit beta sfs resource-pool list --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs resource-pool list" + --limit int Maximum number of entries to list +``` + +### 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 beta sfs resource-pool](./stackit_beta_sfs_resource-pool.md) - Provides functionality for SFS resource pools + diff --git a/docs/stackit_beta_sfs_resource-pool_update.md b/docs/stackit_beta_sfs_resource-pool_update.md new file mode 100644 index 000000000..fbdc85e99 --- /dev/null +++ b/docs/stackit_beta_sfs_resource-pool_update.md @@ -0,0 +1,56 @@ +## stackit beta sfs resource-pool update + +Updates a SFS resource pool + +### Synopsis + +Updates a SFS resource pool. + +The available performance class values can be obtained by running: + $ stackit beta sfs performance-class list + +``` +stackit beta sfs resource-pool update [flags] +``` + +### Examples + +``` + Update the SFS resource pool with ID "xxx" + $ stackit beta sfs resource-pool update xxx --ip-acl 10.88.135.144/28 --performance-class Standard --size 5 + + Update the SFS resource pool with ID "xxx", allow only a single IP which can mount the resource pool + $ stackit beta sfs resource-pool update xxx --ip-acl 250.81.87.224/32 --performance-class Standard --size 5 + + Update the SFS resource pool with ID "xxx", allow multiple IP ACL which can mount the resource pool + $ stackit beta sfs resource-pool update xxx --ip-acl "10.88.135.144/28,250.81.87.224/32" --performance-class Standard --size 5 + + Update the SFS resource pool with ID "xxx", set snapshots visible to false + $ stackit beta sfs resource-pool update xxx --snapshots-visible=false +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs resource-pool update" + --ip-acl strings List of network addresses in the form
, e.g. 192.168.10.0/24 that can mount the resource pool readonly (default []) + --performance-class string Performance class + --size int Size of the pool in Gigabytes + --snapshots-visible Set snapshots visible and accessible to users +``` + +### 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 beta sfs resource-pool](./stackit_beta_sfs_resource-pool.md) - Provides functionality for SFS resource pools + diff --git a/docs/stackit_beta_sfs_share.md b/docs/stackit_beta_sfs_share.md new file mode 100644 index 000000000..f7e75203e --- /dev/null +++ b/docs/stackit_beta_sfs_share.md @@ -0,0 +1,38 @@ +## stackit beta sfs share + +Provides functionality for SFS shares + +### Synopsis + +Provides functionality for SFS shares. + +``` +stackit beta sfs share [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs share" +``` + +### 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 beta sfs](./stackit_beta_sfs.md) - Provides functionality for SFS (stackit file storage) +* [stackit beta sfs share create](./stackit_beta_sfs_share_create.md) - Creates a share +* [stackit beta sfs share delete](./stackit_beta_sfs_share_delete.md) - Deletes a share +* [stackit beta sfs share describe](./stackit_beta_sfs_share_describe.md) - Shows details of a shares +* [stackit beta sfs share list](./stackit_beta_sfs_share_list.md) - Lists all shares of a resource pool +* [stackit beta sfs share update](./stackit_beta_sfs_share_update.md) - Updates a share + diff --git a/docs/stackit_beta_sfs_share_create.md b/docs/stackit_beta_sfs_share_create.md new file mode 100644 index 000000000..15abc66d8 --- /dev/null +++ b/docs/stackit_beta_sfs_share_create.md @@ -0,0 +1,47 @@ +## stackit beta sfs share create + +Creates a share + +### Synopsis + +Creates a share. + +``` +stackit beta sfs share create [flags] +``` + +### Examples + +``` + Create a share in a resource pool with ID "xxx", name "yyy" and no space hard limit + $ stackit beta sfs share create --resource-pool-id xxx --name yyy --hard-limit 0 + + Create a share in a resource pool with ID "xxx", name "yyy" and export policy with name "zzz" + $ stackit beta sfs share create --resource-pool-id xxx --name yyy --export-policy-name zzz --hard-limit 0 +``` + +### Options + +``` + --export-policy-name string The export policy the share is assigned to + --hard-limit int The space hard limit for the share + -h, --help Help for "stackit beta sfs share create" + --name string Share name + --resource-pool-id string The resource pool the share is assigned to +``` + +### 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 beta sfs share](./stackit_beta_sfs_share.md) - Provides functionality for SFS shares + diff --git a/docs/stackit_beta_sfs_share_delete.md b/docs/stackit_beta_sfs_share_delete.md new file mode 100644 index 000000000..f669a175e --- /dev/null +++ b/docs/stackit_beta_sfs_share_delete.md @@ -0,0 +1,41 @@ +## stackit beta sfs share delete + +Deletes a share + +### Synopsis + +Deletes a share. + +``` +stackit beta sfs share delete SHARE_ID [flags] +``` + +### Examples + +``` + Delete a share with ID "xxx" from a resource pool with ID "yyy" + $ stackit beta sfs share delete xxx --resource-pool-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs share delete" + --resource-pool-id string The resource pool the share is assigned to +``` + +### 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 beta sfs share](./stackit_beta_sfs_share.md) - Provides functionality for SFS shares + diff --git a/docs/stackit_beta_sfs_share_describe.md b/docs/stackit_beta_sfs_share_describe.md new file mode 100644 index 000000000..7a881501f --- /dev/null +++ b/docs/stackit_beta_sfs_share_describe.md @@ -0,0 +1,41 @@ +## stackit beta sfs share describe + +Shows details of a shares + +### Synopsis + +Shows details of a shares. + +``` +stackit beta sfs share describe SHARE_ID [flags] +``` + +### Examples + +``` + Describe a shares with ID "xxx" from resource pool with ID "yyy" + $ stackit beta sfs export-policy describe xxx --resource-pool-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs share describe" + --resource-pool-id string The resource pool the share is assigned to +``` + +### 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 beta sfs share](./stackit_beta_sfs_share.md) - Provides functionality for SFS shares + diff --git a/docs/stackit_beta_sfs_share_list.md b/docs/stackit_beta_sfs_share_list.md new file mode 100644 index 000000000..2b3d73461 --- /dev/null +++ b/docs/stackit_beta_sfs_share_list.md @@ -0,0 +1,45 @@ +## stackit beta sfs share list + +Lists all shares of a resource pool + +### Synopsis + +Lists all shares of a resource pool. + +``` +stackit beta sfs share list [flags] +``` + +### Examples + +``` + List all shares from resource pool with ID "xxx" + $ stackit beta sfs export-policy list --resource-pool-id xxx + + List up to 10 shares from resource pool with ID "xxx" + $ stackit beta sfs export-policy list --resource-pool-id xxx --limit 10 +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs share list" + --limit int Maximum number of entries to list + --resource-pool-id string The resource pool the share is assigned to +``` + +### 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 beta sfs share](./stackit_beta_sfs_share.md) - Provides functionality for SFS shares + diff --git a/docs/stackit_beta_sfs_share_update.md b/docs/stackit_beta_sfs_share_update.md new file mode 100644 index 000000000..0a0c1f8b8 --- /dev/null +++ b/docs/stackit_beta_sfs_share_update.md @@ -0,0 +1,46 @@ +## stackit beta sfs share update + +Updates a share + +### Synopsis + +Updates a share. + +``` +stackit beta sfs share update SHARE_ID [flags] +``` + +### Examples + +``` + Update share with ID "xxx" with new export-policy-name "yyy" in resource-pool "zzz" + $ stackit beta sfs share update xxx --export-policy-name yyy --resource-pool-id zzz + + Update share with ID "xxx" with new space hard limit "50" in resource-pool "yyy" + $ stackit beta sfs share update xxx --hard-limit 50 --resource-pool-id yyy +``` + +### Options + +``` + --export-policy-name string The export policy the share is assigned to + --hard-limit int The space hard limit for the share + -h, --help Help for "stackit beta sfs share update" + --resource-pool-id string The resource pool the share is assigned to +``` + +### 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 beta sfs share](./stackit_beta_sfs_share.md) - Provides functionality for SFS shares + diff --git a/docs/stackit_beta_sfs_snapshot.md b/docs/stackit_beta_sfs_snapshot.md new file mode 100644 index 000000000..2c1a31664 --- /dev/null +++ b/docs/stackit_beta_sfs_snapshot.md @@ -0,0 +1,37 @@ +## stackit beta sfs snapshot + +Provides functionality for SFS snapshots + +### Synopsis + +Provides functionality for SFS snapshots. + +``` +stackit beta sfs snapshot [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs snapshot" +``` + +### 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 beta sfs](./stackit_beta_sfs.md) - Provides functionality for SFS (stackit file storage) +* [stackit beta sfs snapshot create](./stackit_beta_sfs_snapshot_create.md) - Creates a new snapshot of a resource pool +* [stackit beta sfs snapshot delete](./stackit_beta_sfs_snapshot_delete.md) - Deletes a snapshot +* [stackit beta sfs snapshot describe](./stackit_beta_sfs_snapshot_describe.md) - Shows details of a snapshot +* [stackit beta sfs snapshot list](./stackit_beta_sfs_snapshot_list.md) - Lists all snapshots of a resource pool + diff --git a/docs/stackit_beta_sfs_snapshot_create.md b/docs/stackit_beta_sfs_snapshot_create.md new file mode 100644 index 000000000..ac7a1988b --- /dev/null +++ b/docs/stackit_beta_sfs_snapshot_create.md @@ -0,0 +1,46 @@ +## stackit beta sfs snapshot create + +Creates a new snapshot of a resource pool + +### Synopsis + +Creates a new snapshot of a resource pool. + +``` +stackit beta sfs snapshot create [flags] +``` + +### Examples + +``` + Create a new snapshot with name "snapshot-name" of a resource pool with ID "xxx" + $ stackit beta sfs snapshot create --name snapshot-name --resource-pool-id xxx + + Create a new snapshot with name "snapshot-name" and comment "snapshot-comment" of a resource pool with ID "xxx" + $ stackit beta sfs snapshot create --name snapshot-name --resource-pool-id xxx --comment "snapshot-comment" +``` + +### Options + +``` + --comment string A comment to add more information to the snapshot + -h, --help Help for "stackit beta sfs snapshot create" + --name string Snapshot name + --resource-pool-id string The resource pool from which the snapshot should be created +``` + +### 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 beta sfs snapshot](./stackit_beta_sfs_snapshot.md) - Provides functionality for SFS snapshots + diff --git a/docs/stackit_beta_sfs_snapshot_delete.md b/docs/stackit_beta_sfs_snapshot_delete.md new file mode 100644 index 000000000..286d98e28 --- /dev/null +++ b/docs/stackit_beta_sfs_snapshot_delete.md @@ -0,0 +1,41 @@ +## stackit beta sfs snapshot delete + +Deletes a snapshot + +### Synopsis + +Deletes a snapshot. + +``` +stackit beta sfs snapshot delete SNAPSHOT_NAME [flags] +``` + +### Examples + +``` + Delete a snapshot with "SNAPSHOT_NAME" from resource pool with ID "yyy" + $ stackit beta sfs snapshot delete SNAPSHOT_NAME --resource-pool-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs snapshot delete" + --resource-pool-id string The resource pool from which the snapshot should be created +``` + +### 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 beta sfs snapshot](./stackit_beta_sfs_snapshot.md) - Provides functionality for SFS snapshots + diff --git a/docs/stackit_beta_sfs_snapshot_describe.md b/docs/stackit_beta_sfs_snapshot_describe.md new file mode 100644 index 000000000..a12e42dd7 --- /dev/null +++ b/docs/stackit_beta_sfs_snapshot_describe.md @@ -0,0 +1,41 @@ +## stackit beta sfs snapshot describe + +Shows details of a snapshot + +### Synopsis + +Shows details of a snapshot. + +``` +stackit beta sfs snapshot describe SNAPSHOT_NAME [flags] +``` + +### Examples + +``` + Describe a snapshot with "SNAPSHOT_NAME" from resource pool with ID "yyy" + stackit beta sfs snapshot describe SNAPSHOT_NAME --resource-pool-id yyy +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs snapshot describe" + --resource-pool-id string The resource pool from which the snapshot should be created +``` + +### 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 beta sfs snapshot](./stackit_beta_sfs_snapshot.md) - Provides functionality for SFS snapshots + diff --git a/docs/stackit_beta_sfs_snapshot_list.md b/docs/stackit_beta_sfs_snapshot_list.md new file mode 100644 index 000000000..4c8b0c986 --- /dev/null +++ b/docs/stackit_beta_sfs_snapshot_list.md @@ -0,0 +1,42 @@ +## stackit beta sfs snapshot list + +Lists all snapshots of a resource pool + +### Synopsis + +Lists all snapshots of a resource pool. + +``` +stackit beta sfs snapshot list [flags] +``` + +### Examples + +``` + List all snapshots of a resource pool with ID "xxx" + $ stackit beta sfs snapshot list --resource-pool-id xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta sfs snapshot list" + --limit int Number of snapshots to list + --resource-pool-id string The resource pool from which the snapshot should be created +``` + +### 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 beta sfs snapshot](./stackit_beta_sfs_snapshot.md) - Provides functionality for SFS snapshots + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 13050384f..b9a4e81a1 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -56,6 +56,7 @@ stackit config set [flags] --service-account-custom-endpoint string Service Account API base URL, used in calls to this API --service-enablement-custom-endpoint string Service Enablement API base URL, used in calls to this API --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s + --sfs-custom-endpoint string SFS API base URL, used in calls to this API --ske-custom-endpoint string SKE API base URL, used in calls to this API --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API --token-custom-endpoint string Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication. diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 88b5b3bd8..9e005607b 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -57,6 +57,7 @@ stackit config unset [flags] --service-account-custom-endpoint Service Account API base URL. If unset, uses the default base URL --service-enablement-custom-endpoint Service Enablement API base URL. If unset, uses the default base URL --session-time-limit Maximum time before authentication is required again. If unset, defaults to 12h + --sfs-custom-endpoint SFS API base URL. If unset, uses the default base URL --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL --token-custom-endpoint Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication. diff --git a/go.mod b/go.mod index 249261c95..79cf8ba04 100644 --- a/go.mod +++ b/go.mod @@ -269,6 +269,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 + github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0 github.com/subosito/gotenv v1.6.0 // indirect golang.org/x/sys v0.39.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index ae0c06e51..d87994781 100644 --- a/go.sum +++ b/go.sum @@ -648,6 +648,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 h1:XV3pPX github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3/go.mod h1:YNJJ1jwBWjEdLH6vECuzoslJY9jQThIvDvTa30J3D0U= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4 h1:h4aSfJPMBBcXrG/BZiLLZRvvGJesRdll4bLP7jetuKA= github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4/go.mod h1:Iv+svIxk5baXnvrEdvVl5JZri6a3H/2OrQDlRWmUFMI= +github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0 h1:DRp1p0Gb1YZSnFXgkiKTHQD9bFfqn6OC3PcsDjqGJiw= +github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0/go.mod h1:XHOtGgBwwCqPSoQt2ojIRb/BeOd4kICwb9RuMXXFGt8= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 h1:HVlBylGwXVR3qDUGwUMqofAcLEawRaWSgeYXbyAcN1E= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1/go.mod h1:NzcTU5GGlUF6Lys3Ra7ylRj4ZKxJr3f/29/yoE5tjPI= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 h1:IUhMJH9fQ+CaMas+5bbnrH7m1Hadf1vWoUtu9KeAEFM= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index de4e2f48f..935791cb9 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -8,6 +8,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -40,6 +41,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(sqlserverflex.NewCmd(params)) + cmd.AddCommand(sfs.NewCmd(params)) cmd.AddCommand(alb.NewCmd(params)) cmd.AddCommand(intake.NewCmd(params)) cmd.AddCommand(kms.NewCmd(params)) diff --git a/internal/cmd/beta/sfs/export-policy/create/create.go b/internal/cmd/beta/sfs/export-policy/create/create.go new file mode 100644 index 000000000..3f3ecf864 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/create/create.go @@ -0,0 +1,151 @@ +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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + nameFlag = "name" + rulesFlag = "rules" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name string + Rules *[]sfs.CreateShareExportPolicyRequestRule +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a export policy", + Long: "Creates a export policy.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a new export policy with name "EXPORT_POLICY_NAME"`, + "$ stackit beta sfs export-policy create --name EXPORT_POLICY_NAME", + ), + examples.NewExample( + `Create a new export policy with name "EXPORT_POLICY_NAME" and rules from file "./rules.json"`, + "$ stackit beta sfs export-policy create --name EXPORT_POLICY_NAME --rules @./rules.json", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure 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 + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a export policy for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create export policy: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "Export policy name") + cmd.Flags().Var(flags.ReadFromFileFlag(), rulesFlag, "Rules of the export policy (format: json)") + + err := flags.MarkFlagsRequired(cmd, nameFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + rulesString := flags.FlagToStringPointer(p, cmd, rulesFlag) + var rules *[]sfs.CreateShareExportPolicyRequestRule + if rulesString != nil && *rulesString != "" { + var r []sfs.CreateShareExportPolicyRequestRule + err := json.Unmarshal([]byte(*rulesString), &r) + if err != nil { + return nil, fmt.Errorf("could not parse rules: %w", err) + } + rules = &r + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringValue(p, cmd, nameFlag), + Rules: rules, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiCreateShareExportPolicyRequest { + req := apiClient.CreateShareExportPolicy(ctx, model.ProjectId, model.Region) + req = req.CreateShareExportPolicyPayload( + sfs.CreateShareExportPolicyPayload{ + Name: utils.Ptr(model.Name), + Rules: model.Rules, + }, + ) + return req +} + +func outputResult(p *print.Printer, outputFormat, projectLabel string, item *sfs.CreateShareExportPolicyResponse) error { + return p.OutputResult(outputFormat, item, func() error { + if item == nil || item.ShareExportPolicy == nil { + return fmt.Errorf("no export policy found") + } + p.Outputf( + "Created export policy %q for project %q.\nExport policy ID: %s\n", + utils.PtrString(item.ShareExportPolicy.Name), + projectLabel, + utils.PtrString(item.ShareExportPolicy.Id), + ) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/export-policy/create/create_test.go b/internal/cmd/beta/sfs/export-policy/create/create_test.go new file mode 100644 index 000000000..f94074b1a --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/create/create_test.go @@ -0,0 +1,212 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" +var testName = "test-name" +var testRulesString = "[]" +var testRules = &[]sfs.CreateShareExportPolicyRequestRule{} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + nameFlag: testName, + rulesFlag: testRulesString, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Name: testName, + Rules: testRules, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiCreateShareExportPolicyRequest)) sfs.ApiCreateShareExportPolicyRequest { + request := testClient.CreateShareExportPolicy(testCtx, testProjectId, testRegion) + request = request.CreateShareExportPolicyPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *sfs.CreateShareExportPolicyPayload)) sfs.CreateShareExportPolicyPayload { + payload := sfs.CreateShareExportPolicyPayload{ + Name: utils.Ptr(testName), + Rules: testRules, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, rulesFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Rules = nil + }), + }, + { + description: "required read rules from file", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[rulesFlag] = "@../test-files/rules-example.json" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Rules = &[]sfs.CreateShareExportPolicyRequestRule{ + { + Description: sfs.NewNullableString( + utils.Ptr("first rule"), + ), + IpAcl: utils.Ptr([]string{"192.168.2.0/24"}), + Order: utils.Ptr(int64(1)), + SetUuid: utils.Ptr(true), + SuperUser: utils.Ptr(false), + }, + { + IpAcl: utils.Ptr([]string{"192.168.2.0/24", "127.0.0.1/32"}), + Order: utils.Ptr(int64(2)), + ReadOnly: utils.Ptr(true), + }, + } + }), + }, + } + opts := []testutils.TestingOption{ + testutils.WithCmpOptions(cmp.AllowUnexported(sfs.NullableString{})), + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInputWithOptions(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, nil, tt.isValid, opts) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiCreateShareExportPolicyRequest + }{ + { + 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), + 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 + exportPolicy *sfs.CreateShareExportPolicyResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty export policy", + args: args{ + exportPolicy: &sfs.CreateShareExportPolicyResponse{}, + }, + wantErr: true, + }, + { + name: "set empty export policy", + args: args{ + exportPolicy: &sfs.CreateShareExportPolicyResponse{ + ShareExportPolicy: &sfs.CreateShareExportPolicyResponseShareExportPolicy{}, + }, + }, + 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.exportPolicy); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/export-policy/delete/delete.go b/internal/cmd/beta/sfs/export-policy/delete/delete.go new file mode 100644 index 000000000..b93807b5c --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/delete/delete.go @@ -0,0 +1,100 @@ +package delete + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const exportPolicyIdArg = "EXPORT_POLICY_ID" + +type inputModel struct { + *globalflags.GlobalFlagModel + ExportPolicyId string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", exportPolicyIdArg), + Short: "Deletes a export policy", + Long: "Deletes a export policy.", + Args: args.SingleArg(exportPolicyIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a export policy with ID "xxx"`, + "$ stackit beta sfs export-policy delete xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + exportPolicyLabel, err := sfsUtils.GetExportPolicyName(ctx, apiClient, model.ProjectId, model.Region, model.ExportPolicyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get export policy name: %v", err) + exportPolicyLabel = model.ExportPolicyId + } else if exportPolicyLabel == "" { + exportPolicyLabel = model.ExportPolicyId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete export policy %q? (This cannot be undone)", exportPolicyLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("delete export policy: %w", err) + } + + params.Printer.Outputf("Deleted export policy %q\n", exportPolicyLabel) + return nil + }, + } + return cmd +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiDeleteShareExportPolicyRequest { + return apiClient.DeleteShareExportPolicy(ctx, model.ProjectId, model.Region, model.ExportPolicyId) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + exportPolicyId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ExportPolicyId: exportPolicyId, + } + + p.DebugInputModel(model) + return &model, nil +} diff --git a/internal/cmd/beta/sfs/export-policy/delete/delete_test.go b/internal/cmd/beta/sfs/export-policy/delete/delete_test.go new file mode 100644 index 000000000..c38c47ae6 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/delete/delete_test.go @@ -0,0 +1,174 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" +var testExportPolicyId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testExportPolicyId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ExportPolicyId: testExportPolicyId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiDeleteShareExportPolicyRequest)) sfs.ApiDeleteShareExportPolicyRequest { + request := testClient.DeleteShareExportPolicy(testCtx, testProjectId, testRegion, testExportPolicyId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "export policy id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "export policy id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiDeleteShareExportPolicyRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/export-policy/describe/describe.go b/internal/cmd/beta/sfs/export-policy/describe/describe.go new file mode 100644 index 000000000..a9bc7b9b3 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/describe/describe.go @@ -0,0 +1,151 @@ +package describe + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const exportPolicyIdArg = "EXPORT_POLICY_ID" + +type inputModel struct { + *globalflags.GlobalFlagModel + ExportPolicyId string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", exportPolicyIdArg), + Short: "Shows details of a export policy", + Long: "Shows details of a export policy.", + Args: args.SingleArg(exportPolicyIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Describe a export policy with ID "xxx"`, + "$ stackit beta sfs export-policy describe xxx", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read export policy: %w", err) + } + + // Get projectLabel + 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 + } + + return outputResult(params.Printer, model.OutputFormat, model.ExportPolicyId, projectLabel, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + exportPolicyId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ExportPolicyId: exportPolicyId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiGetShareExportPolicyRequest { + return apiClient.GetShareExportPolicy(ctx, model.ProjectId, model.Region, model.ExportPolicyId) +} + +func outputResult(p *print.Printer, outputFormat, exportPolicyId, projectLabel string, exportPolicy *sfs.GetShareExportPolicyResponse) error { + return p.OutputResult(outputFormat, exportPolicy, func() error { + if exportPolicy == nil || exportPolicy.ShareExportPolicy == nil { + p.Outputf("Export policy %q not found in project %q", exportPolicyId, projectLabel) + return nil + } + + var content []tables.Table + + table := tables.NewTable() + table.SetTitle("Export Policy") + policy := exportPolicy.ShareExportPolicy + + table.AddRow("ID", utils.PtrString(policy.Id)) + table.AddSeparator() + table.AddRow("NAME", utils.PtrString(policy.Name)) + table.AddSeparator() + table.AddRow("SHARES USING EXPORT POLICY", utils.PtrString(policy.SharesUsingExportPolicy)) + table.AddSeparator() + table.AddRow("CREATED AT", utils.ConvertTimePToDateTimeString(policy.CreatedAt)) + + content = append(content, table) + + if policy.Rules != nil && len(*policy.Rules) > 0 { + rulesTable := tables.NewTable() + rulesTable.SetTitle("Rules") + + rulesTable.SetHeader("ID", "ORDER", "DESCRIPTION", "IP ACL", "READ ONLY", "SET UUID", "SUPER USER", "CREATED AT") + + for _, rule := range *policy.Rules { + var description string + if rule.Description != nil { + description = utils.PtrString(rule.Description.Get()) + } + rulesTable.AddRow( + utils.PtrString(rule.Id), + utils.PtrString(rule.Order), + description, + utils.JoinStringPtr(rule.IpAcl, ", "), + utils.PtrString(rule.ReadOnly), + utils.PtrString(rule.SetUuid), + utils.PtrString(rule.SuperUser), + utils.ConvertTimePToDateTimeString(rule.CreatedAt), + ) + rulesTable.AddSeparator() + } + + content = append(content, rulesTable) + } + + if err := tables.DisplayTables(p, content); err != nil { + return fmt.Errorf("render tables: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/sfs/export-policy/describe/describe_test.go b/internal/cmd/beta/sfs/export-policy/describe/describe_test.go new file mode 100644 index 000000000..73e711879 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/describe/describe_test.go @@ -0,0 +1,221 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" +var testExportPolicyId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testExportPolicyId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ExportPolicyId: testExportPolicyId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiGetShareExportPolicyRequest)) sfs.ApiGetShareExportPolicyRequest { + request := testClient.GetShareExportPolicy(testCtx, testProjectId, testRegion, testExportPolicyId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "export policy id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "export policy id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiGetShareExportPolicyRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + exportPolicyId string + projectLabel string + exportPolicy *sfs.GetShareExportPolicyResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty export policy", + args: args{ + exportPolicy: &sfs.GetShareExportPolicyResponse{}, + }, + wantErr: false, + }, + { + name: "set empty export policy", + args: args{ + exportPolicy: &sfs.GetShareExportPolicyResponse{ + ShareExportPolicy: &sfs.GetShareExportPolicyResponseShareExportPolicy{}, + }, + }, + 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.exportPolicyId, tt.args.projectLabel, tt.args.exportPolicy); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/export-policy/export-policy.go b/internal/cmd/beta/sfs/export-policy/export-policy.go new file mode 100644 index 000000000..221b4f1f3 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/export-policy.go @@ -0,0 +1,33 @@ +package exportpolicy + +import ( + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/export-policy/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/export-policy/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/export-policy/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/export-policy/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/export-policy/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "export-policy", + Short: "Provides functionality for SFS export policies", + Long: "Provides functionality for SFS export policies.", + Args: cobra.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) +} diff --git a/internal/cmd/beta/sfs/export-policy/list/list.go b/internal/cmd/beta/sfs/export-policy/list/list.go new file mode 100644 index 000000000..7620dfc33 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/list/list.go @@ -0,0 +1,147 @@ +package list + +import ( + "context" + "fmt" + "strconv" + + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all export policies of a project", + Long: "Lists all export policies of a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all export policies`, + "$ stackit beta sfs export-policy list", + ), + examples.NewExample( + `List up to 10 export policies`, + "$ stackit beta sfs export-policy list --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list export policies: %w", err) + } + + // Get projectLabel + 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 + } + + // Truncate output + items := utils.GetSliceFromPointer(resp.ShareExportPolicies) + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiListShareExportPoliciesRequest { + return apiClient.ListShareExportPolicies(ctx, model.ProjectId, model.Region) +} + +func outputResult(p *print.Printer, outputFormat, projectLabel string, exportPolicies []sfs.ShareExportPolicy) error { + return p.OutputResult(outputFormat, exportPolicies, func() error { + if len(exportPolicies) == 0 { + p.Outputf("No export policies found for project %q\n", projectLabel) + return nil + } + + table := tables.NewTable() + table.SetHeader("ID", "NAME", "AMOUNT RULES", "SHARES USING THIS EXPORT POLICY", "CREATED AT") + + for _, exportPolicy := range exportPolicies { + amountRules := "-" + if exportPolicy.Rules != nil { + amountRules = strconv.Itoa(len(*exportPolicy.Rules)) + } + table.AddRow( + utils.PtrString(exportPolicy.Id), + utils.PtrString(exportPolicy.Name), + amountRules, + utils.PtrString(exportPolicy.SharesUsingExportPolicy), + utils.ConvertTimePToDateTimeString(exportPolicy.CreatedAt), + ) + } + p.Outputln(table.Render()) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/export-policy/list/list_test.go b/internal/cmd/beta/sfs/export-policy/list/list_test.go new file mode 100644 index 000000000..e2a73ace0 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/list/list_test.go @@ -0,0 +1,176 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + limitFlag: strconv.Itoa(10), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiListShareExportPoliciesRequest)) sfs.ApiListShareExportPoliciesRequest { + request := testClient.ListShareExportPolicies(testCtx, testProjectId, testRegion) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiListShareExportPoliciesRequest + }{ + { + 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), + 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 + exportPolicies []sfs.ShareExportPolicy + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty export policy", + args: args{ + exportPolicies: []sfs.ShareExportPolicy{ + {}, + }, + }, + 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.exportPolicies); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/export-policy/test-files/rules-example.json b/internal/cmd/beta/sfs/export-policy/test-files/rules-example.json new file mode 100644 index 000000000..57b2cbcb1 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/test-files/rules-example.json @@ -0,0 +1,14 @@ +[ + { + "description": "first rule", + "ipAcl": ["192.168.2.0/24"], + "order": 1, + "superUser": false, + "setUuid": true + }, + { + "ipAcl": ["192.168.2.0/24", "127.0.0.1/32"], + "order": 2, + "readonly": true + } +] \ No newline at end of file diff --git a/internal/cmd/beta/sfs/export-policy/update/update.go b/internal/cmd/beta/sfs/export-policy/update/update.go new file mode 100644 index 000000000..cbe394459 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/update/update.go @@ -0,0 +1,172 @@ +package update + +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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + exportPolicyArg = "EXPORT_POLICY_ID" + + rulesFlag = "rules" + removeRulesFlag = "remove-rules" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ExportPolicyId string + Rules *[]sfs.UpdateShareExportPolicyBodyRule +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", exportPolicyArg), + Short: "Updates a export policy", + Long: "Updates a export policy.", + Args: args.SingleArg(exportPolicyArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update a export policy with ID "xxx" and with rules from file "./rules.json"`, + "$ stackit beta sfs export-policy update xxx --rules @./rules.json", + ), + examples.NewExample( + `Update a export policy with ID "xxx" and remove the rules`, + "$ stackit beta sfs export-policy update XXX --remove-rules", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + exportPolicyLabel, err := sfsUtils.GetExportPolicyName(ctx, apiClient, model.ProjectId, model.Region, model.ExportPolicyId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get export policy name: %v", err) + exportPolicyLabel = model.ExportPolicyId + } else if exportPolicyLabel == "" { + exportPolicyLabel = model.ExportPolicyId + } + + 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 + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update export policy %q for project %q?", exportPolicyLabel, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update export policy: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, exportPolicyLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.ReadFromFileFlag(), rulesFlag, "Rules of the export policy") + cmd.Flags().Bool(removeRulesFlag, false, "Remove the export policy rules") + + rulesFlags := []string{rulesFlag, removeRulesFlag} + cmd.MarkFlagsMutuallyExclusive(rulesFlags...) + cmd.MarkFlagsOneRequired(rulesFlags...) // Because the update endpoint supports only rules at the moment, one of the flags must be required +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiUpdateShareExportPolicyRequest { + req := apiClient.UpdateShareExportPolicy(ctx, model.ProjectId, model.Region, model.ExportPolicyId) + + payload := sfs.UpdateShareExportPolicyPayload{ + Rules: model.Rules, + } + return req.UpdateShareExportPolicyPayload(payload) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + exportPolicyId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + var rules *[]sfs.UpdateShareExportPolicyBodyRule + noRulesErr := fmt.Errorf("no rules specified") + if rulesString := flags.FlagToStringPointer(p, cmd, rulesFlag); rulesString != nil { + var r []sfs.UpdateShareExportPolicyBodyRule + err := json.Unmarshal([]byte(*rulesString), &r) + if err != nil { + return nil, fmt.Errorf("could not parse rules: %w", err) + } + if r == nil { + return nil, noRulesErr + } + rules = &r + } + + if removeRules := flags.FlagToBoolPointer(p, cmd, removeRulesFlag); removeRules != nil { + // Create an empty slice for the patch request + rules = &[]sfs.UpdateShareExportPolicyBodyRule{} + } + + // Because the update endpoint supports only rules at the moment, this should not be empty + if rules == nil { + return nil, noRulesErr + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ExportPolicyId: exportPolicyId, + Rules: rules, + } + + p.DebugInputModel(model) + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat, projectLabel, exportPolicyLabel string, resp *sfs.UpdateShareExportPolicyResponse) error { + return p.OutputResult(outputFormat, resp, func() error { + if resp == nil { + p.Outputln("Empty export policy response") + return nil + } + p.Outputf("Updated export policy %q for project %q\n", exportPolicyLabel, projectLabel) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/export-policy/update/update_test.go b/internal/cmd/beta/sfs/export-policy/update/update_test.go new file mode 100644 index 000000000..0ca322850 --- /dev/null +++ b/internal/cmd/beta/sfs/export-policy/update/update_test.go @@ -0,0 +1,251 @@ +package update + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() + +const ( + testRegion = "eu01" + testRulesString = `[ + { + "ipAcl": ["172.16.0.0/24"], + "readOnly": true, + "order": 1 + } +]` +) + +var testRules = &[]sfs.UpdateShareExportPolicyBodyRule{ + { + IpAcl: utils.Ptr([]string{"172.16.0.0/24"}), + ReadOnly: utils.Ptr(true), + Order: utils.Ptr(int64(1)), + }, +} +var testExportPolicyId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + rulesFlag: testRulesString, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testExportPolicyId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ExportPolicyId: testExportPolicyId, + Rules: testRules, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiUpdateShareExportPolicyRequest)) sfs.ApiUpdateShareExportPolicyRequest { + request := testClient.UpdateShareExportPolicy(testCtx, testProjectId, testRegion, testExportPolicyId) + request = request.UpdateShareExportPolicyPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *sfs.UpdateShareExportPolicyPayload)) sfs.UpdateShareExportPolicyPayload { + payload := sfs.UpdateShareExportPolicyPayload{ + Rules: testRules, + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no rules specified", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, rulesFlag) + }), + isValid: false, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Rules = nil + }), + }, + { + description: "conflict rules and remove rules", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[rulesFlag] = testRulesString + flagValues[removeRulesFlag] = "true" + }), + isValid: false, + }, + { + description: "--remove-rules flag set", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[removeRulesFlag] = "true" + delete(flagValues, rulesFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Rules = &[]sfs.UpdateShareExportPolicyBodyRule{} + }), + }, + { + description: "required read rules from file", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[rulesFlag] = "@../test-files/rules-example.json" + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Rules = &[]sfs.UpdateShareExportPolicyBodyRule{ + { + Description: sfs.NewNullableString( + utils.Ptr("first rule"), + ), + IpAcl: utils.Ptr([]string{"192.168.2.0/24"}), + Order: utils.Ptr(int64(1)), + SetUuid: utils.Ptr(true), + SuperUser: utils.Ptr(false), + }, + { + IpAcl: utils.Ptr([]string{"192.168.2.0/24", "127.0.0.1/32"}), + Order: utils.Ptr(int64(2)), + ReadOnly: utils.Ptr(true), + }, + } + }), + }, + } + opts := []testutils.TestingOption{ + testutils.WithCmpOptions(cmp.AllowUnexported(sfs.NullableString{})), + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInputWithOptions(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, nil, tt.isValid, opts) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiUpdateShareExportPolicyRequest + }{ + { + 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), + 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 + exportPolicyLabel string + resp *sfs.UpdateShareExportPolicyResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty resp", + args: args{ + resp: &sfs.UpdateShareExportPolicyResponse{}, + }, + 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.exportPolicyLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/performance-class/list/list.go b/internal/cmd/beta/sfs/performance-class/list/list.go new file mode 100644 index 000000000..0ca22c392 --- /dev/null +++ b/internal/cmd/beta/sfs/performance-class/list/list.go @@ -0,0 +1,110 @@ +package list + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +type inputModel struct { + *globalflags.GlobalFlagModel +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all performances classes available", + Long: "Lists all performances classes available.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all performances classes`, + "$ stackit beta sfs performance-class list", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + resp, err := buildRequest(ctx, apiClient).Execute() + if err != nil { + return fmt.Errorf("list performance-class: %w", err) + } + + // Get projectLabel + 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 + } + + performanceClasses := utils.GetSliceFromPointer(resp.PerformanceClasses) + + return outputResult(params.Printer, model.OutputFormat, projectLabel, performanceClasses) + }, + } + 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, apiClient *sfs.APIClient) sfs.ApiListPerformanceClassesRequest { + return apiClient.ListPerformanceClasses(ctx) +} + +func outputResult(p *print.Printer, outputFormat, projectLabel string, performanceClasses []sfs.PerformanceClass) error { + return p.OutputResult(outputFormat, performanceClasses, func() error { + if len(performanceClasses) == 0 { + p.Outputf("No performance classes found for project %q\n", projectLabel) + return nil + } + + table := tables.NewTable() + table.SetHeader("NAME", "IOPS", "THROUGHPUT") + for _, performanceClass := range performanceClasses { + table.AddRow( + utils.PtrString(performanceClass.Name), + utils.PtrString(performanceClass.Iops), + utils.PtrString(performanceClass.Throughput), + ) + } + p.Outputln(table.Render()) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/performance-class/list/list_test.go b/internal/cmd/beta/sfs/performance-class/list/list_test.go new file mode 100644 index 000000000..655159342 --- /dev/null +++ b/internal/cmd/beta/sfs/performance-class/list/list_test.go @@ -0,0 +1,170 @@ +package list + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiListPerformanceClassesRequest)) sfs.ApiListPerformanceClassesRequest { + request := testClient.ListPerformanceClasses(testCtx) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + expectedRequest sfs.ApiListPerformanceClassesRequest + }{ + { + description: "base", + expectedRequest: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, testClient) + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + 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 + performanceClasses []sfs.PerformanceClass + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty performance class", + args: args{ + performanceClasses: []sfs.PerformanceClass{ + {}, + }, + }, + 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.performanceClasses); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/performance-class/performance_class.go b/internal/cmd/beta/sfs/performance-class/performance_class.go new file mode 100644 index 000000000..f033ee5d3 --- /dev/null +++ b/internal/cmd/beta/sfs/performance-class/performance_class.go @@ -0,0 +1,26 @@ +package performanceclass + +import ( + "github.com/spf13/cobra" + + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/performance-class/list" + + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "performance-class", + Short: "Provides functionality for SFS performance classes", + Long: "Provides functionality for SFS performance classes.", + Args: cobra.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) +} diff --git a/internal/cmd/beta/sfs/resource-pool/create/create.go b/internal/cmd/beta/sfs/resource-pool/create/create.go new file mode 100644 index 000000000..69093d471 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/create/create.go @@ -0,0 +1,184 @@ +package create + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" + "github.com/stackitcloud/stackit-sdk-go/services/sfs/wait" +) + +const ( + performanceClassFlag = "performance-class" + sizeFlag = "size" + ipAclFlag = "ip-acl" + availabilityZoneFlag = "availability-zone" + nameFlag = "name" + snapshotsVisibleFlag = "snapshots-visible" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SizeInGB int64 + PerformanceClass string + IpAcl []string + Name string + AvailabilityZone string + SnapshotsVisible bool +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a SFS resource pool", + Long: `Creates a SFS resource pool. + +The available performance class values can be obtained by running: + $ stackit beta sfs performance-class list`, + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a SFS resource pool`, + "$ stackit beta sfs resource-pool create --availability-zone eu01-m --ip-acl 10.88.135.144/28 --performance-class Standard --size 500 --name resource-pool-01"), + examples.NewExample( + `Create a SFS resource pool, allow only a single IP which can mount the resource pool`, + "$ stackit beta sfs resource-pool create --availability-zone eu01-m --ip-acl 250.81.87.224/32 --performance-class Standard --size 500 --name resource-pool-01"), + examples.NewExample( + `Create a SFS resource pool, allow multiple IP ACL which can mount the resource pool`, + "$ stackit beta sfs resource-pool create --availability-zone eu01-m --ip-acl \"10.88.135.144/28,250.81.87.224/32\" --performance-class Standard --size 500 --name resource-pool-01"), + examples.NewExample( + `Create a SFS resource pool with visible snapshots`, + "$ stackit beta sfs resource-pool create --availability-zone eu01-m --ip-acl 10.88.135.144/28 --performance-class Standard --size 500 --name resource-pool-01 --snapshots-visible"), + ), + 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 + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a resource-pool for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + resp, err := buildRequest(ctx, model, apiClient).Execute() + if err != nil { + return fmt.Errorf("create SFS resource pool: %w", err) + } + var resourcePoolId string + if resp != nil && resp.HasResourcePool() && resp.ResourcePool.HasId() { + resourcePoolId = *resp.ResourcePool.Id + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for resource pool creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(sizeFlag, 0, "Size of the pool in Gigabytes") + cmd.Flags().String(performanceClassFlag, "", "Performance class") + cmd.Flags().Var(flags.CIDRSliceFlag(), ipAclFlag, "List of network addresses in the form
, e.g. 192.168.10.0/24 that can mount the resource pool readonly") + cmd.Flags().String(availabilityZoneFlag, "", "Availability zone") + cmd.Flags().String(nameFlag, "", "Name") + cmd.Flags().Bool(snapshotsVisibleFlag, false, "Set snapshots visible and accessible to users") + + for _, flag := range []string{sizeFlag, performanceClassFlag, ipAclFlag, availabilityZoneFlag, nameFlag} { + err := flags.MarkFlagsRequired(cmd, flag) + cobra.CheckErr(err) + } +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiCreateResourcePoolRequest { + req := apiClient.CreateResourcePool(ctx, model.ProjectId, model.Region) + req = req.CreateResourcePoolPayload(sfs.CreateResourcePoolPayload{ + AvailabilityZone: &model.AvailabilityZone, + IpAcl: &model.IpAcl, + Name: &model.Name, + PerformanceClass: &model.PerformanceClass, + SizeGigabytes: &model.SizeInGB, + SnapshotsAreVisible: &model.SnapshotsVisible, + }) + return req +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + performanceClass := flags.FlagToStringValue(p, cmd, performanceClassFlag) + size := flags.FlagWithDefaultToInt64Value(p, cmd, sizeFlag) + availabilityZone := flags.FlagToStringValue(p, cmd, availabilityZoneFlag) + ipAcls := flags.FlagToStringSlicePointer(p, cmd, ipAclFlag) + name := flags.FlagToStringValue(p, cmd, nameFlag) + snapshotsVisible := flags.FlagToBoolValue(p, cmd, snapshotsVisibleFlag) + + model := inputModel{ + GlobalFlagModel: globalFlags, + SizeInGB: size, + IpAcl: *ipAcls, + PerformanceClass: performanceClass, + AvailabilityZone: availabilityZone, + Name: name, + SnapshotsVisible: snapshotsVisible, + } + + p.DebugInputModel(model) + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat, projectLabel string, resp *sfs.CreateResourcePoolResponse) error { + return p.OutputResult(outputFormat, resp, func() error { + if resp == nil || resp.ResourcePool == nil { + p.Outputln("Resource pool response is empty") + return nil + } + p.Outputf("Created resource pool for project %q. Resource pool ID: %s\n", projectLabel, utils.PtrString(resp.ResourcePool.Id)) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/resource-pool/create/create_test.go b/internal/cmd/beta/sfs/resource-pool/create/create_test.go new file mode 100644 index 000000000..5dd65f643 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/create/create_test.go @@ -0,0 +1,295 @@ +package create + +import ( + "context" + "strconv" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var ( + testProjectId = uuid.NewString() + testRegion = "eu02" + testResourcePoolPerformanceClass = "Standard" + testResourcePoolSizeInGB int64 = 50 + testResourcePoolAvailabilityZone = "eu02-m" + testResourcePoolName = "sfs-resource-pool-01" + testResourcePoolIpAcl = []string{"10.88.135.144/28", "250.81.87.224/32"} + testSnapshotsVisible = true +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + performanceClassFlag: testResourcePoolPerformanceClass, + sizeFlag: strconv.FormatInt(testResourcePoolSizeInGB, 10), + ipAclFlag: strings.Join(testResourcePoolIpAcl, ","), + availabilityZoneFlag: testResourcePoolAvailabilityZone, + nameFlag: testResourcePoolName, + snapshotsVisibleFlag: strconv.FormatBool(testSnapshotsVisible), + } + 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, + }, + PerformanceClass: testResourcePoolPerformanceClass, + AvailabilityZone: testResourcePoolAvailabilityZone, + Name: testResourcePoolName, + SizeInGB: testResourcePoolSizeInGB, + IpAcl: testResourcePoolIpAcl, + SnapshotsVisible: testSnapshotsVisible, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiCreateResourcePoolRequest)) sfs.ApiCreateResourcePoolRequest { + request := testClient.CreateResourcePool(testCtx, testProjectId, testRegion) + request = request.CreateResourcePoolPayload(sfs.CreateResourcePoolPayload{ + Name: &testResourcePoolName, + PerformanceClass: &testResourcePoolPerformanceClass, + AvailabilityZone: &testResourcePoolAvailabilityZone, + IpAcl: &testResourcePoolIpAcl, + SizeGigabytes: &testResourcePoolSizeInGB, + SnapshotsAreVisible: &testSnapshotsVisible, + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + ipAclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "ip acl missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipAclFlag) + }), + isValid: false, + }, + { + description: "name missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + { + description: "performance class missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, performanceClassFlag) + }), + isValid: false, + }, + { + description: "size missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, sizeFlag) + }), + isValid: false, + }, + { + description: "availability zone missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, availabilityZoneFlag) + }), + isValid: false, + }, + { + description: "missing snapshot visible - fallback to false", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, snapshotsVisibleFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.SnapshotsVisible = false + }), + isValid: true, + }, + { + 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: "repeated ip acl flags", + flagValues: fixtureFlagValues(), + ipAclValues: []string{"198.51.100.14/24", "198.51.100.14/32"}, + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IpAcl = append(model.IpAcl, "198.51.100.14/24", "198.51.100.14/32") + }), + }, + { + description: "repeated ip acl flags with list value", + flagValues: fixtureFlagValues(), + ipAclValues: []string{"198.51.100.14/24,198.51.100.14/32"}, + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IpAcl = append(model.IpAcl, "198.51.100.14/24", "198.51.100.14/32") + }), + }, + { + description: "invalid ip acl 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipAclFlag] = "foo-bar" + }), + isValid: false, + }, + { + description: "invalid ip acl 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipAclFlag] = "192.168.178.256/32" + }), + isValid: false, + }, + { + description: "invalid ip acl 3", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipAclFlag] = "192.168.178.255/32," + }), + isValid: false, + }, + { + description: "invalid ip acl 4", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[ipAclFlag] = "192.168.178.255/32," + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInputWithAdditionalFlags(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, map[string][]string{ + ipAclFlag: tt.ipAclValues, + }, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiCreateResourcePoolRequest + }{ + { + 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), + 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 + resp *sfs.CreateResourcePoolResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + resp: &sfs.CreateResourcePoolResponse{}, + }, + wantErr: false, + }, + { + name: "set response", + args: args{ + resp: &sfs.CreateResourcePoolResponse{ + ResourcePool: &sfs.CreateResourcePoolResponseResourcePool{}, + }, + }, + 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.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/resource-pool/delete/delete.go b/internal/cmd/beta/sfs/resource-pool/delete/delete.go new file mode 100644 index 000000000..acd38ae4d --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/delete/delete.go @@ -0,0 +1,120 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "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/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" + "github.com/stackitcloud/stackit-sdk-go/services/sfs/wait" +) + +const ( + resourcePoolIdArg = "RESOURCE_POOL_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes a SFS resource pool", + Long: "Deletes a SFS resource pool.", + Args: args.SingleArg(resourcePoolIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete the SFS resource pool with ID "xxx"`, + "$ stackit beta sfs resource-pool delete xxx"), + ), + 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 + } + + resourcePoolName, err := sfsUtils.GetResourcePoolName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err) + resourcePoolName = model.ResourcePoolId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete resource pool %q? (This cannot be undone)", resourcePoolName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + resp, err := buildRequest(ctx, model, apiClient).Execute() + if err != nil { + return fmt.Errorf("delete SFS resource pool: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for resource pool deletion: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model.OutputFormat, resourcePoolName, resp) + }, + } + return cmd +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiDeleteResourcePoolRequest { + req := apiClient.DeleteResourcePool(ctx, model.ProjectId, model.Region, model.ResourcePoolId) + return req +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + resourcePoolId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ResourcePoolId: resourcePoolId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat, resourcePoolName string, response map[string]interface{}) error { + return p.OutputResult(outputFormat, response, func() error { + p.Outputf("Deleted resource pool %q\n", resourcePoolName) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go b/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go new file mode 100644 index 000000000..b41ed2626 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go @@ -0,0 +1,209 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} +var testProjectId = uuid.NewString() +var testResourcePoolId = uuid.NewString() +var testRegion = "eu02" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testResourcePoolId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +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, + }, + ResourcePoolId: testResourcePoolId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiDeleteResourcePoolRequest)) sfs.ApiDeleteResourcePoolRequest { + request := testClient.DeleteResourcePool(testCtx, testProjectId, testRegion, testResourcePoolId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "resource pool id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "resource pool id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiDeleteResourcePoolRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resourcePoolName string + response map[string]interface{} + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty - output json", + args: args{ + outputFormat: print.JSONOutputFormat, + }, + 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.resourcePoolName, tt.args.response); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/resource-pool/describe/describe.go b/internal/cmd/beta/sfs/resource-pool/describe/describe.go new file mode 100644 index 000000000..0567b950e --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/describe/describe.go @@ -0,0 +1,152 @@ +package describe + +import ( + "context" + "fmt" + "strings" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "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/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + resourcePoolIdArg = "RESOURCE_POOL_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Shows details of a SFS resource pool", + Long: "Shows details of a SFS resource pool.", + Args: args.SingleArg(resourcePoolIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Describe the SFS resource pool with ID "xxx"`, + "$ stackit beta sfs resource-pool describe xxx"), + ), + 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 + } + + // Call API + resp, err := buildRequest(ctx, model, apiClient).Execute() + if err != nil { + return fmt.Errorf("describe SFS resource pool: %w", err) + } + + // Get projectLabel + 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 + } + + return outputResult(params.Printer, model.OutputFormat, model.ResourcePoolId, projectLabel, resp.ResourcePool) + }, + } + return cmd +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiGetResourcePoolRequest { + req := apiClient.GetResourcePool(ctx, model.ProjectId, model.Region, model.ResourcePoolId) + return req +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + resourcePoolId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ResourcePoolId: resourcePoolId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat, resourcePoolId, projectLabel string, resourcePool *sfs.GetResourcePoolResponseResourcePool) error { + return p.OutputResult(outputFormat, resourcePool, func() error { + if resourcePool == nil { + p.Outputf("Resource pool %q not found in project %q\n", resourcePoolId, projectLabel) + return nil + } + table := tables.NewTable() + + // convert the string slice to a comma separated list + var ipAclStr string + if resourcePool.IpAcl != nil { + ipAclStr = strings.Join(*resourcePool.IpAcl, ", ") + } + + table.AddRow("ID", utils.PtrString(resourcePool.Id)) + table.AddSeparator() + table.AddRow("NAME", utils.PtrString(resourcePool.Name)) + table.AddSeparator() + table.AddRow("AVAILABILITY ZONE", utils.PtrString(resourcePool.AvailabilityZone)) + table.AddSeparator() + table.AddRow("NUMBER OF SHARES", utils.PtrString(resourcePool.CountShares)) + table.AddSeparator() + table.AddRow("IP ACL", ipAclStr) + table.AddSeparator() + table.AddRow("MOUNT PATH", utils.PtrString(resourcePool.MountPath)) + table.AddSeparator() + if resourcePool.PerformanceClass != nil { + table.AddRow("PERFORMANCE CLASS", utils.PtrString(resourcePool.PerformanceClass.Name)) + table.AddSeparator() + } + table.AddRow("SNAPSHOTS ARE VISIBLE", utils.PtrString(resourcePool.SnapshotsAreVisible)) + table.AddSeparator() + table.AddRow("NEXT PERFORMANCE CLASS DOWNGRADE TIME", utils.PtrString(resourcePool.PerformanceClassDowngradableAt)) + table.AddSeparator() + table.AddRow("NEXT SIZE REDUCTION TIME", utils.PtrString(resourcePool.SizeReducibleAt)) + table.AddSeparator() + if resourcePool.HasSpace() { + table.AddRow("TOTAL SIZE (GB)", utils.PtrString(resourcePool.Space.SizeGigabytes)) + table.AddSeparator() + table.AddRow("AVAILABLE SIZE (GB)", utils.PtrString(resourcePool.Space.AvailableGigabytes)) + table.AddSeparator() + table.AddRow("USED SIZE (GB)", utils.PtrString(resourcePool.Space.UsedGigabytes)) + table.AddSeparator() + } + table.AddRow("STATE", utils.PtrString(resourcePool.State)) + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/sfs/resource-pool/describe/describe_test.go b/internal/cmd/beta/sfs/resource-pool/describe/describe_test.go new file mode 100644 index 000000000..8fddcd529 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/describe/describe_test.go @@ -0,0 +1,211 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testResourcePoolId = uuid.NewString() +var testRegion = "eu02" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testResourcePoolId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +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, + }, + ResourcePoolId: testResourcePoolId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiGetResourcePoolRequest)) sfs.ApiGetResourcePoolRequest { + request := testClient.GetResourcePool(testCtx, testProjectId, testRegion, testResourcePoolId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "resource pool id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "resource pool id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiGetResourcePoolRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resourcePoolId string + projectLabel string + resp *sfs.GetResourcePoolResponseResourcePool + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + resp: &sfs.GetResourcePoolResponseResourcePool{}, + }, + 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.resourcePoolId, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/resource-pool/list/list.go b/internal/cmd/beta/sfs/resource-pool/list/list.go new file mode 100644 index 000000000..d62dbd7b6 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/list/list.go @@ -0,0 +1,153 @@ +package list + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all SFS resource pools", + Long: "Lists all SFS resource pools.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all SFS resource pools`, + "$ stackit beta sfs resource-pool list"), + examples.NewExample( + `List all SFS resource pools for another region than the default one`, + "$ stackit beta sfs resource-pool list --region eu01"), + examples.NewExample( + `List up to 10 SFS resource pools`, + "$ stackit beta sfs resource-pool list --limit 10"), + ), + 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 + } + + // Call API + resp, err := buildRequest(ctx, model, apiClient).Execute() + if err != nil { + return fmt.Errorf("list SFS resource pools: %w", err) + } + + resourcePools := utils.GetSliceFromPointer(resp.ResourcePools) + + // Truncate output + if model.Limit != nil && len(resourcePools) > int(*model.Limit) { + resourcePools = resourcePools[:*model.Limit] + } + + // Get projectLabel + 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 + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, resourcePools) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiListResourcePoolsRequest { + req := apiClient.ListResourcePools(ctx, model.ProjectId, model.Region) + return req +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &cliErr.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + p.DebugInputModel(model) + return &model, nil +} +func outputResult(p *print.Printer, outputFormat, projectLabel string, resourcePools []sfs.ResourcePool) error { + return p.OutputResult(outputFormat, resourcePools, func() error { + if len(resourcePools) == 0 { + p.Outputf("No resource pools found for project %q\n", projectLabel) + return nil + } + + table := tables.NewTable() + table.SetHeader("ID", "NAME", "AVAILABILITY ZONE", "STATE", "TOTAL SIZE (GB)", "USED SIZE (GB)") + for _, resourcePool := range resourcePools { + totalSizeGigabytes, usedSizeGigabytes := "", "" + if resourcePool.HasSpace() { + totalSizeGigabytes = utils.PtrString(resourcePool.Space.SizeGigabytes) + usedSizeGigabytes = utils.PtrString(resourcePool.Space.UsedGigabytes) + } + table.AddRow( + utils.PtrString(resourcePool.Id), + utils.PtrString(resourcePool.Name), + utils.PtrString(resourcePool.AvailabilityZone), + utils.PtrString(resourcePool.State), + totalSizeGigabytes, + usedSizeGigabytes, + ) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + }) +} diff --git a/internal/cmd/beta/sfs/resource-pool/list/list_test.go b/internal/cmd/beta/sfs/resource-pool/list/list_test.go new file mode 100644 index 000000000..4670a7856 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/list/list_test.go @@ -0,0 +1,199 @@ +package list + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} +var testProjectId = uuid.NewString() +var testRegion = "eu02" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", + } + 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, + }, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiListResourcePoolsRequest)) sfs.ApiListResourcePoolsRequest { + request := testClient.ListResourcePools(testCtx, testProjectId, testRegion) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "limit invalid 3", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "-5" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiListResourcePoolsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resourcePools []sfs.ResourcePool + projectLabel string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty resource pools slice", + args: args{ + resourcePools: []sfs.ResourcePool{}, + }, + wantErr: false, + }, + { + name: "set empty resource pool in resource pools slice", + args: args{ + resourcePools: []sfs.ResourcePool{{}}, + }, + 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.resourcePools); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/resource-pool/resource_pool.go b/internal/cmd/beta/sfs/resource-pool/resource_pool.go new file mode 100644 index 000000000..3198741b4 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/resource_pool.go @@ -0,0 +1,34 @@ +package resourcepool + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/resource-pool/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/resource-pool/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/resource-pool/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/resource-pool/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/resource-pool/update" + "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: "resource-pool", + Short: "Provides functionality for SFS resource pools", + Long: "Provides functionality for SFS resource pools.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) +} diff --git a/internal/cmd/beta/sfs/resource-pool/update/update.go b/internal/cmd/beta/sfs/resource-pool/update/update.go new file mode 100644 index 000000000..267f68939 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/update/update.go @@ -0,0 +1,179 @@ +package update + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" + "github.com/stackitcloud/stackit-sdk-go/services/sfs/wait" +) + +const ( + resourcePoolIdArg = "RESOURCE_POOL_ID" + performanceClassFlag = "performance-class" + sizeFlag = "size" + ipAclFlag = "ip-acl" + snapshotsVisibleFlag = "snapshots-visible" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SizeGigabytes *int64 + PerformanceClass *string + IpAcl *[]string + ResourcePoolId string + SnapshotsVisible *bool +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates a SFS resource pool", + Long: `Updates a SFS resource pool. + +The available performance class values can be obtained by running: + $ stackit beta sfs performance-class list`, + Args: args.SingleArg(resourcePoolIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update the SFS resource pool with ID "xxx"`, + "$ stackit beta sfs resource-pool update xxx --ip-acl 10.88.135.144/28 --performance-class Standard --size 5"), + examples.NewExample( + `Update the SFS resource pool with ID "xxx", allow only a single IP which can mount the resource pool`, + "$ stackit beta sfs resource-pool update xxx --ip-acl 250.81.87.224/32 --performance-class Standard --size 5"), + examples.NewExample( + `Update the SFS resource pool with ID "xxx", allow multiple IP ACL which can mount the resource pool`, + "$ stackit beta sfs resource-pool update xxx --ip-acl \"10.88.135.144/28,250.81.87.224/32\" --performance-class Standard --size 5"), + examples.NewExample( + `Update the SFS resource pool with ID "xxx", set snapshots visible to false`, + "$ stackit beta sfs resource-pool update xxx --snapshots-visible=false"), + ), + 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 + } + + resourcePoolName, err := sfsUtils.GetResourcePoolName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err) + resourcePoolName = model.ResourcePoolId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update resource-pool %q for project %q?", resourcePoolName, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + resp, err := buildRequest(ctx, model, apiClient).Execute() + if err != nil { + return fmt.Errorf("update SFS resource pool: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for resource pool update: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(sizeFlag, 0, "Size of the pool in Gigabytes") + cmd.Flags().String(performanceClassFlag, "", "Performance class") + cmd.Flags().Var(flags.CIDRSliceFlag(), ipAclFlag, "List of network addresses in the form
, e.g. 192.168.10.0/24 that can mount the resource pool readonly") + cmd.Flags().Bool(snapshotsVisibleFlag, false, "Set snapshots visible and accessible to users") +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiUpdateResourcePoolRequest { + req := apiClient.UpdateResourcePool(ctx, model.ProjectId, model.Region, model.ResourcePoolId) + req = req.UpdateResourcePoolPayload(sfs.UpdateResourcePoolPayload{ + IpAcl: model.IpAcl, + PerformanceClass: model.PerformanceClass, + SizeGigabytes: model.SizeGigabytes, + SnapshotsAreVisible: model.SnapshotsVisible, + }) + return req +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + resourcePoolId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + performanceClass := flags.FlagToStringPointer(p, cmd, performanceClassFlag) + size := flags.FlagToInt64Pointer(p, cmd, sizeFlag) + ipAcls := flags.FlagToStringSlicePointer(p, cmd, ipAclFlag) + snapshotsVisible := flags.FlagToBoolPointer(p, cmd, snapshotsVisibleFlag) + + if performanceClass == nil && size == nil && ipAcls == nil && snapshotsVisible == nil { + return nil, &cliErr.EmptyUpdateError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SizeGigabytes: size, + IpAcl: ipAcls, + PerformanceClass: performanceClass, + ResourcePoolId: resourcePoolId, + SnapshotsVisible: snapshotsVisible, + } + + p.DebugInputModel(model) + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat string, resp *sfs.UpdateResourcePoolResponse) error { + return p.OutputResult(outputFormat, resp, func() error { + if resp == nil || resp.ResourcePool == nil { + p.Outputln("Resource pool response is empty") + return nil + } + p.Outputf("Updated resource pool %s\n", utils.PtrString(resp.ResourcePool.Name)) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/resource-pool/update/update_test.go b/internal/cmd/beta/sfs/resource-pool/update/update_test.go new file mode 100644 index 000000000..c94b79b92 --- /dev/null +++ b/internal/cmd/beta/sfs/resource-pool/update/update_test.go @@ -0,0 +1,361 @@ +package update + +import ( + "context" + "slices" + "strconv" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu02" +) + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &sfs.APIClient{} + + testProjectId = uuid.NewString() + testResourcePoolId = uuid.NewString() + testResourcePoolIpAcl = []string{"10.88.135.144/28", "250.81.87.224/32"} + testResourcePoolPerformanceClass = "Standard" + testResourcePoolSizeInGB int64 = 50 + testSnapshotsVisible = true +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testResourcePoolId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + performanceClassFlag: testResourcePoolPerformanceClass, + sizeFlag: strconv.FormatInt(testResourcePoolSizeInGB, 10), + ipAclFlag: strings.Join(testResourcePoolIpAcl, ","), + snapshotsVisibleFlag: strconv.FormatBool(testSnapshotsVisible), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + ipAclClone := slices.Clone(testResourcePoolIpAcl) + + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + ResourcePoolId: testResourcePoolId, + SizeGigabytes: &testResourcePoolSizeInGB, + PerformanceClass: &testResourcePoolPerformanceClass, + IpAcl: &ipAclClone, + SnapshotsVisible: &testSnapshotsVisible, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiUpdateResourcePoolRequest)) sfs.ApiUpdateResourcePoolRequest { + request := testClient.UpdateResourcePool(testCtx, testProjectId, testRegion, testResourcePoolId) + request = request.UpdateResourcePoolPayload(sfs.UpdateResourcePoolPayload{ + IpAcl: &testResourcePoolIpAcl, + PerformanceClass: &testResourcePoolPerformanceClass, + SizeGigabytes: &testResourcePoolSizeInGB, + SnapshotsAreVisible: &testSnapshotsVisible, + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + ipAclValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no values to update", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, sizeFlag) + delete(flagValues, ipAclFlag) + delete(flagValues, performanceClassFlag) + delete(flagValues, snapshotsVisibleFlag) + }), + isValid: false, + }, + { + description: "update only size", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipAclFlag) + delete(flagValues, performanceClassFlag) + delete(flagValues, snapshotsVisibleFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IpAcl = nil + model.PerformanceClass = nil + model.SnapshotsVisible = nil + }), + isValid: true, + }, + { + description: "update only snapshots visibility", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipAclFlag) + delete(flagValues, performanceClassFlag) + delete(flagValues, sizeFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IpAcl = nil + model.PerformanceClass = nil + model.SizeGigabytes = nil + }), + isValid: true, + }, + { + description: "update only performance class", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, ipAclFlag) + delete(flagValues, snapshotsVisibleFlag) + delete(flagValues, sizeFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.IpAcl = nil + model.SnapshotsVisible = nil + model.SizeGigabytes = nil + }), + isValid: true, + }, + { + description: "update only ipAcl", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, performanceClassFlag) + delete(flagValues, snapshotsVisibleFlag) + delete(flagValues, sizeFlag) + }), + expectedModel: fixtureInputModel(func(model *inputModel) { + model.PerformanceClass = nil + model.SnapshotsVisible = nil + model.SizeGigabytes = nil + }), + isValid: true, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + flagValues[sizeFlag] = "50" + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + flagValues[sizeFlag] = "50" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + flagValues[sizeFlag] = "50" + }), + isValid: false, + }, + { + description: "resource pool id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "resource pool id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "repeated acl flags", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + ipAclValues: []string{"198.51.100.14/24", "198.51.100.14/32"}, + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + if model.IpAcl == nil { + model.IpAcl = &[]string{} + } + *model.IpAcl = append(*model.IpAcl, "198.51.100.14/24", "198.51.100.14/32") + }), + }, + { + description: "repeated ip acl flag with list value", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + ipAclValues: []string{"198.51.100.14/24,198.51.100.14/32"}, + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + if model.IpAcl == nil { + model.IpAcl = &[]string{} + } + *model.IpAcl = append(*model.IpAcl, "198.51.100.14/24", "198.51.100.14/32") + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInputWithAdditionalFlags(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, map[string][]string{ + ipAclFlag: tt.ipAclValues, + }, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiUpdateResourcePoolRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp *sfs.UpdateResourcePoolResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty response", + args: args{ + resp: &sfs.UpdateResourcePoolResponse{}, + }, + wantErr: false, + }, + { + name: "valid response with empty resource pool", + args: args{ + resp: &sfs.UpdateResourcePoolResponse{ + ResourcePool: &sfs.UpdateResourcePoolResponseResourcePool{}, + }, + }, + wantErr: false, + }, + { + name: "valid response with name", + args: args{ + resp: &sfs.UpdateResourcePoolResponse{ + ResourcePool: &sfs.UpdateResourcePoolResponseResourcePool{ + Name: utils.Ptr("example name"), + }, + }, + }, + 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.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/sfs.go b/internal/cmd/beta/sfs/sfs.go new file mode 100644 index 000000000..2477e4843 --- /dev/null +++ b/internal/cmd/beta/sfs/sfs.go @@ -0,0 +1,34 @@ +package sfs + +import ( + exportpolicy "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/export-policy" + performanceclass "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/performance-class" + resourcepool "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/resource-pool" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/share" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot" + "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: "sfs", + Short: "Provides functionality for SFS (stackit file storage)", + Long: "Provides functionality for SFS (stackit file storage).", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(resourcepool.NewCmd(params)) + cmd.AddCommand(share.NewCmd(params)) + cmd.AddCommand(exportpolicy.NewCmd(params)) + cmd.AddCommand(snapshot.NewCmd(params)) + cmd.AddCommand(performanceclass.NewCmd(params)) +} diff --git a/internal/cmd/beta/sfs/share/create/create.go b/internal/cmd/beta/sfs/share/create/create.go new file mode 100644 index 000000000..8fc5312bf --- /dev/null +++ b/internal/cmd/beta/sfs/share/create/create.go @@ -0,0 +1,181 @@ +package create + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" + "github.com/stackitcloud/stackit-sdk-go/services/sfs/wait" +) + +const ( + nameFlag = "name" + resourcePoolIdFlag = "resource-pool-id" + exportPolicyNameFlag = "export-policy-name" + hardLimitFlag = "hard-limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Name string + ExportPolicyName *string + ResourcePoolId string + HardLimit *int64 +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a share", + Long: "Creates a share.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a share in a resource pool with ID "xxx", name "yyy" and no space hard limit`, + "$ stackit beta sfs share create --resource-pool-id xxx --name yyy --hard-limit 0", + ), + examples.NewExample( + `Create a share in a resource pool with ID "xxx", name "yyy" and export policy with name "zzz"`, + "$ stackit beta sfs share create --resource-pool-id xxx --name yyy --export-policy-name zzz --hard-limit 0", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + resourcePoolLabel, err := sfsUtils.GetResourcePoolName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err) + resourcePoolLabel = model.ResourcePoolId + } else if resourcePoolLabel == "" { + resourcePoolLabel = model.ResourcePoolId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a SFS share for resource pool %q?", resourcePoolLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create SFS share: %w", err) + } + var shareId string + if resp != nil && resp.HasShare() && resp.Share.HasId() { + shareId = *resp.Share.Id + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("waiting for share creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model.OutputFormat, model.Async, resourcePoolLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "Share name") + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool the share is assigned to") + cmd.Flags().String(exportPolicyNameFlag, "", "The export policy the share is assigned to") + cmd.Flags().Int64(hardLimitFlag, 0, "The space hard limit for the share") + + err := flags.MarkFlagsRequired(cmd, nameFlag, resourcePoolIdFlag, hardLimitFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + hardLimit := flags.FlagToInt64Pointer(p, cmd, hardLimitFlag) + if hardLimit != nil { + if *hardLimit < 0 { + return nil, &errors.FlagValidationError{ + Flag: hardLimitFlag, + Details: "must be a positive integer", + } + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Name: flags.FlagToStringValue(p, cmd, nameFlag), + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + ExportPolicyName: flags.FlagToStringPointer(p, cmd, exportPolicyNameFlag), + HardLimit: hardLimit, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiCreateShareRequest { + req := apiClient.CreateShare(ctx, model.ProjectId, model.Region, model.ResourcePoolId) + req = req.CreateSharePayload( + sfs.CreateSharePayload{ + Name: utils.Ptr(model.Name), + ExportPolicyName: sfs.NewNullableString(model.ExportPolicyName), + SpaceHardLimitGigabytes: model.HardLimit, + }, + ) + return req +} + +func outputResult(p *print.Printer, outputFormat string, async bool, resourcePoolLabel string, item *sfs.CreateShareResponse) error { + return p.OutputResult(outputFormat, item, func() error { + if item == nil || item.Share == nil { + p.Outputln("SFS share response is empty") + return nil + } + operation := "Created" + if async { + operation = "Triggered creation of" + } + p.Outputf( + "%s SFS Share %q in resource pool %q.\nShare ID: %s\n", + operation, + utils.PtrString(item.Share.Name), + resourcePoolLabel, + utils.PtrString(item.Share.Id), + ) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/share/create/create_test.go b/internal/cmd/beta/sfs/share/create/create_test.go new file mode 100644 index 000000000..f535093e3 --- /dev/null +++ b/internal/cmd/beta/sfs/share/create/create_test.go @@ -0,0 +1,207 @@ +package create + +import ( + "context" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testName = "test-name" +var testResourcePoolId = uuid.NewString() +var testExportPolicyName = "test-export-policy" +var testHardLimit int64 = 10 + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + nameFlag: testName, + resourcePoolIdFlag: testResourcePoolId, + exportPolicyNameFlag: testExportPolicyName, + hardLimitFlag: strconv.Itoa(int(testHardLimit)), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Name: testName, + ResourcePoolId: testResourcePoolId, + ExportPolicyName: utils.Ptr(testExportPolicyName), + HardLimit: utils.Ptr(testHardLimit), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiCreateShareRequest)) sfs.ApiCreateShareRequest { + request := testClient.CreateShare(testCtx, testProjectId, testRegion, testResourcePoolId) + request = request.CreateSharePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(request *sfs.CreateSharePayload)) sfs.CreateSharePayload { + payload := sfs.CreateSharePayload{ + Name: utils.Ptr(testName), + ExportPolicyName: sfs.NewNullableString(utils.Ptr(testExportPolicyName)), + SpaceHardLimitGigabytes: utils.Ptr(testHardLimit), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, exportPolicyNameFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.ExportPolicyName = nil + }), + }, + { + description: "missing required name", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + { + description: "missing required resourcePoolId", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, resourcePoolIdFlag) + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiCreateShareRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(sfs.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + resourcePoolLabel string + item *sfs.CreateShareResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + item: &sfs.CreateShareResponse{}, + }, + wantErr: false, + }, + { + name: "set empty response share", + args: args{ + item: &sfs.CreateShareResponse{ + Share: &sfs.CreateShareResponseShare{}, + }, + }, + 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.async, tt.args.resourcePoolLabel, tt.args.item); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/share/delete/delete.go b/internal/cmd/beta/sfs/share/delete/delete.go new file mode 100644 index 000000000..7d5221cf7 --- /dev/null +++ b/internal/cmd/beta/sfs/share/delete/delete.go @@ -0,0 +1,134 @@ +package delete + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" + "github.com/stackitcloud/stackit-sdk-go/services/sfs/wait" +) + +const ( + shareIdArg = "SHARE_ID" + + resourcePoolIdFlag = "resource-pool-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string + ShareId string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", shareIdArg), + Short: "Deletes a share", + Long: "Deletes a share.", + Args: args.SingleArg(shareIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a share with ID "xxx" from a resource pool with ID "yyy"`, + "$ stackit beta sfs share delete xxx --resource-pool-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, inputArgs []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, inputArgs) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + shareLabel, err := sfsUtils.GetShareName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get share name: %v", err) + shareLabel = model.ShareId + } else if shareLabel == "" { + shareLabel = model.ShareId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete SFS share %q? (This cannot be undone)", shareLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("delete SFS share: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("waiting for share deletion: %w", err) + } + s.Stop() + } + + operation := "Deleted" + if model.Async { + operation = "Triggered deletion of" + } + + params.Printer.Outputf("%s share %q\n", operation, shareLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool the share is assigned to") + + err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + shareId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ShareId: shareId, + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiDeleteShareRequest { + return apiClient.DeleteShare(ctx, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId) +} diff --git a/internal/cmd/beta/sfs/share/delete/delete_test.go b/internal/cmd/beta/sfs/share/delete/delete_test.go new file mode 100644 index 000000000..60040fc44 --- /dev/null +++ b/internal/cmd/beta/sfs/share/delete/delete_test.go @@ -0,0 +1,186 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testResourcePoolId = uuid.NewString() +var testShareId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + resourcePoolIdFlag: testResourcePoolId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testShareId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ResourcePoolId: testResourcePoolId, + ShareId: testShareId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiDeleteShareRequest)) sfs.ApiDeleteShareRequest { + request := testClient.DeleteShare(testCtx, testProjectId, testRegion, testResourcePoolId, testShareId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "share id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "share id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "missing required resourcePoolId", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, resourcePoolIdFlag) + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiDeleteShareRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/share/describe/describe.go b/internal/cmd/beta/sfs/share/describe/describe.go new file mode 100644 index 000000000..f593f9122 --- /dev/null +++ b/internal/cmd/beta/sfs/share/describe/describe.go @@ -0,0 +1,191 @@ +package describe + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + shareIdArg = "SHARE_ID" + + resourcePoolIdFlag = "resource-pool-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string + ShareId string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", shareIdArg), + Short: "Shows details of a shares", + Long: "Shows details of a shares.", + Args: args.SingleArg(shareIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Describe a shares with ID "xxx" from resource pool with ID "yyy"`, + "$ stackit beta sfs export-policy describe xxx --resource-pool-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, inputArgs []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, inputArgs) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("describe SFS share: %w", err) + } + + resourcePoolLabel, err := sfsUtils.GetResourcePoolName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err) + resourcePoolLabel = model.ResourcePoolId + } else if resourcePoolLabel == "" { + resourcePoolLabel = model.ResourcePoolId + } + + return outputResult(params.Printer, model.OutputFormat, resourcePoolLabel, model.ShareId, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool the share is assigned to") + + err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + shareId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + ShareId: shareId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiGetShareRequest { + return apiClient.GetShare(ctx, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId) +} + +func outputResult(p *print.Printer, outputFormat, resourcePoolLabel, shareId string, share *sfs.GetShareResponse) error { + return p.OutputResult(outputFormat, share, func() error { + if share == nil || share.Share == nil { + p.Outputf("Share %q not found in resource pool %q\n", shareId, resourcePoolLabel) + return nil + } + + var content []tables.Table + + table := tables.NewTable() + table.SetTitle("Share") + item := *share.Share + + table.AddRow("ID", utils.PtrString(item.Id)) + table.AddSeparator() + table.AddRow("NAME", utils.PtrString(item.Name)) + table.AddSeparator() + table.AddRow("STATE", utils.PtrString(item.State)) + table.AddSeparator() + table.AddRow("MOUNT PATH", utils.PtrString(item.MountPath)) + table.AddSeparator() + table.AddRow("HARD LIMIT (GB)", utils.PtrString(item.SpaceHardLimitGigabytes)) + table.AddSeparator() + table.AddRow("CREATED AT", utils.ConvertTimePToDateTimeString(item.CreatedAt)) + + content = append(content, table) + + if item.HasExportPolicy() { + policyTable := tables.NewTable() + policyTable.SetTitle("Export Policy") + + policyTable.SetHeader( + "ID", + "NAME", + "SHARES USING EXPORT POLICY", + "CREATED AT", + ) + + policy := item.ExportPolicy.Get() + + policyTable.AddRow( + utils.PtrString(policy.Id), + utils.PtrString(policy.Name), + utils.PtrString(policy.SharesUsingExportPolicy), + utils.ConvertTimePToDateTimeString(policy.CreatedAt), + ) + + content = append(content, policyTable) + + if policy.Rules != nil && len(*policy.Rules) > 0 { + ruleTable := tables.NewTable() + ruleTable.SetTitle("Export Policy - Rules") + + ruleTable.SetHeader("ID", "ORDER", "DESCRIPTION", "IP ACL", "READ ONLY", "SET UUID", "SUPER USER", "CREATED AT") + + for _, rule := range *policy.Rules { + var description string + if rule.Description != nil { + description = utils.PtrString(rule.Description.Get()) + } + ruleTable.AddRow( + utils.PtrString(rule.Id), + utils.PtrString(rule.Order), + description, + utils.JoinStringPtr(rule.IpAcl, ", "), + utils.PtrString(rule.ReadOnly), + utils.PtrString(rule.SetUuid), + utils.PtrString(rule.SuperUser), + utils.ConvertTimePToDateTimeString(rule.CreatedAt), + ) + ruleTable.AddSeparator() + } + + content = append(content, ruleTable) + } + } + + if err := tables.DisplayTables(p, content); err != nil { + return fmt.Errorf("render tables: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/sfs/share/describe/describe_test.go b/internal/cmd/beta/sfs/share/describe/describe_test.go new file mode 100644 index 000000000..889117485 --- /dev/null +++ b/internal/cmd/beta/sfs/share/describe/describe_test.go @@ -0,0 +1,233 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testResourcePoolId = uuid.NewString() +var testShareId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + resourcePoolIdFlag: testResourcePoolId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testShareId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ResourcePoolId: testResourcePoolId, + ShareId: testShareId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiGetShareRequest)) sfs.ApiGetShareRequest { + request := testClient.GetShare(testCtx, testProjectId, testRegion, testResourcePoolId, testShareId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "share id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "share id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "missing required resourcePoolId", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, resourcePoolIdFlag) + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiGetShareRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + shareId string + resourcePoolLabel string + share *sfs.GetShareResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + share: &sfs.GetShareResponse{}, + }, + wantErr: false, + }, + { + name: "set empty share", + args: args{ + share: &sfs.GetShareResponse{ + Share: &sfs.GetShareResponseShare{}, + }, + }, + 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.resourcePoolLabel, tt.args.shareId, tt.args.share); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/share/list/list.go b/internal/cmd/beta/sfs/share/list/list.go new file mode 100644 index 000000000..e8945cd04 --- /dev/null +++ b/internal/cmd/beta/sfs/share/list/list.go @@ -0,0 +1,158 @@ +package list + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + resourcePoolIdFlag = "resource-pool-id" + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string + Limit *int64 +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all shares of a resource pool", + Long: "Lists all shares of a resource pool.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all shares from resource pool with ID "xxx"`, + "$ stackit beta sfs export-policy list --resource-pool-id xxx", + ), + examples.NewExample( + `List up to 10 shares from resource pool with ID "xxx"`, + "$ stackit beta sfs export-policy list --resource-pool-id xxx --limit 10", + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list SFS share: %w", err) + } + + resourcePoolLabel, err := sfsUtils.GetResourcePoolName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err) + resourcePoolLabel = model.ResourcePoolId + } else if resourcePoolLabel == "" { + resourcePoolLabel = model.ResourcePoolId + } + + // Truncate output + items := utils.GetSliceFromPointer(resp.Shares) + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(params.Printer, model.OutputFormat, resourcePoolLabel, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool the share is assigned to") + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") + + err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be grater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + Limit: limit, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiListSharesRequest { + return apiClient.ListShares(ctx, model.ProjectId, model.Region, model.ResourcePoolId) +} + +func outputResult(p *print.Printer, outputFormat, resourcePoolLabel string, shares []sfs.Share) error { + return p.OutputResult(outputFormat, shares, func() error { + if len(shares) == 0 { + p.Info("No shares found for resource pool %q\n", resourcePoolLabel) + return nil + } + + table := tables.NewTable() + table.SetHeader("ID", "NAME", "STATE", "EXPORT POLICY", "MOUNT PATH", "HARD LIMIT (GB)", "CREATED AT") + + for _, share := range shares { + var policy string + if share.ExportPolicy != nil { + if name, ok := share.ExportPolicy.Get().GetNameOk(); ok { + policy = name + } else if id, ok := share.ExportPolicy.Get().GetIdOk(); ok { + policy = id + } + } + table.AddRow( + utils.PtrString(share.Id), + utils.PtrString(share.Name), + utils.PtrString(share.State), + policy, + utils.PtrString(share.MountPath), + utils.PtrString(share.SpaceHardLimitGigabytes), + utils.ConvertTimePToDateTimeString(share.CreatedAt), + ) + } + p.Outputln(table.Render()) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/share/list/list_test.go b/internal/cmd/beta/sfs/share/list/list_test.go new file mode 100644 index 000000000..7cff82a0d --- /dev/null +++ b/internal/cmd/beta/sfs/share/list/list_test.go @@ -0,0 +1,207 @@ +package list + +import ( + "context" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testResourcePoolId = uuid.NewString() +var testLimit int64 = 10 + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + resourcePoolIdFlag: testResourcePoolId, + limitFlag: strconv.FormatInt(testLimit, 10), + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ResourcePoolId: testResourcePoolId, + Limit: utils.Ptr(testLimit), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiListSharesRequest)) sfs.ApiListSharesRequest { + request := testClient.ListShares(testCtx, testProjectId, testRegion, testResourcePoolId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no flag values", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "missing required resourcePoolId", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, resourcePoolIdFlag) + }), + isValid: false, + }, + { + description: "invalid limit 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + { + description: "invalid limit 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "-1" + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiListSharesRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resourcePoolLabel string + shares []sfs.Share + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty share in shares", + args: args{ + shares: []sfs.Share{{}}, + }, + wantErr: false, + }, + { + name: "set empty shares", + args: args{ + shares: []sfs.Share{}, + }, + 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.resourcePoolLabel, tt.args.shares); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/share/share.go b/internal/cmd/beta/sfs/share/share.go new file mode 100644 index 000000000..1ea180fd2 --- /dev/null +++ b/internal/cmd/beta/sfs/share/share.go @@ -0,0 +1,34 @@ +package share + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/share/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/share/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/share/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/share/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/share/update" + "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: "share", + Short: "Provides functionality for SFS shares", + Long: "Provides functionality for SFS shares.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) +} diff --git a/internal/cmd/beta/sfs/share/update/update.go b/internal/cmd/beta/sfs/share/update/update.go new file mode 100644 index 000000000..f6178e96a --- /dev/null +++ b/internal/cmd/beta/sfs/share/update/update.go @@ -0,0 +1,181 @@ +package update + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" + "github.com/stackitcloud/stackit-sdk-go/services/sfs/wait" +) + +const ( + shareIdArg = "SHARE_ID" + + resourcePoolIdFlag = "resource-pool-id" + exportPolicyNameFlag = "export-policy-name" + hardLimitFlag = "hard-limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ShareId string + ResourcePoolId string + ExportPolicyName *string + HardLimit *int64 +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", shareIdArg), + Short: "Updates a share", + Long: "Updates a share.", + Args: args.SingleArg(shareIdArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update share with ID "xxx" with new export-policy-name "yyy" in resource-pool "zzz"`, + "$ stackit beta sfs share update xxx --export-policy-name yyy --resource-pool-id zzz", + ), + examples.NewExample( + `Update share with ID "xxx" with new space hard limit "50" in resource-pool "yyy"`, + "$ stackit beta sfs share update xxx --hard-limit 50 --resource-pool-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, inputArgs []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, inputArgs) + if err != nil { + return fmt.Errorf("unable to parse input: %w", err) + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + shareLabel, err := sfsUtils.GetShareName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get share name: %v", err) + shareLabel = model.ShareId + } else if shareLabel == "" { + shareLabel = model.ShareId + } + + resourcePoolLabel, err := sfsUtils.GetResourcePoolName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err) + resourcePoolLabel = model.ResourcePoolId + } else if resourcePoolLabel == "" { + resourcePoolLabel = model.ResourcePoolId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update SFS share %q for resource pool %q?", shareLabel, resourcePoolLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update SFS share: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("waiting for share update: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model.OutputFormat, model.Async, resourcePoolLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool the share is assigned to") + cmd.Flags().String(exportPolicyNameFlag, "", "The export policy the share is assigned to") + cmd.Flags().Int64(hardLimitFlag, 0, "The space hard limit for the share") + + err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + shareId := inputArgs[0] + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + hardLimit := flags.FlagToInt64Pointer(p, cmd, hardLimitFlag) + if hardLimit != nil && *hardLimit < 0 { + return nil, &errors.FlagValidationError{ + Flag: hardLimitFlag, + Details: "must be a positive integer", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + ExportPolicyName: flags.FlagToStringPointer(p, cmd, exportPolicyNameFlag), + HardLimit: hardLimit, + ShareId: shareId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiUpdateShareRequest { + req := apiClient.UpdateShare(ctx, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId) + req = req.UpdateSharePayload(sfs.UpdateSharePayload{ + ExportPolicyName: sfs.NewNullableString(model.ExportPolicyName), + SpaceHardLimitGigabytes: model.HardLimit, + }) + return req +} + +func outputResult(p *print.Printer, outputFormat string, async bool, resourcePoolLabel string, item *sfs.UpdateShareResponse) error { + return p.OutputResult(outputFormat, item, func() error { + if item == nil || item.Share == nil { + p.Outputln("SFS share response is empty") + return nil + } + + operation := "Updated" + if async { + operation = "Triggered update of" + } + p.Outputf( + "%s SFS share %q in resource pool %q.\n", + operation, + utils.PtrString(item.Share.Name), + resourcePoolLabel, + ) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/share/update/update_test.go b/internal/cmd/beta/sfs/share/update/update_test.go new file mode 100644 index 000000000..99494e905 --- /dev/null +++ b/internal/cmd/beta/sfs/share/update/update_test.go @@ -0,0 +1,266 @@ +package update + +import ( + "context" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testResourcePoolId = uuid.NewString() +var testShareId = uuid.NewString() +var testHardLimit int64 = 10 +var testExportPolicy = "test-export-policy" + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + resourcePoolIdFlag: testResourcePoolId, + hardLimitFlag: strconv.FormatInt(testHardLimit, 10), + exportPolicyNameFlag: testExportPolicy, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testShareId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ResourcePoolId: testResourcePoolId, + ShareId: testShareId, + HardLimit: utils.Ptr(testHardLimit), + ExportPolicyName: utils.Ptr(testExportPolicy), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiUpdateShareRequest)) sfs.ApiUpdateShareRequest { + request := testClient.UpdateShare(testCtx, testProjectId, testRegion, testResourcePoolId, testShareId) + request = request.UpdateSharePayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(payload *sfs.UpdateSharePayload)) sfs.UpdateSharePayload { + payload := sfs.UpdateSharePayload{ + ExportPolicyName: sfs.NewNullableString(utils.Ptr(testExportPolicy)), + SpaceHardLimitGigabytes: utils.Ptr(testHardLimit), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "only required flags", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, exportPolicyNameFlag) + delete(flagValues, hardLimitFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.ExportPolicyName = nil + model.HardLimit = nil + }), + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "share id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "share id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "missing required resourcePoolId", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, resourcePoolIdFlag) + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiUpdateShareRequest + }{ + { + 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, sfs.NullableString{}), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + resourcePoolLabel string + item *sfs.UpdateShareResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + item: &sfs.UpdateShareResponse{}, + }, + wantErr: false, + }, + { + name: "set empty share", + args: args{ + item: &sfs.UpdateShareResponse{ + Share: &sfs.UpdateShareResponseShare{}, + }, + }, + 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.async, tt.args.resourcePoolLabel, tt.args.item); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/snapshot/create/create.go b/internal/cmd/beta/sfs/snapshot/create/create.go new file mode 100644 index 000000000..e55d902e9 --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/create/create.go @@ -0,0 +1,142 @@ +package create + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + resourcePoolIdFlag = "resource-pool-id" + nameFlag = "name" + commentFlag = "comment" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string + Name string + Comment *string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a new snapshot of a resource pool", + Long: "Creates a new snapshot of a resource pool.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a new snapshot with name "snapshot-name" of a resource pool with ID "xxx"`, + "$ stackit beta sfs snapshot create --name snapshot-name --resource-pool-id xxx", + ), + examples.NewExample( + `Create a new snapshot with name "snapshot-name" and comment "snapshot-comment" of a resource pool with ID "xxx"`, + `$ stackit beta sfs snapshot create --name snapshot-name --resource-pool-id xxx --comment "snapshot-comment"`, + ), + ), + 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 + } + + resourcePoolLabel, err := sfsUtils.GetResourcePoolName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err) + resourcePoolLabel = model.ResourcePoolId + } else if resourcePoolLabel == "" { + resourcePoolLabel = model.ResourcePoolId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a snapshot for resource pool %q?", resourcePoolLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create snapshot: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, model.Name, resourcePoolLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(nameFlag, "", "Snapshot name") + cmd.Flags().String(commentFlag, "", "A comment to add more information to the snapshot") + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool from which the snapshot should be created") + + err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag, nameFlag) + cobra.CheckErr(err) +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiCreateResourcePoolSnapshotRequest { + req := apiClient.CreateResourcePoolSnapshot(ctx, model.ProjectId, model.Region, model.ResourcePoolId) + req = req.CreateResourcePoolSnapshotPayload(sfs.CreateResourcePoolSnapshotPayload{ + Name: utils.Ptr(model.Name), + Comment: sfs.NewNullableString(model.Comment), + }) + return req +} + +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, + Name: flags.FlagToStringValue(p, cmd, nameFlag), + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + Comment: flags.FlagToStringPointer(p, cmd, commentFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat, snapshotLabel, resourcePoolLabel string, resp *sfs.CreateResourcePoolSnapshotResponse) error { + return p.OutputResult(outputFormat, resp, func() error { + if resp == nil || resp.ResourcePoolSnapshot == nil { + p.Outputln("SFS snapshot response is empty") + return nil + } + + p.Outputf( + "Created snapshot %q for resource pool %q.\n", + snapshotLabel, + resourcePoolLabel, + ) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/snapshot/create/create_test.go b/internal/cmd/beta/sfs/snapshot/create/create_test.go new file mode 100644 index 000000000..9ac34a9a8 --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/create/create_test.go @@ -0,0 +1,218 @@ +package create + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testName = "test-name" +var testComment = "test-comment" +var testResourcePoolId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + nameFlag: testName, + resourcePoolIdFlag: testResourcePoolId, + commentFlag: testComment, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + Name: testName, + ResourcePoolId: testResourcePoolId, + Comment: utils.Ptr(testComment), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiCreateResourcePoolSnapshotRequest)) sfs.ApiCreateResourcePoolSnapshotRequest { + request := testClient.CreateResourcePoolSnapshot(testCtx, testProjectId, testRegion, testResourcePoolId) + request = request.CreateResourcePoolSnapshotPayload(fixturePayload()) + for _, mod := range mods { + mod(&request) + } + return request +} + +func fixturePayload(mods ...func(request *sfs.CreateResourcePoolSnapshotPayload)) sfs.CreateResourcePoolSnapshotPayload { + payload := sfs.CreateResourcePoolSnapshotPayload{ + Name: utils.Ptr(testName), + Comment: sfs.NewNullableString( + utils.Ptr(testComment), + ), + } + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "required only", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commentFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Comment = nil + }), + }, + { + description: "missing required name", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, nameFlag) + }), + isValid: false, + }, + { + description: "missing required resourcePoolId", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, resourcePoolIdFlag) + }), + isValid: false, + }, + { + description: "invalid resource pool id 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[resourcePoolIdFlag] = "" + }), + isValid: false, + }, + { + description: "invalid resource pool id 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[resourcePoolIdFlag] = "invalid-resource-pool-id" + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiCreateResourcePoolSnapshotRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + cmp.AllowUnexported(sfs.NullableString{}), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + snapshotLabel string + resourcePoolLabel string + resp *sfs.CreateResourcePoolSnapshotResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + resp: &sfs.CreateResourcePoolSnapshotResponse{}, + }, + wantErr: false, + }, + { + name: "set empty snapshot", + args: args{ + resp: &sfs.CreateResourcePoolSnapshotResponse{ + ResourcePoolSnapshot: &sfs.CreateResourcePoolSnapshotResponseResourcePoolSnapshot{}, + }, + }, + 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.snapshotLabel, tt.args.resourcePoolLabel, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/snapshot/delete/delete.go b/internal/cmd/beta/sfs/snapshot/delete/delete.go new file mode 100644 index 000000000..6ddfc4435 --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/delete/delete.go @@ -0,0 +1,114 @@ +package delete + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + sfsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + snapshotNameArg = "SNAPSHOT_NAME" + + resourcePoolIdFlag = "resource-pool-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string + SnapshotName string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", snapshotNameArg), + Short: "Deletes a snapshot", + Long: "Deletes a snapshot.", + Args: args.SingleArg(snapshotNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Delete a snapshot with "SNAPSHOT_NAME" from resource pool with ID "yyy"`, + "$ stackit beta sfs snapshot delete SNAPSHOT_NAME --resource-pool-id yyy"), + ), + RunE: func(cmd *cobra.Command, inputArgs []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, inputArgs) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + resourcePoolLabel, err := sfsUtils.GetResourcePoolName(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get resource pool name: %v", err) + resourcePoolLabel = model.ResourcePoolId + } else if resourcePoolLabel == "" { + resourcePoolLabel = model.ResourcePoolId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete snapshot %q for resource pool %q?", model.SnapshotName, resourcePoolLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("delete snapshot: %w", err) + } + + params.Printer.Outputf("Deleted snapshot %q from resource pool %q.\n", model.SnapshotName, resourcePoolLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool from which the snapshot should be created") + + err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag) + cobra.CheckErr(err) +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiDeleteResourcePoolSnapshotRequest { + return apiClient.DeleteResourcePoolSnapshot(ctx, model.ProjectId, model.Region, model.ResourcePoolId, model.SnapshotName) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + snapshotName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SnapshotName: snapshotName, + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} diff --git a/internal/cmd/beta/sfs/snapshot/delete/delete_test.go b/internal/cmd/beta/sfs/snapshot/delete/delete_test.go new file mode 100644 index 000000000..3a3048b64 --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/delete/delete_test.go @@ -0,0 +1,188 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testResourcePoolId = uuid.NewString() +var testSnapshotName = "testSnapshot" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testSnapshotName, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + resourcePoolIdFlag: testResourcePoolId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ResourcePoolId: testResourcePoolId, + SnapshotName: testSnapshotName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiDeleteResourcePoolSnapshotRequest)) sfs.ApiDeleteResourcePoolSnapshotRequest { + request := testClient.DeleteResourcePoolSnapshot(testCtx, testProjectId, testRegion, testResourcePoolId, testSnapshotName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "share id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "resource pool invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[resourcePoolIdFlag] = "" + }), + isValid: false, + }, + { + description: "resource pool invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[resourcePoolIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiDeleteResourcePoolSnapshotRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/snapshot/describe/describe.go b/internal/cmd/beta/sfs/snapshot/describe/describe.go new file mode 100644 index 000000000..4d45233fd --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/describe/describe.go @@ -0,0 +1,129 @@ +package describe + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + snapshotNameArg = "SNAPSHOT_NAME" + + resourcePoolIdFlag = "resource-pool-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string + SnapshotName string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", snapshotNameArg), + Short: "Shows details of a snapshot", + Long: "Shows details of a snapshot.", + Args: args.SingleArg(snapshotNameArg, nil), + Example: examples.Build( + examples.NewExample( + `Describe a snapshot with "SNAPSHOT_NAME" from resource pool with ID "yyy"`, + "stackit beta sfs snapshot describe SNAPSHOT_NAME --resource-pool-id yyy", + ), + ), + RunE: func(cmd *cobra.Command, inputArgs []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, inputArgs) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create snapshot: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool from which the snapshot should be created") + + err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag) + cobra.CheckErr(err) +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiGetResourcePoolSnapshotRequest { + return apiClient.GetResourcePoolSnapshot(ctx, model.ProjectId, model.Region, model.ResourcePoolId, model.SnapshotName) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + snapshotName := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SnapshotName: snapshotName, + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat string, resp *sfs.GetResourcePoolSnapshotResponse) error { + return p.OutputResult(outputFormat, resp, func() error { + if resp == nil || resp.ResourcePoolSnapshot == nil { + p.Outputln("Resource pool snapshot response is empty") + return nil + } + + table := tables.NewTable() + + snap := *resp.ResourcePoolSnapshot + table.AddRow("NAME", utils.PtrString(snap.SnapshotName)) + table.AddSeparator() + if snap.Comment != nil { + table.AddRow("COMMENT", utils.PtrString(snap.Comment.Get())) + table.AddSeparator() + } + table.AddRow("RESOURCE POOL ID", utils.PtrString(snap.ResourcePoolId)) + table.AddSeparator() + table.AddRow("SIZE (GB)", utils.PtrString(snap.SizeGigabytes)) + table.AddSeparator() + table.AddRow("LOGICAL SIZE (GB)", utils.PtrString(snap.LogicalSizeGigabytes)) + table.AddSeparator() + table.AddRow("CREATED AT", utils.ConvertTimePToDateTimeString(snap.CreatedAt)) + table.AddSeparator() + + p.Outputln(table.Render()) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/snapshot/describe/describe_test.go b/internal/cmd/beta/sfs/snapshot/describe/describe_test.go new file mode 100644 index 000000000..f307c1f19 --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/describe/describe_test.go @@ -0,0 +1,233 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testResourcePoolId = uuid.NewString() +var testSnapshotName = "testSnapshotName" + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testSnapshotName, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + resourcePoolIdFlag: testResourcePoolId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ResourcePoolId: testResourcePoolId, + SnapshotName: testSnapshotName, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiGetResourcePoolSnapshotRequest)) sfs.ApiGetResourcePoolSnapshotRequest { + request := testClient.GetResourcePoolSnapshot(testCtx, testProjectId, testRegion, testResourcePoolId, testSnapshotName) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, projectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[projectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "share id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "resource pool invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[resourcePoolIdFlag] = "" + }), + isValid: false, + }, + { + description: "resource pool invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[resourcePoolIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiGetResourcePoolSnapshotRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp *sfs.GetResourcePoolSnapshotResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + resp: &sfs.GetResourcePoolSnapshotResponse{}, + }, + wantErr: false, + }, + { + name: " set empty snapshot", + args: args{ + resp: &sfs.GetResourcePoolSnapshotResponse{ + ResourcePoolSnapshot: &sfs.GetResourcePoolSnapshotResponseResourcePoolSnapshot{}, + }, + }, + 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.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/snapshot/list/list.go b/internal/cmd/beta/sfs/snapshot/list/list.go new file mode 100644 index 000000000..d2caf7b58 --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/list/list.go @@ -0,0 +1,148 @@ +package list + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/sfs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + resourcePoolIdFlag = "resource-pool-id" + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + ResourcePoolId string + Limit *int64 +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists all snapshots of a resource pool", + Long: "Lists all snapshots of a resource pool.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all snapshots of a resource pool with ID "xxx"`, + "$ stackit beta sfs snapshot list --resource-pool-id xxx", + ), + ), + 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 + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("list snapshot: %w", err) + } + + // Truncate output + items := utils.GetSliceFromPointer(resp.ResourcePoolSnapshots) + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(params.Printer, model.OutputFormat, items) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), resourcePoolIdFlag, "The resource pool from which the snapshot should be created") + cmd.Flags().Int64(limitFlag, 0, "Number of snapshots to list") + + err := flags.MarkFlagsRequired(cmd, resourcePoolIdFlag) + cobra.CheckErr(err) +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *sfs.APIClient) sfs.ApiListResourcePoolSnapshotsRequest { + req := apiClient.ListResourcePoolSnapshots(ctx, model.ProjectId, model.Region, model.ResourcePoolId) + return req +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + ResourcePoolId: flags.FlagToStringValue(p, cmd, resourcePoolIdFlag), + Limit: limit, + } + + p.DebugInputModel(model) + return &model, nil +} + +func outputResult(p *print.Printer, outputFormat string, resp []sfs.ResourcePoolSnapshot) error { + return p.OutputResult(outputFormat, resp, func() error { + if len(resp) == 0 { + p.Outputln("No snapshots found") + return nil + } + table := tables.NewTable() + table.SetHeader( + "NAME", + "COMMENT", + "RESOURCE POOL ID", + "SIZE (GB)", + "LOGICAL SIZE (GB)", + "CREATED AT", + ) + + for _, snap := range resp { + var comment string + if snap.Comment != nil { + comment = utils.PtrString(snap.Comment.Get()) + } + table.AddRow( + utils.PtrString(snap.SnapshotName), + comment, + utils.PtrString(snap.ResourcePoolId), + utils.PtrString(snap.SizeGigabytes), + utils.PtrString(snap.LogicalSizeGigabytes), + utils.ConvertTimePToDateTimeString(snap.CreatedAt), + ) + } + + p.Outputln(table.Render()) + return nil + }) +} diff --git a/internal/cmd/beta/sfs/snapshot/list/list_test.go b/internal/cmd/beta/sfs/snapshot/list/list_test.go new file mode 100644 index 000000000..3c63ed05c --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/list/list_test.go @@ -0,0 +1,173 @@ +package list + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +var projectIdFlag = globalflags.ProjectIdFlag +var regionFlag = globalflags.RegionFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &sfs.APIClient{} + +var testProjectId = uuid.NewString() +var testRegion = "eu01" + +var testResourcePoolId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + projectIdFlag: testProjectId, + regionFlag: testRegion, + + resourcePoolIdFlag: testResourcePoolId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + Region: testRegion, + }, + ResourcePoolId: testResourcePoolId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *sfs.ApiListResourcePoolSnapshotsRequest)) sfs.ApiListResourcePoolSnapshotsRequest { + request := testClient.ListResourcePoolSnapshots(testCtx, testProjectId, testRegion, testResourcePoolId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no flags", + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "invalid resource pool id 1", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[resourcePoolIdFlag] = "" + }), + isValid: false, + }, + { + description: "invalid resource pool id 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[resourcePoolIdFlag] = "invalid-resource-pool-id" + }), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest sfs.ApiListResourcePoolSnapshotsRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + resp []sfs.ResourcePoolSnapshot + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + resp: []sfs.ResourcePoolSnapshot{}, + }, + wantErr: false, + }, + { + name: "set empty snapshot", + args: args{ + resp: []sfs.ResourcePoolSnapshot{{}}, + }, + 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.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/sfs/snapshot/snapshot.go b/internal/cmd/beta/sfs/snapshot/snapshot.go new file mode 100644 index 000000000..aab304c52 --- /dev/null +++ b/internal/cmd/beta/sfs/snapshot/snapshot.go @@ -0,0 +1,32 @@ +package snapshot + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs/snapshot/list" + "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: "snapshot", + Short: "Provides functionality for SFS snapshots", + Long: "Provides functionality for SFS snapshots.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) +} diff --git a/internal/cmd/config/profile/import/template/profile.json b/internal/cmd/config/profile/import/template/profile.json index dbc0bad02..fd14150d7 100644 --- a/internal/cmd/config/profile/import/template/profile.json +++ b/internal/cmd/config/profile/import/template/profile.json @@ -26,6 +26,7 @@ "service_account_custom_endpoint": "", "service_enablement_custom_endpoint": "", "session_time_limit": "12h", + "sfs_custom_endpoint": "", "ske_custom_endpoint": "", "sqlserverflex_custom_endpoint": "", "token_custom_endpoint": "", diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index b23fbba9b..cf81c4906 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -49,6 +49,7 @@ const ( iaasCustomEndpointFlag = "iaas-custom-endpoint" tokenCustomEndpointFlag = "token-custom-endpoint" intakeCustomEndpointFlag = "intake-custom-endpoint" + sfsCustomEndpointFlag = "sfs-custom-endpoint" ) type inputModel struct { @@ -164,6 +165,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(iaasCustomEndpointFlag, "", "IaaS API base URL, used in calls to this API") cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication.") cmd.Flags().String(intakeCustomEndpointFlag, "", "Intake API base URL, used in calls to this API") + cmd.Flags().String(sfsCustomEndpointFlag, "", "SFS API base URL, used in calls to this API") err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) cobra.CheckErr(err) @@ -224,6 +226,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.IntakeCustomEndpointKey, cmd.Flags().Lookup(intakeCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.SfsCustomEndpointKey, cmd.Flags().Lookup(sfsCustomEndpointFlag)) + cobra.CheckErr(err) } func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index a269e867b..a3ce21e73 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -48,6 +48,7 @@ const ( serverBackupCustomEndpointFlag = "serverbackup-custom-endpoint" serverOsUpdateCustomEndpointFlag = "server-osupdate-custom-endpoint" runCommandCustomEndpointFlag = "runcommand-custom-endpoint" + sfsCustomEndpointFlag = "sfs-custom-endpoint" skeCustomEndpointFlag = "ske-custom-endpoint" sqlServerFlexCustomEndpointFlag = "sqlserverflex-custom-endpoint" iaasCustomEndpointFlag = "iaas-custom-endpoint" @@ -87,6 +88,7 @@ type inputModel struct { RunCommandCustomEndpoint bool ServiceAccountCustomEndpoint bool ServiceEnablementCustomEndpoint bool + SfsCustomEndpoint bool SKECustomEndpoint bool SQLServerFlexCustomEndpoint bool IaaSCustomEndpoint bool @@ -218,6 +220,9 @@ func NewCmd(params *types.CmdParams) *cobra.Command { if model.IntakeCustomEndpoint { viper.Set(config.IntakeCustomEndpointKey, "") } + if model.SfsCustomEndpoint { + viper.Set(config.SfsCustomEndpointKey, "") + } err := config.Write() if err != nil { @@ -267,6 +272,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(iaasCustomEndpointFlag, false, "IaaS API base URL. If unset, uses the default base URL") cmd.Flags().Bool(tokenCustomEndpointFlag, false, "Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication.") cmd.Flags().Bool(intakeCustomEndpointFlag, false, "Intake API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(sfsCustomEndpointFlag, false, "SFS API base URL. If unset, uses the default base URL") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { @@ -303,6 +309,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { ServerOsUpdateCustomEndpoint: flags.FlagToBoolValue(p, cmd, serverOsUpdateCustomEndpointFlag), RunCommandCustomEndpoint: flags.FlagToBoolValue(p, cmd, runCommandCustomEndpointFlag), SKECustomEndpoint: flags.FlagToBoolValue(p, cmd, skeCustomEndpointFlag), + SfsCustomEndpoint: flags.FlagToBoolValue(p, cmd, sfsCustomEndpointFlag), SQLServerFlexCustomEndpoint: flags.FlagToBoolValue(p, cmd, sqlServerFlexCustomEndpointFlag), IaaSCustomEndpoint: flags.FlagToBoolValue(p, cmd, iaasCustomEndpointFlag), TokenCustomEndpoint: flags.FlagToBoolValue(p, cmd, tokenCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index c356af35b..4ebb6cde7 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -40,6 +40,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool serverBackupCustomEndpointFlag: true, serverOsUpdateCustomEndpointFlag: true, runCommandCustomEndpointFlag: true, + sfsCustomEndpointFlag: true, skeCustomEndpointFlag: true, sqlServerFlexCustomEndpointFlag: true, iaasCustomEndpointFlag: true, @@ -81,6 +82,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { ServerBackupCustomEndpoint: true, ServerOsUpdateCustomEndpoint: true, RunCommandCustomEndpoint: true, + SfsCustomEndpoint: true, SKECustomEndpoint: true, SQLServerFlexCustomEndpoint: true, IaaSCustomEndpoint: true, @@ -138,6 +140,7 @@ func TestParseInput(t *testing.T) { model.ServerBackupCustomEndpoint = false model.ServerOsUpdateCustomEndpoint = false model.RunCommandCustomEndpoint = false + model.SfsCustomEndpoint = false model.SKECustomEndpoint = false model.SQLServerFlexCustomEndpoint = false model.IaaSCustomEndpoint = false @@ -245,6 +248,16 @@ func TestParseInput(t *testing.T) { model.ServiceAccountCustomEndpoint = false }), }, + { + description: "sfs custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[sfsCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.SfsCustomEndpoint = false + }), + }, { description: "ske custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 68ca2ee8c..03170f650 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -43,6 +43,7 @@ const ( ServerBackupCustomEndpointKey = "serverbackup_custom_endpoint" ServerOsUpdateCustomEndpointKey = "serverosupdate_custom_endpoint" RunCommandCustomEndpointKey = "runcommand_custom_endpoint" + SfsCustomEndpointKey = "sfs_custom_endpoint" SKECustomEndpointKey = "ske_custom_endpoint" SQLServerFlexCustomEndpointKey = "sqlserverflex_custom_endpoint" IaaSCustomEndpointKey = "iaas_custom_endpoint" diff --git a/internal/pkg/config/template/test_profile.json b/internal/pkg/config/template/test_profile.json index dbc0bad02..fd14150d7 100644 --- a/internal/pkg/config/template/test_profile.json +++ b/internal/pkg/config/template/test_profile.json @@ -26,6 +26,7 @@ "service_account_custom_endpoint": "", "service_enablement_custom_endpoint": "", "session_time_limit": "12h", + "sfs_custom_endpoint": "", "ske_custom_endpoint": "", "sqlserverflex_custom_endpoint": "", "token_custom_endpoint": "", diff --git a/internal/pkg/services/sfs/client/client.go b/internal/pkg/services/sfs/client/client.go new file mode 100644 index 000000000..3dc2ef801 --- /dev/null +++ b/internal/pkg/services/sfs/client/client.go @@ -0,0 +1,14 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" + + "github.com/spf13/viper" +) + +func ConfigureClient(p *print.Printer, cliVersion string) (*sfs.APIClient, error) { + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.SfsCustomEndpointKey), false, genericclient.CreateApiClient[*sfs.APIClient](sfs.NewAPIClient)) +} diff --git a/internal/pkg/services/sfs/utils/utils.go b/internal/pkg/services/sfs/utils/utils.go new file mode 100644 index 000000000..2507a512e --- /dev/null +++ b/internal/pkg/services/sfs/utils/utils.go @@ -0,0 +1,47 @@ +package utils + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +type SfsClient interface { + GetShareExportPolicyExecute(ctx context.Context, projectId string, region string, policyId string) (*sfs.GetShareExportPolicyResponse, error) + GetShareExecute(ctx context.Context, projectId, region, resourcePoolId, shareId string) (*sfs.GetShareResponse, error) + GetResourcePoolExecute(ctx context.Context, projectId, region, resourcePoolId string) (*sfs.GetResourcePoolResponse, error) +} + +func GetShareName(ctx context.Context, client SfsClient, projectId, region, resourcePoolId, shareId string) (string, error) { + resp, err := client.GetShareExecute(ctx, projectId, region, resourcePoolId, shareId) + if err != nil { + return "", fmt.Errorf("get share: %w", err) + } + if resp != nil && resp.Share != nil && resp.Share.Name != nil { + return *resp.Share.Name, nil + } + return "", nil +} + +func GetExportPolicyName(ctx context.Context, apiClient SfsClient, projectId, region, policyId string) (string, error) { + resp, err := apiClient.GetShareExportPolicyExecute(ctx, projectId, region, policyId) + if err != nil { + return "", fmt.Errorf("get share export policy: %w", err) + } + if resp != nil && resp.ShareExportPolicy != nil && resp.ShareExportPolicy.Name != nil { + return *resp.ShareExportPolicy.Name, nil + } + return "", nil +} + +func GetResourcePoolName(ctx context.Context, client SfsClient, projectId, region, resourcePoolId string) (string, error) { + resp, err := client.GetResourcePoolExecute(ctx, projectId, region, resourcePoolId) + if err != nil { + return "", fmt.Errorf("get resource pool: %w", err) + } + if resp != nil && resp.ResourcePool != nil && resp.ResourcePool.Name != nil { + return *resp.ResourcePool.Name, nil + } + return "", nil +} diff --git a/internal/pkg/services/sfs/utils/utils_test.go b/internal/pkg/services/sfs/utils/utils_test.go new file mode 100644 index 000000000..de4dbe11f --- /dev/null +++ b/internal/pkg/services/sfs/utils/utils_test.go @@ -0,0 +1,206 @@ +package utils + +import ( + "context" + "fmt" + "testing" + + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/sfs" +) + +const ( + testShareName = "share-name" + testResourcePoolName = "resource-pool-name" + testExportPolicyName = "export-policy-name" + testSnapshotName = "snapshot-name" + testRegion = "eu01" +) + +var ( + testPolicyId = uuid.NewString() + testProjectId = uuid.NewString() +) + +type sfsClientMocked struct { + getShareFails bool + getShareResp *sfs.GetShareResponse + getResourcePoolFails bool + getResourcePoolResp *sfs.GetResourcePoolResponse + getExportPolicyFails bool + getExportPolicyResp *sfs.GetShareExportPolicyResponse +} + +func (s *sfsClientMocked) GetShareExecute(_ context.Context, _, _, _, _ string) (*sfs.GetShareResponse, error) { + if s.getShareFails { + return nil, fmt.Errorf("could not get share") + } + return s.getShareResp, nil +} + +func (s *sfsClientMocked) GetResourcePoolExecute(_ context.Context, _, _, _ string) (*sfs.GetResourcePoolResponse, error) { + if s.getResourcePoolFails { + return nil, fmt.Errorf("could not get resource pool") + } + return s.getResourcePoolResp, nil +} + +func (s *sfsClientMocked) GetShareExportPolicyExecute(_ context.Context, _, _, _ string) (*sfs.GetShareExportPolicyResponse, error) { + if s.getExportPolicyFails { + return nil, fmt.Errorf("could not get export policy") + } + return s.getExportPolicyResp, nil +} + +func TestGetExportPolicyName(t *testing.T) { + tests := []struct { + description string + getExportPolicyResp *sfs.GetShareExportPolicyResponse + getExportPolicyFails bool + isValid bool + expectedOutput string + }{ + { + description: "base", + getExportPolicyResp: &sfs.GetShareExportPolicyResponse{ + ShareExportPolicy: &sfs.GetShareExportPolicyResponseShareExportPolicy{ + Name: utils.Ptr(testExportPolicyName), + }, + }, + isValid: true, + expectedOutput: testExportPolicyName, + }, + { + description: "get export policy fails", + getExportPolicyFails: true, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &sfsClientMocked{ + getExportPolicyFails: tt.getExportPolicyFails, + getExportPolicyResp: tt.getExportPolicyResp, + } + + output, err := GetExportPolicyName(context.Background(), client, testProjectId, testRegion, testPolicyId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %s, got %s", tt.expectedOutput, output) + } + }) + } +} + +func TestGetShareName(t *testing.T) { + tests := []struct { + description string + getShareResp *sfs.GetShareResponse + getShareFails bool + isValid bool + expectedOutput string + }{ + { + description: "base", + getShareResp: &sfs.GetShareResponse{ + Share: &sfs.GetShareResponseShare{ + Name: utils.Ptr(testShareName), + }, + }, + isValid: true, + expectedOutput: testShareName, + }, + { + description: "get share fails", + getShareFails: true, + isValid: false, + expectedOutput: "", + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &sfsClientMocked{ + getShareFails: tt.getShareFails, + getShareResp: tt.getShareResp, + } + + output, err := GetShareName(context.Background(), client, testProjectId, testRegion, "", "") + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %s, got %s", tt.expectedOutput, output) + } + }) + } +} + +func TestGetResourcePoolName(t *testing.T) { + tests := []struct { + description string + getResourcePoolResp *sfs.GetResourcePoolResponse + getResourcePoolFails bool + isValid bool + expectedOutput string + }{ + { + description: "base", + getResourcePoolResp: &sfs.GetResourcePoolResponse{ + ResourcePool: &sfs.GetResourcePoolResponseResourcePool{ + Name: utils.Ptr(testResourcePoolName), + }, + }, + isValid: true, + expectedOutput: testResourcePoolName, + }, + { + description: "get resource pool fails", + getResourcePoolFails: true, + isValid: false, + expectedOutput: "", + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &sfsClientMocked{ + getResourcePoolResp: tt.getResourcePoolResp, + getResourcePoolFails: tt.getResourcePoolFails, + } + + output, err := GetResourcePoolName(context.Background(), client, testProjectId, testRegion, "") + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %s, got %s", tt.expectedOutput, output) + } + }) + } +} diff --git a/internal/pkg/testutils/options.go b/internal/pkg/testutils/options.go new file mode 100644 index 000000000..03d6dab2a --- /dev/null +++ b/internal/pkg/testutils/options.go @@ -0,0 +1,16 @@ +package testutils + +import "github.com/google/go-cmp/cmp" + +type Option struct { + cmpOptions []cmp.Option +} + +type TestingOption func(options *Option) error + +func WithCmpOptions(cmpOptions ...cmp.Option) TestingOption { + return func(options *Option) error { + options.cmpOptions = append(options.cmpOptions, cmpOptions...) + return nil + } +} diff --git a/internal/pkg/testutils/testutils.go b/internal/pkg/testutils/testutils.go index f9ac93524..1a045cfbf 100644 --- a/internal/pkg/testutils/testutils.go +++ b/internal/pkg/testutils/testutils.go @@ -19,6 +19,19 @@ func TestParseInput[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobr // TestParseInputWithAdditionalFlags centralizes the logic to test a combination of inputs (arguments, flags) for a cobra command. // It allows to pass multiple instances of a single flag to the cobra command using the `additionalFlagValues` parameter. func TestParseInputWithAdditionalFlags[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, additionalFlagValues map[string][]string, isValid bool) { + TestParseInputWithOptions(t, cmdFactory, parseInputFunc, expectedModel, argValues, flagValues, additionalFlagValues, isValid, nil) +} + +func TestParseInputWithOptions[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, additionalFlagValues map[string][]string, isValid bool, testingOptions []TestingOption) { + opts := Option{} + for _, option := range testingOptions { + err := option(&opts) + if err != nil { + t.Errorf("Configuring testing options: %v", err) + return + } + } + p := print.NewPrinter() cmd := cmdFactory(&types.CmdParams{Printer: p}) err := globalflags.Configure(cmd.Flags()) @@ -85,7 +98,7 @@ func TestParseInputWithAdditionalFlags[T any](t *testing.T, cmdFactory func(*typ if !isValid { t.Fatalf("did not fail on invalid input") } - diff := cmp.Diff(model, expectedModel) + diff := cmp.Diff(model, expectedModel, opts.cmpOptions...) if diff != "" { t.Fatalf("Data does not match: %s", diff) } From 0e1ade048cdf0c18ebd4ceed75a9ba1a15b2e726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:37:03 +0100 Subject: [PATCH 588/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex (#1198) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 79cf8ba04..1735cb211 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 - github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4 + github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.5 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.3 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 diff --git a/go.sum b/go.sum index d87994781..92e6796ff 100644 --- a/go.sum +++ b/go.sum @@ -620,8 +620,8 @@ github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+Ft github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3/go.mod h1:305j9bvzJ+3c4csOw4SUfLSSxRbkpL0osbvqMI89FeM= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOwjKMWpKl0nrqiq7psTf4NJv0IKgwTkc= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3/go.mod h1:TMl5WcpjzUiAlLWaxMKbu9ysDzFziSPgg4xLxj9jjfY= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4 h1:4LA0Mw7Y8swLRQBvQ/JRv1fUSlnrIHilWklX4v3SZ0A= -github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.4/go.mod h1:G/UD3tzPzzu79MiFWUYqogxdLMB+YArNHR6Yqz7Cqr0= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.5 h1:tPISli81nuvLc5DPqgpvYPSjTySV0wXtMtkfdNXG4CU= +github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.5/go.mod h1:G/UD3tzPzzu79MiFWUYqogxdLMB+YArNHR6Yqz7Cqr0= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 h1:nsC6oA1whA4ibxEuD+0Osngmnpz8dLdV6bv+9jYP4Eo= github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2/go.mod h1:WA6QlAAQ8aaw81W0VSVoDrxOfchGkdtmn2jQL/ub/50= github.com/stackitcloud/stackit-sdk-go/services/observability v0.15.1 h1:zk+47GhutK2ajO4Yiek0laGm2PdXvY8BvFZc8yHFnSE= From c7dada1356cdf675d1384e4f0cc945b3505ae59e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 15:46:13 +0000 Subject: [PATCH 589/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex (#1200) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1735cb211..ae7b1e7d3 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4 github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 - github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 + github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.4.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.31.0 golang.org/x/oauth2 v0.34.0 diff --git a/go.sum b/go.sum index 92e6796ff..e968f4abe 100644 --- a/go.sum +++ b/go.sum @@ -652,8 +652,8 @@ github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0 h1:DRp1p0Gb1YZSnFXgki github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0/go.mod h1:XHOtGgBwwCqPSoQt2ojIRb/BeOd4kICwb9RuMXXFGt8= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 h1:HVlBylGwXVR3qDUGwUMqofAcLEawRaWSgeYXbyAcN1E= github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1/go.mod h1:NzcTU5GGlUF6Lys3Ra7ylRj4ZKxJr3f/29/yoE5tjPI= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4 h1:IUhMJH9fQ+CaMas+5bbnrH7m1Hadf1vWoUtu9KeAEFM= -github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.3.4/go.mod h1:fd13ANCU/Pye8uDd/6E0I605+6PYfHuVIQpPEK2Ph6c= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.4.0 h1:KgIRTw4gpxx8qoiaLGLbXPVDcBgCxPl60gigw+tizYc= +github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.4.0/go.mod h1:fd13ANCU/Pye8uDd/6E0I605+6PYfHuVIQpPEK2Ph6c= github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g= github.com/stbenjam/no-sprintf-host-port v0.3.1/go.mod h1:ODbZesTCHMVKthBHskvUUexdcNHAQRXk9NpSsL8p/HQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 68b9c01b55bef7a5f52956fed66b81d0f614ad90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 08:05:12 +0100 Subject: [PATCH 590/619] chore(deps): bump github.com/jedib0t/go-pretty/v6 from 6.7.7 to 6.7.8 (#1206) Bumps [github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty) from 6.7.7 to 6.7.8. - [Release notes](https://github.com/jedib0t/go-pretty/releases) - [Commits](https://github.com/jedib0t/go-pretty/compare/v6.7.7...v6.7.8) --- updated-dependencies: - dependency-name: github.com/jedib0t/go-pretty/v6 dependency-version: 6.7.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ae7b1e7d3..b85766caa 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jedib0t/go-pretty/v6 v6.7.7 + github.com/jedib0t/go-pretty/v6 v6.7.8 github.com/lmittmann/tint v1.1.2 github.com/mattn/go-colorable v0.1.14 github.com/spf13/cobra v1.10.2 diff --git a/go.sum b/go.sum index e968f4abe..1b883da1c 100644 --- a/go.sum +++ b/go.sum @@ -371,8 +371,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jedib0t/go-pretty/v6 v6.7.7 h1:Y1Id3lJ3k4UB8uwWWy3l8EVFnUlx5chR5+VbsofPNX0= -github.com/jedib0t/go-pretty/v6 v6.7.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.7.8 h1:BVYrDy5DPBA3Qn9ICT+PokP9cvCv1KaHv2i+Hc8sr5o= +github.com/jedib0t/go-pretty/v6 v6.7.8/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= From c1f2d3b504cac03864d561de0e63997d1d3e252d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 07:14:11 +0000 Subject: [PATCH 591/619] chore(deps): bump renovatebot/github-action from 44.2.0 to 44.2.3 (#1209) Bumps [renovatebot/github-action](https://github.com/renovatebot/github-action) from 44.2.0 to 44.2.3. - [Release notes](https://github.com/renovatebot/github-action/releases) - [Changelog](https://github.com/renovatebot/github-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/renovatebot/github-action/compare/v44.2.0...v44.2.3) --- updated-dependencies: - dependency-name: renovatebot/github-action dependency-version: 44.2.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index d0c4954cf..4716838ca 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Self-hosted Renovate - uses: renovatebot/github-action@v44.2.0 + uses: renovatebot/github-action@v44.2.3 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From 42aa2c641af73e26ea4f2c19c16a45cc1b79626c Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:19:22 +0100 Subject: [PATCH 592/619] fix(deps): update stackit sdk modules (#1208) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index b85766caa..a5d9ac196 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.20.1 github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3 - github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.1 + github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 @@ -261,7 +261,7 @@ require ( github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect - github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2 + github.com/stackitcloud/stackit-sdk-go/services/kms v1.2.0 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 diff --git a/go.sum b/go.sum index 1b883da1c..4f2a3b049 100644 --- a/go.sum +++ b/go.sum @@ -602,8 +602,8 @@ github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98e github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3 h1:DqRtyuIb34/x9C3/sT7Uz5xrD0TQOL3ERnDOS1gst4E= github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.1 h1:Z7K6CfjbWSAzFbAXFzxefRBap/dujpK2TZgJqBUZ8NQ= -github.com/stackitcloud/stackit-sdk-go/services/authorization v0.10.1/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 h1:4YFY5PG4vP/NiEP1uxCwh+kQHEU7iHG6syuFD7NPqcw= +github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3/go.mod h1:BNiIZkDqwSV1LkWDjMKxVb9pxQ/HMIsXJ0AQ8pFoAo4= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjUZg5qprXG5rDmPnM6dsvplMk/vg= @@ -612,8 +612,8 @@ github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 h1:U/x0tc487X9msMS5y github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0/go.mod h1:6+5+RCDfU7eQN3+/SGdOtx7Bq9dEa2FrHz/jflgY1M4= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 h1:WCSuqD6AoOD/D8u+YU3brMhQwYZYxu809o3uW5SH4HA= github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1/go.mod h1:qq6rNvOuSQ1HDZie8gy4Wzso+a9DrgOODNPyKeBljK4= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2 h1:YsgqwU+qc+AL5yOaXIb/Va3ANAjXDnSJtIflZ6EeM0w= -github.com/stackitcloud/stackit-sdk-go/services/kms v1.1.2/go.mod h1:sHMFoYvVrkRZcH13DkLvp48nW+ssRVVVuwqJHDGpa5M= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.2.0 h1:Ar2n9GKmrTN80G/Ta1R+fL5aX5nEoxL6ODVJl3emzho= +github.com/stackitcloud/stackit-sdk-go/services/kms v1.2.0/go.mod h1:sHMFoYvVrkRZcH13DkLvp48nW+ssRVVVuwqJHDGpa5M= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2 h1:DwwRMzvnKWTbfmLvq2xe+mYhv5fA1AwWdQGznI05sGc= github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2/go.mod h1:dYmNdSNDKUG+E0SwuFWu+c8CuMBF/l6w1bdzAHxQao0= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+FtFDYOm1kv/gJrGBZLjhVOXJOuYfFY= From f0446b49dcedfd8ac05406685c191013875cd9e7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 8 Jan 2026 07:24:25 +0100 Subject: [PATCH 593/619] fix(deps): update module github.com/goccy/go-yaml to v1.19.2 (#1210) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a5d9ac196..abbfb6be5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.0 require ( github.com/fatih/color v1.18.0 - github.com/goccy/go-yaml v1.19.1 + github.com/goccy/go-yaml v1.19.2 github.com/golang-jwt/jwt/v5 v5.3.0 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 4f2a3b049..868cf2f9f 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUW github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/goccy/go-yaml v1.19.1 h1:3rG3+v8pkhRqoQ/88NYNMHYVGYztCOCIZ7UQhu7H+NE= -github.com/goccy/go-yaml v1.19.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godoc-lint/godoc-lint v0.10.2 h1:dksNgK+zebnVlj4Fx83CRnCmPO0qRat/9xfFsir1nfg= From 28776d6baf091856224d9f002390fefe7a67dbe4 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Thu, 8 Jan 2026 07:30:48 +0100 Subject: [PATCH 594/619] chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.8.0 (#1211) Co-authored-by: Renovate Bot --- go.mod | 25 +++++++++++++------------ go.sum | 54 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index abbfb6be5..f0f6cd79e 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,7 @@ require ( 4d63.com/gochecknoglobals v0.2.2 // indirect al.essio.dev/pkg/shellescape v1.5.1 // indirect codeberg.org/chavacava/garif v0.2.0 // indirect + codeberg.org/polyfloyd/go-errorlint v1.9.0 // indirect dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect dev.gaijin.team/go/golib v0.6.0 // indirect github.com/4meepo/tagalign v1.4.3 // indirect @@ -63,15 +64,15 @@ require ( github.com/Antonboom/errname v1.1.1 // indirect github.com/Antonboom/nilnil v1.1.1 // indirect github.com/Antonboom/testifylint v1.6.4 // indirect - github.com/BurntSushi/toml v1.5.0 // indirect + github.com/BurntSushi/toml v1.6.0 // indirect github.com/Djarvur/go-err113 v0.1.1 // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect - github.com/MirrexOne/unqueryvet v1.3.0 // indirect + github.com/MirrexOne/unqueryvet v1.4.0 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect - github.com/alecthomas/chroma/v2 v2.20.0 // indirect + github.com/alecthomas/chroma/v2 v2.21.1 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect - github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alexkohler/prealloc v1.0.1 // indirect github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/alingse/nilnesserr v0.2.0 // indirect @@ -107,8 +108,8 @@ require ( github.com/firefart/nonamedreturns v1.0.6 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.17 // indirect - github.com/go-critic/go-critic v0.14.2 // indirect + github.com/ghostiam/protogetter v0.3.18 // indirect + github.com/go-critic/go-critic v0.14.3 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.2.0 // indirect @@ -119,15 +120,15 @@ require ( github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/godoc-lint/godoc-lint v0.10.2 // indirect + github.com/godoc-lint/godoc-lint v0.11.1 // indirect github.com/gofrs/flock v0.13.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect github.com/golangci/go-printf-func-name v0.1.1 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golangci-lint/v2 v2.7.2 // indirect - github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 // indirect + github.com/golangci/golangci-lint/v2 v2.8.0 // indirect + github.com/golangci/golines v0.14.0 // indirect github.com/golangci/misspell v0.7.0 // indirect github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect @@ -153,8 +154,9 @@ require ( github.com/kunwardeep/paralleltest v1.0.15 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect github.com/ldez/exptostd v0.4.5 // indirect - github.com/ldez/gomoddirectives v0.7.1 // indirect + github.com/ldez/gomoddirectives v0.8.0 // indirect github.com/ldez/grignotin v0.10.1 // indirect + github.com/ldez/structtags v0.6.1 // indirect github.com/ldez/tagliatelle v0.7.2 // indirect github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect @@ -177,7 +179,6 @@ require ( github.com/nishanths/predeclared v0.2.2 // indirect github.com/nunnatsa/ginkgolinter v0.21.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/polyfloyd/go-errorlint v1.8.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect @@ -195,7 +196,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect - github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7 // indirect + github.com/securego/gosec/v2 v2.22.11 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/sonatard/noctx v0.4.0 // indirect diff --git a/go.sum b/go.sum index 868cf2f9f..107ac4d61 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +codeberg.org/polyfloyd/go-errorlint v1.9.0 h1:VkdEEmA1VBpH6ecQoMR4LdphVI3fA4RrCh2an7YmodI= +codeberg.org/polyfloyd/go-errorlint v1.9.0/go.mod h1:GPRRu2LzVijNn4YkrZYJfatQIdS+TrcK8rL5Xs24qw8= dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= @@ -58,25 +60,25 @@ github.com/Antonboom/nilnil v1.1.1/go.mod h1:yCyAmSw3doopbOWhJlVci+HuyNRuHJKIv6V github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ= github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= -github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= +github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g= github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/MirrexOne/unqueryvet v1.3.0 h1:5slWSomgqpYU4zFuZ3NNOfOUxVPlXFDBPAVasZOGlAY= -github.com/MirrexOne/unqueryvet v1.3.0/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= +github.com/MirrexOne/unqueryvet v1.4.0 h1:6KAkqqW2KUnkl9Z0VuTphC3IXRPoFqEkJEtyxxHj5eQ= +github.com/MirrexOne/unqueryvet v1.4.0/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= -github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= +github.com/alecthomas/chroma/v2 v2.21.1 h1:FaSDrp6N+3pphkNKU6HPCiYLgm8dbe5UXIXcoBhZSWA= +github.com/alecthomas/chroma/v2 v2.21.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= -github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= -github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= +github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -84,8 +86,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= -github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= -github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alexkohler/prealloc v1.0.1 h1:A9P1haqowqUxWvU9nk6tQ7YktXIHf+LQM9wPRhuteEE= +github.com/alexkohler/prealloc v1.0.1/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig= github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= @@ -188,10 +190,10 @@ github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sa github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.17 h1:sjGPErP9o7i2Ym+z3LsQzBdLCNaqbYy2iJQPxGXg04Q= -github.com/ghostiam/protogetter v0.3.17/go.mod h1:AivIX1eKA/TcUmzZdzbl+Tb8tjIe8FcyG6JFyemQAH4= -github.com/go-critic/go-critic v0.14.2 h1:PMvP5f+LdR8p6B29npvChUXbD1vrNlKDf60NJtgMBOo= -github.com/go-critic/go-critic v0.14.2/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= +github.com/ghostiam/protogetter v0.3.18 h1:yEpghRGtP9PjKvVXtEzGpYfQj1Wl/ZehAfU6fr62Lfo= +github.com/ghostiam/protogetter v0.3.18/go.mod h1:FjIu5Yfs6FT391m+Fjp3fbAYJ6rkL/J6ySpZBfnODuI= +github.com/go-critic/go-critic v0.14.3 h1:5R1qH2iFeo4I/RJU8vTezdqs08Egi4u5p6vOESA0pog= +github.com/go-critic/go-critic v0.14.3/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -243,8 +245,8 @@ github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godoc-lint/godoc-lint v0.10.2 h1:dksNgK+zebnVlj4Fx83CRnCmPO0qRat/9xfFsir1nfg= -github.com/godoc-lint/godoc-lint v0.10.2/go.mod h1:KleLcHu/CGSvkjUH2RvZyoK1MBC7pDQg4NxMYLcBBsw= +github.com/godoc-lint/godoc-lint v0.11.1 h1:z9as8Qjiy6miRIa3VRymTa+Gt2RLnGICVikcvlUVOaA= +github.com/godoc-lint/godoc-lint v0.11.1/go.mod h1:BAqayheFSuZrEAqCRxgw9MyvsM+S/hZwJbU1s/ejRj8= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -289,10 +291,10 @@ github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarog github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint/v2 v2.7.2 h1:AhBC+YeEueec4AGlIbvPym5C70Thx0JykIqXbdIXWx0= -github.com/golangci/golangci-lint/v2 v2.7.2/go.mod h1:pDijleoBu7e8sejMqyZ3L5n6geqe+cVvOAz2QImqqVc= -github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= -github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= +github.com/golangci/golangci-lint/v2 v2.8.0 h1:wJnr3hJWY3eVzOUcfwbDc2qbi2RDEpvLmQeNFaPSNYA= +github.com/golangci/golangci-lint/v2 v2.8.0/go.mod h1:xl+HafQ9xoP8rzw0z5AwnO5kynxtb80e8u02Ej/47RI= +github.com/golangci/golines v0.14.0 h1:xt9d3RKBjhasA3qpoXs99J2xN2t6eBlpLHt0TrgyyXc= +github.com/golangci/golines v0.14.0/go.mod h1:gf555vPG2Ia7mmy2mzmhVQbVjuK8Orw0maR1G4vVAAQ= github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= @@ -419,10 +421,12 @@ github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0 github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= github.com/ldez/exptostd v0.4.5 h1:kv2ZGUVI6VwRfp/+bcQ6Nbx0ghFWcGIKInkG/oFn1aQ= github.com/ldez/exptostd v0.4.5/go.mod h1:QRjHRMXJrCTIm9WxVNH6VW7oN7KrGSht69bIRwvdFsM= -github.com/ldez/gomoddirectives v0.7.1 h1:FaULkvUIG36hj6chpwa+FdCNGZBsD7/fO+p7CCsM6pE= -github.com/ldez/gomoddirectives v0.7.1/go.mod h1:auDNtakWJR1rC+YX7ar+HmveqXATBAyEK1KYpsIRW/8= +github.com/ldez/gomoddirectives v0.8.0 h1:JqIuTtgvFC2RdH1s357vrE23WJF2cpDCPFgA/TWDGpk= +github.com/ldez/gomoddirectives v0.8.0/go.mod h1:jutzamvZR4XYJLr0d5Honycp4Gy6GEg2mS9+2YX3F1Q= github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o= github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas= +github.com/ldez/structtags v0.6.1 h1:bUooFLbXx41tW8SvkfwfFkkjPYvFFs59AAMgVg6DUBk= +github.com/ldez/structtags v0.6.1/go.mod h1:YDxVSgDy/MON6ariaxLF2X09bh19qL7MtGBN5MrvbdY= github.com/ldez/tagliatelle v0.7.2 h1:KuOlL70/fu9paxuxbeqlicJnCspCRjH0x8FW+NfgYUk= github.com/ldez/tagliatelle v0.7.2/go.mod h1:PtGgm163ZplJfZMZ2sf5nhUT170rSuPgBimoyYtdaSI= github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= @@ -505,8 +509,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.8.0 h1:DL4RestQqRLr8U4LygLw8g2DX6RN1eBJOpa2mzsrl1Q= -github.com/polyfloyd/go-errorlint v1.8.0/go.mod h1:G2W0Q5roxbLCt0ZQbdoxQxXktTjwNyDbEaj3n7jvl4s= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -565,8 +567,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= -github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7 h1:rZg6IGn0ySYZwCX8LHwZoYm03JhG/cVAJJ3O+u3Vclo= -github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7/go.mod h1:9sr22NZO5Kfh7unW/xZxkGYTmj2484/fCiE54gw7UTY= +github.com/securego/gosec/v2 v2.22.11 h1:tW+weM/hCM/GX3iaCV91d5I6hqaRT2TPsFM1+USPXwg= +github.com/securego/gosec/v2 v2.22.11/go.mod h1:KE4MW/eH0GLWztkbt4/7XpyH0zJBBnu7sYB4l6Wn7Mw= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= From 62b8c64e27d28705b8e66f1817c57c1fb0266a1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 18:28:19 +0100 Subject: [PATCH 595/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/alb (#1215) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f0f6cd79e..782ee892f 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.20.1 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 diff --git a/go.sum b/go.sum index 107ac4d61..95d3df2a9 100644 --- a/go.sum +++ b/go.sum @@ -602,8 +602,8 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98edvw2Cd3DcnkepncP3M= github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3 h1:DqRtyuIb34/x9C3/sT7Uz5xrD0TQOL3ERnDOS1gst4E= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.3/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0 h1:RJBgbgZ4w7/e++n7pPTiCwFivll9RHovb4BfR/9CzlA= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 h1:4YFY5PG4vP/NiEP1uxCwh+kQHEU7iHG6syuFD7NPqcw= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= From 6ea5c939c4d0d0d7870a2b38df5cd109f666b1d7 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 12 Jan 2026 07:25:54 +0100 Subject: [PATCH 596/619] fix(deps): update module golang.org/x/mod to v0.32.0 (#1218) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 782ee892f..8a1b31b54 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.4.0 github.com/zalando/go-keyring v0.2.6 - golang.org/x/mod v0.31.0 + golang.org/x/mod v0.32.0 golang.org/x/oauth2 v0.34.0 golang.org/x/term v0.38.0 golang.org/x/text v0.32.0 diff --git a/go.sum b/go.sum index 95d3df2a9..14c31a3cc 100644 --- a/go.sum +++ b/go.sum @@ -794,8 +794,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= -golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 4a30332e961b4afd274a3e7f2f6099f16f54659b Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 12 Jan 2026 07:31:49 +0100 Subject: [PATCH 597/619] fix(deps): update module golang.org/x/term to v0.39.0 (#1219) Co-authored-by: Renovate Bot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 8a1b31b54..40dd1810c 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.32.0 golang.org/x/oauth2 v0.34.0 - golang.org/x/term v0.38.0 + golang.org/x/term v0.39.0 golang.org/x/text v0.32.0 k8s.io/apimachinery v0.34.2 k8s.io/client-go v0.34.2 @@ -272,7 +272,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0 github.com/subosito/gotenv v1.6.0 // indirect - golang.org/x/sys v0.39.0 // indirect + golang.org/x/sys v0.40.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 14c31a3cc..aecacbe58 100644 --- a/go.sum +++ b/go.sum @@ -911,8 +911,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc h1:bH6xUXay0AIFMElXG2rQ4uiE+7ncwtiOdPfYK1NK2XA= golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -921,8 +921,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 8d9cdc46c6d9048afea4718f03cd021b0a513844 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Mon, 12 Jan 2026 08:48:19 +0100 Subject: [PATCH 598/619] fix(deps): update module golang.org/x/text to v0.33.0 (#1220) Co-authored-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 40dd1810c..617c54c23 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( golang.org/x/mod v0.32.0 golang.org/x/oauth2 v0.34.0 golang.org/x/term v0.39.0 - golang.org/x/text v0.32.0 + golang.org/x/text v0.33.0 k8s.io/apimachinery v0.34.2 k8s.io/client-go v0.34.2 ) diff --git a/go.sum b/go.sum index aecacbe58..e3a7f587a 100644 --- a/go.sum +++ b/go.sum @@ -933,8 +933,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From db45e4b3afa802b185e8dbe609db575b04526c44 Mon Sep 17 00:00:00 2001 From: Kai Kummerer <70690427+Kumm-Kai@users.noreply.github.com> Date: Mon, 12 Jan 2026 13:39:01 +0100 Subject: [PATCH 599/619] fix(ske): add profile email to cacheKey on login (#1080) --- internal/cmd/ske/kubeconfig/login/login.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/internal/cmd/ske/kubeconfig/login/login.go b/internal/cmd/ske/kubeconfig/login/login.go index 68775aed3..711ad56bd 100644 --- a/internal/cmd/ske/kubeconfig/login/login.go +++ b/internal/cmd/ske/kubeconfig/login/login.go @@ -19,6 +19,7 @@ import ( "k8s.io/client-go/rest" "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" @@ -150,20 +151,25 @@ func parseClusterConfig(p *print.Printer, cmd *cobra.Command) (*clusterConfig, e if execCredential == nil || execCredential.Spec.Cluster == nil { return nil, fmt.Errorf("ExecCredential contains not all needed fields") } - config := &clusterConfig{} - err = json.Unmarshal(execCredential.Spec.Cluster.Config.Raw, config) + clusterConfig := &clusterConfig{} + err = json.Unmarshal(execCredential.Spec.Cluster.Config.Raw, clusterConfig) if err != nil { return nil, fmt.Errorf("unmarshal: %w", err) } - config.cacheKey = fmt.Sprintf("ske-login-%x", sha256.Sum256([]byte(execCredential.Spec.Cluster.Server))) + authEmail, err := auth.GetAuthEmail() + if err != nil { + return nil, fmt.Errorf("error getting auth email: %w", err) + } + + clusterConfig.cacheKey = fmt.Sprintf("ske-login-%x", sha256.Sum256([]byte(execCredential.Spec.Cluster.Server+"\x00"+authEmail))) // NOTE: Fallback if region is not set in the kubeconfig (this was the case in the past) - if config.Region == "" { - config.Region = globalflags.Parse(p, cmd).Region + if clusterConfig.Region == "" { + clusterConfig.Region = globalflags.Parse(p, cmd).Region } - return config, nil + return clusterConfig, nil } func getCachedKubeConfig(key string) *rest.Config { From 1b5b0c6893c5e5f7b5335964f45e38f5265b69cb Mon Sep 17 00:00:00 2001 From: cgoetz-inovex Date: Mon, 12 Jan 2026 18:31:02 +0100 Subject: [PATCH 600/619] refactor(printer): move AssumeYes logic into printer itself (#1217) relates to STACKITCLI-286 --- internal/cmd/affinity-groups/create/create.go | 10 +++---- internal/cmd/affinity-groups/delete/delete.go | 10 +++---- internal/cmd/beta/alb/create/create.go | 10 +++---- internal/cmd/beta/alb/delete/delete.go | 10 +++---- .../alb/observability-credentials/add/add.go | 10 +++---- .../delete/delete.go | 10 +++---- .../update/update.go | 10 +++---- internal/cmd/beta/alb/pool/update/update.go | 10 +++---- internal/cmd/beta/alb/update/update.go | 10 +++---- .../cmd/beta/intake/runner/create/create.go | 10 +++---- .../cmd/beta/intake/runner/delete/delete.go | 10 +++---- internal/cmd/beta/kms/key/create/create.go | 8 +++--- internal/cmd/beta/kms/key/delete/delete.go | 10 +++---- .../cmd/beta/kms/key/importKey/importKey.go | 10 +++---- internal/cmd/beta/kms/key/restore/restore.go | 10 +++---- internal/cmd/beta/kms/key/rotate/rotate.go | 10 +++---- .../cmd/beta/kms/keyring/create/create.go | 8 +++--- .../cmd/beta/kms/keyring/delete/delete.go | 10 +++---- .../cmd/beta/kms/wrappingkey/create/create.go | 8 +++--- .../cmd/beta/kms/wrappingkey/delete/delete.go | 10 +++---- .../beta/sfs/export-policy/create/create.go | 10 +++---- .../beta/sfs/export-policy/delete/delete.go | 10 +++---- .../beta/sfs/export-policy/update/update.go | 10 +++---- .../beta/sfs/resource-pool/create/create.go | 10 +++---- .../beta/sfs/resource-pool/delete/delete.go | 10 +++---- .../beta/sfs/resource-pool/update/update.go | 10 +++---- internal/cmd/beta/sfs/share/create/create.go | 10 +++---- internal/cmd/beta/sfs/share/delete/delete.go | 10 +++---- internal/cmd/beta/sfs/share/update/update.go | 10 +++---- .../cmd/beta/sfs/snapshot/create/create.go | 10 +++---- .../cmd/beta/sfs/snapshot/delete/delete.go | 10 +++---- .../sqlserverflex/database/create/create.go | 10 +++---- .../sqlserverflex/database/delete/delete.go | 10 +++---- .../sqlserverflex/instance/create/create.go | 10 +++---- .../sqlserverflex/instance/delete/delete.go | 10 +++---- .../sqlserverflex/instance/update/update.go | 10 +++---- .../beta/sqlserverflex/user/create/create.go | 10 +++---- .../beta/sqlserverflex/user/delete/delete.go | 10 +++---- .../user/reset-password/reset_password.go | 10 +++---- internal/cmd/config/profile/delete/delete.go | 10 +++---- internal/cmd/dns/record-set/create/create.go | 10 +++---- internal/cmd/dns/record-set/delete/delete.go | 10 +++---- internal/cmd/dns/record-set/update/update.go | 10 +++---- internal/cmd/dns/zone/clone/clone.go | 10 +++---- internal/cmd/dns/zone/create/create.go | 10 +++---- internal/cmd/dns/zone/delete/delete.go | 10 +++---- internal/cmd/dns/zone/update/update.go | 10 +++---- internal/cmd/git/instance/create/create.go | 10 +++---- internal/cmd/git/instance/delete/delete.go | 10 +++---- internal/cmd/image/create/create.go | 10 +++---- internal/cmd/image/delete/delete.go | 10 +++---- internal/cmd/image/update/update.go | 10 +++---- internal/cmd/key-pair/create/create.go | 10 +++---- internal/cmd/key-pair/delete/delete.go | 10 +++---- internal/cmd/key-pair/update/update.go | 10 +++---- internal/cmd/load-balancer/create/create.go | 10 +++---- internal/cmd/load-balancer/delete/delete.go | 10 +++---- .../observability-credentials/add/add.go | 10 +++---- .../cleanup/cleanup.go | 26 +++++++++---------- .../delete/delete.go | 10 +++---- .../update/update.go | 10 +++---- .../target-pool/add-target/add_target.go | 10 +++---- .../remove-target/remove_target.go | 10 +++---- internal/cmd/load-balancer/update/update.go | 10 +++---- .../cmd/logme/credentials/create/create.go | 10 +++---- .../cmd/logme/credentials/delete/delete.go | 10 +++---- internal/cmd/logme/instance/create/create.go | 10 +++---- internal/cmd/logme/instance/delete/delete.go | 10 +++---- internal/cmd/logme/instance/update/update.go | 10 +++---- .../cmd/mariadb/credentials/create/create.go | 10 +++---- .../cmd/mariadb/credentials/delete/delete.go | 10 +++---- .../cmd/mariadb/instance/create/create.go | 10 +++---- .../cmd/mariadb/instance/delete/delete.go | 10 +++---- .../cmd/mariadb/instance/update/update.go | 10 +++---- .../cmd/mongodbflex/backup/restore/restore.go | 10 +++---- .../backup/update-schedule/update_schedule.go | 10 +++---- .../cmd/mongodbflex/instance/create/create.go | 10 +++---- .../cmd/mongodbflex/instance/delete/delete.go | 10 +++---- .../cmd/mongodbflex/instance/update/update.go | 10 +++---- .../cmd/mongodbflex/user/create/create.go | 10 +++---- .../cmd/mongodbflex/user/delete/delete.go | 10 +++---- .../user/reset-password/reset_password.go | 10 +++---- .../cmd/mongodbflex/user/update/update.go | 10 +++---- internal/cmd/network-area/create/create.go | 12 ++++----- internal/cmd/network-area/delete/delete.go | 10 +++---- .../network-range/create/create.go | 10 +++---- .../network-range/delete/delete.go | 10 +++---- .../cmd/network-area/region/create/create.go | 10 +++---- .../cmd/network-area/region/delete/delete.go | 10 +++---- .../cmd/network-area/region/update/update.go | 10 +++---- .../cmd/network-area/route/create/create.go | 10 +++---- .../cmd/network-area/route/delete/delete.go | 10 +++---- internal/cmd/network-area/update/update.go | 10 +++---- .../cmd/network-interface/create/create.go | 10 +++---- .../cmd/network-interface/delete/delete.go | 10 +++---- .../cmd/network-interface/update/update.go | 10 +++---- internal/cmd/network/create/create.go | 10 +++---- internal/cmd/network/delete/delete.go | 10 +++---- internal/cmd/network/update/update.go | 10 +++---- .../object-storage/bucket/create/create.go | 10 +++---- .../object-storage/bucket/delete/delete.go | 10 +++---- .../credentials-group/create/create.go | 10 +++---- .../credentials-group/delete/delete.go | 10 +++---- .../credentials/create/create.go | 10 +++---- .../credentials/delete/delete.go | 10 +++---- .../cmd/object-storage/disable/disable.go | 10 +++---- internal/cmd/object-storage/enable/enable.go | 10 +++---- .../credentials/create/create.go | 10 +++---- .../credentials/delete/delete.go | 10 +++---- .../public-read-access/disable/disable.go | 10 +++---- .../public-read-access/enable/enable.go | 10 +++---- .../grafana/single-sign-on/disable/disable.go | 10 +++---- .../grafana/single-sign-on/enable/enable.go | 10 +++---- .../observability/instance/create/create.go | 10 +++---- .../observability/instance/delete/delete.go | 10 +++---- .../observability/instance/update/update.go | 10 +++---- .../scrape-config/create/create.go | 10 +++---- .../scrape-config/delete/delete.go | 10 +++---- .../scrape-config/update/update.go | 10 +++---- .../opensearch/credentials/create/create.go | 10 +++---- .../opensearch/credentials/delete/delete.go | 10 +++---- .../cmd/opensearch/instance/create/create.go | 10 +++---- .../cmd/opensearch/instance/delete/delete.go | 10 +++---- .../cmd/opensearch/instance/update/update.go | 10 +++---- internal/cmd/organization/member/add/add.go | 10 +++---- .../cmd/organization/member/remove/remove.go | 16 +++++------- .../backup/update-schedule/update_schedule.go | 10 +++---- .../cmd/postgresflex/instance/clone/clone.go | 10 +++---- .../postgresflex/instance/create/create.go | 10 +++---- .../postgresflex/instance/delete/delete.go | 10 +++---- .../postgresflex/instance/update/update.go | 10 +++---- .../cmd/postgresflex/user/create/create.go | 10 +++---- .../cmd/postgresflex/user/delete/delete.go | 10 +++---- .../user/reset-password/reset_password.go | 10 +++---- .../cmd/postgresflex/user/update/update.go | 10 +++---- internal/cmd/project/create/create.go | 10 +++---- internal/cmd/project/delete/delete.go | 10 +++---- internal/cmd/project/member/add/add.go | 10 +++---- internal/cmd/project/member/remove/remove.go | 16 +++++------- internal/cmd/project/update/update.go | 10 +++---- internal/cmd/public-ip/associate/associate.go | 10 +++---- internal/cmd/public-ip/create/create.go | 10 +++---- internal/cmd/public-ip/delete/delete.go | 10 +++---- .../public-ip/disassociate/disassociate.go | 10 +++---- internal/cmd/public-ip/update/update.go | 10 +++---- .../cmd/rabbitmq/credentials/create/create.go | 10 +++---- .../cmd/rabbitmq/credentials/delete/delete.go | 10 +++---- .../cmd/rabbitmq/instance/create/create.go | 10 +++---- .../cmd/rabbitmq/instance/delete/delete.go | 10 +++---- .../cmd/rabbitmq/instance/update/update.go | 10 +++---- .../cmd/redis/credentials/create/create.go | 10 +++---- .../cmd/redis/credentials/delete/delete.go | 10 +++---- internal/cmd/redis/instance/create/create.go | 10 +++---- internal/cmd/redis/instance/delete/delete.go | 10 +++---- internal/cmd/redis/instance/update/update.go | 10 +++---- internal/cmd/root.go | 5 +++- .../secrets-manager/instance/create/create.go | 10 +++---- .../secrets-manager/instance/delete/delete.go | 10 +++---- .../secrets-manager/instance/update/update.go | 10 +++---- .../cmd/secrets-manager/user/create/create.go | 10 +++---- .../cmd/secrets-manager/user/delete/delete.go | 10 +++---- .../cmd/secrets-manager/user/update/update.go | 10 +++---- internal/cmd/security-group/create/create.go | 10 +++---- internal/cmd/security-group/delete/delete.go | 10 +++---- .../cmd/security-group/rule/create/create.go | 10 +++---- .../cmd/security-group/rule/delete/delete.go | 10 +++---- internal/cmd/security-group/update/update.go | 10 +++---- internal/cmd/server/backup/create/create.go | 10 +++---- internal/cmd/server/backup/delete/delete.go | 10 +++---- internal/cmd/server/backup/disable/disable.go | 10 +++---- internal/cmd/server/backup/enable/enable.go | 10 +++---- internal/cmd/server/backup/restore/restore.go | 10 +++---- .../server/backup/schedule/create/create.go | 10 +++---- .../server/backup/schedule/delete/delete.go | 10 +++---- .../server/backup/schedule/update/update.go | 10 +++---- .../backup/volume-backup/delete/delete.go | 10 +++---- .../backup/volume-backup/restore/restore.go | 10 +++---- internal/cmd/server/command/create/create.go | 10 +++---- internal/cmd/server/create/create.go | 10 +++---- internal/cmd/server/deallocate/deallocate.go | 10 +++---- internal/cmd/server/delete/delete.go | 10 +++---- .../server/network-interface/attach/attach.go | 22 +++++++--------- .../server/network-interface/detach/detach.go | 22 +++++++--------- .../cmd/server/os-update/create/create.go | 10 +++---- .../cmd/server/os-update/disable/disable.go | 10 +++---- .../cmd/server/os-update/enable/enable.go | 10 +++---- .../os-update/schedule/create/create.go | 10 +++---- .../os-update/schedule/delete/delete.go | 10 +++---- .../os-update/schedule/update/update.go | 10 +++---- .../cmd/server/public-ip/attach/attach.go | 10 +++---- .../cmd/server/public-ip/detach/detach.go | 10 +++---- internal/cmd/server/reboot/reboot.go | 10 +++---- internal/cmd/server/rescue/rescue.go | 10 +++---- internal/cmd/server/resize/resize.go | 10 +++---- .../server/service-account/attach/attach.go | 10 +++---- .../server/service-account/detach/detach.go | 10 +++---- internal/cmd/server/stop/stop.go | 10 +++---- internal/cmd/server/unrescue/unrescue.go | 10 +++---- internal/cmd/server/update/update.go | 10 +++---- internal/cmd/server/volume/attach/attach.go | 10 +++---- internal/cmd/server/volume/detach/detach.go | 10 +++---- internal/cmd/server/volume/update/update.go | 10 +++---- internal/cmd/service-account/create/create.go | 10 +++---- internal/cmd/service-account/delete/delete.go | 10 +++---- .../cmd/service-account/key/create/create.go | 18 ++++++------- .../cmd/service-account/key/delete/delete.go | 10 +++---- .../cmd/service-account/key/update/update.go | 10 +++---- .../service-account/token/create/create.go | 10 +++---- .../service-account/token/revoke/revoke.go | 10 +++---- internal/cmd/ske/cluster/create/create.go | 10 +++---- internal/cmd/ske/cluster/delete/delete.go | 10 +++---- .../cmd/ske/cluster/hibernate/hibernate.go | 10 +++---- .../ske/cluster/maintenance/maintenance.go | 10 +++---- internal/cmd/ske/cluster/update/update.go | 10 +++---- .../complete-rotation/complete_rotation.go | 10 +++---- .../start-rotation/start_rotation.go | 10 +++---- internal/cmd/ske/disable/disable.go | 10 +++---- internal/cmd/ske/enable/enable.go | 10 +++---- internal/cmd/ske/kubeconfig/create/create.go | 2 +- internal/cmd/volume/backup/create/create.go | 10 +++---- internal/cmd/volume/backup/delete/delete.go | 10 +++---- internal/cmd/volume/backup/restore/restore.go | 10 +++---- internal/cmd/volume/backup/update/update.go | 10 +++---- internal/cmd/volume/create/create.go | 10 +++---- internal/cmd/volume/delete/delete.go | 10 +++---- internal/cmd/volume/resize/resize.go | 10 +++---- internal/cmd/volume/snapshot/create/create.go | 10 +++---- internal/cmd/volume/snapshot/delete/delete.go | 10 +++---- internal/cmd/volume/snapshot/update/update.go | 10 +++---- internal/cmd/volume/update/update.go | 10 +++---- internal/pkg/print/print.go | 9 +++++++ internal/pkg/print/print_test.go | 9 +++++++ 232 files changed, 963 insertions(+), 1398 deletions(-) diff --git a/internal/cmd/affinity-groups/create/create.go b/internal/cmd/affinity-groups/create/create.go index ca5332eb8..d8b0d5a1b 100644 --- a/internal/cmd/affinity-groups/create/create.go +++ b/internal/cmd/affinity-groups/create/create.go @@ -54,12 +54,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create the affinity group %q?", model.Name) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create the affinity group %q?", model.Name) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/affinity-groups/delete/delete.go b/internal/cmd/affinity-groups/delete/delete.go index 31df4cb18..ba3f83efc 100644 --- a/internal/cmd/affinity-groups/delete/delete.go +++ b/internal/cmd/affinity-groups/delete/delete.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { affinityGroupLabel = model.AffinityGroupId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete affinity group %q?", affinityGroupLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete affinity group %q?", affinityGroupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go index cf8429d10..2232d7aad 100644 --- a/internal/cmd/beta/alb/create/create.go +++ b/internal/cmd/beta/alb/create/create.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create an application loadbalancer for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create an application loadbalancer for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/alb/delete/delete.go b/internal/cmd/beta/alb/delete/delete.go index 5d0c23ec5..94b8163ee 100644 --- a/internal/cmd/beta/alb/delete/delete.go +++ b/internal/cmd/beta/alb/delete/delete.go @@ -57,12 +57,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the application loadbalancer %q for project %q?", model.Name, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the application loadbalancer %q for project %q?", model.Name, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/alb/observability-credentials/add/add.go b/internal/cmd/beta/alb/observability-credentials/add/add.go index 039a76ebe..69d21973b 100644 --- a/internal/cmd/beta/alb/observability-credentials/add/add.go +++ b/internal/cmd/beta/alb/observability-credentials/add/add.go @@ -55,12 +55,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := "Are your sure you want to add credentials?" - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := "Are your sure you want to add credentials?" + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/alb/observability-credentials/delete/delete.go b/internal/cmd/beta/alb/observability-credentials/delete/delete.go index d27de6d3e..274f977f2 100644 --- a/internal/cmd/beta/alb/observability-credentials/delete/delete.go +++ b/internal/cmd/beta/alb/observability-credentials/delete/delete.go @@ -50,12 +50,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials %q?", model.CredentialsRef) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials %q?", model.CredentialsRef) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/alb/observability-credentials/update/update.go b/internal/cmd/beta/alb/observability-credentials/update/update.go index 222c94559..18cbf8eb2 100644 --- a/internal/cmd/beta/alb/observability-credentials/update/update.go +++ b/internal/cmd/beta/alb/observability-credentials/update/update.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get project name: %v", err) projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update credential %q for %q?", *model.CredentialsRef, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return fmt.Errorf("update credential: %w", err) - } + prompt := fmt.Sprintf("Are you sure you want to update credential %q for %q?", *model.CredentialsRef, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return fmt.Errorf("update credential: %w", err) } // Call API diff --git a/internal/cmd/beta/alb/pool/update/update.go b/internal/cmd/beta/alb/pool/update/update.go index dcc51b7c6..a98d5f822 100644 --- a/internal/cmd/beta/alb/pool/update/update.go +++ b/internal/cmd/beta/alb/pool/update/update.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update an application target pool for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update an application target pool for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go index 5b34fea74..1221cba4f 100644 --- a/internal/cmd/beta/alb/update/update.go +++ b/internal/cmd/beta/alb/update/update.go @@ -67,12 +67,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update an application loadbalancer for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update an application loadbalancer for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // for updates of an existing ALB the current version must be passed to the request diff --git a/internal/cmd/beta/intake/runner/create/create.go b/internal/cmd/beta/intake/runner/create/create.go index 95b6b4211..72cff3b29 100644 --- a/internal/cmd/beta/intake/runner/create/create.go +++ b/internal/cmd/beta/intake/runner/create/create.go @@ -73,12 +73,10 @@ func NewCmd(p *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create an Intake Runner for project %q?", projectLabel) - err = p.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create an Intake Runner for project %q?", projectLabel) + err = p.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/intake/runner/delete/delete.go b/internal/cmd/beta/intake/runner/delete/delete.go index fcb4ae69d..92d5b1acf 100644 --- a/internal/cmd/beta/intake/runner/delete/delete.go +++ b/internal/cmd/beta/intake/runner/delete/delete.go @@ -54,12 +54,10 @@ func NewCmd(p *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete Intake Runner %q?", model.RunnerId) - err = p.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete Intake Runner %q?", model.RunnerId) + err = p.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/key/create/create.go b/internal/cmd/beta/kms/key/create/create.go index 91c6ab3c9..de64af6a7 100644 --- a/internal/cmd/beta/kms/key/create/create.go +++ b/internal/cmd/beta/kms/key/create/create.go @@ -85,11 +85,9 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS Key?") - if err != nil { - return err - } + err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS Key?") + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/key/delete/delete.go b/internal/cmd/beta/kms/key/delete/delete.go index 5ead9aca5..d7a6e02f6 100644 --- a/internal/cmd/beta/kms/key/delete/delete.go +++ b/internal/cmd/beta/kms/key/delete/delete.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { keyName = model.KeyId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete key %q? (This cannot be undone)", keyName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete key %q? (This cannot be undone)", keyName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/key/importKey/importKey.go b/internal/cmd/beta/kms/key/importKey/importKey.go index 78c70270e..38010860e 100644 --- a/internal/cmd/beta/kms/key/importKey/importKey.go +++ b/internal/cmd/beta/kms/key/importKey/importKey.go @@ -79,12 +79,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { keyRingName = model.KeyRingId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to import a new version for the KMS Key %q inside the key ring %q?", keyName, keyRingName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to import a new version for the KMS Key %q inside the key ring %q?", keyName, keyRingName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/key/restore/restore.go b/internal/cmd/beta/kms/key/restore/restore.go index 43164aa89..c4fc71173 100644 --- a/internal/cmd/beta/kms/key/restore/restore.go +++ b/internal/cmd/beta/kms/key/restore/restore.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { keyName = model.KeyId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to restore key %q? (This cannot be undone)", keyName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to restore key %q? (This cannot be undone)", keyName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/key/rotate/rotate.go b/internal/cmd/beta/kms/key/rotate/rotate.go index 0761554df..972234e7e 100644 --- a/internal/cmd/beta/kms/key/rotate/rotate.go +++ b/internal/cmd/beta/kms/key/rotate/rotate.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { keyName = model.KeyId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to rotate the key %q? (this cannot be undone)", keyName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to rotate the key %q? (this cannot be undone)", keyName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/keyring/create/create.go b/internal/cmd/beta/kms/keyring/create/create.go index 6a44529ed..0e773b364 100644 --- a/internal/cmd/beta/kms/keyring/create/create.go +++ b/internal/cmd/beta/kms/keyring/create/create.go @@ -64,11 +64,9 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS key ring?") - if err != nil { - return err - } + err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS key ring?") + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/keyring/delete/delete.go b/internal/cmd/beta/kms/keyring/delete/delete.go index 79c7316ea..6e028c75b 100644 --- a/internal/cmd/beta/kms/keyring/delete/delete.go +++ b/internal/cmd/beta/kms/keyring/delete/delete.go @@ -58,12 +58,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { keyRingLabel = model.KeyRingId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete key ring %q? (this cannot be undone)", keyRingLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete key ring %q? (this cannot be undone)", keyRingLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/wrappingkey/create/create.go b/internal/cmd/beta/kms/wrappingkey/create/create.go index d652da5ac..885c3b3e2 100644 --- a/internal/cmd/beta/kms/wrappingkey/create/create.go +++ b/internal/cmd/beta/kms/wrappingkey/create/create.go @@ -71,11 +71,9 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS wrapping key?") - if err != nil { - return err - } + err = params.Printer.PromptForConfirmation("Are you sure you want to create a KMS wrapping key?") + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/kms/wrappingkey/delete/delete.go b/internal/cmd/beta/kms/wrappingkey/delete/delete.go index 38b659cdf..75ce76a05 100644 --- a/internal/cmd/beta/kms/wrappingkey/delete/delete.go +++ b/internal/cmd/beta/kms/wrappingkey/delete/delete.go @@ -62,12 +62,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { wrappingKeyName = model.WrappingKeyId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the wrapping key %q? (this cannot be undone)", wrappingKeyName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the wrapping key %q? (this cannot be undone)", wrappingKeyName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/export-policy/create/create.go b/internal/cmd/beta/sfs/export-policy/create/create.go index 3f3ecf864..8732825aa 100644 --- a/internal/cmd/beta/sfs/export-policy/create/create.go +++ b/internal/cmd/beta/sfs/export-policy/create/create.go @@ -67,12 +67,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a export policy for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a export policy for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/export-policy/delete/delete.go b/internal/cmd/beta/sfs/export-policy/delete/delete.go index b93807b5c..8ae903d23 100644 --- a/internal/cmd/beta/sfs/export-policy/delete/delete.go +++ b/internal/cmd/beta/sfs/export-policy/delete/delete.go @@ -56,12 +56,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { exportPolicyLabel = model.ExportPolicyId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete export policy %q? (This cannot be undone)", exportPolicyLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete export policy %q? (This cannot be undone)", exportPolicyLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/export-policy/update/update.go b/internal/cmd/beta/sfs/export-policy/update/update.go index cbe394459..a0ab0a6dc 100644 --- a/internal/cmd/beta/sfs/export-policy/update/update.go +++ b/internal/cmd/beta/sfs/export-policy/update/update.go @@ -78,12 +78,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update export policy %q for project %q?", exportPolicyLabel, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update export policy %q for project %q?", exportPolicyLabel, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/resource-pool/create/create.go b/internal/cmd/beta/sfs/resource-pool/create/create.go index 69093d471..4b97f16bb 100644 --- a/internal/cmd/beta/sfs/resource-pool/create/create.go +++ b/internal/cmd/beta/sfs/resource-pool/create/create.go @@ -82,12 +82,10 @@ The available performance class values can be obtained by running: projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a resource-pool for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a resource-pool for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/resource-pool/delete/delete.go b/internal/cmd/beta/sfs/resource-pool/delete/delete.go index acd38ae4d..6883c3987 100644 --- a/internal/cmd/beta/sfs/resource-pool/delete/delete.go +++ b/internal/cmd/beta/sfs/resource-pool/delete/delete.go @@ -59,12 +59,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { resourcePoolName = model.ResourcePoolId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete resource pool %q? (This cannot be undone)", resourcePoolName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete resource pool %q? (This cannot be undone)", resourcePoolName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/resource-pool/update/update.go b/internal/cmd/beta/sfs/resource-pool/update/update.go index 267f68939..a276fb91e 100644 --- a/internal/cmd/beta/sfs/resource-pool/update/update.go +++ b/internal/cmd/beta/sfs/resource-pool/update/update.go @@ -87,12 +87,10 @@ The available performance class values can be obtained by running: resourcePoolName = model.ResourcePoolId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update resource-pool %q for project %q?", resourcePoolName, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update resource-pool %q for project %q?", resourcePoolName, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/share/create/create.go b/internal/cmd/beta/sfs/share/create/create.go index 8fc5312bf..c2b2246b8 100644 --- a/internal/cmd/beta/sfs/share/create/create.go +++ b/internal/cmd/beta/sfs/share/create/create.go @@ -72,12 +72,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { resourcePoolLabel = model.ResourcePoolId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a SFS share for resource pool %q?", resourcePoolLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a SFS share for resource pool %q?", resourcePoolLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/share/delete/delete.go b/internal/cmd/beta/sfs/share/delete/delete.go index 7d5221cf7..aed603d52 100644 --- a/internal/cmd/beta/sfs/share/delete/delete.go +++ b/internal/cmd/beta/sfs/share/delete/delete.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { shareLabel = model.ShareId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete SFS share %q? (This cannot be undone)", shareLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete SFS share %q? (This cannot be undone)", shareLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/share/update/update.go b/internal/cmd/beta/sfs/share/update/update.go index f6178e96a..7f368fa3d 100644 --- a/internal/cmd/beta/sfs/share/update/update.go +++ b/internal/cmd/beta/sfs/share/update/update.go @@ -81,12 +81,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { resourcePoolLabel = model.ResourcePoolId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update SFS share %q for resource pool %q?", shareLabel, resourcePoolLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update SFS share %q for resource pool %q?", shareLabel, resourcePoolLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/snapshot/create/create.go b/internal/cmd/beta/sfs/snapshot/create/create.go index e55d902e9..c531009de 100644 --- a/internal/cmd/beta/sfs/snapshot/create/create.go +++ b/internal/cmd/beta/sfs/snapshot/create/create.go @@ -68,12 +68,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { resourcePoolLabel = model.ResourcePoolId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a snapshot for resource pool %q?", resourcePoolLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a snapshot for resource pool %q?", resourcePoolLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sfs/snapshot/delete/delete.go b/internal/cmd/beta/sfs/snapshot/delete/delete.go index 6ddfc4435..15e0cec17 100644 --- a/internal/cmd/beta/sfs/snapshot/delete/delete.go +++ b/internal/cmd/beta/sfs/snapshot/delete/delete.go @@ -61,12 +61,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { resourcePoolLabel = model.ResourcePoolId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete snapshot %q for resource pool %q?", model.SnapshotName, resourcePoolLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete snapshot %q for resource pool %q?", model.SnapshotName, resourcePoolLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index 072c3b91e..9a2b8c2e0 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create database %q? (This cannot be undone)", model.DatabaseName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create database %q? (This cannot be undone)", model.DatabaseName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete.go b/internal/cmd/beta/sqlserverflex/database/delete/delete.go index edfd47f83..3408cc85d 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete.go @@ -58,12 +58,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete database %q? (This cannot be undone)", model.DatabaseName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete database %q? (This cannot be undone)", model.DatabaseName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 04841a4c7..4cc0469e5 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -103,12 +103,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a SQLServer Flex instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a SQLServer Flex instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go index 5e320f039..74840b4db 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index 019826e3b..81a4b5008 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -94,12 +94,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sqlserverflex/user/create/create.go b/internal/cmd/beta/sqlserverflex/user/create/create.go index 5a818be70..1f3887390 100644 --- a/internal/cmd/beta/sqlserverflex/user/create/create.go +++ b/internal/cmd/beta/sqlserverflex/user/create/create.go @@ -75,12 +75,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sqlserverflex/user/delete/delete.go b/internal/cmd/beta/sqlserverflex/user/delete/delete.go index 0908a227f..c1dd038d0 100644 --- a/internal/cmd/beta/sqlserverflex/user/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/user/delete/delete.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = model.UserId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go index b27b6e923..f76922fc8 100644 --- a/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go +++ b/internal/cmd/beta/sqlserverflex/user/reset-password/reset_password.go @@ -72,12 +72,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = model.UserId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/config/profile/delete/delete.go b/internal/cmd/config/profile/delete/delete.go index 631374a84..a81bf7888 100644 --- a/internal/cmd/config/profile/delete/delete.go +++ b/internal/cmd/config/profile/delete/delete.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Warn("The profile you are trying to delete is the active profile. The default profile will be set to active.\n") } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete profile %q? (This cannot be undone)", model.Profile) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete profile %q? (This cannot be undone)", model.Profile) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } err = config.DeleteProfile(params.Printer, model.Profile) diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 3dcc666e9..2687b34da 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -73,12 +73,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { zoneLabel = model.ZoneId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a record set for zone %s?", zoneLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a record set for zone %s?", zoneLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/dns/record-set/delete/delete.go b/internal/cmd/dns/record-set/delete/delete.go index dcfa6d300..09337b89e 100644 --- a/internal/cmd/dns/record-set/delete/delete.go +++ b/internal/cmd/dns/record-set/delete/delete.go @@ -70,12 +70,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { recordSetLabel = model.RecordSetId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete record set %s of zone %s? (This cannot be undone)", recordSetLabel, zoneLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete record set %s of zone %s? (This cannot be undone)", recordSetLabel, zoneLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/dns/record-set/update/update.go b/internal/cmd/dns/record-set/update/update.go index e3df19d91..b9fb0e942 100644 --- a/internal/cmd/dns/record-set/update/update.go +++ b/internal/cmd/dns/record-set/update/update.go @@ -93,12 +93,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update record set %s of zone %s?", recordSetLabel, zoneLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update record set %s of zone %s?", recordSetLabel, zoneLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index 0611348f9..6bc02546d 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -75,12 +75,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { zoneLabel = model.ZoneId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to clone the zone %q?", zoneLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to clone the zone %q?", zoneLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 3454e654d..75ef0a3e5 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -88,12 +88,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a zone for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a zone for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/dns/zone/delete/delete.go b/internal/cmd/dns/zone/delete/delete.go index 499ba920a..a204a5dbe 100644 --- a/internal/cmd/dns/zone/delete/delete.go +++ b/internal/cmd/dns/zone/delete/delete.go @@ -59,12 +59,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get zone name: %v", err) zoneLabel = model.ZoneId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete zone %q? (This cannot be undone)", zoneLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete zone %q? (This cannot be undone)", zoneLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/dns/zone/update/update.go b/internal/cmd/dns/zone/update/update.go index 128f1c3f0..a3c31b097 100644 --- a/internal/cmd/dns/zone/update/update.go +++ b/internal/cmd/dns/zone/update/update.go @@ -82,12 +82,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { zoneLabel = model.ZoneId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update zone %s?", zoneLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update zone %s?", zoneLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index f1323fb49..b11bb16a6 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -67,12 +67,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create the instance %q?", model.Name) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create the instance %q?", model.Name) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/git/instance/delete/delete.go b/internal/cmd/git/instance/delete/delete.go index ae9394c83..7c056829a 100644 --- a/internal/cmd/git/instance/delete/delete.go +++ b/internal/cmd/git/instance/delete/delete.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceName = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the stackit git instance %q for %q?", instanceName, projectName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the stackit git instance %q for %q?", instanceName, projectName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index 784c4389f..e463bf41e 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -127,12 +127,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } }() - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create the image %q?", model.Name) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create the image %q?", model.Name) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/image/delete/delete.go b/internal/cmd/image/delete/delete.go index ffbbf8714..c41746f58 100644 --- a/internal/cmd/image/delete/delete.go +++ b/internal/cmd/image/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { imageName = model.ImageId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the image %q for %q?", imageName, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the image %q for %q?", imageName, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index 7aa3851c0..26d8ca088 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -139,12 +139,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { imageLabel = model.Id } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update the image %q?", imageLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update the image %q?", imageLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/key-pair/create/create.go b/internal/cmd/key-pair/create/create.go index 4ce01cfdf..5bb18ef2e 100644 --- a/internal/cmd/key-pair/create/create.go +++ b/internal/cmd/key-pair/create/create.go @@ -67,12 +67,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := "Are your sure you want to create a key pair?" - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := "Are your sure you want to create a key pair?" + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/key-pair/delete/delete.go b/internal/cmd/key-pair/delete/delete.go index 70d7e9a8f..17984e936 100644 --- a/internal/cmd/key-pair/delete/delete.go +++ b/internal/cmd/key-pair/delete/delete.go @@ -50,12 +50,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete key pair %q?", model.KeyPairName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete key pair %q?", model.KeyPairName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/key-pair/update/update.go b/internal/cmd/key-pair/update/update.go index 450329082..14988bf28 100644 --- a/internal/cmd/key-pair/update/update.go +++ b/internal/cmd/key-pair/update/update.go @@ -51,12 +51,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update key pair %q?", *model.KeyPairName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return fmt.Errorf("update key pair: %w", err) - } + prompt := fmt.Sprintf("Are you sure you want to update key pair %q?", *model.KeyPairName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return fmt.Errorf("update key pair: %w", err) } // Call API diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index 0ebaaee16..31e74d9ba 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -78,12 +78,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a load balancer for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a load balancer for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/load-balancer/delete/delete.go b/internal/cmd/load-balancer/delete/delete.go index 0c43431f1..e1c3a33af 100644 --- a/internal/cmd/load-balancer/delete/delete.go +++ b/internal/cmd/load-balancer/delete/delete.go @@ -51,12 +51,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete load balancer %q? (This cannot be undone)", model.LoadBalancerName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete load balancer %q? (This cannot be undone)", model.LoadBalancerName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/load-balancer/observability-credentials/add/add.go b/internal/cmd/load-balancer/observability-credentials/add/add.go index 0aa0c8532..edb3f447e 100644 --- a/internal/cmd/load-balancer/observability-credentials/add/add.go +++ b/internal/cmd/load-balancer/observability-credentials/add/add.go @@ -76,12 +76,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { model.Password = utils.Ptr(pwd) } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to add observability credentials for Load Balancer on project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to add observability credentials for Load Balancer on project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go index ce2df7311..35e123ee3 100644 --- a/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go +++ b/internal/cmd/load-balancer/observability-credentials/cleanup/cleanup.go @@ -72,21 +72,19 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return nil } - if !model.AssumeYes { - prompt := "Will delete the following unused observability credentials: \n" - for _, credential := range credentials { - if credential.DisplayName == nil || credential.Username == nil { - return fmt.Errorf("list unused Load Balancer observability credentials: credentials %q missing display name or username", *credential.CredentialsRef) - } - name := *credential.DisplayName - username := *credential.Username - prompt += fmt.Sprintf(" - %s (username: %q)\n", name, username) - } - prompt += fmt.Sprintf("Are you sure you want to delete unused observability credentials on project %q? (This cannot be undone)", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err + prompt := "Will delete the following unused observability credentials: \n" + for _, credential := range credentials { + if credential.DisplayName == nil || credential.Username == nil { + return fmt.Errorf("list unused Load Balancer observability credentials: credentials %q missing display name or username", *credential.CredentialsRef) } + name := *credential.DisplayName + username := *credential.Username + prompt += fmt.Sprintf(" - %s (username: %q)\n", name, username) + } + prompt += fmt.Sprintf("Are you sure you want to delete unused observability credentials on project %q? (This cannot be undone)", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } for _, credential := range credentials { diff --git a/internal/cmd/load-balancer/observability-credentials/delete/delete.go b/internal/cmd/load-balancer/observability-credentials/delete/delete.go index 238a9fcfb..4139f56db 100644 --- a/internal/cmd/load-balancer/observability-credentials/delete/delete.go +++ b/internal/cmd/load-balancer/observability-credentials/delete/delete.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsLabel = model.CredentialsRef } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete observability credentials %q on project %q?(This cannot be undone)", credentialsLabel, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete observability credentials %q on project %q?(This cannot be undone)", credentialsLabel, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/load-balancer/observability-credentials/update/update.go b/internal/cmd/load-balancer/observability-credentials/update/update.go index dfa4e6f1a..f19afb714 100644 --- a/internal/cmd/load-balancer/observability-credentials/update/update.go +++ b/internal/cmd/load-balancer/observability-credentials/update/update.go @@ -95,12 +95,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { model.Password = utils.Ptr(pwd) } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update observability credentials %q for Load Balancer on project %q?", credentialsLabel, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update observability credentials %q for Load Balancer on project %q?", credentialsLabel, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/load-balancer/target-pool/add-target/add_target.go b/internal/cmd/load-balancer/target-pool/add-target/add_target.go index 8bd1032ea..4cc41d4ef 100644 --- a/internal/cmd/load-balancer/target-pool/add-target/add_target.go +++ b/internal/cmd/load-balancer/target-pool/add-target/add_target.go @@ -62,12 +62,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to add a target with IP %q to target pool %q of load balancer %q?", model.IP, model.TargetPoolName, model.LBName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to add a target with IP %q to target pool %q of load balancer %q?", model.IP, model.TargetPoolName, model.LBName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go index c0550ade6..4cb053eff 100644 --- a/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go +++ b/internal/cmd/load-balancer/target-pool/remove-target/remove_target.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { targetLabel = model.IP } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to remove target %q from target pool %q of load balancer %q?", targetLabel, model.TargetPoolName, model.LBName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to remove target %q from target pool %q of load balancer %q?", targetLabel, model.TargetPoolName, model.LBName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/load-balancer/update/update.go b/internal/cmd/load-balancer/update/update.go index 7a3184e1c..5e55a414b 100644 --- a/internal/cmd/load-balancer/update/update.go +++ b/internal/cmd/load-balancer/update/update.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update load balancer %q?", model.LoadBalancerName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update load balancer %q?", model.LoadBalancerName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/logme/credentials/create/create.go b/internal/cmd/logme/credentials/create/create.go index 5c2451e73..79d5577c4 100644 --- a/internal/cmd/logme/credentials/create/create.go +++ b/internal/cmd/logme/credentials/create/create.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/logme/credentials/delete/delete.go b/internal/cmd/logme/credentials/delete/delete.go index 3254e6f32..26d2750fd 100644 --- a/internal/cmd/logme/credentials/delete/delete.go +++ b/internal/cmd/logme/credentials/delete/delete.go @@ -68,12 +68,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsLabel = model.CredentialsId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index f3b1118c1..c0b1fcd48 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -91,12 +91,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a LogMe instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a LogMe instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/logme/instance/delete/delete.go b/internal/cmd/logme/instance/delete/delete.go index f804e3b6d..9cdfac9d0 100644 --- a/internal/cmd/logme/instance/delete/delete.go +++ b/internal/cmd/logme/instance/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/logme/instance/update/update.go b/internal/cmd/logme/instance/update/update.go index 6d503a394..4cefddf26 100644 --- a/internal/cmd/logme/instance/update/update.go +++ b/internal/cmd/logme/instance/update/update.go @@ -90,12 +90,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mariadb/credentials/create/create.go b/internal/cmd/mariadb/credentials/create/create.go index 9ac022e6f..f3d9e1155 100644 --- a/internal/cmd/mariadb/credentials/create/create.go +++ b/internal/cmd/mariadb/credentials/create/create.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mariadb/credentials/delete/delete.go b/internal/cmd/mariadb/credentials/delete/delete.go index 830ebd840..7fd89c4e9 100644 --- a/internal/cmd/mariadb/credentials/delete/delete.go +++ b/internal/cmd/mariadb/credentials/delete/delete.go @@ -68,12 +68,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsLabel = model.CredentialsId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index 2793da086..22a8a2b91 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -91,12 +91,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a MariaDB instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a MariaDB instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mariadb/instance/delete/delete.go b/internal/cmd/mariadb/instance/delete/delete.go index 3e59476f6..1cd809204 100644 --- a/internal/cmd/mariadb/instance/delete/delete.go +++ b/internal/cmd/mariadb/instance/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mariadb/instance/update/update.go b/internal/cmd/mariadb/instance/update/update.go index 6aa6f701d..ebb48e315 100644 --- a/internal/cmd/mariadb/instance/update/update.go +++ b/internal/cmd/mariadb/instance/update/update.go @@ -88,12 +88,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index f7e5feb79..a4b6e5ca9 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -77,12 +77,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to restore MongoDB Flex instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to restore MongoDB Flex instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // If backupInstanceId is not provided, the target is the same instance as the backup diff --git a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go index ce4dce055..6934fb862 100644 --- a/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/mongodbflex/backup/update-schedule/update_schedule.go @@ -88,12 +88,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = *model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update backup schedule of instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update backup schedule of instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Get current instance diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index 6a7c181e6..e0239d2f5 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -93,12 +93,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a MongoDB Flex instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a MongoDB Flex instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Fill in version, if needed diff --git a/internal/cmd/mongodbflex/instance/delete/delete.go b/internal/cmd/mongodbflex/instance/delete/delete.go index f5316c8fe..cb4a2be9c 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete.go +++ b/internal/cmd/mongodbflex/instance/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index fa160df07..bcd4bb894 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -88,12 +88,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mongodbflex/user/create/create.go b/internal/cmd/mongodbflex/user/create/create.go index b1d32aed9..9fc9def6d 100644 --- a/internal/cmd/mongodbflex/user/create/create.go +++ b/internal/cmd/mongodbflex/user/create/create.go @@ -77,12 +77,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mongodbflex/user/delete/delete.go b/internal/cmd/mongodbflex/user/delete/delete.go index 54f28cdc2..823f43d65 100644 --- a/internal/cmd/mongodbflex/user/delete/delete.go +++ b/internal/cmd/mongodbflex/user/delete/delete.go @@ -72,12 +72,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = model.UserId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mongodbflex/user/reset-password/reset_password.go b/internal/cmd/mongodbflex/user/reset-password/reset_password.go index e92c189db..749b8f9d0 100644 --- a/internal/cmd/mongodbflex/user/reset-password/reset_password.go +++ b/internal/cmd/mongodbflex/user/reset-password/reset_password.go @@ -72,12 +72,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = model.UserId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/mongodbflex/user/update/update.go b/internal/cmd/mongodbflex/user/update/update.go index caa91c059..200873a77 100644 --- a/internal/cmd/mongodbflex/user/update/update.go +++ b/internal/cmd/mongodbflex/user/update/update.go @@ -73,12 +73,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = model.UserId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update user %q of instance %q?", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update user %q of instance %q?", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index 15e9b8192..078a6568c 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -114,12 +114,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "configure resource manager client: %v", err) } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a network area for organization %q?", orgLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a network area for organization %q?", orgLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API @@ -147,7 +145,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("create network area region: %w", err) } - if !model.AssumeYes { + 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) diff --git a/internal/cmd/network-area/delete/delete.go b/internal/cmd/network-area/delete/delete.go index becf4524c..e1dbca35e 100644 --- a/internal/cmd/network-area/delete/delete.go +++ b/internal/cmd/network-area/delete/delete.go @@ -69,12 +69,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkAreaLabel = model.AreaId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete network area %q?", networkAreaLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete network area %q?", networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Check if the network area has a regional configuration diff --git a/internal/cmd/network-area/network-range/create/create.go b/internal/cmd/network-area/network-range/create/create.go index a77852fb3..0502663d8 100644 --- a/internal/cmd/network-area/network-range/create/create.go +++ b/internal/cmd/network-area/network-range/create/create.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkAreaLabel = *model.NetworkAreaId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a network range for STACKIT Network Area (SNA) %q?", networkAreaLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a network range for STACKIT Network Area (SNA) %q?", networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-area/network-range/delete/delete.go b/internal/cmd/network-area/network-range/delete/delete.go index 82e697109..84ceb85c7 100644 --- a/internal/cmd/network-area/network-range/delete/delete.go +++ b/internal/cmd/network-area/network-range/delete/delete.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkRangeLabel = model.NetworkRangeId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete network range %q on STACKIT Network Area (SNA) %q?", networkRangeLabel, networkAreaLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete network range %q on STACKIT Network Area (SNA) %q?", networkRangeLabel, networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-area/region/create/create.go b/internal/cmd/network-area/region/create/create.go index 4adf5cee9..63a8c6348 100644 --- a/internal/cmd/network-area/region/create/create.go +++ b/internal/cmd/network-area/region/create/create.go @@ -90,12 +90,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkAreaLabel = model.NetworkAreaId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-area/region/delete/delete.go b/internal/cmd/network-area/region/delete/delete.go index ff31aeaa2..bbbd44262 100644 --- a/internal/cmd/network-area/region/delete/delete.go +++ b/internal/cmd/network-area/region/delete/delete.go @@ -68,12 +68,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkAreaName = model.NetworkAreaId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-area/region/update/update.go b/internal/cmd/network-area/region/update/update.go index 1d1f64bf7..8b68195ff 100644 --- a/internal/cmd/network-area/region/update/update.go +++ b/internal/cmd/network-area/region/update/update.go @@ -83,12 +83,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkAreaLabel = model.NetworkAreaId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update the regional configuration %q for STACKIT Network Area (SNA) %q?", model.Region, networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-area/route/create/create.go b/internal/cmd/network-area/route/create/create.go index d0ad72a2b..72c9fe006 100644 --- a/internal/cmd/network-area/route/create/create.go +++ b/internal/cmd/network-area/route/create/create.go @@ -98,12 +98,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkAreaLabel = *model.NetworkAreaId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a static route for STACKIT Network Area (SNA) %q?", networkAreaLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a static route for STACKIT Network Area (SNA) %q?", networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-area/route/delete/delete.go b/internal/cmd/network-area/route/delete/delete.go index 6292f3cd7..dbad67c03 100644 --- a/internal/cmd/network-area/route/delete/delete.go +++ b/internal/cmd/network-area/route/delete/delete.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkAreaLabel = *model.NetworkAreaId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete static route %q on STACKIT Network Area (SNA) %q?", model.RouteId, networkAreaLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete static route %q on STACKIT Network Area (SNA) %q?", model.RouteId, networkAreaLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-area/update/update.go b/internal/cmd/network-area/update/update.go index 71d9bd899..98f778bc3 100644 --- a/internal/cmd/network-area/update/update.go +++ b/internal/cmd/network-area/update/update.go @@ -103,12 +103,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "configure resource manager client: %v", err) } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update a network area for organization %q?", orgLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update a network area for organization %q?", orgLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-interface/create/create.go b/internal/cmd/network-interface/create/create.go index c660bb561..5939d712d 100644 --- a/internal/cmd/network-interface/create/create.go +++ b/internal/cmd/network-interface/create/create.go @@ -86,12 +86,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a network interface for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a network interface for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-interface/delete/delete.go b/internal/cmd/network-interface/delete/delete.go index 8db2f2376..de6d972cb 100644 --- a/internal/cmd/network-interface/delete/delete.go +++ b/internal/cmd/network-interface/delete/delete.go @@ -54,12 +54,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the network interface %q? (This cannot be undone)", model.NicId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the network interface %q? (This cannot be undone)", model.NicId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network-interface/update/update.go b/internal/cmd/network-interface/update/update.go index 283083698..eeae44774 100644 --- a/internal/cmd/network-interface/update/update.go +++ b/internal/cmd/network-interface/update/update.go @@ -80,12 +80,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update the network interface %q?", model.NicId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update the network interface %q?", model.NicId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index 4a2098191..fee9123ce 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -108,12 +108,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a network for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a network for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network/delete/delete.go b/internal/cmd/network/delete/delete.go index 4cb4410be..1f3b00b95 100644 --- a/internal/cmd/network/delete/delete.go +++ b/internal/cmd/network/delete/delete.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkLabel = model.NetworkId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete network %q?", networkLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete network %q?", networkLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/network/update/update.go b/internal/cmd/network/update/update.go index 6a752b5e1..13e7e5acc 100644 --- a/internal/cmd/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -93,12 +93,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { networkLabel = model.NetworkId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update network %q?", networkLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update network %q?", networkLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index a3409a6a5..9b8aae9a3 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -53,12 +53,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create bucket %q? (This cannot be undone)", model.BucketName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create bucket %q? (This cannot be undone)", model.BucketName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Check if the project is enabled before trying to create diff --git a/internal/cmd/object-storage/bucket/delete/delete.go b/internal/cmd/object-storage/bucket/delete/delete.go index 010aa121e..c06e88718 100644 --- a/internal/cmd/object-storage/bucket/delete/delete.go +++ b/internal/cmd/object-storage/bucket/delete/delete.go @@ -52,12 +52,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete bucket %q? (This cannot be undone)", model.BucketName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete bucket %q? (This cannot be undone)", model.BucketName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/object-storage/credentials-group/create/create.go b/internal/cmd/object-storage/credentials-group/create/create.go index 2081d3550..9150b98fe 100644 --- a/internal/cmd/object-storage/credentials-group/create/create.go +++ b/internal/cmd/object-storage/credentials-group/create/create.go @@ -52,12 +52,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a credentials group with name %q?", model.CredentialsGroupName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a credentials group with name %q?", model.CredentialsGroupName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/object-storage/credentials-group/delete/delete.go b/internal/cmd/object-storage/credentials-group/delete/delete.go index aad80623e..79daa26b3 100644 --- a/internal/cmd/object-storage/credentials-group/delete/delete.go +++ b/internal/cmd/object-storage/credentials-group/delete/delete.go @@ -58,12 +58,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsGroupLabel = model.CredentialsGroupId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials group %q? (This cannot be undone)", credentialsGroupLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials group %q? (This cannot be undone)", credentialsGroupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/object-storage/credentials/create/create.go b/internal/cmd/object-storage/credentials/create/create.go index ef75cac78..c970dcb21 100644 --- a/internal/cmd/object-storage/credentials/create/create.go +++ b/internal/cmd/object-storage/credentials/create/create.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsGroupLabel = model.CredentialsGroupId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create credentials in group %q?", credentialsGroupLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create credentials in group %q?", credentialsGroupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/object-storage/credentials/delete/delete.go b/internal/cmd/object-storage/credentials/delete/delete.go index c8f1c63d8..84a3b363b 100644 --- a/internal/cmd/object-storage/credentials/delete/delete.go +++ b/internal/cmd/object-storage/credentials/delete/delete.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsLabel = model.CredentialsId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials %q of credentials group %q? (This cannot be undone)", credentialsLabel, credentialsGroupLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials %q of credentials group %q? (This cannot be undone)", credentialsLabel, credentialsGroupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/object-storage/disable/disable.go b/internal/cmd/object-storage/disable/disable.go index 0272151f4..e7b0f501b 100644 --- a/internal/cmd/object-storage/disable/disable.go +++ b/internal/cmd/object-storage/disable/disable.go @@ -52,12 +52,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable Object Storage for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to disable Object Storage for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/object-storage/enable/enable.go b/internal/cmd/object-storage/enable/enable.go index c135a1212..bd5304493 100644 --- a/internal/cmd/object-storage/enable/enable.go +++ b/internal/cmd/object-storage/enable/enable.go @@ -52,12 +52,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable Object Storage for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to enable Object Storage for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/credentials/create/create.go b/internal/cmd/observability/credentials/create/create.go index a3ef3f615..12ff53649 100644 --- a/internal/cmd/observability/credentials/create/create.go +++ b/internal/cmd/observability/credentials/create/create.go @@ -61,12 +61,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/credentials/delete/delete.go b/internal/cmd/observability/credentials/delete/delete.go index 86617ab82..a28888dc9 100644 --- a/internal/cmd/observability/credentials/delete/delete.go +++ b/internal/cmd/observability/credentials/delete/delete.go @@ -61,12 +61,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials for username %q of instance %q? (This cannot be undone)", model.Username, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials for username %q of instance %q? (This cannot be undone)", model.Username, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/grafana/public-read-access/disable/disable.go b/internal/cmd/observability/grafana/public-read-access/disable/disable.go index 4f63f776f..70a3ff85b 100644 --- a/internal/cmd/observability/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/observability/grafana/public-read-access/disable/disable.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable Grafana public read access for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to disable Grafana public read access for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/grafana/public-read-access/enable/enable.go b/internal/cmd/observability/grafana/public-read-access/enable/enable.go index 87a79cfd8..04f9eabf2 100644 --- a/internal/cmd/observability/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/observability/grafana/public-read-access/enable/enable.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable Grafana public read access for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to enable Grafana public read access for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go index 806bd02d0..57d7d7b8b 100644 --- a/internal/cmd/observability/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/observability/grafana/single-sign-on/disable/disable.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable single sign-on for Grafana for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to disable single sign-on for Grafana for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go index fa8f7f6de..3aca5bbe8 100644 --- a/internal/cmd/observability/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/observability/grafana/single-sign-on/enable/enable.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable single sign-on for Grafana for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to enable single sign-on for Grafana for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index 23c4bc51a..c492902e5 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create an Observability instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create an Observability instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/instance/delete/delete.go b/internal/cmd/observability/instance/delete/delete.go index b06179e6c..0aec201da 100644 --- a/internal/cmd/observability/instance/delete/delete.go +++ b/internal/cmd/observability/instance/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/instance/update/update.go b/internal/cmd/observability/instance/update/update.go index c97eb98ba..51d0b9f56 100644 --- a/internal/cmd/observability/instance/update/update.go +++ b/internal/cmd/observability/instance/update/update.go @@ -76,12 +76,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go index c4e8a4dac..f3e9a0515 100644 --- a/internal/cmd/observability/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -89,12 +89,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { model.Payload = &defaultPayload } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create scrape configuration %q on Observability instance %q?", *model.Payload.JobName, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create scrape configuration %q on Observability instance %q?", *model.Payload.JobName, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/scrape-config/delete/delete.go b/internal/cmd/observability/scrape-config/delete/delete.go index ceae80ac5..4cd15229b 100644 --- a/internal/cmd/observability/scrape-config/delete/delete.go +++ b/internal/cmd/observability/scrape-config/delete/delete.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete scrape configuration %q on Observability instance %q? (This cannot be undone)", model.JobName, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete scrape configuration %q on Observability instance %q? (This cannot be undone)", model.JobName, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/observability/scrape-config/update/update.go b/internal/cmd/observability/scrape-config/update/update.go index 3556e6620..130199713 100644 --- a/internal/cmd/observability/scrape-config/update/update.go +++ b/internal/cmd/observability/scrape-config/update/update.go @@ -69,12 +69,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update scrape configuration %q?", model.JobName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update scrape configuration %q?", model.JobName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index f44215219..06c5b87dd 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/opensearch/credentials/delete/delete.go b/internal/cmd/opensearch/credentials/delete/delete.go index d8b57c185..236b9c626 100644 --- a/internal/cmd/opensearch/credentials/delete/delete.go +++ b/internal/cmd/opensearch/credentials/delete/delete.go @@ -68,12 +68,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsLabel = model.CredentialsId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index 91fe825c8..bc03d82dd 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -93,12 +93,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create an OpenSearch instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create an OpenSearch instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/opensearch/instance/delete/delete.go b/internal/cmd/opensearch/instance/delete/delete.go index 31983b4a5..e1cc328fb 100644 --- a/internal/cmd/opensearch/instance/delete/delete.go +++ b/internal/cmd/opensearch/instance/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/opensearch/instance/update/update.go b/internal/cmd/opensearch/instance/update/update.go index fab2792f0..aa9b90eb5 100644 --- a/internal/cmd/opensearch/instance/update/update.go +++ b/internal/cmd/opensearch/instance/update/update.go @@ -91,12 +91,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/organization/member/add/add.go b/internal/cmd/organization/member/add/add.go index f41eaa06d..db8754c5f 100644 --- a/internal/cmd/organization/member/add/add.go +++ b/internal/cmd/organization/member/add/add.go @@ -58,12 +58,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to add the %s role to %s on organization with ID %q?", *model.Role, model.Subject, *model.OrganizationId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to add the %s role to %s on organization with ID %q?", *model.Role, model.Subject, *model.OrganizationId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Configure API client diff --git a/internal/cmd/organization/member/remove/remove.go b/internal/cmd/organization/member/remove/remove.go index f0d5ee13c..27e95be67 100644 --- a/internal/cmd/organization/member/remove/remove.go +++ b/internal/cmd/organization/member/remove/remove.go @@ -68,15 +68,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to remove the %s role from %s on organization with ID %q?", *model.Role, model.Subject, *model.OrganizationId) - if model.Force { - prompt = fmt.Sprintf("%s This will also remove other roles of the subject that would stop the removal of the requested role", prompt) - } - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to remove the %s role from %s on organization with ID %q?", *model.Role, model.Subject, *model.OrganizationId) + if model.Force { + prompt = fmt.Sprintf("%s This will also remove other roles of the subject that would stop the removal of the requested role", prompt) + } + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go index 5e954322e..16bb967fe 100644 --- a/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go +++ b/internal/cmd/postgresflex/backup/update-schedule/update_schedule.go @@ -62,12 +62,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = *model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update backup schedule of instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update backup schedule of instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index 9c72a9874..d9a784d2a 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -78,12 +78,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to clone instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to clone instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index de9106998..8359ad2f7 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -94,12 +94,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a PostgreSQL Flex instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a PostgreSQL Flex instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Fill in version, if needed diff --git a/internal/cmd/postgresflex/instance/delete/delete.go b/internal/cmd/postgresflex/instance/delete/delete.go index 56401d564..2108d31c3 100644 --- a/internal/cmd/postgresflex/instance/delete/delete.go +++ b/internal/cmd/postgresflex/instance/delete/delete.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } toDelete, toForceDelete, err := getNextOperations(ctx, model, apiClient) diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 821d10b1c..8623a78f4 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -88,12 +88,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q? (This may cause downtime)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q? (This may cause downtime)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/postgresflex/user/create/create.go b/internal/cmd/postgresflex/user/create/create.go index 7623ba786..fc53b1f07 100644 --- a/internal/cmd/postgresflex/user/create/create.go +++ b/internal/cmd/postgresflex/user/create/create.go @@ -75,12 +75,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/postgresflex/user/delete/delete.go b/internal/cmd/postgresflex/user/delete/delete.go index 219798121..d3646805a 100644 --- a/internal/cmd/postgresflex/user/delete/delete.go +++ b/internal/cmd/postgresflex/user/delete/delete.go @@ -72,12 +72,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = model.UserId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/postgresflex/user/reset-password/reset_password.go b/internal/cmd/postgresflex/user/reset-password/reset_password.go index 3c78d191f..c899b5659 100644 --- a/internal/cmd/postgresflex/user/reset-password/reset_password.go +++ b/internal/cmd/postgresflex/user/reset-password/reset_password.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = model.UserId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to reset the password of user %q of instance %q? (This cannot be undone)", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/postgresflex/user/update/update.go b/internal/cmd/postgresflex/user/update/update.go index 3ebb2231f..fa8d8e445 100644 --- a/internal/cmd/postgresflex/user/update/update.go +++ b/internal/cmd/postgresflex/user/update/update.go @@ -70,12 +70,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = model.UserId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update user %q of instance %q?", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update user %q of instance %q?", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index e00210b71..c18e083fc 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -77,12 +77,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a project under the parent with ID %q?", *model.ParentId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a project under the parent with ID %q?", *model.ParentId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/project/delete/delete.go b/internal/cmd/project/delete/delete.go index 314fb621e..14de5b63f 100644 --- a/internal/cmd/project/delete/delete.go +++ b/internal/cmd/project/delete/delete.go @@ -55,12 +55,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/project/member/add/add.go b/internal/cmd/project/member/add/add.go index d08437440..0901fba52 100644 --- a/internal/cmd/project/member/add/add.go +++ b/internal/cmd/project/member/add/add.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to add the role %q to %s on project %q?", *model.Role, model.Subject, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to add the role %q to %s on project %q?", *model.Role, model.Subject, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/project/member/remove/remove.go b/internal/cmd/project/member/remove/remove.go index 8b7089283..70a7c46d6 100644 --- a/internal/cmd/project/member/remove/remove.go +++ b/internal/cmd/project/member/remove/remove.go @@ -74,15 +74,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to remove the role %q from %s on project %q?", *model.Role, model.Subject, projectLabel) - if model.Force { - prompt = fmt.Sprintf("%s This will also remove other roles of the subject that would stop the removal of the requested role", prompt) - } - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to remove the role %q from %s on project %q?", *model.Role, model.Subject, projectLabel) + if model.Force { + prompt = fmt.Sprintf("%s This will also remove other roles of the subject that would stop the removal of the requested role", prompt) + } + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/project/update/update.go b/internal/cmd/project/update/update.go index 37e799a36..a0ee9ae4f 100644 --- a/internal/cmd/project/update/update.go +++ b/internal/cmd/project/update/update.go @@ -74,12 +74,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/public-ip/associate/associate.go b/internal/cmd/public-ip/associate/associate.go index a3ed8cc0e..357a6c87f 100644 --- a/internal/cmd/public-ip/associate/associate.go +++ b/internal/cmd/public-ip/associate/associate.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { publicIpLabel = model.PublicIpId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to associate public IP %q with resource %v?", publicIpLabel, *model.AssociatedResourceId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to associate public IP %q with resource %v?", publicIpLabel, *model.AssociatedResourceId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/public-ip/create/create.go b/internal/cmd/public-ip/create/create.go index a467529d9..a13574190 100644 --- a/internal/cmd/public-ip/create/create.go +++ b/internal/cmd/public-ip/create/create.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a public IP for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a public IP for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/public-ip/delete/delete.go b/internal/cmd/public-ip/delete/delete.go index 4cbcd1094..2bf9c234f 100644 --- a/internal/cmd/public-ip/delete/delete.go +++ b/internal/cmd/public-ip/delete/delete.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { publicIpLabel = model.PublicIpId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete public IP %q? (This cannot be undone)", publicIpLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete public IP %q? (This cannot be undone)", publicIpLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/public-ip/disassociate/disassociate.go b/internal/cmd/public-ip/disassociate/disassociate.go index 69a5dc77d..7df01b637 100644 --- a/internal/cmd/public-ip/disassociate/disassociate.go +++ b/internal/cmd/public-ip/disassociate/disassociate.go @@ -61,12 +61,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { publicIpLabel = model.PublicIpId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disassociate public IP %q from the associated resource %q?", publicIpLabel, associatedResourceId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to disassociate public IP %q from the associated resource %q?", publicIpLabel, associatedResourceId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/public-ip/update/update.go b/internal/cmd/public-ip/update/update.go index df2687a76..8fb1d8a77 100644 --- a/internal/cmd/public-ip/update/update.go +++ b/internal/cmd/public-ip/update/update.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { publicIpLabel = model.PublicIpId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update public IP %q?", publicIpLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update public IP %q?", publicIpLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/rabbitmq/credentials/create/create.go b/internal/cmd/rabbitmq/credentials/create/create.go index 9c43e2ca1..3aeea6efe 100644 --- a/internal/cmd/rabbitmq/credentials/create/create.go +++ b/internal/cmd/rabbitmq/credentials/create/create.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/rabbitmq/credentials/delete/delete.go b/internal/cmd/rabbitmq/credentials/delete/delete.go index 7dcd75143..a30d2e9d0 100644 --- a/internal/cmd/rabbitmq/credentials/delete/delete.go +++ b/internal/cmd/rabbitmq/credentials/delete/delete.go @@ -68,12 +68,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsLabel = model.CredentialsId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index 2778e082a..1ac8e7cc2 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -93,12 +93,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create an RabbitMQ instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create an RabbitMQ instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/rabbitmq/instance/delete/delete.go b/internal/cmd/rabbitmq/instance/delete/delete.go index 8be4dacfb..766ced827 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete.go +++ b/internal/cmd/rabbitmq/instance/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/rabbitmq/instance/update/update.go b/internal/cmd/rabbitmq/instance/update/update.go index f2a87e12b..d3cf53603 100644 --- a/internal/cmd/rabbitmq/instance/update/update.go +++ b/internal/cmd/rabbitmq/instance/update/update.go @@ -91,12 +91,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/redis/credentials/create/create.go b/internal/cmd/redis/credentials/create/create.go index c7793c1c7..a3e3e8e63 100644 --- a/internal/cmd/redis/credentials/create/create.go +++ b/internal/cmd/redis/credentials/create/create.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create credentials for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/redis/credentials/delete/delete.go b/internal/cmd/redis/credentials/delete/delete.go index 2209c45b1..496a43dd2 100644 --- a/internal/cmd/redis/credentials/delete/delete.go +++ b/internal/cmd/redis/credentials/delete/delete.go @@ -68,12 +68,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { credentialsLabel = model.CredentialsId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete credentials %s of instance %q? (This cannot be undone)", credentialsLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index f6b4d050c..8993b98ca 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -91,12 +91,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a Redis instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a Redis instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/redis/instance/delete/delete.go b/internal/cmd/redis/instance/delete/delete.go index 1b314ea33..0c8124906 100644 --- a/internal/cmd/redis/instance/delete/delete.go +++ b/internal/cmd/redis/instance/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/redis/instance/update/update.go b/internal/cmd/redis/instance/update/update.go index 98b192ad6..3fcc2e7b4 100644 --- a/internal/cmd/redis/instance/update/update.go +++ b/internal/cmd/redis/instance/update/update.go @@ -88,12 +88,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 33b38ebfa..ccb1b9f5a 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -62,7 +62,9 @@ func NewRootCmd(version, date string, p *print.Printer) *cobra.Command { DisableAutoGenTag: true, PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { p.Cmd = cmd - p.Verbosity = print.Level(globalflags.Parse(p, cmd).Verbosity) + globalFlags := globalflags.Parse(p, cmd) + p.Verbosity = print.Level(globalFlags.Verbosity) + p.AssumeYes = globalFlags.AssumeYes argsString := print.BuildDebugStrFromSlice(os.Args) p.Debug(print.DebugLevel, "arguments: %s", argsString) @@ -209,6 +211,7 @@ func Execute(version, date string) { // We need to set the printer and verbosity here because the // PersistentPreRun is not called when the command is wrongly called + // In this case Printer.AssumeYes isn't set either, but `false` as default is acceptable p.Cmd = cmd p.Verbosity = print.InfoLevel diff --git a/internal/cmd/secrets-manager/instance/create/create.go b/internal/cmd/secrets-manager/instance/create/create.go index abc0bb5f2..0c6d8420b 100644 --- a/internal/cmd/secrets-manager/instance/create/create.go +++ b/internal/cmd/secrets-manager/instance/create/create.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a Secrets Manager instance for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a Secrets Manager instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API to create instance diff --git a/internal/cmd/secrets-manager/instance/delete/delete.go b/internal/cmd/secrets-manager/instance/delete/delete.go index ec8148e34..94ed3385a 100644 --- a/internal/cmd/secrets-manager/instance/delete/delete.go +++ b/internal/cmd/secrets-manager/instance/delete/delete.go @@ -57,12 +57,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete instance %q? (This cannot be undone)", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/secrets-manager/instance/update/update.go b/internal/cmd/secrets-manager/instance/update/update.go index c3cfb5956..58786ffd6 100644 --- a/internal/cmd/secrets-manager/instance/update/update.go +++ b/internal/cmd/secrets-manager/instance/update/update.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/secrets-manager/user/create/create.go b/internal/cmd/secrets-manager/user/create/create.go index eba0d736b..1584b5cf5 100644 --- a/internal/cmd/secrets-manager/user/create/create.go +++ b/internal/cmd/secrets-manager/user/create/create.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { instanceLabel = model.InstanceId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/secrets-manager/user/delete/delete.go b/internal/cmd/secrets-manager/user/delete/delete.go index e2ad75eb5..65193fac3 100644 --- a/internal/cmd/secrets-manager/user/delete/delete.go +++ b/internal/cmd/secrets-manager/user/delete/delete.go @@ -72,12 +72,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = fmt.Sprintf("%q", model.UserId) } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete user %s of instance %q? (This cannot be undone)", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete user %s of instance %q? (This cannot be undone)", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/secrets-manager/user/update/update.go b/internal/cmd/secrets-manager/user/update/update.go index 31a8e5a6e..38507699b 100644 --- a/internal/cmd/secrets-manager/user/update/update.go +++ b/internal/cmd/secrets-manager/user/update/update.go @@ -76,12 +76,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { userLabel = fmt.Sprintf("%q", model.UserId) } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update user %s of instance %q?", userLabel, instanceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update user %s of instance %q?", userLabel, instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/security-group/create/create.go b/internal/cmd/security-group/create/create.go index b5e7143a2..5c52d133a 100644 --- a/internal/cmd/security-group/create/create.go +++ b/internal/cmd/security-group/create/create.go @@ -56,12 +56,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create the security group %q?", *model.Name) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create the security group %q?", *model.Name) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/security-group/delete/delete.go b/internal/cmd/security-group/delete/delete.go index 37c0b283c..1950d712b 100644 --- a/internal/cmd/security-group/delete/delete.go +++ b/internal/cmd/security-group/delete/delete.go @@ -60,12 +60,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { groupLabel = model.SecurityGroupId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the security group %q for %q?", groupLabel, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the security group %q for %q?", groupLabel, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/security-group/rule/create/create.go b/internal/cmd/security-group/rule/create/create.go index 5e08c09b0..b2f443ace 100644 --- a/internal/cmd/security-group/rule/create/create.go +++ b/internal/cmd/security-group/rule/create/create.go @@ -101,12 +101,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { securityGroupLabel = model.SecurityGroupId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a security group rule for security group %q for project %q?", securityGroupLabel, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a security group rule for security group %q for project %q?", securityGroupLabel, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/security-group/rule/delete/delete.go b/internal/cmd/security-group/rule/delete/delete.go index 722142f9d..388e3b0b7 100644 --- a/internal/cmd/security-group/rule/delete/delete.go +++ b/internal/cmd/security-group/rule/delete/delete.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { securityGroupRuleLabel = model.SecurityGroupRuleId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete security group rule %q from security group %q?", securityGroupRuleLabel, securityGroupLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete security group rule %q from security group %q?", securityGroupRuleLabel, securityGroupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/security-group/update/update.go b/internal/cmd/security-group/update/update.go index 5a5039fa9..6f612f744 100644 --- a/internal/cmd/security-group/update/update.go +++ b/internal/cmd/security-group/update/update.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { groupLabel = model.SecurityGroupId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update the security group %q?", groupLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update the security group %q?", groupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/create/create.go b/internal/cmd/server/backup/create/create.go index c2ab4b028..50b36dce4 100644 --- a/internal/cmd/server/backup/create/create.go +++ b/internal/cmd/server/backup/create/create.go @@ -79,12 +79,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a Backup for server %s?", model.ServerId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a Backup for server %s?", model.ServerId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/delete/delete.go b/internal/cmd/server/backup/delete/delete.go index e4cb8118d..5eedcde2d 100644 --- a/internal/cmd/server/backup/delete/delete.go +++ b/internal/cmd/server/backup/delete/delete.go @@ -54,12 +54,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete server backup %q? (This cannot be undone)", model.BackupId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete server backup %q? (This cannot be undone)", model.BackupId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/disable/disable.go b/internal/cmd/server/backup/disable/disable.go index a9cc28ac4..4aecf6553 100644 --- a/internal/cmd/server/backup/disable/disable.go +++ b/internal/cmd/server/backup/disable/disable.go @@ -74,12 +74,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return nil } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable the backup service for server %s?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to disable the backup service for server %s?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/enable/enable.go b/internal/cmd/server/backup/enable/enable.go index 419d54076..7f6854be3 100644 --- a/internal/cmd/server/backup/enable/enable.go +++ b/internal/cmd/server/backup/enable/enable.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable the Server Backup service for server %s?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to enable the Server Backup service for server %s?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/restore/restore.go b/internal/cmd/server/backup/restore/restore.go index 8d3899dd5..b55b2b465 100644 --- a/internal/cmd/server/backup/restore/restore.go +++ b/internal/cmd/server/backup/restore/restore.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to restore server backup %q? (This cannot be undone)", model.BackupId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to restore server backup %q? (This cannot be undone)", model.BackupId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/schedule/create/create.go b/internal/cmd/server/backup/schedule/create/create.go index 9f113f0e6..6b722c0b0 100644 --- a/internal/cmd/server/backup/schedule/create/create.go +++ b/internal/cmd/server/backup/schedule/create/create.go @@ -87,12 +87,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a Backup Schedule for server %s?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a Backup Schedule for server %s?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/schedule/delete/delete.go b/internal/cmd/server/backup/schedule/delete/delete.go index 498f7cacd..42e4c07ef 100644 --- a/internal/cmd/server/backup/schedule/delete/delete.go +++ b/internal/cmd/server/backup/schedule/delete/delete.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete server backup schedule %q? (This cannot be undone)", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete server backup schedule %q? (This cannot be undone)", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/schedule/update/update.go b/internal/cmd/server/backup/schedule/update/update.go index 3a54a12eb..d16db4d63 100644 --- a/internal/cmd/server/backup/schedule/update/update.go +++ b/internal/cmd/server/backup/schedule/update/update.go @@ -82,12 +82,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update Server Backup Schedule %q?", model.BackupScheduleId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update Server Backup Schedule %q?", model.BackupScheduleId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/volume-backup/delete/delete.go b/internal/cmd/server/backup/volume-backup/delete/delete.go index f13d85633..1a7241bba 100644 --- a/internal/cmd/server/backup/volume-backup/delete/delete.go +++ b/internal/cmd/server/backup/volume-backup/delete/delete.go @@ -56,12 +56,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete server volume backup %q? (This cannot be undone)", model.VolumeId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete server volume backup %q? (This cannot be undone)", model.VolumeId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/backup/volume-backup/restore/restore.go b/internal/cmd/server/backup/volume-backup/restore/restore.go index 676b5135e..343f4ade8 100644 --- a/internal/cmd/server/backup/volume-backup/restore/restore.go +++ b/internal/cmd/server/backup/volume-backup/restore/restore.go @@ -58,12 +58,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to restore volume backup %q? (This cannot be undone)", model.VolumeBackupId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to restore volume backup %q? (This cannot be undone)", model.VolumeBackupId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/command/create/create.go b/internal/cmd/server/command/create/create.go index 1937f4e28..1561ab3b5 100644 --- a/internal/cmd/server/command/create/create.go +++ b/internal/cmd/server/command/create/create.go @@ -75,12 +75,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a Command for server %s?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a Command for server %s?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 86f0af5dc..a93efcbf7 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -128,12 +128,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a server for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a server for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/deallocate/deallocate.go b/internal/cmd/server/deallocate/deallocate.go index 9c8d7971c..bed42bf7a 100644 --- a/internal/cmd/server/deallocate/deallocate.go +++ b/internal/cmd/server/deallocate/deallocate.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to deallocate server %q?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to deallocate server %q?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/delete/delete.go b/internal/cmd/server/delete/delete.go index 85c264b5e..412c099dc 100644 --- a/internal/cmd/server/delete/delete.go +++ b/internal/cmd/server/delete/delete.go @@ -66,12 +66,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete server %q?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete server %q?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/network-interface/attach/attach.go b/internal/cmd/server/network-interface/attach/attach.go index 3e98a366e..5bcf7ed6d 100644 --- a/internal/cmd/server/network-interface/attach/attach.go +++ b/internal/cmd/server/network-interface/attach/attach.go @@ -78,13 +78,12 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = *model.NetworkId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a network interface for network %q and attach it to server %q?", networkLabel, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a network interface for network %q and attach it to server %q?", networkLabel, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } + // Call API req := buildRequestCreateAndAttach(ctx, model, apiClient) err = req.Execute() @@ -95,13 +94,12 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return nil } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to attach network interface %q to server %q?", *model.NicId, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to attach network interface %q to server %q?", *model.NicId, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } + // Call API req := buildRequestAttach(ctx, model, apiClient) err = req.Execute() diff --git a/internal/cmd/server/network-interface/detach/detach.go b/internal/cmd/server/network-interface/detach/detach.go index 1e8babe16..ed891e912 100644 --- a/internal/cmd/server/network-interface/detach/detach.go +++ b/internal/cmd/server/network-interface/detach/detach.go @@ -80,13 +80,12 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get network name: %v", err) networkLabel = *model.NetworkId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to detach and delete all network interfaces of network %q from server %q? (This cannot be undone)", networkLabel, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to detach and delete all network interfaces of network %q from server %q? (This cannot be undone)", networkLabel, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } + // Call API req := buildRequestDetachAndDelete(ctx, model, apiClient) err = req.Execute() @@ -97,13 +96,12 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return nil } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to detach network interface %q from server %q?", *model.NicId, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to detach network interface %q from server %q?", *model.NicId, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } + // Call API req := buildRequestDetach(ctx, model, apiClient) err = req.Execute() diff --git a/internal/cmd/server/os-update/create/create.go b/internal/cmd/server/os-update/create/create.go index eac250845..1d1ad8962 100644 --- a/internal/cmd/server/os-update/create/create.go +++ b/internal/cmd/server/os-update/create/create.go @@ -74,12 +74,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a os-update for server %s?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a os-update for server %s?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/os-update/disable/disable.go b/internal/cmd/server/os-update/disable/disable.go index c0cc0bb8d..c2a308710 100644 --- a/internal/cmd/server/os-update/disable/disable.go +++ b/internal/cmd/server/os-update/disable/disable.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable the os-update service for server %s?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to disable the os-update service for server %s?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/os-update/enable/enable.go b/internal/cmd/server/os-update/enable/enable.go index 5e25334bb..0d4630c45 100644 --- a/internal/cmd/server/os-update/enable/enable.go +++ b/internal/cmd/server/os-update/enable/enable.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable the server os-update service for server %s?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to enable the server os-update service for server %s?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/os-update/schedule/create/create.go b/internal/cmd/server/os-update/schedule/create/create.go index 446859534..421a173c6 100644 --- a/internal/cmd/server/os-update/schedule/create/create.go +++ b/internal/cmd/server/os-update/schedule/create/create.go @@ -82,12 +82,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a os-update Schedule for server %s?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a os-update Schedule for server %s?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/os-update/schedule/delete/delete.go b/internal/cmd/server/os-update/schedule/delete/delete.go index de1d19d3e..b26084c9a 100644 --- a/internal/cmd/server/os-update/schedule/delete/delete.go +++ b/internal/cmd/server/os-update/schedule/delete/delete.go @@ -53,12 +53,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete server os-update schedule %q? (This cannot be undone)", model.ScheduleId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete server os-update schedule %q? (This cannot be undone)", model.ScheduleId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/os-update/schedule/update/update.go b/internal/cmd/server/os-update/schedule/update/update.go index 59ca210b1..72c3f92f4 100644 --- a/internal/cmd/server/os-update/schedule/update/update.go +++ b/internal/cmd/server/os-update/schedule/update/update.go @@ -74,12 +74,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update Server os-update Schedule %q?", model.ScheduleId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update Server os-update Schedule %q?", model.ScheduleId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/public-ip/attach/attach.go b/internal/cmd/server/public-ip/attach/attach.go index 52ef99867..7532eac13 100644 --- a/internal/cmd/server/public-ip/attach/attach.go +++ b/internal/cmd/server/public-ip/attach/attach.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to attach public IP %q to server %q?", publicIpLabel, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to attach public IP %q to server %q?", publicIpLabel, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/public-ip/detach/detach.go b/internal/cmd/server/public-ip/detach/detach.go index adfa2ad47..8c85195e9 100644 --- a/internal/cmd/server/public-ip/detach/detach.go +++ b/internal/cmd/server/public-ip/detach/detach.go @@ -72,12 +72,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to detach public IP %q from server %q?", publicIpLabel, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to detach public IP %q from server %q?", publicIpLabel, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/reboot/reboot.go b/internal/cmd/server/reboot/reboot.go index 4f4b3e268..bf689cfcc 100644 --- a/internal/cmd/server/reboot/reboot.go +++ b/internal/cmd/server/reboot/reboot.go @@ -70,12 +70,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } else if serverLabel == "" { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to reboot server %q?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to reboot server %q?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/rescue/rescue.go b/internal/cmd/server/rescue/rescue.go index 746fbadc4..dd77e4625 100644 --- a/internal/cmd/server/rescue/rescue.go +++ b/internal/cmd/server/rescue/rescue.go @@ -67,12 +67,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to rescue server %q?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to rescue server %q?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/resize/resize.go b/internal/cmd/server/resize/resize.go index d2a7836a2..804dbce1a 100644 --- a/internal/cmd/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -67,12 +67,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to resize server %q to machine type %q?", serverLabel, *model.MachineType) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to resize server %q to machine type %q?", serverLabel, *model.MachineType) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 1bf853199..e7c7ea762 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to attach service account %q to server %q?", model.ServiceAccMail, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to attach service account %q to server %q?", model.ServiceAccMail, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index ab9fbbe03..00830e7d6 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are your sure you want to detach service account %q from a server %q?", model.ServiceAccMail, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are your sure you want to detach service account %q from a server %q?", model.ServiceAccMail, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/stop/stop.go b/internal/cmd/server/stop/stop.go index 07a8008c3..a7a9b4604 100644 --- a/internal/cmd/server/stop/stop.go +++ b/internal/cmd/server/stop/stop.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to stop server %q?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to stop server %q?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/unrescue/unrescue.go b/internal/cmd/server/unrescue/unrescue.go index e65d13d6e..f47ef6794 100644 --- a/internal/cmd/server/unrescue/unrescue.go +++ b/internal/cmd/server/unrescue/unrescue.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to unrescue server %q?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to unrescue server %q?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/update/update.go b/internal/cmd/server/update/update.go index 76973b91c..7349d1c28 100644 --- a/internal/cmd/server/update/update.go +++ b/internal/cmd/server/update/update.go @@ -70,12 +70,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update server %q?", serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update server %q?", serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/volume/attach/attach.go b/internal/cmd/server/volume/attach/attach.go index f8bf74a2f..27c734f8d 100644 --- a/internal/cmd/server/volume/attach/attach.go +++ b/internal/cmd/server/volume/attach/attach.go @@ -78,12 +78,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to attach volume %q to server %q?", volumeLabel, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to attach volume %q to server %q?", volumeLabel, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/volume/detach/detach.go b/internal/cmd/server/volume/detach/detach.go index 7ae8dee8e..0c8081a5d 100644 --- a/internal/cmd/server/volume/detach/detach.go +++ b/internal/cmd/server/volume/detach/detach.go @@ -70,12 +70,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to detach volume %q from server %q?", volumeLabel, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to detach volume %q from server %q?", volumeLabel, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/server/volume/update/update.go b/internal/cmd/server/volume/update/update.go index b3faf2d2f..4ba1a9342 100644 --- a/internal/cmd/server/volume/update/update.go +++ b/internal/cmd/server/volume/update/update.go @@ -74,12 +74,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { serverLabel = model.ServerId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update attached volume %q of server %q?", volumeLabel, serverLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update attached volume %q of server %q?", volumeLabel, serverLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/service-account/create/create.go b/internal/cmd/service-account/create/create.go index aca5c8133..8d9daf092 100644 --- a/internal/cmd/service-account/create/create.go +++ b/internal/cmd/service-account/create/create.go @@ -59,12 +59,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a service account for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a service account for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/service-account/delete/delete.go b/internal/cmd/service-account/delete/delete.go index ff843534d..eefc8a3e3 100644 --- a/internal/cmd/service-account/delete/delete.go +++ b/internal/cmd/service-account/delete/delete.go @@ -50,12 +50,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete service account %s? (This cannot be undone)", model.Email) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete service account %s? (This cannot be undone)", model.Email) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/service-account/key/create/create.go b/internal/cmd/service-account/key/create/create.go index 6af133cdc..49bdd3918 100644 --- a/internal/cmd/service-account/key/create/create.go +++ b/internal/cmd/service-account/key/create/create.go @@ -69,16 +69,14 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - validUntilInfo := "The key will be valid until deleted" - if model.ExpiresInDays != nil { - validUntilInfo = fmt.Sprintf("The key will be valid for %d days", *model.ExpiresInDays) - } - prompt := fmt.Sprintf("Are you sure you want to create a key for service account %s? %s", model.ServiceAccountEmail, validUntilInfo) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + validUntilInfo := "The key will be valid until deleted" + if model.ExpiresInDays != nil { + validUntilInfo = fmt.Sprintf("The key will be valid for %d days", *model.ExpiresInDays) + } + prompt := fmt.Sprintf("Are you sure you want to create a key for service account %s? %s", model.ServiceAccountEmail, validUntilInfo) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/service-account/key/delete/delete.go b/internal/cmd/service-account/key/delete/delete.go index b6ff682d8..c468d72a7 100644 --- a/internal/cmd/service-account/key/delete/delete.go +++ b/internal/cmd/service-account/key/delete/delete.go @@ -56,12 +56,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete the key %s from service account %s?", model.KeyId, model.ServiceAccountEmail) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete the key %s from service account %s?", model.KeyId, model.ServiceAccountEmail) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/service-account/key/update/update.go b/internal/cmd/service-account/key/update/update.go index fd5d3383a..5594396e4 100644 --- a/internal/cmd/service-account/key/update/update.go +++ b/internal/cmd/service-account/key/update/update.go @@ -73,12 +73,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update the key with ID %q?", model.KeyId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update the key with ID %q?", model.KeyId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/service-account/token/create/create.go b/internal/cmd/service-account/token/create/create.go index ea0b1f39d..a3286219b 100644 --- a/internal/cmd/service-account/token/create/create.go +++ b/internal/cmd/service-account/token/create/create.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create an access token for service account %s?", model.ServiceAccountEmail) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create an access token for service account %s?", model.ServiceAccountEmail) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/service-account/token/revoke/revoke.go b/internal/cmd/service-account/token/revoke/revoke.go index ee3c05a81..2a892e005 100644 --- a/internal/cmd/service-account/token/revoke/revoke.go +++ b/internal/cmd/service-account/token/revoke/revoke.go @@ -59,12 +59,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to revoke the access token with ID %q?", model.TokenId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to revoke the access token with ID %q?", model.TokenId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index 18113539b..1602e3680 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -82,12 +82,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a cluster for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a cluster for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Configure ServiceEnable API client diff --git a/internal/cmd/ske/cluster/delete/delete.go b/internal/cmd/ske/cluster/delete/delete.go index fc8b70978..34de6f2c7 100644 --- a/internal/cmd/ske/cluster/delete/delete.go +++ b/internal/cmd/ske/cluster/delete/delete.go @@ -52,12 +52,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete cluster %q? (This cannot be undone)", model.ClusterName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete cluster %q? (This cannot be undone)", model.ClusterName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/ske/cluster/hibernate/hibernate.go b/internal/cmd/ske/cluster/hibernate/hibernate.go index ce4c416e5..5e679e38b 100644 --- a/internal/cmd/ske/cluster/hibernate/hibernate.go +++ b/internal/cmd/ske/cluster/hibernate/hibernate.go @@ -57,12 +57,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to trigger hibernate for %q in project %q?", model.ClusterName, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to trigger hibernate for %q in project %q?", model.ClusterName, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/ske/cluster/maintenance/maintenance.go b/internal/cmd/ske/cluster/maintenance/maintenance.go index cc3c1ab1d..0b5f406ca 100644 --- a/internal/cmd/ske/cluster/maintenance/maintenance.go +++ b/internal/cmd/ske/cluster/maintenance/maintenance.go @@ -57,12 +57,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to trigger maintenance for %q in project %q?", model.ClusterName, projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to trigger maintenance for %q in project %q?", model.ClusterName, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index e59fa9990..6150a9bda 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -70,12 +70,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update cluster %q?", model.ClusterName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update cluster %q?", model.ClusterName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Check if cluster exists diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go index 5fc0f81bb..25f2601aa 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go @@ -69,12 +69,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to complete the rotation of the credentials for SKE cluster %q?", model.ClusterName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to complete the rotation of the credentials for SKE cluster %q?", model.ClusterName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation.go b/internal/cmd/ske/credentials/start-rotation/start_rotation.go index fa239775a..3cb3cee55 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation.go @@ -72,12 +72,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to start the rotation of the credentials for SKE cluster %q?", model.ClusterName) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to start the rotation of the credentials for SKE cluster %q?", model.ClusterName) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index cd2dc87db..075711b1a 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -55,12 +55,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable SKE for project %q? (This will delete all associated clusters)", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to disable SKE for project %q? (This will delete all associated clusters)", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index 411140edc..366f8d5f2 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -55,12 +55,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable SKE for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to enable SKE for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/ske/kubeconfig/create/create.go b/internal/cmd/ske/kubeconfig/create/create.go index 725c53636..355364098 100644 --- a/internal/cmd/ske/kubeconfig/create/create.go +++ b/internal/cmd/ske/kubeconfig/create/create.go @@ -90,7 +90,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - if !model.AssumeYes && !model.DisableWriting { + if !model.DisableWriting { var prompt string if model.Overwrite { prompt = fmt.Sprintf("Are you sure you want to create a kubeconfig for SKE cluster %q? This will OVERWRITE your current kubeconfig file, if it exists.", model.ClusterName) diff --git a/internal/cmd/volume/backup/create/create.go b/internal/cmd/volume/backup/create/create.go index 3673b6ac8..fc9e0b3cd 100644 --- a/internal/cmd/volume/backup/create/create.go +++ b/internal/cmd/volume/backup/create/create.go @@ -96,12 +96,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create backup from %s? (This cannot be undone)", sourceLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create backup from %s? (This cannot be undone)", sourceLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/backup/delete/delete.go b/internal/cmd/volume/backup/delete/delete.go index e8e2ce676..9c9717427 100644 --- a/internal/cmd/volume/backup/delete/delete.go +++ b/internal/cmd/volume/backup/delete/delete.go @@ -58,12 +58,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get backup name: %v", err) } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete backup %q? (This cannot be undone)", backupLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete backup %q? (This cannot be undone)", backupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/backup/restore/restore.go b/internal/cmd/volume/backup/restore/restore.go index 29239a7fe..63fc0d915 100644 --- a/internal/cmd/volume/backup/restore/restore.go +++ b/internal/cmd/volume/backup/restore/restore.go @@ -71,12 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to restore %q with backup %q? (This cannot be undone)", sourceLabel, backupLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to restore %q with backup %q? (This cannot be undone)", sourceLabel, backupLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/backup/update/update.go b/internal/cmd/volume/backup/update/update.go index 02fe3703a..9141f9a2b 100644 --- a/internal/cmd/volume/backup/update/update.go +++ b/internal/cmd/volume/backup/update/update.go @@ -65,12 +65,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get backup name: %v", err) } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update backup %q? (This cannot be undone)", model.BackupId) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update backup %q? (This cannot be undone)", model.BackupId) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index 8b3a536a5..f0bda5f69 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -88,12 +88,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { projectLabel = model.ProjectId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create a volume for project %q?", projectLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create a volume for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go index f6550714c..599f3bf56 100644 --- a/internal/cmd/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -64,12 +64,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { volumeLabel = model.VolumeId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete volume %q?", volumeLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete volume %q?", volumeLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/resize/resize.go b/internal/cmd/volume/resize/resize.go index 7bcc40dc0..0bfbc0797 100644 --- a/internal/cmd/volume/resize/resize.go +++ b/internal/cmd/volume/resize/resize.go @@ -63,12 +63,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { volumeLabel = model.VolumeId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to resize volume %q?", volumeLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to resize volume %q?", volumeLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/snapshot/create/create.go b/internal/cmd/volume/snapshot/create/create.go index 29dd2894c..f63a38b16 100644 --- a/internal/cmd/volume/snapshot/create/create.go +++ b/internal/cmd/volume/snapshot/create/create.go @@ -79,12 +79,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { volumeLabel = model.VolumeID } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to create snapshot from volume %q? (This cannot be undone)", volumeLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to create snapshot from volume %q? (This cannot be undone)", volumeLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/snapshot/delete/delete.go b/internal/cmd/volume/snapshot/delete/delete.go index c4c06b34d..7334cac51 100644 --- a/internal/cmd/volume/snapshot/delete/delete.go +++ b/internal/cmd/volume/snapshot/delete/delete.go @@ -61,12 +61,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { snapshotLabel = model.SnapshotId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to delete snapshot %q? (This cannot be undone)", snapshotLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to delete snapshot %q? (This cannot be undone)", snapshotLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/snapshot/update/update.go b/internal/cmd/volume/snapshot/update/update.go index b43072bce..f48649743 100644 --- a/internal/cmd/volume/snapshot/update/update.go +++ b/internal/cmd/volume/snapshot/update/update.go @@ -67,12 +67,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { snapshotLabel = model.SnapshotId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update snapshot %q?", snapshotLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update snapshot %q?", snapshotLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/cmd/volume/update/update.go b/internal/cmd/volume/update/update.go index 194a70db3..3c8f447d3 100644 --- a/internal/cmd/volume/update/update.go +++ b/internal/cmd/volume/update/update.go @@ -74,12 +74,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { volumeLabel = model.VolumeId } - if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to update volume %q?", volumeLabel) - err = params.Printer.PromptForConfirmation(prompt) - if err != nil { - return err - } + prompt := fmt.Sprintf("Are you sure you want to update volume %q?", volumeLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err } // Call API diff --git a/internal/pkg/print/print.go b/internal/pkg/print/print.go index d8e06a25c..4098b9cb5 100644 --- a/internal/pkg/print/print.go +++ b/internal/pkg/print/print.go @@ -51,6 +51,7 @@ var ( type Printer struct { Cmd *cobra.Command + AssumeYes bool Verbosity Level } @@ -134,6 +135,10 @@ func (p *Printer) Error(msg string, args ...any) { // Returns nil only if the user (explicitly) answers positive. // Returns ErrAborted if the user answers negative. func (p *Printer) PromptForConfirmation(prompt string) error { + if p.AssumeYes { + p.Warn("Auto-confirming prompt: %q\n", prompt) + return nil + } question := fmt.Sprintf("%s [y/N] ", prompt) reader := bufio.NewReader(p.Cmd.InOrStdin()) for i := 0; i < 3; i++ { @@ -157,6 +162,10 @@ func (p *Printer) PromptForConfirmation(prompt string) error { // // Returns nil if the user presses Enter. func (p *Printer) PromptForEnter(prompt string) error { + if p.AssumeYes { + p.Warn("Auto-confirming prompt: %q", prompt) + return nil + } reader := bufio.NewReader(p.Cmd.InOrStdin()) p.Cmd.PrintErr(prompt) _, err := reader.ReadString('\n') diff --git a/internal/pkg/print/print_test.go b/internal/pkg/print/print_test.go index 8cb2e8ee2..d52af5241 100644 --- a/internal/pkg/print/print_test.go +++ b/internal/pkg/print/print_test.go @@ -509,6 +509,7 @@ func TestPromptForConfirmation(t *testing.T) { verbosity Level isValid bool isAborted bool + assumeYes bool }{ // Note: Some of these inputs have normal spaces, others have tabs { @@ -647,6 +648,13 @@ func TestPromptForConfirmation(t *testing.T) { verbosity: DebugLevel, isValid: false, }, + { + description: "no input with assume yes", + input: "", + verbosity: DebugLevel, + isValid: true, + assumeYes: true, + }, } for _, tt := range tests { @@ -665,6 +673,7 @@ func TestPromptForConfirmation(t *testing.T) { p := &Printer{ Cmd: cmd, Verbosity: tt.verbosity, + AssumeYes: tt.assumeYes, } err = p.PromptForConfirmation("") From 1a43e78a17b76bce2e9587fb40914d8b8711aa34 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 13 Jan 2026 10:26:16 +0100 Subject: [PATCH 601/619] chore(deps): update module golang.org/x/tools to v0.41.0 (#1225) Co-authored-by: Renovate Bot --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 617c54c23..656654080 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( ) require ( - golang.org/x/net v0.48.0 // indirect + golang.org/x/net v0.49.0 // indirect golang.org/x/time v0.11.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) @@ -232,8 +232,8 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/sync v0.19.0 // indirect - golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc // indirect - golang.org/x/tools v0.40.0 // indirect + golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 // indirect + golang.org/x/tools v0.41.0 // indirect google.golang.org/protobuf v1.36.8 // indirect honnef.co/go/tools v0.6.1 // indirect mvdan.cc/gofumpt v0.9.2 // indirect diff --git a/go.sum b/go.sum index e3a7f587a..0d69feaf8 100644 --- a/go.sum +++ b/go.sum @@ -834,8 +834,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -913,8 +913,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc h1:bH6xUXay0AIFMElXG2rQ4uiE+7ncwtiOdPfYK1NK2XA= -golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= +golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 h1:O1cMQHRfwNpDfDJerqRoE2oD+AFlyid87D40L/OkkJo= +golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -992,8 +992,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= -golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= From c0f0576c84a9ead91bf2c9f501f30b007cc8ad24 Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Tue, 13 Jan 2026 10:32:47 +0100 Subject: [PATCH 602/619] chore(deps): update renovatebot/github-action action to v44.2.4 (#1224) Co-authored-by: Renovate Bot --- .github/workflows/renovate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 4716838ca..c2e439819 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -13,7 +13,7 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Self-hosted Renovate - uses: renovatebot/github-action@v44.2.3 + uses: renovatebot/github-action@v44.2.4 with: configurationFile: .github/renovate.json token: ${{ secrets.RENOVATE_TOKEN }} From c00da4622bbc1078a20b1abf3897e961d67d406e Mon Sep 17 00:00:00 2001 From: Robert Gogolok Date: Tue, 13 Jan 2026 11:47:30 +0100 Subject: [PATCH 603/619] feat(goreleaser): Ship FreeBSD binaries (#1048) * feat(goreleaser): Ship FreeBSD binaries * Add FreeBSD installation instructions --------- Co-authored-by: cgoetz-inovex --- .goreleaser.yaml | 11 +++++++++++ INSTALLATION.md | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index b86115c5f..2ef5c2ad1 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -53,6 +53,16 @@ builds: - cmd: sh -c 'go run main.go completion bash > ./dist/completions/stackit.bash' - cmd: sh -c 'go run main.go completion fish > ./dist/completions/stackit.fish' + - id: freebsd-builds + env: + - CGO_ENABLED=0 + goos: + - freebsd + goarch: + - arm64 + - amd64 + binary: "stackit" + archives: - id: windows-archives ids: @@ -61,6 +71,7 @@ archives: - ids: - linux-builds - macos-builds + - freebsd-builds formats: [ 'tar.gz' ] files: - src: ./dist/completions/* diff --git a/INSTALLATION.md b/INSTALLATION.md index c2e7bf751..14976fe69 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -215,6 +215,24 @@ You can also get the STACKIT CLI by compiling it from source or downloading a pr go run . ``` +### FreeBSD + +The STACKIT CLI can be installed through the [FreeBSD ports or packages](https://docs.freebsd.org/en/books/handbook/ports/). + +To install the port: + +```shell +cd /usr/ports/sysutils/stackit/ && make install clean +``` + +To add the package, run one of these commands: + +```shell +pkg install sysutils/stackit +# OR +pkg install stackit +``` + ### Pre-compiled binary 1. Download the binary corresponding to your operating system and CPU architecture from our [Releases](https://github.com/stackitcloud/stackit-cli/releases) page From e2123e2e321248e0d993d0e9e00756b359aaa123 Mon Sep 17 00:00:00 2001 From: Robert Ruf <240721653+RobertRuf@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:10:24 +0100 Subject: [PATCH 604/619] Initial release of the STACKIT Edge-Cloud service CLI (BETA) (#1223) * Add new custom error types * Add new test utils * Initial Release of the STACKIT Edge-Cloud service CLI --- docs/stackit_beta.md | 1 + docs/stackit_beta_edge-cloud.md | 37 + docs/stackit_beta_edge-cloud_instance.md | 38 + ...stackit_beta_edge-cloud_instance_create.md | 43 + ...stackit_beta_edge-cloud_instance_delete.md | 45 + ...ackit_beta_edge-cloud_instance_describe.md | 45 + docs/stackit_beta_edge-cloud_instance_list.md | 44 + ...stackit_beta_edge-cloud_instance_update.md | 50 ++ docs/stackit_beta_edge-cloud_kubeconfig.md | 34 + ...ackit_beta_edge-cloud_kubeconfig_create.md | 61 ++ docs/stackit_beta_edge-cloud_plans.md | 34 + docs/stackit_beta_edge-cloud_plans_list.md | 44 + docs/stackit_beta_edge-cloud_token.md | 34 + docs/stackit_beta_edge-cloud_token_create.md | 49 ++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 2 + internal/cmd/beta/beta.go | 2 + internal/cmd/beta/edge/edge.go | 34 + .../cmd/beta/edge/instance/create/create.go | 228 +++++ .../beta/edge/instance/create/create_test.go | 419 +++++++++ .../cmd/beta/edge/instance/delete/delete.go | 241 +++++ .../beta/edge/instance/delete/delete_test.go | 557 ++++++++++++ .../beta/edge/instance/describe/describe.go | 203 +++++ .../edge/instance/describe/describe_test.go | 575 ++++++++++++ internal/cmd/beta/edge/instance/instance.go | 38 + internal/cmd/beta/edge/instance/list/list.go | 194 +++++ .../cmd/beta/edge/instance/list/list_test.go | 460 ++++++++++ .../cmd/beta/edge/instance/update/update.go | 281 ++++++ .../beta/edge/instance/update/update_test.go | 541 ++++++++++++ .../cmd/beta/edge/kubeconfig/create/create.go | 396 +++++++++ .../edge/kubeconfig/create/create_test.go | 820 ++++++++++++++++++ .../cmd/beta/edge/kubeconfig/kubeconfig.go | 29 + internal/cmd/beta/edge/plans/list/list.go | 193 +++++ .../cmd/beta/edge/plans/list/list_test.go | 450 ++++++++++ internal/cmd/beta/edge/plans/plans.go | 29 + internal/cmd/beta/edge/token/create/create.go | 291 +++++++ .../cmd/beta/edge/token/create/create_test.go | 675 ++++++++++++++ internal/cmd/beta/edge/token/token.go | 29 + .../profile/import/template/profile.json | 3 +- internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 13 + internal/pkg/config/config.go | 3 + .../pkg/config/template/test_profile.json | 3 +- internal/pkg/errors/errors.go | 136 +++ internal/pkg/errors/errors_test.go | 243 ++++++ internal/pkg/services/edge/client/client.go | 36 + .../pkg/services/edge/common/error/error.go | 85 ++ .../services/edge/common/error/error_test.go | 180 ++++ .../services/edge/common/instance/instance.go | 140 +++ .../edge/common/instance/instance_test.go | 348 ++++++++ .../edge/common/kubeconfig/kubeconfig.go | 361 ++++++++ .../edge/common/kubeconfig/kubeconfig_test.go | 744 ++++++++++++++++ .../services/edge/common/validation/input.go | 51 ++ .../edge/common/validation/input_test.go | 81 ++ internal/pkg/testutils/assert.go | 181 ++++ internal/pkg/testutils/assert_test.go | 227 +++++ internal/pkg/testutils/parse_input.go | 126 +++ internal/pkg/testutils/parse_input_test.go | 169 ++++ 61 files changed, 10388 insertions(+), 2 deletions(-) create mode 100644 docs/stackit_beta_edge-cloud.md create mode 100644 docs/stackit_beta_edge-cloud_instance.md create mode 100644 docs/stackit_beta_edge-cloud_instance_create.md create mode 100644 docs/stackit_beta_edge-cloud_instance_delete.md create mode 100644 docs/stackit_beta_edge-cloud_instance_describe.md create mode 100644 docs/stackit_beta_edge-cloud_instance_list.md create mode 100644 docs/stackit_beta_edge-cloud_instance_update.md create mode 100644 docs/stackit_beta_edge-cloud_kubeconfig.md create mode 100644 docs/stackit_beta_edge-cloud_kubeconfig_create.md create mode 100644 docs/stackit_beta_edge-cloud_plans.md create mode 100644 docs/stackit_beta_edge-cloud_plans_list.md create mode 100644 docs/stackit_beta_edge-cloud_token.md create mode 100644 docs/stackit_beta_edge-cloud_token_create.md create mode 100644 internal/cmd/beta/edge/edge.go create mode 100755 internal/cmd/beta/edge/instance/create/create.go create mode 100755 internal/cmd/beta/edge/instance/create/create_test.go create mode 100755 internal/cmd/beta/edge/instance/delete/delete.go create mode 100755 internal/cmd/beta/edge/instance/delete/delete_test.go create mode 100755 internal/cmd/beta/edge/instance/describe/describe.go create mode 100755 internal/cmd/beta/edge/instance/describe/describe_test.go create mode 100644 internal/cmd/beta/edge/instance/instance.go create mode 100755 internal/cmd/beta/edge/instance/list/list.go create mode 100755 internal/cmd/beta/edge/instance/list/list_test.go create mode 100755 internal/cmd/beta/edge/instance/update/update.go create mode 100755 internal/cmd/beta/edge/instance/update/update_test.go create mode 100755 internal/cmd/beta/edge/kubeconfig/create/create.go create mode 100755 internal/cmd/beta/edge/kubeconfig/create/create_test.go create mode 100644 internal/cmd/beta/edge/kubeconfig/kubeconfig.go create mode 100755 internal/cmd/beta/edge/plans/list/list.go create mode 100755 internal/cmd/beta/edge/plans/list/list_test.go create mode 100644 internal/cmd/beta/edge/plans/plans.go create mode 100755 internal/cmd/beta/edge/token/create/create.go create mode 100755 internal/cmd/beta/edge/token/create/create_test.go create mode 100644 internal/cmd/beta/edge/token/token.go create mode 100644 internal/pkg/services/edge/client/client.go create mode 100755 internal/pkg/services/edge/common/error/error.go create mode 100755 internal/pkg/services/edge/common/error/error_test.go create mode 100644 internal/pkg/services/edge/common/instance/instance.go create mode 100755 internal/pkg/services/edge/common/instance/instance_test.go create mode 100755 internal/pkg/services/edge/common/kubeconfig/kubeconfig.go create mode 100755 internal/pkg/services/edge/common/kubeconfig/kubeconfig_test.go create mode 100644 internal/pkg/services/edge/common/validation/input.go create mode 100755 internal/pkg/services/edge/common/validation/input_test.go create mode 100755 internal/pkg/testutils/assert.go create mode 100755 internal/pkg/testutils/assert_test.go create mode 100755 internal/pkg/testutils/parse_input.go create mode 100755 internal/pkg/testutils/parse_input_test.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index fab1825e5..a0c177662 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -42,6 +42,7 @@ stackit beta [flags] * [stackit](./stackit.md) - Manage STACKIT resources using the command line * [stackit beta alb](./stackit_beta_alb.md) - Manages application loadbalancers +* [stackit beta edge-cloud](./stackit_beta_edge-cloud.md) - Provides functionality for edge services. * [stackit beta intake](./stackit_beta_intake.md) - Provides functionality for intake * [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS * [stackit beta sfs](./stackit_beta_sfs.md) - Provides functionality for SFS (stackit file storage) diff --git a/docs/stackit_beta_edge-cloud.md b/docs/stackit_beta_edge-cloud.md new file mode 100644 index 000000000..161433446 --- /dev/null +++ b/docs/stackit_beta_edge-cloud.md @@ -0,0 +1,37 @@ +## stackit beta edge-cloud + +Provides functionality for edge services. + +### Synopsis + +Provides functionality for STACKIT Edge Cloud (STEC) services. + +``` +stackit beta edge-cloud [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta edge-cloud instance](./stackit_beta_edge-cloud_instance.md) - Provides functionality for edge instances. +* [stackit beta edge-cloud kubeconfig](./stackit_beta_edge-cloud_kubeconfig.md) - Provides functionality for edge kubeconfig. +* [stackit beta edge-cloud plans](./stackit_beta_edge-cloud_plans.md) - Provides functionality for edge service plans. +* [stackit beta edge-cloud token](./stackit_beta_edge-cloud_token.md) - Provides functionality for edge service token. + diff --git a/docs/stackit_beta_edge-cloud_instance.md b/docs/stackit_beta_edge-cloud_instance.md new file mode 100644 index 000000000..853ac56f0 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_instance.md @@ -0,0 +1,38 @@ +## stackit beta edge-cloud instance + +Provides functionality for edge instances. + +### Synopsis + +Provides functionality for STACKIT Edge Cloud (STEC) instance management. + +``` +stackit beta edge-cloud instance [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud instance" +``` + +### 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 beta edge-cloud](./stackit_beta_edge-cloud.md) - Provides functionality for edge services. +* [stackit beta edge-cloud instance create](./stackit_beta_edge-cloud_instance_create.md) - Creates an edge instance +* [stackit beta edge-cloud instance delete](./stackit_beta_edge-cloud_instance_delete.md) - Deletes an edge instance +* [stackit beta edge-cloud instance describe](./stackit_beta_edge-cloud_instance_describe.md) - Describes an edge instance +* [stackit beta edge-cloud instance list](./stackit_beta_edge-cloud_instance_list.md) - Lists edge instances +* [stackit beta edge-cloud instance update](./stackit_beta_edge-cloud_instance_update.md) - Updates an edge instance + diff --git a/docs/stackit_beta_edge-cloud_instance_create.md b/docs/stackit_beta_edge-cloud_instance_create.md new file mode 100644 index 000000000..78c123ec1 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_instance_create.md @@ -0,0 +1,43 @@ +## stackit beta edge-cloud instance create + +Creates an edge instance + +### Synopsis + +Creates a STACKIT Edge Cloud (STEC) instance. The instance will take a moment to become fully functional. + +``` +stackit beta edge-cloud instance create [flags] +``` + +### Examples + +``` + Creates an edge instance with the name "xxx" and plan-id "yyy" + $ stackit beta edge-cloud instance create --name "xxx" --plan-id "yyy" +``` + +### Options + +``` + -d, --description string A user chosen description to distinguish multiple instances. + -h, --help Help for "stackit beta edge-cloud instance create" + -n, --name string The displayed name to distinguish multiple instances. + --plan-id string Service Plan configures the size of the Instance. +``` + +### 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 beta edge-cloud instance](./stackit_beta_edge-cloud_instance.md) - Provides functionality for edge instances. + diff --git a/docs/stackit_beta_edge-cloud_instance_delete.md b/docs/stackit_beta_edge-cloud_instance_delete.md new file mode 100644 index 000000000..b8aa5834d --- /dev/null +++ b/docs/stackit_beta_edge-cloud_instance_delete.md @@ -0,0 +1,45 @@ +## stackit beta edge-cloud instance delete + +Deletes an edge instance + +### Synopsis + +Deletes a STACKIT Edge Cloud (STEC) instance. The instance will be deleted permanently. + +``` +stackit beta edge-cloud instance delete [flags] +``` + +### Examples + +``` + Delete an edge instance with id "xxx" + $ stackit beta edge-cloud instance delete --id "xxx" + + Delete an edge instance with name "xxx" + $ stackit beta edge-cloud instance delete --name "xxx" +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud instance delete" + -i, --id string The project-unique identifier of this instance. + -n, --name string The displayed name to distinguish multiple instances. +``` + +### 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 beta edge-cloud instance](./stackit_beta_edge-cloud_instance.md) - Provides functionality for edge instances. + diff --git a/docs/stackit_beta_edge-cloud_instance_describe.md b/docs/stackit_beta_edge-cloud_instance_describe.md new file mode 100644 index 000000000..534bc9cf0 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_instance_describe.md @@ -0,0 +1,45 @@ +## stackit beta edge-cloud instance describe + +Describes an edge instance + +### Synopsis + +Describes a STACKIT Edge Cloud (STEC) instance. + +``` +stackit beta edge-cloud instance describe [flags] +``` + +### Examples + +``` + Describe an edge instance with id "xxx" + $ stackit beta edge-cloud instance describe --id + + Describe an edge instance with name "xxx" + $ stackit beta edge-cloud instance describe --name +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud instance describe" + -i, --id string The project-unique identifier of this instance. + -n, --name string The displayed name to distinguish multiple instances. +``` + +### 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 beta edge-cloud instance](./stackit_beta_edge-cloud_instance.md) - Provides functionality for edge instances. + diff --git a/docs/stackit_beta_edge-cloud_instance_list.md b/docs/stackit_beta_edge-cloud_instance_list.md new file mode 100644 index 000000000..e605d6f64 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_instance_list.md @@ -0,0 +1,44 @@ +## stackit beta edge-cloud instance list + +Lists edge instances + +### Synopsis + +Lists STACKIT Edge Cloud (STEC) instances of a project. + +``` +stackit beta edge-cloud instance list [flags] +``` + +### Examples + +``` + Lists all edge instances of a given project + $ stackit beta edge-cloud instance list + + Lists all edge instances of a given project and limits the output to two instances + $ stackit beta edge-cloud instance list --limit 2 +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud instance list" + --limit int Maximum number of entries to list +``` + +### 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 beta edge-cloud instance](./stackit_beta_edge-cloud_instance.md) - Provides functionality for edge instances. + diff --git a/docs/stackit_beta_edge-cloud_instance_update.md b/docs/stackit_beta_edge-cloud_instance_update.md new file mode 100644 index 000000000..9f3cb39b7 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_instance_update.md @@ -0,0 +1,50 @@ +## stackit beta edge-cloud instance update + +Updates an edge instance + +### Synopsis + +Updates a STACKIT Edge Cloud (STEC) instance. + +``` +stackit beta edge-cloud instance update [flags] +``` + +### Examples + +``` + Updates the description of an edge instance with id "xxx" + $ stackit beta edge-cloud instance update --id "xxx" --description "yyy" + + Updates the plan of an edge instance with name "xxx" + $ stackit beta edge-cloud instance update --name "xxx" --plan-id "yyy" + + Updates the description and plan of an edge instance with id "xxx" + $ stackit beta edge-cloud instance update --id "xxx" --description "yyy" --plan-id "zzz" +``` + +### Options + +``` + -d, --description string A user chosen description to distinguish multiple instances. + -h, --help Help for "stackit beta edge-cloud instance update" + -i, --id string The project-unique identifier of this instance. + -n, --name string The displayed name to distinguish multiple instances. + --plan-id string Service Plan configures the size of the Instance. +``` + +### 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 beta edge-cloud instance](./stackit_beta_edge-cloud_instance.md) - Provides functionality for edge instances. + diff --git a/docs/stackit_beta_edge-cloud_kubeconfig.md b/docs/stackit_beta_edge-cloud_kubeconfig.md new file mode 100644 index 000000000..be5078f00 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_kubeconfig.md @@ -0,0 +1,34 @@ +## stackit beta edge-cloud kubeconfig + +Provides functionality for edge kubeconfig. + +### Synopsis + +Provides functionality for STACKIT Edge Cloud (STEC) kubeconfig management. + +``` +stackit beta edge-cloud kubeconfig [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud kubeconfig" +``` + +### 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 beta edge-cloud](./stackit_beta_edge-cloud.md) - Provides functionality for edge services. +* [stackit beta edge-cloud kubeconfig create](./stackit_beta_edge-cloud_kubeconfig_create.md) - Creates or updates a local kubeconfig file of an edge instance + diff --git a/docs/stackit_beta_edge-cloud_kubeconfig_create.md b/docs/stackit_beta_edge-cloud_kubeconfig_create.md new file mode 100644 index 000000000..2d9a5ad40 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_kubeconfig_create.md @@ -0,0 +1,61 @@ +## stackit beta edge-cloud kubeconfig create + +Creates or updates a local kubeconfig file of an edge instance + +### Synopsis + +Creates or updates a local kubeconfig file of a STACKIT Edge Cloud (STEC) instance. If the config exists in the kubeconfig file, the information will be updated. + +By default, the kubeconfig information of the edge instance is merged into the current kubeconfig file which is determined by Kubernetes client logic. If the kubeconfig file doesn't exist, a new one will be created. +You can override this behavior by specifying a custom filepath with the --filepath flag or disable writing with the --disable-writing flag. +An expiration time can be set for the kubeconfig. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 3600 seconds. +Note: the format for the duration is , e.g. 30d for 30 days. You may not combine units. + +``` +stackit beta edge-cloud kubeconfig create [flags] +``` + +### Examples + +``` + Create or update a kubeconfig for the edge instance with id "xxx". If the config exists in the kubeconfig file, the information will be updated. + $ stackit beta edge-cloud kubeconfig create --id "xxx" + + Create or update a kubeconfig for the edge instance with name "xxx" in a custom filepath. + $ stackit beta edge-cloud kubeconfig create --name "xxx" --filepath "yyy" + + Get a kubeconfig for the edge instance with name "xxx" without writing it to a file and format the output as json. + $ stackit beta edge-cloud kubeconfig create --name "xxx" --disable-writing --output-format json + + Create a kubeconfig for the edge instance with id "xxx". This will replace your current kubeconfig file. + $ stackit beta edge-cloud kubeconfig create --id "xxx" --overwrite +``` + +### Options + +``` + --disable-writing Disable writing the kubeconfig to a file. + -e, --expiration string Expiration time for the kubeconfig, e.g. 5d. By default, the token is valid for 1h. + -f, --filepath string Path to the kubeconfig file. A default is chosen by Kubernetes if not set. + -h, --help Help for "stackit beta edge-cloud kubeconfig create" + -i, --id string The project-unique identifier of this instance. + -n, --name string The displayed name to distinguish multiple instances. + --overwrite Force overwrite the kubeconfig file if it exists. + --switch-context Switch to the context in the kubeconfig file to the new context. +``` + +### 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 beta edge-cloud kubeconfig](./stackit_beta_edge-cloud_kubeconfig.md) - Provides functionality for edge kubeconfig. + diff --git a/docs/stackit_beta_edge-cloud_plans.md b/docs/stackit_beta_edge-cloud_plans.md new file mode 100644 index 000000000..c58e5a8e1 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_plans.md @@ -0,0 +1,34 @@ +## stackit beta edge-cloud plans + +Provides functionality for edge service plans. + +### Synopsis + +Provides functionality for STACKIT Edge Cloud (STEC) service plan management. + +``` +stackit beta edge-cloud plans [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud plans" +``` + +### 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 beta edge-cloud](./stackit_beta_edge-cloud.md) - Provides functionality for edge services. +* [stackit beta edge-cloud plans list](./stackit_beta_edge-cloud_plans_list.md) - Lists available edge service plans + diff --git a/docs/stackit_beta_edge-cloud_plans_list.md b/docs/stackit_beta_edge-cloud_plans_list.md new file mode 100644 index 000000000..a57c7e197 --- /dev/null +++ b/docs/stackit_beta_edge-cloud_plans_list.md @@ -0,0 +1,44 @@ +## stackit beta edge-cloud plans list + +Lists available edge service plans + +### Synopsis + +Lists available STACKIT Edge Cloud (STEC) service plans of a project + +``` +stackit beta edge-cloud plans list [flags] +``` + +### Examples + +``` + Lists all edge plans for a given project + $ stackit beta edge-cloud plan list + + Lists all edge plans for a given project and limits the output to two plans + $ stackit beta edge-cloud plan list --limit 2 +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud plans list" + --limit int Maximum number of entries to list +``` + +### 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 beta edge-cloud plans](./stackit_beta_edge-cloud_plans.md) - Provides functionality for edge service plans. + diff --git a/docs/stackit_beta_edge-cloud_token.md b/docs/stackit_beta_edge-cloud_token.md new file mode 100644 index 000000000..ba7fe0b3a --- /dev/null +++ b/docs/stackit_beta_edge-cloud_token.md @@ -0,0 +1,34 @@ +## stackit beta edge-cloud token + +Provides functionality for edge service token. + +### Synopsis + +Provides functionality for STACKIT Edge Cloud (STEC) token management. + +``` +stackit beta edge-cloud token [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta edge-cloud token" +``` + +### 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 beta edge-cloud](./stackit_beta_edge-cloud.md) - Provides functionality for edge services. +* [stackit beta edge-cloud token create](./stackit_beta_edge-cloud_token_create.md) - Creates a token for an edge instance + diff --git a/docs/stackit_beta_edge-cloud_token_create.md b/docs/stackit_beta_edge-cloud_token_create.md new file mode 100644 index 000000000..4d96d548c --- /dev/null +++ b/docs/stackit_beta_edge-cloud_token_create.md @@ -0,0 +1,49 @@ +## stackit beta edge-cloud token create + +Creates a token for an edge instance + +### Synopsis + +Creates a token for a STACKIT Edge Cloud (STEC) instance. + +An expiration time can be set for the token. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is 3600 seconds. +Note: the format for the duration is , e.g. 30d for 30 days. You may not combine units. + +``` +stackit beta edge-cloud token create [flags] +``` + +### Examples + +``` + Create a token for the edge instance with id "xxx". + $ stackit beta edge-cloud token create --id "xxx" + + Create a token for the edge instance with name "xxx". The token will be valid for one day. + $ stackit beta edge-cloud token create --name "xxx" --expiration 1d +``` + +### Options + +``` + -e, --expiration string Expiration time for the kubeconfig, e.g. 5d. By default, the token is valid for 1h. + -h, --help Help for "stackit beta edge-cloud token create" + -i, --id string The project-unique identifier of this instance. + -n, --name string The displayed name to distinguish multiple instances. +``` + +### 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 beta edge-cloud token](./stackit_beta_edge-cloud_token.md) - Provides functionality for edge service token. + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index b9a4e81a1..211bc1113 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -32,6 +32,7 @@ stackit config set [flags] --allowed-url-domain string Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command --authorization-custom-endpoint string Authorization API base URL, used in calls to this API --dns-custom-endpoint string DNS API base URL, used in calls to this API + --edge-custom-endpoint string Edge API base URL, used in calls to this API -h, --help Help for "stackit config set" --iaas-custom-endpoint string IaaS API base URL, used in calls to this API --identity-provider-custom-client-id string Identity Provider client ID, used for user authentication diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 9e005607b..07b161c8c 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -30,6 +30,7 @@ stackit config unset [flags] --async Configuration option to run commands asynchronously --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL + --edge-custom-endpoint Edge API base URL. If unset, uses the default base URL -h, --help Help for "stackit config unset" --iaas-custom-endpoint IaaS API base URL. If unset, uses the default base URL --identity-provider-custom-client-id Identity Provider client ID, used for user authentication diff --git a/go.mod b/go.mod index 656654080..819818a8b 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 + github.com/stackitcloud/stackit-sdk-go/services/edge v0.2.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 diff --git a/go.sum b/go.sum index 0d69feaf8..6c2cf3173 100644 --- a/go.sum +++ b/go.sum @@ -608,6 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 h1:4YFY5PG github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3/go.mod h1:BNiIZkDqwSV1LkWDjMKxVb9pxQ/HMIsXJ0AQ8pFoAo4= +github.com/stackitcloud/stackit-sdk-go/services/edge v0.2.0 h1:ElmnEg3V4MisAgqqJFxl3nCmKraxbHtN+vv1DNiWYfM= +github.com/stackitcloud/stackit-sdk-go/services/edge v0.2.0/go.mod h1:tFDkVkK+ESBTiH2XIcMPPR/pJJmeqT1VNDghg+ZxfMI= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjUZg5qprXG5rDmPnM6dsvplMk/vg= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1/go.mod h1:3nTaj8IGjNNGYUD2CpuXkXwc5c4giTUmoPggFhjVFxo= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 h1:U/x0tc487X9msMS5yZYjrBAAKrCx87Trmt0kh8JiARA= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 935791cb9..973a87c21 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -6,6 +6,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs" @@ -43,6 +44,7 @@ func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(sqlserverflex.NewCmd(params)) cmd.AddCommand(sfs.NewCmd(params)) cmd.AddCommand(alb.NewCmd(params)) + cmd.AddCommand(edge.NewCmd(params)) cmd.AddCommand(intake.NewCmd(params)) cmd.AddCommand(kms.NewCmd(params)) } diff --git a/internal/cmd/beta/edge/edge.go b/internal/cmd/beta/edge/edge.go new file mode 100644 index 000000000..11d1b1e16 --- /dev/null +++ b/internal/cmd/beta/edge/edge.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package edge + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/instance" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/kubeconfig" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/plans" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/token" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "edge-cloud", + Short: "Provides functionality for edge services.", + Long: "Provides functionality for STACKIT Edge Cloud (STEC) services.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) + cmd.AddCommand(plans.NewCmd(params)) + cmd.AddCommand(kubeconfig.NewCmd(params)) + cmd.AddCommand(token.NewCmd(params)) +} diff --git a/internal/cmd/beta/edge/instance/create/create.go b/internal/cmd/beta/edge/instance/create/create.go new file mode 100755 index 000000000..bc264ddb5 --- /dev/null +++ b/internal/cmd/beta/edge/instance/create/create.go @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package create + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/edge" + "github.com/stackitcloud/stackit-sdk-go/services/edge/wait" +) + +// Command constructor +// Instance id and displayname are likely to be refactored in future. For the time being we decided to use flags +// instead of args to provide the instance-id xor displayname to uniquely identify an instance. The displayname +// is guaranteed to be unique within a given project as of today. The chosen flag over args approach ensures we +// won't need a breaking change of the CLI when we refactor the commands to take the identifier as arg at some point. +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates an edge instance", + Long: "Creates a STACKIT Edge Cloud (STEC) instance. The instance will take a moment to become fully functional.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + fmt.Sprintf(`Creates an edge instance with the %s "xxx" and %s "yyy"`, commonInstance.DisplayNameFlag, commonInstance.PlanIdFlag), + fmt.Sprintf(`$ stackit beta edge-cloud instance create --%s "xxx" --%s "yyy"`, commonInstance.DisplayNameFlag, commonInstance.PlanIdFlag)), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + // Parse user input (arguments and/or flags) + model, err := parseInput(params.Printer, cmd) + 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) + // If project label can't be determined, fall back to project ID + projectLabel = model.ProjectId + } + + // Prompt for confirmation + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to create a new edge instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + resp, err := run(ctx, model, apiClient) + if err != nil { + return err + } + if resp == nil { + return fmt.Errorf("create instance: empty response from API") + } + if resp.Id == nil { + return fmt.Errorf("create instance: instance id missing in response") + } + instanceId := *resp.Id + + // Wait for async operation, if async mode not enabled + 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) + + if err != nil { + return fmt.Errorf("wait for edge instance creation: %w", err) + } + s.Stop() + } + + // Handle output to printer + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +// inputModel represents the user input for creating an edge instance. +type inputModel struct { + *globalflags.GlobalFlagModel + DisplayName string + Description string + PlanId string +} + +// createRequestSpec captures the details of the request for testing. +type createRequestSpec struct { + // Exported fields allow tests to inspect the request inputs + ProjectID string + Region string + Payload edge.PostInstancesPayload + + // Execute is a closure that wraps the actual SDK call + Execute func() (*edge.Instance, error) +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(commonInstance.DisplayNameFlag, commonInstance.DisplayNameShorthand, "", commonInstance.DisplayNameUsage) + cmd.Flags().StringP(commonInstance.DescriptionFlag, commonInstance.DescriptionShorthand, "", commonInstance.DescriptionUsage) + cmd.Flags().String(commonInstance.PlanIdFlag, "", commonInstance.PlanIdUsage) + + cobra.CheckErr(flags.MarkFlagsRequired(cmd, commonInstance.DisplayNameFlag, commonInstance.PlanIdFlag)) +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // Parse and validate user input then add it to the model + displayNameValue := flags.FlagToStringPointer(p, cmd, commonInstance.DisplayNameFlag) + if err := commonInstance.ValidateDisplayName(displayNameValue); err != nil { + return nil, err + } + + planIdValue := flags.FlagToStringPointer(p, cmd, commonInstance.PlanIdFlag) + if err := commonInstance.ValidatePlanId(planIdValue); err != nil { + return nil, err + } + + descriptionValue := flags.FlagWithDefaultToStringValue(p, cmd, commonInstance.DescriptionFlag) + if err := commonInstance.ValidateDescription(descriptionValue); err != nil { + return nil, err + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + DisplayName: *displayNameValue, + Description: descriptionValue, + PlanId: *planIdValue, + } + + // Log the parsed model if --verbosity is set to debug + p.DebugInputModel(model) + return &model, nil +} + +// Run is the main execution function used by the command runner. +// It is decoupled from TTY output to have the ability to mock the API client during testing. +func run(ctx context.Context, model *inputModel, apiClient client.APIClient) (*edge.Instance, error) { + spec, err := buildRequest(ctx, model, apiClient) + if err != nil { + return nil, err + } + + resp, err := spec.Execute() + if err != nil { + return nil, cliErr.NewRequestFailedError(err) + } + + return resp, nil +} + +// buildRequest constructs the spec that can be tested. +func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*createRequestSpec, error) { + req := apiClient.PostInstances(ctx, model.ProjectId, model.Region) + + // Build request payload + payload := edge.PostInstancesPayload{ + DisplayName: &model.DisplayName, + Description: &model.Description, + PlanId: &model.PlanId, + } + req = req.PostInstancesPayload(payload) + + return &createRequestSpec{ + ProjectID: model.ProjectId, + Region: model.Region, + Payload: payload, + Execute: req.Execute, + }, nil +} + +// Output result based on the configured output format +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, instance *edge.Instance) error { + if instance == nil { + // This is only to prevent nil pointer deref. + // As long as the API behaves as defined by it's spec, instance can not be empty (HTTP 200 with an empty body) + return commonErr.NewNoInstanceError("") + } + + return p.OutputResult(outputFormat, instance, func() error { + operationState := "Created" + if async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %q.\n", operationState, projectLabel, utils.PtrString(instance.Id)) + return nil + }) +} diff --git a/internal/cmd/beta/edge/instance/create/create_test.go b/internal/cmd/beta/edge/instance/create/create_test.go new file mode 100755 index 000000000..bbec4b074 --- /dev/null +++ b/internal/cmd/beta/edge/instance/create/create_test.go @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package create + +import ( + "context" + "errors" + "strings" + "testing" + + "github.com/google/uuid" + "github.com/spf13/cobra" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testProjectId = uuid.NewString() + testRegion = "eu01" + + testName = "test" + testPlanId = uuid.NewString() + testDescription = "Initial instance description" + testInstanceId = uuid.NewString() +) + +// mockExecutable is a mock for the Executable interface used by the SDK +type mockExecutable struct { + executeFails bool + resp *edge.Instance +} + +func (m *mockExecutable) PostInstancesPayload(_ edge.PostInstancesPayload) edge.ApiPostInstancesRequest { + // This method is needed to satisfy the interface. It allows chaining in buildRequest. + return m +} +func (m *mockExecutable) Execute() (*edge.Instance, error) { + if m.executeFails { + return nil, errors.New("API error") + } + if m.resp != nil { + return m.resp, nil + } + return &edge.Instance{Id: &testInstanceId}, nil +} + +// mockAPIClient is a mock for the client.APIClient interface +type mockAPIClient struct { + postInstancesMock edge.ApiPostInstancesRequest +} + +func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { + if m.postInstancesMock != nil { + return m.postInstancesMock + } + return &mockExecutable{} +} + +// Unused methods to satisfy the client.APIClient interface +func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { + return nil +} +func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { + return nil +} +func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { + return nil +} +func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { + return nil +} +func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceNameRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceNameRequest { + return nil +} + +func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiListPlansProjectRequest { + return nil +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + commonInstance.DisplayNameFlag: testName, + commonInstance.DescriptionFlag: testDescription, + commonInstance.PlanIdFlag: testPlanId, + } + 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, + }, + DisplayName: testName, + Description: testDescription, + PlanId: testPlanId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + type args struct { + flags map[string]string + cmpOpts []testUtils.ValueComparisonOption + } + + tests := []struct { + name string + wantErr any + want *inputModel + args args + }{ + { + name: "create success", + want: fixtureInputModel(), + args: args{ + flags: fixtureFlagValues(), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}, globalflags.GlobalFlagModel{}), + }, + }, + }, + { + name: "no flag values", + wantErr: true, + args: args{ + flags: map[string]string{}, + }, + }, + { + name: "project id missing", + wantErr: &cliErr.ProjectIdError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + }, + }, + { + name: "project id empty", + wantErr: "value cannot be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + }, + }, + { + name: "project id invalid", + wantErr: "invalid UUID length", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "name missing", + wantErr: "required flag(s) \"name\" not set", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.DisplayNameFlag) + }), + }, + }, + { + name: "name too long", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DisplayNameFlag] = "this-name-is-way-too-long-for-the-validation" + }), + }, + }, + { + name: "name too short", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DisplayNameFlag] = "in" + }), + }, + }, + { + name: "name invalid", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DisplayNameFlag] = "1test" + }), + }, + }, + { + name: "plan invalid", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.PlanIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "description too long", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DescriptionFlag] = strings.Repeat("a", 257) + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + caseOpts := []testUtils.ParseInputCaseOption{} + if len(tt.args.cmpOpts) > 0 { + caseOpts = append(caseOpts, testUtils.WithParseInputCmpOptions(tt.args.cmpOpts...)) + } + + testUtils.RunParseInputCase(t, testUtils.ParseInputTestCase[*inputModel]{ + Name: tt.name, + Flags: tt.args.flags, + WantModel: tt.want, + WantErr: tt.wantErr, + CmdFactory: NewCmd, + ParseInputFunc: func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, + }, caseOpts...) + }) + } +} + +func TestBuildRequest(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + tests := []struct { + name string + args args + want *createRequestSpec + }{ + { + name: "success", + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + postInstancesMock: &mockExecutable{}, + }, + }, + want: &createRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + Payload: edge.PostInstancesPayload{ + DisplayName: &testName, + Description: &testDescription, + PlanId: &testPlanId, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, _ := buildRequest(testCtx, tt.args.model, tt.args.client) + + if got != nil { + if got.Execute == nil { + t.Error("expected non-nil Execute function") + } + testUtils.AssertValue(t, got, tt.want, testUtils.WithIgnoreFields(createRequestSpec{}, "Execute")) + } + }) + } +} + +func TestRun(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want *edge.Instance + args args + }{ + { + name: "create success", + want: &edge.Instance{Id: &testInstanceId}, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + postInstancesMock: &mockExecutable{ + resp: &edge.Instance{Id: &testInstanceId}, + }, + }, + }, + }, + { + name: "create API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + postInstancesMock: &mockExecutable{ + executeFails: true, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := run(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + testUtils.AssertValue(t, got, tt.want) + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + instance *edge.Instance + projectLabel string + } + + tests := []struct { + name string + wantErr error + args args + }{ + { + name: "no instance", + wantErr: &commonErr.NoInstanceError{}, + args: args{ + model: fixtureInputModel(), + }, + }, + { + name: "output json", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + }), + instance: &edge.Instance{}, + }, + }, + { + name: "output yaml", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.YAMLOutputFormat + }), + instance: &edge.Instance{}, + }, + }, + { + name: "output default", + args: args{ + model: fixtureInputModel(), + instance: &edge.Instance{Id: &testInstanceId}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + + err := outputResult(p, tt.args.model.OutputFormat, tt.args.model.Async, tt.args.projectLabel, tt.args.instance) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} diff --git a/internal/cmd/beta/edge/instance/delete/delete.go b/internal/cmd/beta/edge/instance/delete/delete.go new file mode 100755 index 000000000..d6650e7e6 --- /dev/null +++ b/internal/cmd/beta/edge/instance/delete/delete.go @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "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/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/edge" + "github.com/stackitcloud/stackit-sdk-go/services/edge/wait" +) + +// Struct to model user input (arguments and/or flags) +type inputModel struct { + *globalflags.GlobalFlagModel + identifier *commonValidation.Identifier +} + +// deleteRequestSpec captures the details of a request for testing. +type deleteRequestSpec struct { + // Exported fields allow tests to inspect the request inputs + ProjectID string + Region string + InstanceId string // Set if deleting by ID + InstanceName string // Set if deleting by Name + + // Execute is a closure that wraps the actual SDK call + Execute func() error +} + +// OpenApi generated code will have different types for by-instance-id and by-display-name API calls and therefore different wait handlers. +// InstanceWaiter is an interface to abstract the different wait handlers so they can be used interchangeably. +type instanceWaiter interface { + WaitWithContext(context.Context) (*edge.Instance, error) +} + +// A function that creates an instance waiter +type instanceWaiterFactory = func(client *edge.APIClient) instanceWaiter + +// Command constructor +// Instance id and displayname are likely to be refactored in future. For the time being we decided to use flags +// instead of args to provide the instance-id xor displayname to uniquely identify an instance. The displayname +// is guaranteed to be unique within a given project as of today. The chosen flag over args approach ensures we +// won't need a breaking change of the CLI when we refactor the commands to take the identifier as arg at some point. +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Deletes an edge instance", + Long: "Deletes a STACKIT Edge Cloud (STEC) instance. The instance will be deleted permanently.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + fmt.Sprintf(`Delete an edge instance with %s "xxx"`, commonInstance.InstanceIdFlag), + fmt.Sprintf(`$ stackit beta edge-cloud instance delete --%s "xxx"`, commonInstance.InstanceIdFlag)), + examples.NewExample( + fmt.Sprintf(`Delete an edge instance with %s "xxx"`, commonInstance.DisplayNameFlag), + fmt.Sprintf(`$ stackit beta edge-cloud instance delete --%s "xxx"`, commonInstance.DisplayNameFlag)), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + // Parse user input (arguments and/or flags) + model, err := parseInput(params.Printer, cmd) + 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) + // If project label can't be determined, fall back to project ID + projectLabel = model.ProjectId + } + + // Prompt for confirmation + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to delete the edge instance %q of project %q?", model.identifier.Value, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + err = run(ctx, model, apiClient) + if err != nil { + return err + } + + // Wait for async operation, if async mode not enabled + operationState := "Triggered deletion of" + 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 { + 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 { + return fmt.Errorf("wait for edge instance deletion: %w", err) + } + operationState = "Deleted" + s.Stop() + } + + params.Printer.Info("%s instance with %q %q of project %q.\n", operationState, model.identifier.Flag, model.identifier.Value, projectLabel) + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(commonInstance.InstanceIdFlag, commonInstance.InstanceIdShorthand, "", commonInstance.InstanceIdUsage) + cmd.Flags().StringP(commonInstance.DisplayNameFlag, commonInstance.DisplayNameShorthand, "", commonInstance.DisplayNameUsage) + + identifierFlags := []string{commonInstance.InstanceIdFlag, commonInstance.DisplayNameFlag} + cmd.MarkFlagsMutuallyExclusive(identifierFlags...) // InstanceId xor DisplayName + cmd.MarkFlagsOneRequired(identifierFlags...) +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // Generate input model based on chosen flags + model := inputModel{ + GlobalFlagModel: globalFlags, + } + + // Parse and validate user input then add it to the model + id, err := commonValidation.GetValidatedInstanceIdentifier(p, cmd) + if err != nil { + return nil, err + } + model.identifier = id + + // Log the parsed model if --verbosity is set to debug + p.DebugInputModel(model) + return &model, nil +} + +// Run is the main execution function used by the command runner. +// It is decoupled from TTY output to have the ability to mock the API client during testing. +func run(ctx context.Context, model *inputModel, apiClient client.APIClient) error { + spec, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + + if err := spec.Execute(); err != nil { + return cliErr.NewRequestFailedError(err) + } + + return nil +} + +// buildRequest constructs the spec that can be tested. +// It handles the logic of choosing between DeleteInstance and DeleteInstanceByName. +func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*deleteRequestSpec, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + spec := &deleteRequestSpec{ + ProjectID: model.ProjectId, + Region: model.Region, + } + + // Switch the concrete client based on the identifier flag used + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + spec.InstanceId = model.identifier.Value + req := apiClient.DeleteInstance(ctx, model.ProjectId, model.Region, model.identifier.Value) + spec.Execute = req.Execute + case commonInstance.DisplayNameFlag: + spec.InstanceName = model.identifier.Value + req := apiClient.DeleteInstanceByName(ctx, model.ProjectId, model.Region, model.identifier.Value) + spec.Execute = req.Execute + default: + return nil, fmt.Errorf("%w: %w", cliErr.NewBuildRequestError("invalid identifier flag", nil), commonErr.NewInvalidIdentifierError(model.identifier.Flag)) + } + + return spec, nil +} + +// Returns a factory function to create the appropriate waiter based on the input model. +func getWaiterFactory(ctx context.Context, model *inputModel) (instanceWaiterFactory, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + factory := func(c *edge.APIClient) instanceWaiter { + return wait.DeleteInstanceWaitHandler(ctx, c, model.ProjectId, model.Region, model.identifier.Value) + } + return factory, nil + case commonInstance.DisplayNameFlag: + factory := func(c *edge.APIClient) instanceWaiter { + return wait.DeleteInstanceByNameWaitHandler(ctx, c, model.ProjectId, model.Region, model.identifier.Value) + } + return factory, nil + default: + return nil, commonErr.NewInvalidIdentifierError(model.identifier.Flag) + } +} diff --git a/internal/cmd/beta/edge/instance/delete/delete_test.go b/internal/cmd/beta/edge/instance/delete/delete_test.go new file mode 100755 index 000000000..2772b8c97 --- /dev/null +++ b/internal/cmd/beta/edge/instance/delete/delete_test.go @@ -0,0 +1,557 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package delete + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/google/uuid" + "github.com/spf13/cobra" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testProjectId = uuid.NewString() + testRegion = "eu01" + + testInstanceId = "instance" + testDisplayName = "test" +) + +// mockExecutable implements the SDK delete request interface for testing. +type mockExecutable struct { + executeFails bool + executeNotFound bool +} + +func (m *mockExecutable) Execute() error { + if m.executeNotFound { + return &oapierror.GenericOpenAPIError{ + StatusCode: http.StatusNotFound, + Body: []byte(`{"message":"not found"}`), + } + } + if m.executeFails { + return errors.New("execute failed") + } + return nil +} + +// mockAPIClient provides the minimal API client behavior required by the tests. +type mockAPIClient struct { + deleteInstanceMock edge.ApiDeleteInstanceRequest + deleteInstanceByNameMock edge.ApiDeleteInstanceByNameRequest +} + +func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { + if m.deleteInstanceMock != nil { + return m.deleteInstanceMock + } + return &mockExecutable{} +} + +func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceByNameRequest { + if m.deleteInstanceByNameMock != nil { + return m.deleteInstanceByNameMock + } + return &mockExecutable{} +} + +// Unused methods to satisfy the client.APIClient interface. +func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { + return nil +} +func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { + return nil +} +func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { + return nil +} +func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { + return nil +} +func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceNameRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceNameRequest { + return nil +} +func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiListPlansProjectRequest { + return nil +} + +func fixtureFlagValues(mods ...func(map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + commonInstance.InstanceIdFlag: testInstanceId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(useDisplayName bool, mods ...func(*inputModel)) *inputModel { + identifier := &commonValidation.Identifier{ + Flag: commonInstance.InstanceIdFlag, + Value: testInstanceId, + } + if useDisplayName { + identifier = &commonValidation.Identifier{ + Flag: commonInstance.DisplayNameFlag, + Value: testDisplayName, + } + } + + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + identifier: identifier, + } + + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureByIdInputModel(mods ...func(*inputModel)) *inputModel { + return fixtureInputModel(false, mods...) +} + +func fixtureByNameInputModel(mods ...func(*inputModel)) *inputModel { + return fixtureInputModel(true, mods...) +} + +func TestParseInput(t *testing.T) { + type args struct { + flags map[string]string + cmpOpts []testUtils.ValueComparisonOption + } + + tests := []struct { + name string + wantErr any + want *inputModel + args args + }{ + { + name: "by id", + want: fixtureByIdInputModel(), + args: args{ + flags: fixtureFlagValues(), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}, globalflags.GlobalFlagModel{}), + }, + }, + }, + { + name: "by name", + want: fixtureByNameInputModel(), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}, globalflags.GlobalFlagModel{}), + }, + }, + }, + { + name: "by id and name", + wantErr: true, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + }, + }, + { + name: "no flag values", + wantErr: true, + args: args{ + flags: map[string]string{}, + }, + }, + { + name: "project id missing", + wantErr: &cliErr.ProjectIdError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + }, + }, + { + name: "project id empty", + wantErr: "value cannot be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + }, + }, + { + name: "project id invalid", + wantErr: "invalid UUID length", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "instance id empty", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "" + }), + }, + }, + { + name: "instance id too long", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "invalid-instance-id" + }), + }, + }, + { + name: "instance id too short", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "id" + }), + }, + }, + { + name: "name too short", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = "foo" + }), + }, + }, + { + name: "name too long", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = "foofoofoo" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + caseOpts := []testUtils.ParseInputCaseOption{} + if len(tt.args.cmpOpts) > 0 { + caseOpts = append(caseOpts, testUtils.WithParseInputCmpOptions(tt.args.cmpOpts...)) + } + + testUtils.RunParseInputCase(t, testUtils.ParseInputTestCase[*inputModel]{ + Name: tt.name, + Flags: tt.args.flags, + WantModel: tt.want, + WantErr: tt.wantErr, + CmdFactory: NewCmd, + ParseInputFunc: func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, + }, caseOpts...) + }) + } +} + +func TestRun(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + tests := []struct { + name string + args args + wantErr error + }{ + { + name: "delete by id success", + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + deleteInstanceMock: &mockExecutable{}, + }, + }, + }, + { + name: "delete by id API error", + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + deleteInstanceMock: &mockExecutable{executeFails: true}, + }, + }, + wantErr: &cliErr.RequestFailedError{}, + }, + { + name: "delete by id not found", + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + deleteInstanceMock: &mockExecutable{executeNotFound: true}, + }, + }, + wantErr: &cliErr.RequestFailedError{}, + }, + { + name: "delete by name success", + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + deleteInstanceByNameMock: &mockExecutable{}, + }, + }, + }, + { + name: "delete by name API error", + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + deleteInstanceByNameMock: &mockExecutable{executeFails: true}, + }, + }, + wantErr: &cliErr.RequestFailedError{}, + }, + { + name: "delete by name not found", + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + deleteInstanceByNameMock: &mockExecutable{executeNotFound: true}, + }, + }, + wantErr: &cliErr.RequestFailedError{}, + }, + { + name: "no identifier", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + }, + wantErr: &commonErr.NoIdentifierError{}, + }, + { + name: "invalid identifier", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.identifier = &commonValidation.Identifier{Flag: "unknown", Value: "value"} + }), + client: &mockAPIClient{}, + }, + wantErr: &cliErr.BuildRequestError{}, + }, + { + name: "nil model", + args: args{ + model: nil, + client: &mockAPIClient{}, + }, + wantErr: &commonErr.NoIdentifierError{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := run(testCtx, tt.args.model, tt.args.client) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} + +func TestBuildRequest(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + tests := []struct { + name string + args args + want *deleteRequestSpec + wantErr error + }{ + { + name: "by id", + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + deleteInstanceMock: &mockExecutable{}, + }, + }, + want: &deleteRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceId: testInstanceId, + }, + }, + { + name: "by name", + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + deleteInstanceByNameMock: &mockExecutable{}, + }, + }, + want: &deleteRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceName: testDisplayName, + }, + }, + { + name: "no identifier", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + }, + wantErr: &commonErr.NoIdentifierError{}, + }, + { + name: "invalid identifier", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.identifier = &commonValidation.Identifier{Flag: "unknown", Value: "val"} + }), + client: &mockAPIClient{}, + }, + wantErr: &cliErr.BuildRequestError{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildRequest(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + if got != nil { + if got.Execute == nil { + t.Error("expected non-nil Execute function") + } + testUtils.AssertValue(t, got, tt.want, testUtils.WithIgnoreFields(deleteRequestSpec{}, "Execute")) + } + }) + } +} + +func TestGetWaiterFactory(t *testing.T) { + type args struct { + model *inputModel + } + + tests := []struct { + name string + wantErr error + want bool + args args + }{ + { + name: "by id identifier", + want: true, + args: args{ + model: fixtureByIdInputModel(), + }, + }, + { + name: "by name identifier", + want: true, + args: args{ + model: fixtureByNameInputModel(), + }, + }, + { + name: "nil model", + wantErr: &commonErr.NoIdentifierError{}, + want: false, + args: args{ + model: nil, + }, + }, + { + name: "nil identifier", + wantErr: &commonErr.NoIdentifierError{}, + want: false, + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.identifier = nil + }), + }, + }, + { + name: "invalid identifier", + wantErr: &commonErr.InvalidIdentifierError{}, + want: false, + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.identifier = &commonValidation.Identifier{Flag: "unsupported", Value: "value"} + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getWaiterFactory(testCtx, tt.args.model) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + + if tt.want && got == nil { + t.Fatal("expected non-nil waiter factory") + } + if !tt.want && got != nil { + t.Fatal("expected nil waiter factory") + } + }) + } +} diff --git a/internal/cmd/beta/edge/instance/describe/describe.go b/internal/cmd/beta/edge/instance/describe/describe.go new file mode 100755 index 000000000..5a7d85ed6 --- /dev/null +++ b/internal/cmd/beta/edge/instance/describe/describe.go @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package describe + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "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/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + identifier *commonValidation.Identifier +} + +// describeRequestSpec captures the details of the request for testing. +type describeRequestSpec struct { + // Exported fields allow tests to inspect the request inputs + ProjectID string + Region string + InstanceId string // Set if describing by ID + InstanceName string // Set if describing by Name + + // Execute is a closure that wraps the actual SDK call + Execute func() (*edge.Instance, error) +} + +// Command constructor +// Instance id and displayname are likely to be refactored in future. For the time being we decided to use flags +// instead of args to provide the instance-id xor displayname to uniquely identify an instance. The displayname +// is guaranteed to be unique within a given project as of today. The chosen flag over args approach ensures we +// won't need a breaking change of the CLI when we refactor the commands to take the identifier as arg at some point. +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Describes an edge instance", + Long: "Describes a STACKIT Edge Cloud (STEC) instance.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + fmt.Sprintf(`Describe an edge instance with %s "xxx"`, commonInstance.InstanceIdFlag), + fmt.Sprintf(`$ stackit beta edge-cloud instance describe --%s `, commonInstance.InstanceIdFlag)), + examples.NewExample( + fmt.Sprintf(`Describe an edge instance with %s "xxx"`, commonInstance.DisplayNameFlag), + fmt.Sprintf(`$ stackit beta edge-cloud instance describe --%s `, commonInstance.DisplayNameFlag)), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + // Parse user input (arguments and/or flags) + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Call API + resp, err := run(ctx, model, apiClient) + if err != nil { + return err + } + + // Handle output to printer + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(commonInstance.InstanceIdFlag, commonInstance.InstanceIdShorthand, "", commonInstance.InstanceIdUsage) + cmd.Flags().StringP(commonInstance.DisplayNameFlag, commonInstance.DisplayNameShorthand, "", commonInstance.DisplayNameUsage) + + identifierFlags := []string{commonInstance.InstanceIdFlag, commonInstance.DisplayNameFlag} + cmd.MarkFlagsMutuallyExclusive(identifierFlags...) // InstanceId xor DisplayName + cmd.MarkFlagsOneRequired(identifierFlags...) +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // Generate input model based on chosen flags + model := inputModel{ + GlobalFlagModel: globalFlags, + } + + // Parse and validate user input then add it to the model + id, err := commonValidation.GetValidatedInstanceIdentifier(p, cmd) + if err != nil { + return nil, err + } + model.identifier = id + + // Log the parsed model if --verbosity is set to debug + p.DebugInputModel(model) + return &model, nil +} + +// Run is the main execution function used by the command runner. +// It is decoupled from TTY output to have the ability to mock the API client during testing. +func run(ctx context.Context, model *inputModel, apiClient client.APIClient) (*edge.Instance, error) { + spec, err := buildRequest(ctx, model, apiClient) + if err != nil { + return nil, err + } + + resp, err := spec.Execute() + if err != nil { + return nil, cliErr.NewRequestFailedError(err) + } + + return resp, nil +} + +// buildRequest constructs the spec that can be tested. +// It handles the logic of choosing between GetInstance and GetInstanceByName. +func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*describeRequestSpec, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + spec := &describeRequestSpec{ + ProjectID: model.ProjectId, + Region: model.Region, + } + + // Switch the concrete client based on the identifier flag used + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + spec.InstanceId = model.identifier.Value + req := apiClient.GetInstance(ctx, model.ProjectId, model.Region, model.identifier.Value) + spec.Execute = req.Execute + case commonInstance.DisplayNameFlag: + spec.InstanceName = model.identifier.Value + req := apiClient.GetInstanceByName(ctx, model.ProjectId, model.Region, model.identifier.Value) + spec.Execute = req.Execute + default: + return nil, fmt.Errorf("%w: %w", cliErr.NewBuildRequestError("invalid identifier flag", nil), commonErr.NewInvalidIdentifierError(model.identifier.Flag)) + } + + return spec, nil +} + +// Output result based on the configured output format +func outputResult(p *print.Printer, outputFormat string, instance *edge.Instance) error { + if instance == nil { + // This is only to prevent nil pointer deref. + // As long as the API behaves as defined by it's spec, instance can not be empty (HTTP 200 with an empty body) + return commonErr.NewNoInstanceError("") + } + + return p.OutputResult(outputFormat, instance, func() error { + table := tables.NewTable() + // Describe: output all fields. Be sure to filter for any non-required fields. + table.AddRow("CREATED", utils.PtrString(instance.Created)) + table.AddSeparator() + table.AddRow("ID", utils.PtrString(instance.Id)) + table.AddSeparator() + table.AddRow("NAME", utils.PtrString(instance.DisplayName)) + table.AddSeparator() + if instance.HasDescription() { + table.AddRow("DESCRIPTION", utils.PtrString(instance.Description)) + table.AddSeparator() + } + table.AddRow("UI", utils.PtrString(instance.FrontendUrl)) + table.AddSeparator() + table.AddRow("STATE", utils.PtrString(instance.Status)) + table.AddSeparator() + table.AddRow("PLAN", utils.PtrString(instance.PlanId)) + table.AddSeparator() + + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/edge/instance/describe/describe_test.go b/internal/cmd/beta/edge/instance/describe/describe_test.go new file mode 100755 index 000000000..1f08cd0c6 --- /dev/null +++ b/internal/cmd/beta/edge/instance/describe/describe_test.go @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package describe + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/google/uuid" + "github.com/spf13/cobra" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testProjectId = uuid.NewString() + testRegion = "eu01" + + testInstanceId = "instance" + testDisplayName = "test" +) + +// mockExecutable is a mock for the Executable interface +type mockExecutable struct { + executeFails bool + executeNotFound bool + executeResp *edge.Instance +} + +func (m *mockExecutable) Execute() (*edge.Instance, error) { + if m.executeFails { + return nil, errors.New("API error") + } + if m.executeNotFound { + return nil, &oapierror.GenericOpenAPIError{ + StatusCode: http.StatusNotFound, + } + } + return m.executeResp, nil +} + +// mockAPIClient is a mock for the edge.APIClient interface +type mockAPIClient struct { + getInstanceMock edge.ApiGetInstanceRequest + getInstanceByNameMock edge.ApiGetInstanceByNameRequest +} + +func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { + if m.getInstanceMock != nil { + return m.getInstanceMock + } + return &mockExecutable{} +} + +func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { + if m.getInstanceByNameMock != nil { + return m.getInstanceByNameMock + } + return &mockExecutable{} +} + +// Unused methods to satisfy the interface +func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { + return nil +} +func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { + return nil +} +func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { + return nil +} +func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { + return nil +} +func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceNameRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceNameRequest { + return nil +} + +func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiListPlansProjectRequest { + return nil +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + + commonInstance.InstanceIdFlag: testInstanceId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureByIdInputModel(mods ...func(model *inputModel)) *inputModel { + return fixtureInputModel(false, mods...) +} + +func fixtureByNameInputModel(mods ...func(model *inputModel)) *inputModel { + return fixtureInputModel(true, mods...) +} + +func fixtureInputModel(useName bool, mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + } + + if useName { + model.identifier = &commonValidation.Identifier{ + Flag: commonInstance.DisplayNameFlag, + Value: testDisplayName, + } + } else { + model.identifier = &commonValidation.Identifier{ + Flag: commonInstance.InstanceIdFlag, + Value: testInstanceId, + } + } + + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + type args struct { + flags map[string]string + cmpOpts []testUtils.ValueComparisonOption + } + + tests := []struct { + name string + wantErr any + want *inputModel + args args + }{ + { + name: "by id", + want: fixtureByIdInputModel(), + args: args{ + flags: fixtureFlagValues(), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "by name", + want: fixtureByNameInputModel(), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "by id and name", + wantErr: true, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + }, + }, + { + name: "no flag values", + wantErr: true, + args: args{ + flags: map[string]string{}, + }, + }, + { + name: "project id missing", + wantErr: &cliErr.ProjectIdError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + }, + }, + { + name: "project id empty", + wantErr: "value cannot be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + }, + }, + { + name: "project id invalid", + wantErr: "invalid UUID length", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "instanceId missing", + want: fixtureByNameInputModel(), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "instanceId empty", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "" + }), + }, + }, + { + name: "instanceId too long", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "invalid-instance-id" + }), + }, + }, + { + name: "instanceId too short", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "id" + }), + }, + }, + { + name: "name too short", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = "foo" + }), + }, + }, + { + name: "name too long", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = "foofoofoo" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + caseOpts := []testUtils.ParseInputCaseOption{} + if len(tt.args.cmpOpts) > 0 { + caseOpts = append(caseOpts, testUtils.WithParseInputCmpOptions(tt.args.cmpOpts...)) + } + + testUtils.RunParseInputCase(t, testUtils.ParseInputTestCase[*inputModel]{ + Name: tt.name, + Flags: tt.args.flags, + WantModel: tt.want, + WantErr: tt.wantErr, + CmdFactory: NewCmd, + ParseInputFunc: func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, + }, caseOpts...) + }) + } +} + +func TestRun(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want *edge.Instance + args args + }{ + { + name: "get by id success", + want: &edge.Instance{ + Id: &testInstanceId, + DisplayName: &testDisplayName, + }, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + getInstanceMock: &mockExecutable{ + executeResp: &edge.Instance{ + Id: &testInstanceId, + DisplayName: &testDisplayName, + }, + }, + }, + }, + }, + { + name: "get by name success", + want: &edge.Instance{ + Id: &testInstanceId, + DisplayName: &testDisplayName, + }, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + getInstanceByNameMock: &mockExecutable{ + executeResp: &edge.Instance{ + Id: &testInstanceId, + DisplayName: &testDisplayName, + }, + }, + }, + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + }, + }, + { + name: "instance not found error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + getInstanceMock: &mockExecutable{ + executeNotFound: true, + }, + }, + }, + }, + { + name: "get by id API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + getInstanceMock: &mockExecutable{ + executeFails: true, + }, + }, + }, + }, + { + name: "get by name API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + getInstanceByNameMock: &mockExecutable{ + executeFails: true, + }, + }, + }, + }, + { + name: "identifier invalid", + wantErr: &commonErr.InvalidIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = &commonValidation.Identifier{ + Flag: "unknown-flag", + Value: "some-value", + } + }), + client: &mockAPIClient{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := run(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + + testUtils.AssertValue(t, got, tt.want) + }) + } +} + +func TestOutputResult(t *testing.T) { + type outputArgs struct { + model *inputModel + instance *edge.Instance + } + + tests := []struct { + name string + wantErr error + args outputArgs + }{ + { + name: "no instance", + wantErr: &commonErr.NoInstanceError{}, + args: outputArgs{ + model: fixtureByIdInputModel(), + instance: nil, + }, + }, + { + name: "output json", + args: outputArgs{ + model: fixtureInputModel(false, func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + model.identifier = nil + }), + instance: &edge.Instance{}, + }, + }, + { + name: "output yaml", + args: outputArgs{ + model: fixtureInputModel(false, func(model *inputModel) { + model.OutputFormat = print.YAMLOutputFormat + model.identifier = nil + }), + instance: &edge.Instance{}, + }, + }, + { + name: "output default", + args: outputArgs{ + model: fixtureByIdInputModel(), + instance: &edge.Instance{Id: &testInstanceId}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + + err := outputResult(p, tt.args.model.OutputFormat, tt.args.instance) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} + +func TestBuildRequest(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want *describeRequestSpec + args args + }{ + { + name: "get by id", + want: &describeRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceId: testInstanceId, + }, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + getInstanceMock: &mockExecutable{}, + }, + }, + }, + { + name: "get by name", + want: &describeRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceName: testDisplayName, + }, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + getInstanceByNameMock: &mockExecutable{}, + }, + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + }, + }, + { + name: "identifier invalid", + wantErr: &commonErr.InvalidIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = &commonValidation.Identifier{ + Flag: "unknown-flag", + Value: "some-value", + } + }), + client: &mockAPIClient{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildRequest(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + testUtils.AssertValue(t, got, tt.want, testUtils.WithIgnoreFields(describeRequestSpec{}, "Execute")) + }) + } +} diff --git a/internal/cmd/beta/edge/instance/instance.go b/internal/cmd/beta/edge/instance/instance.go new file mode 100644 index 000000000..748371cda --- /dev/null +++ b/internal/cmd/beta/edge/instance/instance.go @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package instance + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/instance/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/instance/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/instance/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/instance/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/instance/update" + + "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: "instance", + Short: "Provides functionality for edge instances.", + Long: "Provides functionality for STACKIT Edge Cloud (STEC) instance management.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) +} diff --git a/internal/cmd/beta/edge/instance/list/list.go b/internal/cmd/beta/edge/instance/list/list.go new file mode 100755 index 000000000..ca84cca87 --- /dev/null +++ b/internal/cmd/beta/edge/instance/list/list.go @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package list + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +const ( + limitFlag = "limit" +) + +// Struct to model user input (arguments and/or flags) +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +// listRequestSpec captures the details of the request for testing. +type listRequestSpec struct { + // Exported fields allow tests to inspect the request inputs + ProjectID string + Region string + Limit *int64 + + // Execute is a closure that wraps the actual SDK call + Execute func() (*edge.InstanceList, error) +} + +// Command constructor +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists edge instances", + Long: "Lists STACKIT Edge Cloud (STEC) instances of a project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all edge instances of a given project`, + `$ stackit beta edge-cloud instance list`), + examples.NewExample( + `Lists all edge instances of a given project and limits the output to two instances`, + fmt.Sprintf(`$ stackit beta edge-cloud instance list --%s 2`, limitFlag)), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + // Parse user input (arguments and/or flags) + model, err := parseInput(params.Printer, cmd) + 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) + // If project label can't be determined, fall back to project ID + projectLabel = model.ProjectId + } + + // Call API + resp, err := run(ctx, model, apiClient) + if err != nil { + return err + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // Parse and validate user input then add it to the model + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &cliErr.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + // Log the parsed model if --verbosity is set to debug + p.DebugInputModel(model) + return &model, nil +} + +// Run is the main execution function used by the command runner. +// It is decoupled from TTY output to have the ability to mock the API client during testing. +func run(ctx context.Context, model *inputModel, apiClient client.APIClient) ([]edge.Instance, error) { + spec, err := buildRequest(ctx, model, apiClient) + if err != nil { + return nil, err + } + + resp, err := spec.Execute() + if err != nil { + return nil, cliErr.NewRequestFailedError(err) + } + if resp == nil { + return nil, fmt.Errorf("list instances: empty response from API") + } + if resp.Instances == nil { + return nil, fmt.Errorf("list instances: instances missing in response") + } + instances := *resp.Instances + + // Truncate output if limit is set + if spec.Limit != nil && len(instances) > int(*spec.Limit) { + instances = instances[:*spec.Limit] + } + + return instances, nil +} + +// buildRequest constructs the spec that can be tested. +func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*listRequestSpec, error) { + req := apiClient.GetInstances(ctx, model.ProjectId, model.Region) + + return &listRequestSpec{ + ProjectID: model.ProjectId, + Region: model.Region, + Limit: model.Limit, + Execute: req.Execute, + }, nil +} + +// Output result based on the configured output format +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []edge.Instance) error { + return p.OutputResult(outputFormat, instances, func() error { + // No instances found for project + if len(instances) == 0 { + p.Outputf("No instances found for project %q\n", projectLabel) + return nil + } + + // Display instances found for project in a table + table := tables.NewTable() + // List: only output the most important fields. Be sure to filter for any non-required fields. + table.SetHeader("ID", "NAME", "UI", "STATE") + for i := range instances { + instance := instances[i] + table.AddRow( + utils.PtrString(instance.Id), + utils.PtrString(instance.DisplayName), + utils.PtrString(instance.FrontendUrl), + utils.PtrString(instance.Status)) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/edge/instance/list/list_test.go b/internal/cmd/beta/edge/instance/list/list_test.go new file mode 100755 index 000000000..2c809d95f --- /dev/null +++ b/internal/cmd/beta/edge/instance/list/list_test.go @@ -0,0 +1,460 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package list + +import ( + "context" + "errors" + "testing" + + "github.com/google/uuid" + "github.com/spf13/cobra" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testProjectId = uuid.NewString() + testRegion = "eu01" +) + +// mockExecutable is a mock for the Executable interface +type mockExecutable struct { + executeFails bool + executeResp *edge.InstanceList +} + +func (m *mockExecutable) Execute() (*edge.InstanceList, error) { + if m.executeFails { + return nil, errors.New("API error") + } + + if m.executeResp != nil { + return m.executeResp, nil + } + return &edge.InstanceList{ + Instances: &[]edge.Instance{ + {Id: utils.Ptr("instance-1"), DisplayName: utils.Ptr("namea")}, + {Id: utils.Ptr("instance-2"), DisplayName: utils.Ptr("nameb")}, + }, + }, nil +} + +// mockAPIClient is a mock for the edge.APIClient interface +type mockAPIClient struct { + getInstancesMock edge.ApiGetInstancesRequest +} + +func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { + if m.getInstancesMock != nil { + return m.getInstancesMock + } + return &mockExecutable{} +} + +// Unused methods to satisfy the interface +func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { + return nil +} +func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { + return nil +} +func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { + return nil +} +func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { + return nil +} +func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceNameRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceNameRequest { + return nil +} + +func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiListPlansProjectRequest { + return nil +} + +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 TestParseInput(t *testing.T) { + type args struct { + flags map[string]string + cmpOpts []testUtils.ValueComparisonOption + } + + tests := []struct { + name string + wantErr any + want *inputModel + args args + }{ + { + name: "success", + want: fixtureInputModel(), + args: args{ + flags: fixtureFlagValues(), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "with limit", + want: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(10)) + }), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "10" + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "no flag values", + wantErr: true, + args: args{ + flags: map[string]string{}, + }, + }, + { + name: "project id missing", + wantErr: &cliErr.ProjectIdError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + }, + }, + { + name: "project id empty", + wantErr: "value cannot be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + }, + }, + { + name: "project id invalid", + wantErr: "invalid UUID length", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "limit invalid", + wantErr: "invalid syntax", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + }, + }, + { + name: "limit less than 1", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + caseOpts := []testUtils.ParseInputCaseOption{} + if len(tt.args.cmpOpts) > 0 { + caseOpts = append(caseOpts, testUtils.WithParseInputCmpOptions(tt.args.cmpOpts...)) + } + + testUtils.RunParseInputCase(t, testUtils.ParseInputTestCase[*inputModel]{ + Name: tt.name, + Flags: tt.args.flags, + WantModel: tt.want, + WantErr: tt.wantErr, + CmdFactory: NewCmd, + ParseInputFunc: func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, + }, caseOpts...) + }) + } +} + +func TestRun(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want []edge.Instance + args args + }{ + { + name: "list success", + want: []edge.Instance{ + {Id: utils.Ptr("instance-1"), DisplayName: utils.Ptr("namea")}, + {Id: utils.Ptr("instance-2"), DisplayName: utils.Ptr("nameb")}, + }, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{}, + }, + }, + { + name: "list success with limit", + want: []edge.Instance{ + {Id: utils.Ptr("instance-1"), DisplayName: utils.Ptr("namea")}, + }, + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(1)) + }), + client: &mockAPIClient{}, + }, + }, + { + name: "list success with limit greater than items", + want: []edge.Instance{ + {Id: utils.Ptr("instance-1"), DisplayName: utils.Ptr("namea")}, + {Id: utils.Ptr("instance-2"), DisplayName: utils.Ptr("nameb")}, + }, + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(5)) + }), + client: &mockAPIClient{}, + }, + }, + { + name: "list success with no items", + want: []edge.Instance{}, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + getInstancesMock: &mockExecutable{ + executeResp: &edge.InstanceList{Instances: &[]edge.Instance{}}, + }, + }, + }, + }, + { + name: "list API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + getInstancesMock: &mockExecutable{ + executeFails: true, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := run(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + + testUtils.AssertValue(t, got, tt.want) + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + instances []edge.Instance + projectLabel string + } + + tests := []struct { + name string + wantErr error + args args + }{ + { + name: "no instance", + args: args{ + model: fixtureInputModel(), + }, + }, + { + name: "output json", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + }), + instances: []edge.Instance{ + {Id: utils.Ptr("instance-1"), DisplayName: utils.Ptr("namea")}, + }, + projectLabel: "test-project", + }, + }, + { + name: "output yaml", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.YAMLOutputFormat + }), + instances: []edge.Instance{ + {Id: utils.Ptr("instance-1"), DisplayName: utils.Ptr("namea")}, + }, + projectLabel: "test-project", + }, + }, + { + name: "output default with instances", + args: args{ + model: fixtureInputModel(), + instances: []edge.Instance{ + { + Id: utils.Ptr("instance-1"), + DisplayName: utils.Ptr("namea"), + FrontendUrl: utils.Ptr("https://example.com"), + }, + { + Id: utils.Ptr("instance-2"), + DisplayName: utils.Ptr("nameb"), + FrontendUrl: utils.Ptr("https://example2.com"), + }, + }, + projectLabel: "test-project", + }, + }, + { + name: "output default with no instances", + args: args{ + model: fixtureInputModel(), + instances: []edge.Instance{}, + projectLabel: "test-project", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + + err := outputResult(p, tt.args.model.OutputFormat, tt.args.projectLabel, tt.args.instances) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} + +func TestBuildRequest(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want *listRequestSpec + args args + }{ + { + name: "success", + want: &listRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + }, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + getInstancesMock: &mockExecutable{}, + }, + }, + }, + { + name: "success with limit", + want: &listRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + Limit: utils.Ptr(int64(10)), + }, + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(10)) + }), + client: &mockAPIClient{ + getInstancesMock: &mockExecutable{}, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildRequest(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + testUtils.AssertValue(t, got, tt.want, testUtils.WithIgnoreFields(listRequestSpec{}, "Execute")) + }) + } +} diff --git a/internal/cmd/beta/edge/instance/update/update.go b/internal/cmd/beta/edge/instance/update/update.go new file mode 100755 index 000000000..28ec3437a --- /dev/null +++ b/internal/cmd/beta/edge/instance/update/update.go @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package update + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-sdk-go/services/edge" + "github.com/stackitcloud/stackit-sdk-go/services/edge/wait" +) + +// Struct to model user input (arguments and/or flags) +type inputModel struct { + *globalflags.GlobalFlagModel + identifier *commonValidation.Identifier + Description *string + PlanId *string +} + +// updateRequestSpec captures the details of the request for testing. +type updateRequestSpec struct { + // Exported fields allow tests to inspect the request inputs + ProjectID string + Region string + InstanceId string // Set if updating by ID + InstanceName string // Set if updating by Name + Payload edge.UpdateInstancePayload + + // Execute is a closure that wraps the actual SDK call + Execute func() error +} + +// OpenApi generated code will have different types for by-instance-id and by-display-name API calls and therefore different wait handlers. +// InstanceWaiter is an interface to abstract the different wait handlers so they can be used interchangeably. +type instanceWaiter interface { + WaitWithContext(context.Context) (*edge.Instance, error) +} + +// A function that creates an instance waiter +type instanceWaiterFactory = func(client *edge.APIClient) instanceWaiter + +// Command constructor +// Instance id and displayname are likely to be refactored in future. For the time being we decided to use flags +// instead of args to provide the instance-id xor displayname to uniquely identify an instance. The displayname +// is guaranteed to be unique within a given project as of today. The chosen flag over args approach ensures we +// won't need a breaking change of the CLI when we refactor the commands to take the identifier as arg at some point. +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Updates an edge instance", + Long: "Updates a STACKIT Edge Cloud (STEC) instance.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + fmt.Sprintf(`Updates the description of an edge instance with %s "xxx"`, commonInstance.InstanceIdFlag), + fmt.Sprintf(`$ stackit beta edge-cloud instance update --%s "xxx" --%s "yyy"`, commonInstance.InstanceIdFlag, commonInstance.DescriptionFlag)), + examples.NewExample( + fmt.Sprintf(`Updates the plan of an edge instance with %s "xxx"`, commonInstance.DisplayNameFlag), + fmt.Sprintf(`$ stackit beta edge-cloud instance update --%s "xxx" --%s "yyy"`, commonInstance.DisplayNameFlag, commonInstance.PlanIdFlag)), + examples.NewExample( + fmt.Sprintf(`Updates the description and plan of an edge instance with %s "xxx"`, commonInstance.InstanceIdFlag), + fmt.Sprintf(`$ stackit beta edge-cloud instance update --%s "xxx" --%s "yyy" --%s "zzz"`, commonInstance.InstanceIdFlag, commonInstance.DescriptionFlag, commonInstance.PlanIdFlag)), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + // Parse user input (arguments and/or flags) + model, err := parseInput(params.Printer, cmd) + 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) + // If project label can't be determined, fall back to project ID + projectLabel = model.ProjectId + } + + // Prompt for confirmation + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to update the edge instance %q of project %q?", model.identifier.Value, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + err = run(ctx, model, apiClient) + if err != nil { + return err + } + + // Wait for async operation, if async mode not enabled + operationState := "Triggered update of" + if !model.Async { + // Wait for async operation, if async mode not enabled + // 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 { + 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 { + return fmt.Errorf("wait for edge instance update: %w", err) + } + operationState = "Updated" + s.Stop() + } + + params.Printer.Info("%s instance with %q %q of project %q.\n", operationState, model.identifier.Flag, model.identifier.Value, projectLabel) + + return nil + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(commonInstance.InstanceIdFlag, commonInstance.InstanceIdShorthand, "", commonInstance.InstanceIdUsage) + cmd.Flags().StringP(commonInstance.DisplayNameFlag, commonInstance.DisplayNameShorthand, "", commonInstance.DisplayNameUsage) + cmd.Flags().StringP(commonInstance.DescriptionFlag, commonInstance.DescriptionShorthand, "", commonInstance.DescriptionUsage) + cmd.Flags().StringP(commonInstance.PlanIdFlag, "", "", commonInstance.PlanIdUsage) + + identifierFlags := []string{commonInstance.InstanceIdFlag, commonInstance.DisplayNameFlag} + cmd.MarkFlagsMutuallyExclusive(identifierFlags...) // InstanceId xor DisplayName + cmd.MarkFlagsOneRequired(identifierFlags...) + + // Make sure at least one updatable field is provided, otherwise it would be a no-op + updatedFields := []string{commonInstance.DescriptionFlag, commonInstance.PlanIdFlag} + cmd.MarkFlagsOneRequired(updatedFields...) +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // Generate input model based on chosen flags + model := inputModel{ + GlobalFlagModel: globalFlags, + } + + // Parse and validate user input then add it to the model + id, err := commonValidation.GetValidatedInstanceIdentifier(p, cmd) + if err != nil { + return nil, err + } + model.identifier = id + + if planIdValue := flags.FlagToStringPointer(p, cmd, commonInstance.PlanIdFlag); planIdValue != nil { + if err := commonInstance.ValidatePlanId(planIdValue); err != nil { + return nil, err + } + model.PlanId = planIdValue + } + + if descriptionValue := flags.FlagToStringPointer(p, cmd, commonInstance.DescriptionFlag); descriptionValue != nil { + if err := commonInstance.ValidateDescription(*descriptionValue); err != nil { + return nil, err + } + model.Description = descriptionValue + } + + // Log the parsed model if --verbosity is set to debug + p.DebugInputModel(model) + return &model, nil +} + +// Run is the main execution function used by the command runner. +// It is decoupled from TTY output to have the ability to mock the API client during testing. +func run(ctx context.Context, model *inputModel, apiClient client.APIClient) error { + spec, err := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + + err = spec.Execute() + if err != nil { + return cliErr.NewRequestFailedError(err) + } + + return nil +} + +// buildRequest constructs the spec that can be tested. +// It handles the logic of choosing between UpdateInstance and UpdateInstanceByName. +func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*updateRequestSpec, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + spec := &updateRequestSpec{ + ProjectID: model.ProjectId, + Region: model.Region, + Payload: edge.UpdateInstancePayload{ + Description: model.Description, + PlanId: model.PlanId, + }, + } + + // Switch the concrete client based on the identifier flag used + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + spec.InstanceId = model.identifier.Value + req := apiClient.UpdateInstance(ctx, model.ProjectId, model.Region, model.identifier.Value) + req = req.UpdateInstancePayload(spec.Payload) + spec.Execute = req.Execute + case commonInstance.DisplayNameFlag: + spec.InstanceName = model.identifier.Value + req := apiClient.UpdateInstanceByName(ctx, model.ProjectId, model.Region, model.identifier.Value) + req = req.UpdateInstanceByNamePayload(edge.UpdateInstanceByNamePayload{ + Description: spec.Payload.Description, + PlanId: spec.Payload.PlanId, + }) + spec.Execute = req.Execute + default: + return nil, fmt.Errorf("%w: %w", cliErr.NewBuildRequestError("invalid identifier flag", nil), commonErr.NewInvalidIdentifierError(model.identifier.Flag)) + } + + return spec, nil +} + +// Returns a factory function to create the appropriate waiter based on the input model. +func getWaiterFactory(ctx context.Context, model *inputModel) (instanceWaiterFactory, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + factory := func(c *edge.APIClient) instanceWaiter { + return wait.CreateOrUpdateInstanceWaitHandler(ctx, c, model.ProjectId, model.Region, model.identifier.Value) + } + return factory, nil + case commonInstance.DisplayNameFlag: + factory := func(c *edge.APIClient) instanceWaiter { + return wait.CreateOrUpdateInstanceByNameWaitHandler(ctx, c, model.ProjectId, model.Region, model.identifier.Value) + } + return factory, nil + default: + return nil, commonErr.NewInvalidIdentifierError(model.identifier.Flag) + } +} diff --git a/internal/cmd/beta/edge/instance/update/update_test.go b/internal/cmd/beta/edge/instance/update/update_test.go new file mode 100755 index 000000000..434a74337 --- /dev/null +++ b/internal/cmd/beta/edge/instance/update/update_test.go @@ -0,0 +1,541 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package update + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/google/uuid" + "github.com/spf13/cobra" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = "instance" + testDisplayName = "test" + testDescription = "new description" + testPlanId = uuid.NewString() +) + +type mockExecutable struct { + executeFails bool + executeNotFound bool + capturedUpdatePayload *edge.UpdateInstancePayload + capturedUpdateByNamePayload *edge.UpdateInstanceByNamePayload +} + +func (m *mockExecutable) Execute() error { + if m.executeFails { + return errors.New("API error") + } + if m.executeNotFound { + return &oapierror.GenericOpenAPIError{ + StatusCode: http.StatusNotFound, + } + } + return nil +} + +func (m *mockExecutable) UpdateInstancePayload(payload edge.UpdateInstancePayload) edge.ApiUpdateInstanceRequest { + if m.capturedUpdatePayload != nil { + *m.capturedUpdatePayload = payload + } + return m +} + +func (m *mockExecutable) UpdateInstanceByNamePayload(payload edge.UpdateInstanceByNamePayload) edge.ApiUpdateInstanceByNameRequest { + if m.capturedUpdateByNamePayload != nil { + *m.capturedUpdateByNamePayload = payload + } + return m +} + +type mockAPIClient struct { + updateInstanceMock edge.ApiUpdateInstanceRequest + updateInstanceByNameMock edge.ApiUpdateInstanceByNameRequest +} + +func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { + if m.updateInstanceMock != nil { + return m.updateInstanceMock + } + return &mockExecutable{} +} + +func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceByNameRequest { + if m.updateInstanceByNameMock != nil { + return m.updateInstanceByNameMock + } + return &mockExecutable{} +} + +// Unused methods to satisfy the interface +func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { + return nil +} +func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { + return nil +} +func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { + return nil +} +func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { + return nil +} +func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceNameRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceNameRequest { + return nil +} + +func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiListPlansProjectRequest { + return nil +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + commonInstance.InstanceIdFlag: testInstanceId, + commonInstance.DescriptionFlag: testDescription, + commonInstance.PlanIdFlag: testPlanId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureByIdInputModel(mods ...func(model *inputModel)) *inputModel { + return fixtureInputModel(false, mods...) +} + +func fixtureByNameInputModel(mods ...func(model *inputModel)) *inputModel { + return fixtureInputModel(true, mods...) +} + +func fixtureInputModel(useName bool, mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + Description: &testDescription, + PlanId: &testPlanId, + } + + if useName { + model.identifier = &commonValidation.Identifier{ + Flag: commonInstance.DisplayNameFlag, + Value: testDisplayName, + } + } else { + model.identifier = &commonValidation.Identifier{ + Flag: commonInstance.InstanceIdFlag, + Value: testInstanceId, + } + } + + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + type args struct { + flags map[string]string + cmpOpts []testUtils.ValueComparisonOption + } + + tests := []struct { + name string + wantErr any + want *inputModel + args args + }{ + { + name: "by id", + want: fixtureByIdInputModel(), + args: args{ + flags: fixtureFlagValues(), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "by name", + want: fixtureByNameInputModel(), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "by id and name", + wantErr: true, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + }, + }, + { + name: "no flag values", + wantErr: true, + args: args{ + flags: map[string]string{}, + }, + }, + { + name: "no update flags", + wantErr: true, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.DescriptionFlag) + delete(flagValues, commonInstance.PlanIdFlag) + }), + }, + }, + { + name: "project id missing", + wantErr: &cliErr.ProjectIdError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + }, + }, + { + name: "project id empty", + wantErr: "value cannot be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + }, + }, + { + name: "project id invalid", + wantErr: "invalid UUID length", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "plan id invalid", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.PlanIdFlag] = "not-a-uuid" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + caseOpts := []testUtils.ParseInputCaseOption{} + if len(tt.args.cmpOpts) > 0 { + caseOpts = append(caseOpts, testUtils.WithParseInputCmpOptions(tt.args.cmpOpts...)) + } + + testUtils.RunParseInputCase(t, testUtils.ParseInputTestCase[*inputModel]{ + Name: tt.name, + Flags: tt.args.flags, + WantModel: tt.want, + WantErr: tt.wantErr, + CmdFactory: NewCmd, + ParseInputFunc: func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, + }, caseOpts...) + }) + } +} + +func TestBuildRequest(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + tests := []struct { + name string + args args + want *updateRequestSpec + wantErr error + }{ + { + name: "by id", + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + updateInstanceMock: &mockExecutable{}, + }, + }, + want: &updateRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceId: testInstanceId, + Payload: edge.UpdateInstancePayload{ + Description: &testDescription, + PlanId: &testPlanId, + }, + }, + }, + { + name: "by name", + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + updateInstanceByNameMock: &mockExecutable{}, + }, + }, + want: &updateRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceName: testDisplayName, + Payload: edge.UpdateInstancePayload{ + Description: &testDescription, + PlanId: &testPlanId, + }, + }, + }, + { + name: "no identifier", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + }, + wantErr: &commonErr.NoIdentifierError{}, + }, + { + name: "invalid identifier", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.identifier = &commonValidation.Identifier{Flag: "unknown", Value: "val"} + }), + client: &mockAPIClient{}, + }, + wantErr: &cliErr.BuildRequestError{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildRequest(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + if got != nil { + if got.Execute == nil { + t.Error("expected non-nil Execute function") + } + testUtils.AssertValue(t, got, tt.want, testUtils.WithIgnoreFields(updateRequestSpec{}, "Execute")) + } + }) + } +} + +func TestRun(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + args args + }{ + { + name: "update by id success", + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + updateInstanceMock: &mockExecutable{}, + }, + }, + }, + { + name: "update by name success", + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + updateInstanceByNameMock: &mockExecutable{}, + }, + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + }, + }, + { + name: "instance not found error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + updateInstanceMock: &mockExecutable{ + executeNotFound: true, + }, + }, + }, + }, + { + name: "update by id API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{ + updateInstanceMock: &mockExecutable{ + executeFails: true, + }, + }, + }, + }, + { + name: "update by name API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{ + updateInstanceByNameMock: &mockExecutable{ + executeFails: true, + }, + }, + }, + }, + { + name: "identifier invalid", + wantErr: &commonErr.InvalidIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = &commonValidation.Identifier{ + Flag: "unknown-flag", + Value: "some-value", + } + }), + client: &mockAPIClient{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := run(testCtx, tt.args.model, tt.args.client) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} + +func TestGetWaiterFactory(t *testing.T) { + type args struct { + model *inputModel + } + + tests := []struct { + name string + wantErr error + want bool + args args + }{ + { + name: "by id", + want: true, + args: args{ + model: fixtureByIdInputModel(), + }, + }, + { + name: "by name", + want: true, + args: args{ + model: fixtureByNameInputModel(), + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + want: false, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + }, + }, + { + name: "unknown identifier", + wantErr: &commonErr.InvalidIdentifierError{}, + want: false, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier.Flag = "unknown" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getWaiterFactory(testCtx, tt.args.model) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + + if tt.want && got == nil { + t.Fatal("expected non-nil waiter factory") + } + if !tt.want && got != nil { + t.Fatal("expected nil waiter factory") + } + }) + } +} diff --git a/internal/cmd/beta/edge/kubeconfig/create/create.go b/internal/cmd/beta/edge/kubeconfig/create/create.go new file mode 100755 index 000000000..b22b7a1b3 --- /dev/null +++ b/internal/cmd/beta/edge/kubeconfig/create/create.go @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package create + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonKubeconfig "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/kubeconfig" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/edge" + "github.com/stackitcloud/stackit-sdk-go/services/edge/wait" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + identifier *commonValidation.Identifier + DisableWriting bool + Filepath *string + Overwrite bool + Expiration uint64 + SwitchContext bool +} + +// createRequestSpec captures the details of the request for testing. +type createRequestSpec struct { + // Exported fields allow tests to inspect the request inputs + ProjectID string + Region string + InstanceId string + InstanceName string + Expiration int64 + + // Execute is a closure that wraps the actual SDK call + Execute func() (*edge.Kubeconfig, error) +} + +// OpenApi generated code will have different types for by-instance-id and by-display-name API calls and therefore different wait handlers. +// KubeconfigWaiter is an interface to abstract the different wait handlers so they can be used interchangeably. +type kubeconfigWaiter interface { + WaitWithContext(context.Context) (*edge.Kubeconfig, error) +} + +// A function that creates a kubeconfig waiter +type kubeconfigWaiterFactory = func(client *edge.APIClient) kubeconfigWaiter + +// waiterFactoryProvider is an interface that provides kubeconfig waiters so we can inject different impl. while testing. +type waiterFactoryProvider interface { + getKubeconfigWaiter(ctx context.Context, model *inputModel, apiClient client.APIClient) (kubeconfigWaiter, error) +} + +// productionWaiterFactoryProvider is the real implementation used in production. +// It handles the concrete client type casting required by the SDK's wait handlers. +type productionWaiterFactoryProvider struct{} + +func (p *productionWaiterFactoryProvider) getKubeconfigWaiter(ctx context.Context, model *inputModel, apiClient client.APIClient) (kubeconfigWaiter, error) { + waiterFactory, err := getWaiterFactory(ctx, model) + if err != nil { + return nil, err + } + // The waiter handler needs a concrete client type. We can safely cast here as the real implementation will always match. + edgeClient, ok := apiClient.(*edge.APIClient) + if !ok { + return nil, cliErr.NewBuildRequestError("failed to configure API client", nil) + } + return waiterFactory(edgeClient), nil +} + +// waiterProvider is the package-level variable used to get the waiter. +// It is initialized with the production implementation but can be overridden in tests. +var waiterProvider waiterFactoryProvider = &productionWaiterFactoryProvider{} + +// Command constructor +// Instance id and displayname are likely to be refactored in future. For the time being we decided to use flags +// instead of args to provide the instance-id xor displayname to uniquely identify an instance. The displayname +// is guaranteed to be unique within a given project as of today. The chosen flag over args approach ensures we +// won't need a breaking change of the CLI when we refactor the commands to take the identifier as arg at some point. +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates or updates a local kubeconfig file of an edge instance", + Long: fmt.Sprintf("%s\n\n%s\n%s\n%s\n%s", + "Creates or updates a local kubeconfig file of a STACKIT Edge Cloud (STEC) instance. If the config exists in the kubeconfig file, the information will be updated.", + "By default, the kubeconfig information of the edge instance is merged into the current kubeconfig file which is determined by Kubernetes client logic. If the kubeconfig file doesn't exist, a new one will be created.", + fmt.Sprintf("You can override this behavior by specifying a custom filepath with the --%s flag or disable writing with the --%s flag.", commonKubeconfig.FilepathFlag, commonKubeconfig.DisableWritingFlag), + fmt.Sprintf("An expiration time can be set for the kubeconfig. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is %d seconds.", commonKubeconfig.ExpirationSecondsDefault), + "Note: the format for the duration is , e.g. 30d for 30 days. You may not combine units."), + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + fmt.Sprintf(`Create or update a kubeconfig for the edge instance with %s "xxx". If the config exists in the kubeconfig file, the information will be updated.`, commonInstance.InstanceIdFlag), + fmt.Sprintf(`$ stackit beta edge-cloud kubeconfig create --%s "xxx"`, commonInstance.InstanceIdFlag)), + examples.NewExample( + fmt.Sprintf(`Create or update a kubeconfig for the edge instance with %s "xxx" in a custom filepath.`, commonInstance.DisplayNameFlag), + fmt.Sprintf(`$ stackit beta edge-cloud kubeconfig create --%s "xxx" --filepath "yyy"`, commonInstance.DisplayNameFlag)), + examples.NewExample( + fmt.Sprintf(`Get a kubeconfig for the edge instance with %s "xxx" without writing it to a file and format the output as json.`, commonInstance.DisplayNameFlag), + fmt.Sprintf(`$ stackit beta edge-cloud kubeconfig create --%s "xxx" --disable-writing --output-format json`, commonInstance.DisplayNameFlag)), + examples.NewExample( + fmt.Sprintf(`Create a kubeconfig for the edge instance with %s "xxx". This will replace your current kubeconfig file.`, commonInstance.InstanceIdFlag), + fmt.Sprintf(`$ stackit beta edge-cloud kubeconfig create --%s "xxx" --overwrite`, commonInstance.InstanceIdFlag)), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + // Parse user input (arguments and/or flags) + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + // Prompt for confirmation is handled in outputResult + + if model.Async { + return fmt.Errorf("async mode is not supported for kubeconfig create") + } + + // Call API via waiter (which handles both the API call and waiting) + kubeconfig, err := run(ctx, model, apiClient) + if err != nil { + return err + } + + // Handle file operations or output to printer + return outputResult(params.Printer, model.OutputFormat, model, kubeconfig) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(commonInstance.InstanceIdFlag, commonInstance.InstanceIdShorthand, "", commonInstance.InstanceIdUsage) + cmd.Flags().StringP(commonInstance.DisplayNameFlag, commonInstance.DisplayNameShorthand, "", commonInstance.DisplayNameUsage) + cmd.Flags().Bool(commonKubeconfig.DisableWritingFlag, false, commonKubeconfig.DisableWritingUsage) + cmd.Flags().StringP(commonKubeconfig.FilepathFlag, commonKubeconfig.FilepathShorthand, "", commonKubeconfig.FilepathUsage) + cmd.Flags().StringP(commonKubeconfig.ExpirationFlag, commonKubeconfig.ExpirationShorthand, "", commonKubeconfig.ExpirationUsage) + cmd.Flags().Bool(commonKubeconfig.OverwriteFlag, false, commonKubeconfig.OverwriteUsage) + cmd.Flags().Bool(commonKubeconfig.SwitchContextFlag, false, commonKubeconfig.SwitchContextUsage) + + identifierFlags := []string{commonInstance.InstanceIdFlag, commonInstance.DisplayNameFlag} + cmd.MarkFlagsMutuallyExclusive(identifierFlags...) // InstanceId xor DisplayName + cmd.MarkFlagsOneRequired(identifierFlags...) + cmd.MarkFlagsMutuallyExclusive(commonKubeconfig.DisableWritingFlag, commonKubeconfig.FilepathFlag) // DisableWriting xor Filepath + cmd.MarkFlagsMutuallyExclusive(commonKubeconfig.DisableWritingFlag, commonKubeconfig.OverwriteFlag) // DisableWriting xor Overwrite +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // Generate input model based on chosen flags + model := inputModel{ + GlobalFlagModel: globalFlags, + Filepath: flags.FlagToStringPointer(p, cmd, commonKubeconfig.FilepathFlag), + Overwrite: flags.FlagToBoolValue(p, cmd, commonKubeconfig.OverwriteFlag), + SwitchContext: flags.FlagToBoolValue(p, cmd, commonKubeconfig.SwitchContextFlag), + } + + // Parse and validate user input then add it to the model + id, err := commonValidation.GetValidatedInstanceIdentifier(p, cmd) + if err != nil { + return nil, err + } + model.identifier = id + + // Parse and validate kubeconfig expiration time + if expString := flags.FlagToStringPointer(p, cmd, commonKubeconfig.ExpirationFlag); expString != nil { + expTime, err := utils.ConvertToSeconds(*expString) + if err != nil { + return nil, &cliErr.FlagValidationError{ + Flag: commonKubeconfig.ExpirationFlag, + Details: err.Error(), + } + } + if err := commonKubeconfig.ValidateExpiration(&expTime); err != nil { + return nil, &cliErr.FlagValidationError{ + Flag: commonKubeconfig.ExpirationFlag, + Details: err.Error(), + } + } + model.Expiration = expTime + } else { + // Default expiration is 1 hour + defaultExp := uint64(commonKubeconfig.ExpirationSecondsDefault) + model.Expiration = defaultExp + } + + disableWriting := flags.FlagToBoolValue(p, cmd, commonKubeconfig.DisableWritingFlag) + model.DisableWriting = disableWriting + // Make sure to only output if the format is explicitly set + if disableWriting { + if globalFlags.OutputFormat == "" || globalFlags.OutputFormat == print.NoneOutputFormat { + return nil, &cliErr.FlagValidationError{ + Flag: commonKubeconfig.DisableWritingFlag, + Details: fmt.Sprintf("must be used with --%s", globalflags.OutputFormatFlag), + } + } + if globalFlags.OutputFormat != print.JSONOutputFormat && globalFlags.OutputFormat != print.YAMLOutputFormat { + return nil, &cliErr.FlagValidationError{ + Flag: globalflags.OutputFormatFlag, + Details: fmt.Sprintf("valid output formats for this command are: %s", fmt.Sprintf("%s, %s", print.JSONOutputFormat, print.YAMLOutputFormat)), + } + } + } + + // Log the parsed model if --verbosity is set to debug + p.DebugInputModel(model) + return &model, nil +} + +// Run is the main execution function used by the command runner. +// It is decoupled from TTY output to have the ability to mock the API client during testing. +func run(ctx context.Context, model *inputModel, apiClient client.APIClient) (*edge.Kubeconfig, error) { + spec, err := buildRequest(ctx, model, apiClient) + if err != nil { + return nil, err + } + + resp, err := spec.Execute() + if err != nil { + return nil, cliErr.NewRequestFailedError(err) + } + + return resp, nil +} + +// buildRequest constructs the spec that can be tested. +func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*createRequestSpec, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + spec := &createRequestSpec{ + ProjectID: model.ProjectId, + Region: model.Region, + Expiration: int64(model.Expiration), // #nosec G115 ValidateExpiration ensures safe bounds, conversion is safe + } + + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + spec.InstanceId = model.identifier.Value + case commonInstance.DisplayNameFlag: + spec.InstanceName = model.identifier.Value + default: + return nil, fmt.Errorf("%w: %w", cliErr.NewBuildRequestError("invalid identifier flag", nil), commonErr.NewInvalidIdentifierError(model.identifier.Flag)) + } + + // Closure used to decouple the actual SDK call for easier testing + spec.Execute = func() (*edge.Kubeconfig, error) { + // Get the waiter from the provider (handles client type casting internally) + waiter, err := waiterProvider.getKubeconfigWaiter(ctx, model, apiClient) + if err != nil { + return nil, err + } + + return waiter.WaitWithContext(ctx) + } + + return spec, nil +} + +// Returns a factory function to create the appropriate waiter based on the input model. +func getWaiterFactory(ctx context.Context, model *inputModel) (kubeconfigWaiterFactory, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + // The KubeconfigWaitHandlers don't wait for the kubeconfig to be created, but for the instance to be ready to return a kubeconfig. + // Convert uint64 to int64 to match the API's type. + var expiration = int64(model.Expiration) // #nosec G115 ValidateExpiration ensures safe bounds, conversion is safe + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + factory := func(c *edge.APIClient) kubeconfigWaiter { + return wait.KubeconfigWaitHandler(ctx, c, model.ProjectId, model.Region, model.identifier.Value, &expiration) + } + return factory, nil + case commonInstance.DisplayNameFlag: + factory := func(c *edge.APIClient) kubeconfigWaiter { + return wait.KubeconfigByInstanceNameWaitHandler(ctx, c, model.ProjectId, model.Region, model.identifier.Value, &expiration) + } + return factory, nil + default: + return nil, commonErr.NewInvalidIdentifierError(model.identifier.Flag) + } +} + +// Output result based on the configured output format +func outputResult(p *print.Printer, outputFormat string, model *inputModel, kubeconfig *edge.Kubeconfig) error { + // Ensure kubeconfig data is present + if kubeconfig == nil || kubeconfig.Kubeconfig == nil { + return fmt.Errorf("no kubeconfig returned from the API") + } + kubeconfigMap := *kubeconfig.Kubeconfig + + // Determine output format for terminal or file output + var format string + switch outputFormat { + case print.JSONOutputFormat: + // JSON if explicitly requested + format = print.JSONOutputFormat + case print.YAMLOutputFormat: + // YAML if explicitly requested + format = print.YAMLOutputFormat + default: + if model.DisableWriting { + // If not explicitly requested, use JSON as default for terminal output + format = print.JSONOutputFormat + } else { + // If not explicitly requested, use YAML as default for file output + format = print.YAMLOutputFormat + } + } + + // Marshal kubeconfig data based on the determined format + kubeconfigData, err := marshalKubeconfig(kubeconfigMap, format) + if err != nil { + return err + } + + // Handle file writing and output + if !model.DisableWriting { + // Build options for writing kubeconfig + opts := commonKubeconfig.NewWriteOptions(). + WithOverwrite(model.Overwrite). + WithSwitchContext(model.SwitchContext) + + // Add confirmation callback if not assumeYes + if !model.AssumeYes { + confirmFn := func(message string) error { + return p.PromptForConfirmation(message) + } + opts = opts.WithConfirmation(confirmFn) + } + + path, err := commonKubeconfig.WriteKubeconfig(model.Filepath, kubeconfigData, opts) + if err != nil { + return err + } + + // Inform the user about the successful write operation + p.Outputf("Wrote kubeconfig for instance %q to %q.\n", model.identifier.Value, *path) + + if model.SwitchContext { + p.Outputln("Switched context as requested.") + } + } else { + p.Outputln(kubeconfigData) + } + return nil +} + +// Marshal kubeconfig data to the specified format +func marshalKubeconfig(kubeconfigMap map[string]interface{}, format string) (string, error) { + switch format { + case print.JSONOutputFormat: + kubeconfigJSON, err := json.MarshalIndent(kubeconfigMap, "", " ") + if err != nil { + return "", fmt.Errorf("marshal kubeconfig to JSON: %w", err) + } + return string(kubeconfigJSON), nil + case print.YAMLOutputFormat: + kubeconfigYAML, err := yaml.MarshalWithOptions(kubeconfigMap, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) + if err != nil { + return "", fmt.Errorf("marshal kubeconfig to YAML: %w", err) + } + return string(kubeconfigYAML), nil + default: + return "", fmt.Errorf("%w: %s", commonErr.NewNoIdentifierError(""), format) + } +} diff --git a/internal/cmd/beta/edge/kubeconfig/create/create_test.go b/internal/cmd/beta/edge/kubeconfig/create/create_test.go new file mode 100755 index 000000000..b1fbe2810 --- /dev/null +++ b/internal/cmd/beta/edge/kubeconfig/create/create_test.go @@ -0,0 +1,820 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package create + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/goccy/go-yaml" + "github.com/google/uuid" + "github.com/spf13/cobra" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonKubeconfig "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/kubeconfig" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = "instance" + testDisplayName = "test" + testExpiration = "1h" +) + +const ( + testKubeconfig = ` +apiVersion: v1 +clusters: +- cluster: + server: https://server-1.com + name: cluster-1 +contexts: +- context: + cluster: cluster-1 + user: user-1 + name: context-1 +current-context: context-1 +kind: Config +preferences: {} +users: +- name: user-1 + user: {} +` +) + +// Helper function to create a new instance of Kubeconfig +// +//nolint:gocritic // ptrToRefParam: Required by edge.Kubeconfig API which expects *map[string]interface{} +func testKubeconfigMap() *map[string]interface{} { + var kubeconfigMap map[string]interface{} + err := yaml.Unmarshal([]byte(testKubeconfig), &kubeconfigMap) + if err != nil { + // This should never happen in tests with valid YAML + panic(err) + } + return utils.Ptr(kubeconfigMap) +} + +// mockKubeconfigWaiter is a mock for the kubeconfigWaiter interface +type mockKubeconfigWaiter struct { + waitFails bool + waitNotFound bool + waitResp *edge.Kubeconfig +} + +func (m *mockKubeconfigWaiter) WaitWithContext(_ context.Context) (*edge.Kubeconfig, error) { + if m.waitFails { + return nil, errors.New("wait error") + } + if m.waitNotFound { + return nil, &oapierror.GenericOpenAPIError{ + StatusCode: http.StatusNotFound, + } + } + if m.waitResp != nil { + return m.waitResp, nil + } + + // Default kubeconfig response + return &edge.Kubeconfig{ + Kubeconfig: testKubeconfigMap(), + }, nil +} + +// testWaiterFactoryProvider is a test implementation that returns mock waiters. +type testWaiterFactoryProvider struct { + waiter kubeconfigWaiter +} + +func (t *testWaiterFactoryProvider) getKubeconfigWaiter(_ context.Context, model *inputModel, _ client.APIClient) (kubeconfigWaiter, error) { + if model == nil || model.identifier == nil { + return nil, &commonErr.NoIdentifierError{} + } + + // Validate identifier like the real implementation + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag, commonInstance.DisplayNameFlag: + // Return our mock waiter directly, bypassing the client type casting issue + return t.waiter, nil + default: + return nil, commonErr.NewInvalidIdentifierError(model.identifier.Flag) + } +} + +// mockAPIClient is a mock for the edge.APIClient interface +type mockAPIClient struct{} + +// Unused methods to satisfy the interface +func (m *mockAPIClient) GetKubeconfigByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceIdRequest { + return nil +} + +func (m *mockAPIClient) GetKubeconfigByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceNameRequest { + return nil +} + +func (m *mockAPIClient) GetTokenByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceIdRequest { + return nil +} + +func (m *mockAPIClient) GetTokenByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceNameRequest { + return nil +} + +func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiListPlansProjectRequest { + return nil +} + +func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { + return nil +} + +func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { + return nil +} + +func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceByNameRequest { + return nil +} + +func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { + return nil +} + +func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { + return nil +} + +func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { + return nil +} + +func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { + return nil +} + +func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceByNameRequest { + return nil +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + commonInstance.InstanceIdFlag: testInstanceId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureByIdInputModel(mods ...func(model *inputModel)) *inputModel { + return fixtureInputModel(false, mods...) +} + +func fixtureByNameInputModel(mods ...func(model *inputModel)) *inputModel { + return fixtureInputModel(true, mods...) +} + +func fixtureInputModel(useName bool, mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + DisableWriting: false, + Filepath: nil, + Overwrite: false, + Expiration: uint64(3600), // Default 1 hour + SwitchContext: false, + } + + if useName { + model.identifier = &commonValidation.Identifier{ + Flag: commonInstance.DisplayNameFlag, + Value: testDisplayName, + } + } else { + model.identifier = &commonValidation.Identifier{ + Flag: commonInstance.InstanceIdFlag, + Value: testInstanceId, + } + } + + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + type args struct { + flags map[string]string + cmpOpts []testUtils.ValueComparisonOption + } + + tests := []struct { + name string + wantErr any + want *inputModel + args args + }{ + { + name: "by id", + want: fixtureByIdInputModel(), + args: args{ + flags: fixtureFlagValues(), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "by name", + want: fixtureByNameInputModel(), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "with expiration", + want: fixtureByIdInputModel(func(model *inputModel) { + model.Expiration = uint64(3600) + }), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.ExpirationFlag] = testExpiration + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "by id and name", + wantErr: true, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + }, + }, + { + name: "no flag values", + wantErr: true, + args: args{ + flags: map[string]string{}, + }, + }, + { + name: "project id missing", + wantErr: &cliErr.ProjectIdError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + }, + }, + { + name: "project id empty", + wantErr: "value cannot be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + }, + }, + { + name: "project id invalid", + wantErr: "invalid UUID length", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "instance id missing", + wantErr: true, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + }), + }, + }, + { + name: "instance id empty", + wantErr: "id may not be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "" + }), + }, + }, + { + name: "instance id too long", + wantErr: "id is too long", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "invalid-instance-id" + }), + }, + }, + { + name: "instance id too short", + wantErr: "id is too short", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "id" + }), + }, + }, + { + name: "name too short", + wantErr: "name is too short", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = "foo" + }), + }, + }, + { + name: "name too long", + wantErr: "name is too long", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = "foofoofoo" + }), + }, + }, + { + name: "disable writing and invalid output format", + wantErr: "valid output formats for this command are", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.DisableWritingFlag] = "true" + flagValues[globalflags.OutputFormatFlag] = print.PrettyOutputFormat + }), + }, + }, + { + name: "disable writing and default output format", + wantErr: "must be used with --output-format", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.DisableWritingFlag] = "true" + }), + }, + }, + { + name: "disable writing and valid output format", + want: fixtureByIdInputModel(func(model *inputModel) { + model.DisableWriting = true + model.OutputFormat = print.YAMLOutputFormat + }), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.DisableWritingFlag] = "true" + flagValues[globalflags.OutputFormatFlag] = print.YAMLOutputFormat + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "invalid expiration format", + wantErr: "invalid time string format", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.ExpirationFlag] = "invalid" + }), + }, + }, + { + name: "expiration too short", + wantErr: "expiration is too small", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.ExpirationFlag] = "1s" + }), + }, + }, + { + name: "expiration too long", + wantErr: "expiration is too large", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.ExpirationFlag] = "13M" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + caseOpts := []testUtils.ParseInputCaseOption{} + if len(tt.args.cmpOpts) > 0 { + caseOpts = append(caseOpts, testUtils.WithParseInputCmpOptions(tt.args.cmpOpts...)) + } + + testUtils.RunParseInputCase(t, testUtils.ParseInputTestCase[*inputModel]{ + Name: tt.name, + Flags: tt.args.flags, + WantModel: tt.want, + WantErr: tt.wantErr, + CmdFactory: NewCmd, + ParseInputFunc: func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, + }, caseOpts...) + }) + } +} + +func TestRun(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + waiter kubeconfigWaiter + } + + tests := []struct { + name string + wantErr error + args args + }{ + { + name: "run by id success", + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{}, + waiter: &mockKubeconfigWaiter{}, + }, + }, + { + name: "run by name success", + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{}, + waiter: &mockKubeconfigWaiter{}, + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + waiter: &mockKubeconfigWaiter{}, + }, + }, + { + name: "instance not found error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{}, + waiter: &mockKubeconfigWaiter{waitNotFound: true}, + }, + }, + { + name: "get kubeconfig by id API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{}, + waiter: &mockKubeconfigWaiter{waitFails: true}, + }, + }, + { + name: "get kubeconfig by name API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{}, + waiter: &mockKubeconfigWaiter{waitFails: true}, + }, + }, + { + name: "identifier invalid", + wantErr: &commonErr.InvalidIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = &commonValidation.Identifier{ + Flag: "unknown-flag", + Value: "some-value", + } + }), + client: &mockAPIClient{}, + waiter: &mockKubeconfigWaiter{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Override production waiterProvider package level variable for testing + prodWaiterProvider := waiterProvider + waiterProvider = &testWaiterFactoryProvider{waiter: tt.args.waiter} + defer func() { waiterProvider = prodWaiterProvider }() + + _, err := run(testCtx, tt.args.model, tt.args.client) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} + +func TestBuildRequest(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want *createRequestSpec + args args + }{ + { + name: "by id", + want: &createRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceId: testInstanceId, + Expiration: int64(commonKubeconfig.ExpirationSecondsDefault), + }, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{}, + }, + }, + { + name: "by name", + want: &createRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceName: testDisplayName, + Expiration: int64(commonKubeconfig.ExpirationSecondsDefault), + }, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{}, + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + }, + }, + { + name: "identifier invalid", + wantErr: &commonErr.InvalidIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = &commonValidation.Identifier{ + Flag: "unknown-flag", + Value: "some-value", + } + }), + client: &mockAPIClient{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildRequest(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + testUtils.AssertValue(t, got, tt.want, testUtils.WithIgnoreFields(createRequestSpec{}, "Execute")) + }) + } +} + +func TestGetWaiterFactory(t *testing.T) { + type args struct { + model *inputModel + } + + tests := []struct { + name string + wantErr error + want bool + args args + }{ + { + name: "by id", + want: true, + args: args{ + model: fixtureByIdInputModel(), + }, + }, + { + name: "by name", + want: true, + args: args{ + model: fixtureByNameInputModel(), + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + want: false, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + }, + }, + { + name: "unknown identifier", + wantErr: &commonErr.InvalidIdentifierError{}, + want: false, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier.Flag = "unknown" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getWaiterFactory(testCtx, tt.args.model) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + + if tt.want && got == nil { + t.Fatal("expected non-nil waiter factory") + } + if !tt.want && got != nil { + t.Fatal("expected nil waiter factory") + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + kubeconfig *edge.Kubeconfig + } + + tests := []struct { + name string + wantErr any + args args + }{ + { + name: "no kubeconfig", + wantErr: true, + args: args{ + model: fixtureByIdInputModel(), + kubeconfig: nil, + }, + }, + { + name: "kubeconfig with nil kubeconfig data", + wantErr: true, + args: args{ + model: fixtureByIdInputModel(), + kubeconfig: &edge.Kubeconfig{Kubeconfig: nil}, + }, + }, + { + name: "output json with disable writing", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + model.DisableWriting = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + { + name: "output yaml with disable writing", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.OutputFormat = print.YAMLOutputFormat + model.DisableWriting = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + { + name: "output default with disable writing", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.DisableWriting = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + { + name: "output by name with json format and disable writing", + args: args{ + model: fixtureByNameInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + model.DisableWriting = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + { + name: "output by name with yaml format and disable writing", + args: args{ + model: fixtureByNameInputModel(func(model *inputModel) { + model.OutputFormat = print.YAMLOutputFormat + model.DisableWriting = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + { + name: "output by name default with disable writing", + args: args{ + model: fixtureByNameInputModel(func(model *inputModel) { + model.DisableWriting = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + { + name: "file writing enabled (default behavior)", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.AssumeYes = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + { + name: "file writing with overwrite enabled", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.Overwrite = true + model.AssumeYes = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + { + name: "file writing with switch context enabled", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.SwitchContext = true + model.AssumeYes = true + }), + kubeconfig: &edge.Kubeconfig{Kubeconfig: testKubeconfigMap()}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + + err := outputResult(p, tt.args.model.OutputFormat, tt.args.model, tt.args.kubeconfig) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} diff --git a/internal/cmd/beta/edge/kubeconfig/kubeconfig.go b/internal/cmd/beta/edge/kubeconfig/kubeconfig.go new file mode 100644 index 000000000..b44c2e1a4 --- /dev/null +++ b/internal/cmd/beta/edge/kubeconfig/kubeconfig.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package kubeconfig + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/kubeconfig/create" + "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: "kubeconfig", + Short: "Provides functionality for edge kubeconfig.", + Long: "Provides functionality for STACKIT Edge Cloud (STEC) kubeconfig management.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) +} diff --git a/internal/cmd/beta/edge/plans/list/list.go b/internal/cmd/beta/edge/plans/list/list.go new file mode 100755 index 000000000..ad4c3e178 --- /dev/null +++ b/internal/cmd/beta/edge/plans/list/list.go @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package list + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +// User input struct for the command +const ( + limitFlag = "limit" +) + +// Struct to model user input (arguments and/or flags) +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +// listRequestSpec captures the details of the request for testing. +type listRequestSpec struct { + // Exported fields allow tests to inspect the request inputs + ProjectID string + Limit *int64 + + // Execute is a closure that wraps the actual SDK call + Execute func() (*edge.PlanList, error) +} + +// Command constructor +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists available edge service plans", + Long: "Lists available STACKIT Edge Cloud (STEC) service plans of a project", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Lists all edge plans for a given project`, + `$ stackit beta edge-cloud plan list`), + examples.NewExample( + `Lists all edge plans for a given project and limits the output to two plans`, + fmt.Sprintf(`$ stackit beta edge-cloud plan list --%s 2`, limitFlag)), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + // Parse user input (arguments and/or flags) + model, err := parseInput(params.Printer, cmd) + 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) + // If project label can't be determined, fall back to project ID + projectLabel = model.ProjectId + } + + // Call API + resp, err := run(ctx, model, apiClient) + if err != nil { + return err + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // Parse and validate user input then add it to the model + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &cliErr.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + // Log the parsed model if --verbosity is set to debug + p.DebugInputModel(model) + return &model, nil +} + +// Run is the main execution function used by the command runner. +// It is decoupled from TTY output to have the ability to mock the API client during testing. +func run(ctx context.Context, model *inputModel, apiClient client.APIClient) ([]edge.Plan, error) { + spec, err := buildRequest(ctx, model, apiClient) + if err != nil { + return nil, err + } + + resp, err := spec.Execute() + if err != nil { + return nil, cliErr.NewRequestFailedError(err) + } + if resp == nil { + return nil, fmt.Errorf("list plans: empty response from API") + } + if resp.ValidPlans == nil { + return nil, fmt.Errorf("list plans: valid plans missing in response") + } + plans := *resp.ValidPlans + + // Truncate output + if spec.Limit != nil && len(plans) > int(*spec.Limit) { + plans = plans[:*spec.Limit] + } + + return plans, nil +} + +// buildRequest constructs the spec that can be tested. +func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*listRequestSpec, error) { + req := apiClient.ListPlansProject(ctx, model.ProjectId) + + return &listRequestSpec{ + ProjectID: model.ProjectId, + Limit: model.Limit, + Execute: req.Execute, + }, nil +} + +// Output result based on the configured output format +func outputResult(p *print.Printer, outputFormat, projectLabel string, plans []edge.Plan) error { + return p.OutputResult(outputFormat, plans, func() error { + // No plans found for project + if len(plans) == 0 { + p.Outputf("No plans found for project %q\n", projectLabel) + return nil + } + + // Display plans found for project in a table + table := tables.NewTable() + // List: only output the most important fields. Be sure to filter for any non-required fields. + table.SetHeader("ID", "NAME", "DESCRIPTION", "MAX EDGE HOSTS") + for i := range plans { + plan := plans[i] + table.AddRow( + utils.PtrString(plan.Id), + utils.PtrString(plan.Name), + utils.PtrString(plan.Description), + utils.PtrString(plan.MaxEdgeHosts)) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/edge/plans/list/list_test.go b/internal/cmd/beta/edge/plans/list/list_test.go new file mode 100755 index 000000000..6b6f78275 --- /dev/null +++ b/internal/cmd/beta/edge/plans/list/list_test.go @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package list + +import ( + "context" + "errors" + "testing" + + "github.com/google/uuid" + "github.com/spf13/cobra" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testProjectId = uuid.NewString() + testRegion = "eu01" +) + +// mockExecutable is a mock for the Executable interface +type mockExecutable struct { + executeFails bool + executeResp *edge.PlanList +} + +func (m *mockExecutable) Execute() (*edge.PlanList, error) { + if m.executeFails { + return nil, errors.New("API error") + } + + if m.executeResp != nil { + return m.executeResp, nil + } + return &edge.PlanList{ + ValidPlans: &[]edge.Plan{ + {Id: utils.Ptr("plan-1"), Name: utils.Ptr("Standard")}, + {Id: utils.Ptr("plan-2"), Name: utils.Ptr("Premium")}, + }, + }, nil +} + +// mockAPIClient is a mock for the edge.APIClient interface +type mockAPIClient struct { + getPlansMock edge.ApiListPlansProjectRequest +} + +func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiListPlansProjectRequest { + if m.getPlansMock != nil { + return m.getPlansMock + } + return &mockExecutable{} +} + +// Unused methods to satisfy the interface +func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { + return nil +} +func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { + return nil +} + +func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { + return nil +} + +func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { + return nil +} +func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { + return nil +} +func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceNameRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetTokenByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceNameRequest { + return nil +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", + } + 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, + }, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + type args struct { + flags map[string]string + cmpOpts []testUtils.ValueComparisonOption + } + + tests := []struct { + name string + wantErr any + want *inputModel + args args + }{ + { + name: "list success", + want: fixtureInputModel(), + args: args{ + flags: fixtureFlagValues(), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "no flag values", + wantErr: true, + args: args{ + flags: map[string]string{}, + }, + }, + { + name: "project id missing", + wantErr: &cliErr.ProjectIdError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + }, + }, + { + name: "project id empty", + wantErr: "value cannot be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + }, + }, + { + name: "project id invalid", + wantErr: "invalid UUID length", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "limit invalid value", + wantErr: "invalid syntax", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + }, + }, + { + name: "limit is zero", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + }, + }, + { + name: "limit is negative", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "-0" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + caseOpts := []testUtils.ParseInputCaseOption{} + if len(tt.args.cmpOpts) > 0 { + caseOpts = append(caseOpts, testUtils.WithParseInputCmpOptions(tt.args.cmpOpts...)) + } + + testUtils.RunParseInputCase(t, testUtils.ParseInputTestCase[*inputModel]{ + Name: tt.name, + Flags: tt.args.flags, + WantModel: tt.want, + WantErr: tt.wantErr, + CmdFactory: NewCmd, + ParseInputFunc: func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, + }, caseOpts...) + }) + } +} + +func TestRun(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want []edge.Plan + args args + }{ + { + name: "list success", + want: []edge.Plan{ + {Id: utils.Ptr("plan-1"), Name: utils.Ptr("Standard")}, + {Id: utils.Ptr("plan-2"), Name: utils.Ptr("Premium")}, + }, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{}, + }, + }, + { + name: "list success with limit", + want: []edge.Plan{ + {Id: utils.Ptr("plan-1"), Name: utils.Ptr("Standard")}, + }, + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(1)) + }), + client: &mockAPIClient{}, + }, + }, + { + name: "list success with limit greater than items", + want: []edge.Plan{ + {Id: utils.Ptr("plan-1"), Name: utils.Ptr("Standard")}, + {Id: utils.Ptr("plan-2"), Name: utils.Ptr("Premium")}, + }, + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.Limit = utils.Ptr(int64(5)) + }), + client: &mockAPIClient{}, + }, + }, + { + name: "list success with no items", + want: []edge.Plan{}, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + getPlansMock: &mockExecutable{ + executeResp: &edge.PlanList{ValidPlans: &[]edge.Plan{}}, + }, + }, + }, + }, + { + name: "list API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + getPlansMock: &mockExecutable{ + executeFails: true, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := run(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + + testUtils.AssertValue(t, got, tt.want) + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + plans []edge.Plan + projectLabel string + } + + tests := []struct { + name string + wantErr error + args args + }{ + { + name: "output json", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + }), + plans: []edge.Plan{ + {Id: utils.Ptr("plan-1"), Name: utils.Ptr("Standard")}, + }, + projectLabel: "test-project", + }, + }, + { + name: "output yaml", + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.OutputFormat = print.YAMLOutputFormat + }), + plans: []edge.Plan{ + {Id: utils.Ptr("plan-1"), Name: utils.Ptr("Standard")}, + }, + projectLabel: "test-project", + }, + }, + { + name: "output default with plans", + args: args{ + model: fixtureInputModel(), + plans: []edge.Plan{ + { + Id: utils.Ptr("plan-1"), + Name: utils.Ptr("Standard"), + Description: utils.Ptr("Standard plan description"), + }, + { + Id: utils.Ptr("plan-2"), + Name: utils.Ptr("Premium"), + Description: utils.Ptr("Premium plan description"), + }, + }, + projectLabel: "test-project", + }, + }, + { + name: "output default with no plans", + args: args{ + model: fixtureInputModel(), + plans: []edge.Plan{}, + projectLabel: "test-project", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + + err := outputResult(p, tt.args.model.OutputFormat, tt.args.projectLabel, tt.args.plans) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} + +func TestBuildRequest(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want *listRequestSpec + args args + }{ + { + name: "success", + want: &listRequestSpec{ + ProjectID: testProjectId, + }, + args: args{ + model: fixtureInputModel(func(model *inputModel) { + model.Limit = nil + }), + client: &mockAPIClient{ + getPlansMock: &mockExecutable{}, + }, + }, + }, + { + name: "success with limit", + want: &listRequestSpec{ + ProjectID: testProjectId, + Limit: utils.Ptr(int64(10)), + }, + args: args{ + model: fixtureInputModel(), + client: &mockAPIClient{ + getPlansMock: &mockExecutable{}, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildRequest(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + testUtils.AssertValue(t, got, tt.want, testUtils.WithIgnoreFields(listRequestSpec{}, "Execute")) + }) + } +} diff --git a/internal/cmd/beta/edge/plans/plans.go b/internal/cmd/beta/edge/plans/plans.go new file mode 100644 index 000000000..d5ccb0721 --- /dev/null +++ b/internal/cmd/beta/edge/plans/plans.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package plans + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/plans/list" + "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: "plans", + Short: "Provides functionality for edge service plans.", + Long: "Provides functionality for STACKIT Edge Cloud (STEC) service plan management.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) +} diff --git a/internal/cmd/beta/edge/token/create/create.go b/internal/cmd/beta/edge/token/create/create.go new file mode 100755 index 000000000..f28e196ab --- /dev/null +++ b/internal/cmd/beta/edge/token/create/create.go @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package create + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonKubeconfig "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/kubeconfig" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/edge" + "github.com/stackitcloud/stackit-sdk-go/services/edge/wait" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + identifier *commonValidation.Identifier + Expiration uint64 +} + +// createRequestSpec captures the details of the request for testing. +type createRequestSpec struct { + // Exported fields allow tests to inspect the request inputs + ProjectID string + Region string + InstanceId string + InstanceName string + Expiration int64 + + // Execute is a closure that wraps the actual SDK call + Execute func() (*edge.Token, error) +} + +// OpenApi generated code will have different types for by-instance-id and by-display-name API calls and therefore different wait handlers. +// tokenWaiter is an interface to abstract the different wait handlers so they can be used interchangeably. +type tokenWaiter interface { + WaitWithContext(context.Context) (*edge.Token, error) +} + +// A function that creates a token waiter +type tokenWaiterFactory = func(client *edge.APIClient) tokenWaiter + +// waiterFactoryProvider is an interface that provides token waiters so we can inject different impl. while testing. +type waiterFactoryProvider interface { + getTokenWaiter(ctx context.Context, model *inputModel, apiClient client.APIClient) (tokenWaiter, error) +} + +// productionWaiterFactoryProvider is the real implementation used in production. +// It handles the concrete client type casting required by the SDK's wait handlers. +type productionWaiterFactoryProvider struct{} + +func (p *productionWaiterFactoryProvider) getTokenWaiter(ctx context.Context, model *inputModel, apiClient client.APIClient) (tokenWaiter, error) { + waiterFactory, err := getWaiterFactory(ctx, model) + if err != nil { + return nil, err + } + // The waiter handler needs a concrete client type. We can safely cast here as the real implementation will always match. + edgeClient, ok := apiClient.(*edge.APIClient) + if !ok { + return nil, cliErr.NewBuildRequestError("failed to configure API client", nil) + } + return waiterFactory(edgeClient), nil +} + +// waiterProvider is the package-level variable used to get the waiter. +// It is initialized with the production implementation but can be overridden in tests. +var waiterProvider waiterFactoryProvider = &productionWaiterFactoryProvider{} + +// Command constructor +// Instance id and displayname are likely to be refactored in future. For the time being we decided to use flags +// instead of args to provide the instance-id xor displayname to uniquely identify an instance. The displayname +// is guaranteed to be unique within a given project as of today. The chosen flag over args approach ensures we +// won't need a breaking change of the CLI when we refactor the commands to take the identifier as arg at some point. +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a token for an edge instance", + Long: fmt.Sprintf("%s\n\n%s\n%s", + "Creates a token for a STACKIT Edge Cloud (STEC) instance.", + fmt.Sprintf("An expiration time can be set for the token. The expiration time is set in seconds(s), minutes(m), hours(h), days(d) or months(M). Default is %d seconds.", commonKubeconfig.ExpirationSecondsDefault), + "Note: the format for the duration is , e.g. 30d for 30 days. You may not combine units."), + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + fmt.Sprintf(`Create a token for the edge instance with %s "xxx".`, commonInstance.InstanceIdFlag), + fmt.Sprintf(`$ stackit beta edge-cloud token create --%s "xxx"`, commonInstance.InstanceIdFlag)), + examples.NewExample( + fmt.Sprintf(`Create a token for the edge instance with %s "xxx". The token will be valid for one day.`, commonInstance.DisplayNameFlag), + fmt.Sprintf(`$ stackit beta edge-cloud token create --%s "xxx" --expiration 1d`, commonInstance.DisplayNameFlag)), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + + // Parse user input (arguments and/or flags) + model, err := parseInput(params.Printer, cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + if model.Async { + return fmt.Errorf("async mode is not supported for token create") + } + + // Call API + resp, err := run(ctx, model, apiClient) + if err != nil { + return err + } + + // Handle output to printer + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().StringP(commonInstance.InstanceIdFlag, commonInstance.InstanceIdShorthand, "", commonInstance.InstanceIdUsage) + cmd.Flags().StringP(commonInstance.DisplayNameFlag, commonInstance.DisplayNameShorthand, "", commonInstance.DisplayNameUsage) + cmd.Flags().StringP(commonKubeconfig.ExpirationFlag, commonKubeconfig.ExpirationShorthand, "", commonKubeconfig.ExpirationUsage) + + identifierFlags := []string{commonInstance.InstanceIdFlag, commonInstance.DisplayNameFlag} + cmd.MarkFlagsMutuallyExclusive(identifierFlags...) // InstanceId xor DisplayName + cmd.MarkFlagsOneRequired(identifierFlags...) +} + +// Parse user input (arguments and/or flags) +func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + // Generate input model based on chosen flags + model := inputModel{ + GlobalFlagModel: globalFlags, + } + + // Parse and validate user input then add it to the model + id, err := commonValidation.GetValidatedInstanceIdentifier(p, cmd) + if err != nil { + return nil, err + } + model.identifier = id + + // Parse and validate kubeconfig expiration time + if expString := flags.FlagToStringPointer(p, cmd, commonKubeconfig.ExpirationFlag); expString != nil { + expTime, err := utils.ConvertToSeconds(*expString) + if err != nil { + return nil, &cliErr.FlagValidationError{ + Flag: commonKubeconfig.ExpirationFlag, + Details: err.Error(), + } + } + if err := commonKubeconfig.ValidateExpiration(&expTime); err != nil { + return nil, &cliErr.FlagValidationError{ + Flag: commonKubeconfig.ExpirationFlag, + Details: err.Error(), + } + } + model.Expiration = expTime + } else { + // Default expiration is 1 hour + defaultExp := uint64(commonKubeconfig.ExpirationSecondsDefault) + model.Expiration = defaultExp + } + + // Make sure to only output if the format is not none + if globalFlags.OutputFormat == print.NoneOutputFormat { + return nil, &cliErr.FlagValidationError{ + Flag: globalflags.OutputFormatFlag, + Details: fmt.Sprintf("valid formats for this command are: %s", fmt.Sprintf("%s, %s, %s", print.PrettyOutputFormat, print.JSONOutputFormat, print.YAMLOutputFormat)), + } + } + + // Log the parsed model if --verbosity is set to debug + p.DebugInputModel(model) + return &model, nil +} + +// Run is the main execution function used by the command runner. +// It is decoupled from TTY output to have the ability to mock the API client during testing. +func run(ctx context.Context, model *inputModel, apiClient client.APIClient) (*edge.Token, error) { + spec, err := buildRequest(ctx, model, apiClient) + if err != nil { + return nil, err + } + + resp, err := spec.Execute() + if err != nil { + return nil, cliErr.NewRequestFailedError(err) + } + + return resp, nil +} + +// buildRequest constructs the spec that can be tested. +func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*createRequestSpec, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + spec := &createRequestSpec{ + ProjectID: model.ProjectId, + Region: model.Region, + Expiration: int64(model.Expiration), // #nosec G115 ValidateExpiration ensures safe bounds, conversion is safe + } + + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + spec.InstanceId = model.identifier.Value + case commonInstance.DisplayNameFlag: + spec.InstanceName = model.identifier.Value + default: + return nil, fmt.Errorf("%w: %w", cliErr.NewBuildRequestError("invalid identifier flag", nil), commonErr.NewInvalidIdentifierError(model.identifier.Flag)) + } + + // Closure used to decouple the actual SDK call for easier testing + spec.Execute = func() (*edge.Token, error) { + // Get the waiter from the provider (handles client type casting internally) + waiter, err := waiterProvider.getTokenWaiter(ctx, model, apiClient) + if err != nil { + return nil, err + } + + return waiter.WaitWithContext(ctx) + } + + return spec, nil +} + +// Returns a factory function to create the appropriate waiter based on the input model. +func getWaiterFactory(ctx context.Context, model *inputModel) (tokenWaiterFactory, error) { + if model == nil || model.identifier == nil { + return nil, commonErr.NewNoIdentifierError("") + } + + // The tokenWaitHandlers don't wait for the token to be created, but for the instance to be ready to return a token. + // Convert uint64 to int64 to match the API's type. + var expiration = int64(model.Expiration) // #nosec G115 ValidateExpiration ensures safe bounds, conversion is safe + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag: + factory := func(c *edge.APIClient) tokenWaiter { + return wait.TokenWaitHandler(ctx, c, model.ProjectId, model.Region, model.identifier.Value, &expiration) + } + return factory, nil + case commonInstance.DisplayNameFlag: + factory := func(c *edge.APIClient) tokenWaiter { + return wait.TokenByInstanceNameWaitHandler(ctx, c, model.ProjectId, model.Region, model.identifier.Value, &expiration) + } + return factory, nil + default: + return nil, commonErr.NewInvalidIdentifierError(model.identifier.Flag) + } +} + +// Output result based on the configured output format +func outputResult(p *print.Printer, outputFormat string, token *edge.Token) error { + if token == nil || token.Token == nil { + // This is only to prevent nil pointer deref. + // As long as the API behaves as defined by it's spec, instance can not be empty (HTTP 200 with an empty body) + return fmt.Errorf("no token returned from the API") + } + tokenString := *token.Token + + return p.OutputResult(outputFormat, token, func() error { + p.Outputln(tokenString) + return nil + }) +} diff --git a/internal/cmd/beta/edge/token/create/create_test.go b/internal/cmd/beta/edge/token/create/create_test.go new file mode 100755 index 000000000..8a78d5e29 --- /dev/null +++ b/internal/cmd/beta/edge/token/create/create_test.go @@ -0,0 +1,675 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package create + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/google/uuid" + "github.com/spf13/cobra" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/client" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + commonKubeconfig "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/kubeconfig" + commonValidation "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/validation" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = "instance" + testDisplayName = "test" + testExpiration = "1h" +) + +// mockTokenWaiter is a mock for the tokenWaiter interface +type mockTokenWaiter struct { + waitFails bool + waitNotFound bool + waitResp *edge.Token +} + +func (m *mockTokenWaiter) WaitWithContext(_ context.Context) (*edge.Token, error) { + if m.waitFails { + return nil, errors.New("wait error") + } + if m.waitNotFound { + return nil, &oapierror.GenericOpenAPIError{ + StatusCode: http.StatusNotFound, + } + } + if m.waitResp != nil { + return m.waitResp, nil + } + + // Default token response + tokenString := "test-token-string" + return &edge.Token{ + Token: &tokenString, + }, nil +} + +// testWaiterFactoryProvider is a test implementation that returns mock waiters. +type testWaiterFactoryProvider struct { + waiter tokenWaiter +} + +func (t *testWaiterFactoryProvider) getTokenWaiter(_ context.Context, model *inputModel, _ client.APIClient) (tokenWaiter, error) { + if model == nil || model.identifier == nil { + return nil, &commonErr.NoIdentifierError{} + } + + // Validate identifier like the real implementation + switch model.identifier.Flag { + case commonInstance.InstanceIdFlag, commonInstance.DisplayNameFlag: + // Return our mock waiter directly, bypassing the client type casting issue + return t.waiter, nil + default: + return nil, commonErr.NewInvalidIdentifierError(model.identifier.Flag) + } +} + +// mockAPIClient is a mock for the edge.APIClient interface +type mockAPIClient struct{} + +// Unused methods to satisfy the interface +func (m *mockAPIClient) GetTokenByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceIdRequest { + return nil +} + +func (m *mockAPIClient) GetTokenByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetTokenByInstanceNameRequest { + return nil +} + +func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiListPlansProjectRequest { + return nil +} + +func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { + return nil +} +func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { + return nil +} +func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { + return nil +} +func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { + return nil +} +func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { + return nil +} +func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceByNameRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceId(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceIdRequest { + return nil +} +func (m *mockAPIClient) GetKubeconfigByInstanceName(_ context.Context, _, _, _ string) edge.ApiGetKubeconfigByInstanceNameRequest { + return nil +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + commonInstance.InstanceIdFlag: testInstanceId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureByIdInputModel(mods ...func(model *inputModel)) *inputModel { + return fixtureInputModel(false, mods...) +} + +func fixtureByNameInputModel(mods ...func(model *inputModel)) *inputModel { + return fixtureInputModel(true, mods...) +} + +func fixtureInputModel(useName bool, mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + Expiration: uint64(commonKubeconfig.ExpirationSecondsDefault), // Default 1 hour + } + + if useName { + model.identifier = &commonValidation.Identifier{ + Flag: commonInstance.DisplayNameFlag, + Value: testDisplayName, + } + } else { + model.identifier = &commonValidation.Identifier{ + Flag: commonInstance.InstanceIdFlag, + Value: testInstanceId, + } + } + + for _, mod := range mods { + mod(model) + } + return model +} + +func TestParseInput(t *testing.T) { + type args struct { + flags map[string]string + cmpOpts []testUtils.ValueComparisonOption + } + + tests := []struct { + name string + wantErr any + want *inputModel + args args + }{ + { + name: "by id", + want: fixtureByIdInputModel(), + args: args{ + flags: fixtureFlagValues(), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "by name", + want: fixtureByNameInputModel(), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "with expiration", + want: fixtureByIdInputModel(func(model *inputModel) { + model.Expiration = uint64(3600) + }), + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.ExpirationFlag] = testExpiration + }), + cmpOpts: []testUtils.ValueComparisonOption{ + testUtils.WithAllowUnexported(inputModel{}), + }, + }, + }, + { + name: "by id and name", + wantErr: true, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.DisplayNameFlag] = testDisplayName + }), + }, + }, + { + name: "no flag values", + wantErr: true, + args: args{ + flags: map[string]string{}, + }, + }, + { + name: "project id missing", + wantErr: &cliErr.ProjectIdError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + }, + }, + { + name: "project id empty", + wantErr: "value cannot be empty", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + }, + }, + { + name: "project id invalid", + wantErr: "invalid UUID length", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + }, + }, + { + name: "instance id missing", + wantErr: true, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + }), + }, + }, + { + name: "instance id empty", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "" + }), + }, + }, + { + name: "instance id too long", + wantErr: &cliErr.FlagValidationError{}, + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "invalid-instance-id" + }), + }, + }, + { + name: "instance id too short", + wantErr: "id is too short", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonInstance.InstanceIdFlag] = "id" + }), + }, + }, + { + name: "name too short", + wantErr: "name is too short", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = "foo" + }), + }, + }, + { + name: "name too long", + wantErr: "name is too long", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, commonInstance.InstanceIdFlag) + flagValues[commonInstance.DisplayNameFlag] = "foofoofoo" + }), + }, + }, + { + name: "invalid expiration format", + wantErr: "invalid time string format", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.ExpirationFlag] = "invalid" + }), + }, + }, + { + name: "expiration too short", + wantErr: "expiration is too small", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.ExpirationFlag] = "1s" + }), + }, + }, + { + name: "expiration too long", + wantErr: "expiration is too large", + args: args{ + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[commonKubeconfig.ExpirationFlag] = "13M" + }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + caseOpts := []testUtils.ParseInputCaseOption{} + if len(tt.args.cmpOpts) > 0 { + caseOpts = append(caseOpts, testUtils.WithParseInputCmpOptions(tt.args.cmpOpts...)) + } + + testUtils.RunParseInputCase(t, testUtils.ParseInputTestCase[*inputModel]{ + Name: tt.name, + Flags: tt.args.flags, + WantModel: tt.want, + WantErr: tt.wantErr, + CmdFactory: NewCmd, + ParseInputFunc: func(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + return parseInput(p, cmd) + }, + }, caseOpts...) + }) + } +} + +func TestRun(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + waiter tokenWaiter + } + tests := []struct { + name string + wantErr any + wantToken bool + args args + }{ + { + name: "run by id success", + wantToken: true, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{}, + waiter: &mockTokenWaiter{}, + }, + }, + { + name: "run by name success", + wantToken: true, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{}, + waiter: &mockTokenWaiter{}, + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + waiter: &mockTokenWaiter{}, + }, + }, + { + name: "instance not found error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{}, + waiter: &mockTokenWaiter{waitNotFound: true}, + }, + }, + { + name: "get token by id API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{}, + waiter: &mockTokenWaiter{waitFails: true}, + }, + }, + { + name: "get token by name API error", + wantErr: &cliErr.RequestFailedError{}, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{}, + waiter: &mockTokenWaiter{waitFails: true}, + }, + }, + { + name: "identifier invalid", + wantErr: &commonErr.InvalidIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = &commonValidation.Identifier{ + Flag: "unknown-flag", + Value: "some-value", + } + }), + client: &mockAPIClient{}, + waiter: &mockTokenWaiter{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Override production waiterProvider package level variable for testing + prodWaiterProvider := waiterProvider + waiterProvider = &testWaiterFactoryProvider{waiter: tt.args.waiter} + defer func() { waiterProvider = prodWaiterProvider }() + + got, err := run(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + if tt.wantToken && got == nil { + t.Fatal("expected non-nil token") + } + }) + } +} + +func TestBuildRequest(t *testing.T) { + type args struct { + model *inputModel + client client.APIClient + } + + tests := []struct { + name string + wantErr error + want *createRequestSpec + args args + }{ + { + name: "by id", + want: &createRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceId: testInstanceId, + Expiration: int64(commonKubeconfig.ExpirationSecondsDefault), + }, + args: args{ + model: fixtureByIdInputModel(), + client: &mockAPIClient{}, + }, + }, + { + name: "by name", + want: &createRequestSpec{ + ProjectID: testProjectId, + Region: testRegion, + InstanceName: testDisplayName, + Expiration: int64(commonKubeconfig.ExpirationSecondsDefault), + }, + args: args{ + model: fixtureByNameInputModel(), + client: &mockAPIClient{}, + }, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + }), + client: &mockAPIClient{}, + }, + }, + { + name: "identifier invalid", + wantErr: &commonErr.InvalidIdentifierError{}, + args: args{ + model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = &commonValidation.Identifier{ + Flag: "unknown-flag", + Value: "some-value", + } + }), + client: &mockAPIClient{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildRequest(testCtx, tt.args.model, tt.args.client) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + testUtils.AssertValue(t, got, tt.want, testUtils.WithIgnoreFields(createRequestSpec{}, "Execute")) + }) + } +} + +func TestGetWaiterFactory(t *testing.T) { + type args struct { + model *inputModel + } + tests := []struct { + name string + want bool + wantErr error + args args + }{ + { + name: "by id", + want: true, + args: args{model: fixtureByIdInputModel()}, + }, + { + name: "by name", + want: true, + args: args{model: fixtureByNameInputModel()}, + }, + { + name: "no id or name", + wantErr: &commonErr.NoIdentifierError{}, + args: args{model: fixtureInputModel(false, func(model *inputModel) { + model.identifier = nil + })}, + }, + { + name: "unknown identifier", + wantErr: &commonErr.InvalidIdentifierError{}, + args: args{model: fixtureInputModel(false, func(model *inputModel) { + model.identifier.Flag = "unknown" + })}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getWaiterFactory(testCtx, tt.args.model) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + + if tt.want && got == nil { + t.Fatal("expected non-nil waiter factory") + } + if !tt.want && got != nil { + t.Fatal("expected nil waiter factory") + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + model *inputModel + token *edge.Token + } + tests := []struct { + name string + wantErr any + args args + }{ + { + name: "default output format", + args: args{ + model: fixtureByIdInputModel(), + token: &edge.Token{ + Token: func() *string { s := "test-token"; return &s }(), + }, + }, + }, + { + name: "JSON output format", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.OutputFormat = print.JSONOutputFormat + }), + token: &edge.Token{ + Token: func() *string { s := "test-token"; return &s }(), + }, + }, + }, + { + name: "YAML output format", + args: args{ + model: fixtureByIdInputModel(func(model *inputModel) { + model.OutputFormat = print.YAMLOutputFormat + }), + token: &edge.Token{ + Token: func() *string { s := "test-token"; return &s }(), + }, + }, + }, + { + name: "nil token", + wantErr: true, + args: args{ + model: fixtureByIdInputModel(), + token: nil, + }, + }, + { + name: "nil token string", + wantErr: true, + args: args{ + model: fixtureByIdInputModel(), + token: &edge.Token{Token: nil}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + err := outputResult(p, tt.args.model.OutputFormat, tt.args.token) + testUtils.AssertError(t, err, tt.wantErr) + }) + } +} diff --git a/internal/cmd/beta/edge/token/token.go b/internal/cmd/beta/edge/token/token.go new file mode 100644 index 000000000..8fd725a72 --- /dev/null +++ b/internal/cmd/beta/edge/token/token.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package token + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge/token/create" + "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: "token", + Short: "Provides functionality for edge service token.", + Long: "Provides functionality for STACKIT Edge Cloud (STEC) token management.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) +} diff --git a/internal/cmd/config/profile/import/template/profile.json b/internal/cmd/config/profile/import/template/profile.json index fd14150d7..ed2702e7e 100644 --- a/internal/cmd/config/profile/import/template/profile.json +++ b/internal/cmd/config/profile/import/template/profile.json @@ -3,6 +3,7 @@ "async": false, "authorization_custom_endpoint": "", "dns_custom_endpoint": "", + "edge_custom_endpoint": "", "iaas_custom_endpoint": "", "identity_provider_custom_client_id": "", "identity_provider_custom_well_known_configuration": "", @@ -31,4 +32,4 @@ "sqlserverflex_custom_endpoint": "", "token_custom_endpoint": "", "verbosity": "info" -} \ No newline at end of file +} diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index cf81c4906..64ee916f4 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -26,6 +26,7 @@ const ( authorizationCustomEndpointFlag = "authorization-custom-endpoint" dnsCustomEndpointFlag = "dns-custom-endpoint" + edgeCustomEndpointFlag = "edge-custom-endpoint" loadBalancerCustomEndpointFlag = "load-balancer-custom-endpoint" logMeCustomEndpointFlag = "logme-custom-endpoint" mariaDBCustomEndpointFlag = "mariadb-custom-endpoint" @@ -143,6 +144,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(observabilityCustomEndpointFlag, "", "Observability API base URL, used in calls to this API") cmd.Flags().String(authorizationCustomEndpointFlag, "", "Authorization API base URL, used in calls to this API") cmd.Flags().String(dnsCustomEndpointFlag, "", "DNS API base URL, used in calls to this API") + cmd.Flags().String(edgeCustomEndpointFlag, "", "Edge API base URL, used in calls to this API") cmd.Flags().String(loadBalancerCustomEndpointFlag, "", "Load Balancer API base URL, used in calls to this API") cmd.Flags().String(logMeCustomEndpointFlag, "", "LogMe API base URL, used in calls to this API") cmd.Flags().String(mariaDBCustomEndpointFlag, "", "MariaDB API base URL, used in calls to this API") @@ -182,6 +184,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.DNSCustomEndpointKey, cmd.Flags().Lookup(dnsCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.EdgeCustomEndpointKey, cmd.Flags().Lookup(edgeCustomEndpointFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.LoadBalancerCustomEndpointKey, cmd.Flags().Lookup(loadBalancerCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.LogMeCustomEndpointKey, cmd.Flags().Lookup(logMeCustomEndpointFlag)) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index a3ce21e73..c20aa131c 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -30,6 +30,7 @@ const ( authorizationCustomEndpointFlag = "authorization-custom-endpoint" dnsCustomEndpointFlag = "dns-custom-endpoint" + edgeCustomEndpointFlag = "edge-custom-endpoint" loadBalancerCustomEndpointFlag = "load-balancer-custom-endpoint" logMeCustomEndpointFlag = "logme-custom-endpoint" mariaDBCustomEndpointFlag = "mariadb-custom-endpoint" @@ -70,6 +71,7 @@ type inputModel struct { AuthorizationCustomEndpoint bool DNSCustomEndpoint bool + EdgeCustomEndpoint bool LoadBalancerCustomEndpoint bool LogMeCustomEndpoint bool MariaDBCustomEndpoint bool @@ -154,6 +156,9 @@ func NewCmd(params *types.CmdParams) *cobra.Command { if model.DNSCustomEndpoint { viper.Set(config.DNSCustomEndpointKey, "") } + if model.EdgeCustomEndpoint { + viper.Set(config.EdgeCustomEndpointKey, "") + } if model.LoadBalancerCustomEndpoint { viper.Set(config.LoadBalancerCustomEndpointKey, "") } @@ -250,6 +255,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(observabilityCustomEndpointFlag, false, "Observability API base URL. If unset, uses the default base URL") cmd.Flags().Bool(authorizationCustomEndpointFlag, false, "Authorization API base URL. If unset, uses the default base URL") cmd.Flags().Bool(dnsCustomEndpointFlag, false, "DNS API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(edgeCustomEndpointFlag, false, "Edge API base URL. If unset, uses the default base URL") cmd.Flags().Bool(loadBalancerCustomEndpointFlag, false, "Load Balancer API base URL. If unset, uses the default base URL") cmd.Flags().Bool(logMeCustomEndpointFlag, false, "LogMe API base URL. If unset, uses the default base URL") cmd.Flags().Bool(mariaDBCustomEndpointFlag, false, "MariaDB API base URL. If unset, uses the default base URL") @@ -290,6 +296,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { AuthorizationCustomEndpoint: flags.FlagToBoolValue(p, cmd, authorizationCustomEndpointFlag), DNSCustomEndpoint: flags.FlagToBoolValue(p, cmd, dnsCustomEndpointFlag), + EdgeCustomEndpoint: flags.FlagToBoolValue(p, cmd, edgeCustomEndpointFlag), LoadBalancerCustomEndpoint: flags.FlagToBoolValue(p, cmd, loadBalancerCustomEndpointFlag), LogMeCustomEndpoint: flags.FlagToBoolValue(p, cmd, logMeCustomEndpointFlag), MariaDBCustomEndpoint: flags.FlagToBoolValue(p, cmd, mariaDBCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 4ebb6cde7..37ee8f7d2 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -25,6 +25,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool authorizationCustomEndpointFlag: true, dnsCustomEndpointFlag: true, + edgeCustomEndpointFlag: true, loadBalancerCustomEndpointFlag: true, logMeCustomEndpointFlag: true, mariaDBCustomEndpointFlag: true, @@ -67,6 +68,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { AuthorizationCustomEndpoint: true, DNSCustomEndpoint: true, + EdgeCustomEndpoint: true, LoadBalancerCustomEndpoint: true, LogMeCustomEndpoint: true, MariaDBCustomEndpoint: true, @@ -125,6 +127,7 @@ func TestParseInput(t *testing.T) { model.AuthorizationCustomEndpoint = false model.DNSCustomEndpoint = false + model.EdgeCustomEndpoint = false model.LoadBalancerCustomEndpoint = false model.LogMeCustomEndpoint = false model.MariaDBCustomEndpoint = false @@ -218,6 +221,16 @@ func TestParseInput(t *testing.T) { model.DNSCustomEndpoint = false }), }, + { + description: "edge custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[edgeCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.EdgeCustomEndpoint = false + }), + }, { description: "secrets manager custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 03170f650..a60bbd17b 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -25,6 +25,7 @@ const ( AuthorizationCustomEndpointKey = "authorization_custom_endpoint" AlbCustomEndpoint = "alb_custom _endpoint" DNSCustomEndpointKey = "dns_custom_endpoint" + EdgeCustomEndpointKey = "edge_custom_endpoint" LoadBalancerCustomEndpointKey = "load_balancer_custom_endpoint" LogMeCustomEndpointKey = "logme_custom_endpoint" MariaDBCustomEndpointKey = "mariadb_custom_endpoint" @@ -85,6 +86,7 @@ var ConfigKeys = []string{ AllowedUrlDomainKey, DNSCustomEndpointKey, + EdgeCustomEndpointKey, LoadBalancerCustomEndpointKey, LogMeCustomEndpointKey, MariaDBCustomEndpointKey, @@ -179,6 +181,7 @@ func setConfigDefaults() { viper.SetDefault(IdentityProviderCustomClientIdKey, "") viper.SetDefault(AllowedUrlDomainKey, AllowedUrlDomainDefault) viper.SetDefault(DNSCustomEndpointKey, "") + viper.SetDefault(EdgeCustomEndpointKey, "") viper.SetDefault(ObservabilityCustomEndpointKey, "") viper.SetDefault(AuthorizationCustomEndpointKey, "") viper.SetDefault(MongoDBFlexCustomEndpointKey, "") diff --git a/internal/pkg/config/template/test_profile.json b/internal/pkg/config/template/test_profile.json index fd14150d7..ed2702e7e 100644 --- a/internal/pkg/config/template/test_profile.json +++ b/internal/pkg/config/template/test_profile.json @@ -3,6 +3,7 @@ "async": false, "authorization_custom_endpoint": "", "dns_custom_endpoint": "", + "edge_custom_endpoint": "", "iaas_custom_endpoint": "", "identity_provider_custom_client_id": "", "identity_provider_custom_well_known_configuration": "", @@ -31,4 +32,4 @@ "sqlserverflex_custom_endpoint": "", "token_custom_endpoint": "", "verbosity": "info" -} \ No newline at end of file +} diff --git a/internal/pkg/errors/errors.go b/internal/pkg/errors/errors.go index 814929497..d690259ea 100644 --- a/internal/pkg/errors/errors.go +++ b/internal/pkg/errors/errors.go @@ -1,10 +1,13 @@ package errors import ( + "encoding/json" + sysErrors "errors" "fmt" "strings" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" ) const ( @@ -548,3 +551,136 @@ type OneOfFlagsIsMissing struct { func (e *OneOfFlagsIsMissing) Error() string { return fmt.Sprintf(ONE_OF_THE_FLAGS_MUST_BE_PROVIDED_WHEN_ANOTHER_FLAG_IS_SET, e.MissingFlags, e.SetFlag) } + +// ___FORMATTING_ERRORS_________________________________________________________ + +// InvalidFormatError indicates that an unsupported format was provided. +type InvalidFormatError struct { + Format string // The invalid format that was provided +} + +func (e *InvalidFormatError) Error() string { + if e.Format != "" { + return fmt.Sprintf("unsupported format provided: %s", e.Format) + } + return "unsupported format provided" +} + +// NewInvalidFormatError creates a new InvalidFormatError with the provided format. +func NewInvalidFormatError(format string) *InvalidFormatError { + return &InvalidFormatError{ + Format: format, + } +} + +// ___BUILD_REQUEST_ERRORS______________________________________________________ +// BuildRequestError indicates that a request could not be built. +type BuildRequestError struct { + Reason string // Optional: specific reason why the request failed to build + Err error // Optional: underlying error +} + +func (e *BuildRequestError) Error() string { + if e.Reason != "" && e.Err != nil { + return fmt.Sprintf("could not build request (%s): %v", e.Reason, e.Err) + } + if e.Reason != "" { + return fmt.Sprintf("could not build request: %s", e.Reason) + } + if e.Err != nil { + return fmt.Sprintf("could not build request: %v", e.Err) + } + return "could not build request" +} + +func (e *BuildRequestError) Unwrap() error { + return e.Err +} + +// NewBuildRequestError creates a new BuildRequestError with optional reason and underlying error. +func NewBuildRequestError(reason string, err error) *BuildRequestError { + return &BuildRequestError{ + Reason: reason, + Err: err, + } +} + +// ___REQUESTS_ERRORS___________________________________________________________ +// RequestFailedError indicates that an API request failed. +// If the provided error is an OpenAPI error, the status code and message from the error body will be included in the error message. +type RequestFailedError struct { + Err error // Optional: underlying error +} + +func (e *RequestFailedError) Error() string { + var msg = "request failed" + + if e.Err != nil { + var oApiErr *oapierror.GenericOpenAPIError + if sysErrors.As(e.Err, &oApiErr) { + // Extract status code from OpenAPI error header if it exists + if oApiErr.StatusCode > 0 { + msg += fmt.Sprintf(" (%d)", oApiErr.StatusCode) + } + + // Try to extract message from OpenAPI error body + if bodyMsg := extractOpenApiMessageFromBody(oApiErr.Body); bodyMsg != "" { + msg += fmt.Sprintf(": %s", bodyMsg) + } else if trimmedBody := strings.TrimSpace(string(oApiErr.Body)); trimmedBody != "" { + msg += fmt.Sprintf(": %s", trimmedBody) + } else { + // Otherwise use the Go error + msg += fmt.Sprintf(": %v", e.Err) + } + } else { + // If this can't be cased into a OpenApi error use the Go error + msg += fmt.Sprintf(": %v", e.Err) + } + } + + return msg +} + +func (e *RequestFailedError) Unwrap() error { + return e.Err +} + +// NewRequestFailedError creates a new RequestFailedError with optional details. +func NewRequestFailedError(err error) *RequestFailedError { + return &RequestFailedError{ + Err: err, + } +} + +// ___HELPERS___________________________________________________________________ +// extractOpenApiMessageFromBody attempts to parse a JSON body and extract the "message" +// field. It returns an empty string if parsing fails or if no message is found. +func extractOpenApiMessageFromBody(body []byte) string { + trimmedBody := strings.TrimSpace(string(body)) + // Return early if empty. + if trimmedBody == "" { + return "" + } + + // Try to unmarshal as a structured error first + var errorBody struct { + Message string `json:"message"` + } + if err := json.Unmarshal(body, &errorBody); err == nil && errorBody.Message != "" { + if msg := strings.TrimSpace(errorBody.Message); msg != "" { + return msg + } + } + + // If that fails, try to unmarshal as a plain string + var plainBody string + if err := json.Unmarshal(body, &plainBody); err == nil && plainBody != "" { + if msg := strings.TrimSpace(plainBody); msg != "" { + return msg + } + return "" + } + + // All parsing attempts failed or yielded no message + return "" +} diff --git a/internal/pkg/errors/errors_test.go b/internal/pkg/errors/errors_test.go index d2942e87f..8a1c3d117 100644 --- a/internal/pkg/errors/errors_test.go +++ b/internal/pkg/errors/errors_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" ) var cmd *cobra.Command @@ -13,6 +14,13 @@ var service *cobra.Command var resource *cobra.Command var operation *cobra.Command +var ( + testErrorMessage = "test error message" + errStringErrTest = errors.New(testErrorMessage) + errOpenApi404 = &oapierror.GenericOpenAPIError{StatusCode: 404, Body: []byte(`{"message":"not found"}`)} + errOpenApi500 = &oapierror.GenericOpenAPIError{StatusCode: 500, Body: []byte(`invalid-json`)} +) + func setupCmd() { cmd = &cobra.Command{ Use: "stackit", @@ -686,3 +694,238 @@ func TestAppendUsageTip(t *testing.T) { }) } } + +func TestInvalidFormatError(t *testing.T) { + type args struct { + format string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "empty", + args: args{ + format: "", + }, + want: "unsupported format provided", + }, + { + name: "with format", + args: args{ + format: "yaml", + }, + want: "unsupported format provided: yaml", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := (&InvalidFormatError{Format: tt.args.format}).Error() + if got != tt.want { + t.Errorf("got %q, want %q", got, tt.want) + } + }) + } +} + +func TestBuildRequestError(t *testing.T) { + type args struct { + reason string + err error + } + tests := []struct { + name string + args args + want string + }{ + { + name: "empty", + args: args{ + reason: "", + err: nil, + }, + want: "could not build request", + }, + { + name: "reason only", + args: args{ + reason: testErrorMessage, + err: nil, + }, + want: fmt.Sprintf("could not build request: %s", testErrorMessage), + }, + { + name: "error only", + args: args{ + reason: "", + err: errStringErrTest, + }, + want: fmt.Sprintf("could not build request: %s", testErrorMessage), + }, + { + name: "reason and error", + args: args{ + reason: testErrorMessage, + err: errStringErrTest, + }, + want: fmt.Sprintf("could not build request (%s): %s", testErrorMessage, testErrorMessage), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := (&BuildRequestError{Reason: tt.args.reason, Err: tt.args.err}).Error() + if got != tt.want { + t.Errorf("got %q, want %q", got, tt.want) + } + }) + } +} + +func TestRequestFailedError(t *testing.T) { + type args struct { + err error + } + tests := []struct { + name string + args args + want string + }{ + { + name: "nil underlying", + args: args{ + err: nil, + }, + want: "request failed", + }, + { + name: "non-openapi error", + args: args{ + err: errStringErrTest, + }, + want: fmt.Sprintf("request failed: %s", testErrorMessage), + }, + { + name: "openapi error with message", + args: args{ + err: errOpenApi404, + }, + want: "request failed (404): not found", + }, + { + name: "openapi error without message", + args: args{ + err: errOpenApi500, + }, + want: "request failed (500): invalid-json", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := (&RequestFailedError{Err: tt.args.err}).Error() + if got != tt.want { + t.Errorf("got %q, want %q", got, tt.want) + } + }) + } +} + +func TestExtractMessageFromBody(t *testing.T) { + type args struct { + body []byte + } + tests := []struct { + name string + args args + want string + }{ + { + name: "empty body", + args: args{ + body: []byte(""), + }, + want: "", + }, + { + name: "invalid json", + args: args{ + body: []byte("not-json"), + }, + want: "", + }, + { + name: "missing message field", + args: args{ + body: []byte(`{"error":"oops"}`), + }, + want: "", + }, + { + name: "with message field", + args: args{ + body: []byte(`{"message":"the reason"}`), + }, + want: "the reason", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := extractOpenApiMessageFromBody(tt.args.body) + if got != tt.want { + t.Errorf("got %q, want %q", got, tt.want) + } + }) + } +} + +func TestConstructorsReturnExpected(t *testing.T) { + buildRequestError := NewBuildRequestError(testErrorMessage, errStringErrTest) + + tests := []struct { + name string + got any + want any + }{ + { + name: "InvalidFormat format", + got: NewInvalidFormatError("fmt").Format, + want: "fmt", + }, + { + name: "BuildRequestError error", + got: buildRequestError.Err, + want: errStringErrTest, + }, + { + name: "BuildRequestError reason", + got: buildRequestError.Reason, + want: testErrorMessage, + }, + { + name: "RequestFailed error", + got: NewRequestFailedError(errStringErrTest).Err, + want: errStringErrTest, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + wantErr, wantIsErr := tt.want.(error) + gotErr, gotIsErr := tt.got.(error) + if wantIsErr { + if !gotIsErr { + t.Fatalf("expected error but got %T", tt.got) + } + if !errors.Is(gotErr, wantErr) { + t.Errorf("got error %v, want %v", gotErr, wantErr) + } + return + } + + if tt.got != tt.want { + t.Errorf("got %v, want %v", tt.got, tt.want) + } + }) + } +} diff --git a/internal/pkg/services/edge/client/client.go b/internal/pkg/services/edge/client/client.go new file mode 100644 index 000000000..566e4cc05 --- /dev/null +++ b/internal/pkg/services/edge/client/client.go @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package client + +import ( + "context" + + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/edge" +) + +// APIClient is an interface that consolidates all client functionality to allow for mocking of the API client during testing. +type APIClient interface { + PostInstances(ctx context.Context, projectId, region string) edge.ApiPostInstancesRequest + DeleteInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiDeleteInstanceRequest + DeleteInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiDeleteInstanceByNameRequest + GetInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiGetInstanceRequest + GetInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiGetInstanceByNameRequest + GetInstances(ctx context.Context, projectId, region string) edge.ApiGetInstancesRequest + UpdateInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiUpdateInstanceRequest + UpdateInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiUpdateInstanceByNameRequest + GetKubeconfigByInstanceId(ctx context.Context, projectId, region, instanceId string) edge.ApiGetKubeconfigByInstanceIdRequest + GetKubeconfigByInstanceName(ctx context.Context, projectId, region, instanceName string) edge.ApiGetKubeconfigByInstanceNameRequest + GetTokenByInstanceId(ctx context.Context, projectId, region, instanceId string) edge.ApiGetTokenByInstanceIdRequest + GetTokenByInstanceName(ctx context.Context, projectId, region, instanceName string) edge.ApiGetTokenByInstanceNameRequest + ListPlansProject(ctx context.Context, projectId string) edge.ApiListPlansProjectRequest +} + +// ConfigureClient configures and returns a new API client for the Edge service. +func ConfigureClient(p *print.Printer, cliVersion string) (APIClient, error) { + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.EdgeCustomEndpointKey), false, edge.NewAPIClient) +} diff --git a/internal/pkg/services/edge/common/error/error.go b/internal/pkg/services/edge/common/error/error.go new file mode 100755 index 000000000..2fd1433c3 --- /dev/null +++ b/internal/pkg/services/edge/common/error/error.go @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +// Package error provides custom error types for STACKIT Edge Cloud operations. +// +// This package defines structured error types that provide better error handling +// and type checking compared to simple string errors. Each error type can carry +// additional context and implements the standard error interface. +package error + +import ( + "fmt" +) + +// NoIdentifierError indicates that no identifier was provided when one was required. +type NoIdentifierError struct { + Operation string // Optional: which operation failed +} + +func (e *NoIdentifierError) Error() string { + if e.Operation != "" { + return fmt.Sprintf("no identifier provided for %s", e.Operation) + } + return "no identifier provided" +} + +// InvalidIdentifierError indicates that an unsupported identifier was provided. +type InvalidIdentifierError struct { + Identifier string // The invalid identifier that was provided +} + +func (e *InvalidIdentifierError) Error() string { + if e.Identifier != "" { + return fmt.Sprintf("unsupported identifier provided: %s", e.Identifier) + } + return "unsupported identifier provided" +} + +// InstanceExistsError indicates that a specific instance already exists. +type InstanceExistsError struct { + DisplayName string // Optional: the display name that was searched for +} + +func (e *InstanceExistsError) Error() string { + if e.DisplayName != "" { + return fmt.Sprintf("instance already exists: %s", e.DisplayName) + } + return "instance already exists" +} + +// NoInstanceError indicates that no instance was provided in a context where one was expected. +type NoInstanceError struct { + Context string // Optional: context where no instance was found (e.g., "in response", "in project") +} + +func (e *NoInstanceError) Error() string { + if e.Context != "" { + return fmt.Sprintf("no instance provided %s", e.Context) + } + return "no instance provided" +} + +// NewNoIdentifierError creates a new NoIdentifierError with optional context. +func NewNoIdentifierError(operation string) *NoIdentifierError { + return &NoIdentifierError{Operation: operation} +} + +// NewInvalidIdentifierError creates a new InvalidIdentifierError with the provided identifier. +func NewInvalidIdentifierError(identifier string) *InvalidIdentifierError { + return &InvalidIdentifierError{ + Identifier: identifier, + } +} + +// NewInstanceExistsError creates a new InstanceExistsError with optional instance details. +func NewInstanceExistsError(displayName string) *InstanceExistsError { + return &InstanceExistsError{ + DisplayName: displayName, + } +} + +// NewNoInstanceError creates a new NoInstanceError with optional context. +func NewNoInstanceError(context string) *NoInstanceError { + return &NoInstanceError{Context: context} +} diff --git a/internal/pkg/services/edge/common/error/error_test.go b/internal/pkg/services/edge/common/error/error_test.go new file mode 100755 index 000000000..1268d898a --- /dev/null +++ b/internal/pkg/services/edge/common/error/error_test.go @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +// Unit tests for package error +package error + +import ( + "testing" + + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" +) + +func TestNoIdentifierError(t *testing.T) { + type args struct { + operation string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "empty", + args: args{ + operation: "", + }, + want: "no identifier provided", + }, + { + name: "with operation", + args: args{ + operation: "create", + }, + want: "no identifier provided for create", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := (&NoIdentifierError{Operation: tt.args.operation}).Error() + testUtils.AssertValue(t, got, tt.want) + }) + } +} + +func TestInvalidIdentifierError(t *testing.T) { + type args struct { + id string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "empty", + args: args{ + id: "", + }, + want: "unsupported identifier provided", + }, + { + name: "with identifier", + args: args{ + id: "x-123", + }, + want: "unsupported identifier provided: x-123", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := (&InvalidIdentifierError{Identifier: tt.args.id}).Error() + testUtils.AssertValue(t, got, tt.want) + }) + } +} + +func TestInstanceExistsError(t *testing.T) { + type args struct { + name string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "empty", + args: args{name: ""}, + want: "instance already exists"}, + { + name: "with display name", + args: args{name: "my-inst"}, + want: "instance already exists: my-inst", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := (&InstanceExistsError{DisplayName: tt.args.name}).Error() + testUtils.AssertValue(t, got, tt.want) + }) + } +} + +func TestNoInstanceError(t *testing.T) { + type args struct { + ctx string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "empty", + args: args{ + ctx: "", + }, + want: "no instance provided", + }, + { + name: "with context", + args: args{ + ctx: "in project", + }, + want: "no instance provided in project", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := (&NoInstanceError{Context: tt.args.ctx}).Error() + testUtils.AssertValue(t, got, tt.want) + }) + } +} + +func TestConstructorsReturnExpected(t *testing.T) { + tests := []struct { + name string + got any + want any + }{ + { + name: "NoIdentifier operation", + got: NewNoIdentifierError("op").Operation, + want: "op", + }, + { + name: "InvalidIdentifier identifier", + got: NewInvalidIdentifierError("id").Identifier, + want: "id", + }, + { + name: "InstanceExists displayName", + got: NewInstanceExistsError("name").DisplayName, + want: "name", + }, + { + name: "NoInstance context", + got: NewNoInstanceError("ctx").Context, + want: "ctx", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + wantErr, wantIsErr := tt.want.(error) + gotErr, gotIsErr := tt.got.(error) + if wantIsErr { + if !gotIsErr { + t.Fatalf("expected error but got %T", tt.got) + } + testUtils.AssertError(t, gotErr, wantErr) + return + } + + testUtils.AssertValue(t, tt.got, tt.want) + }) + } +} diff --git a/internal/pkg/services/edge/common/instance/instance.go b/internal/pkg/services/edge/common/instance/instance.go new file mode 100644 index 000000000..6dc35c672 --- /dev/null +++ b/internal/pkg/services/edge/common/instance/instance.go @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package instance + +import ( + "fmt" + "regexp" + + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + cliUtils "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +// Validation constants taken from OpenApi spec. +const ( + displayNameMinimumChars = 4 + displayNameMaximumChars = 8 + displayNameRegex = `^[a-z]([-a-z0-9]*[a-z0-9])?$` + descriptionMaxLength = 256 + instanceIdMaxLength = 16 + instanceIdMinLength = displayNameMinimumChars + 1 // Instance ID is generated by extending the display name. +) + +// User input flags for instance commands +const ( + DisplayNameFlag = "name" // > displayNameMinimumChars <= displayNameMaximumChars characters + regex displayNameRegex + DescriptionFlag = "description" // <= descriptionMaxLength characters + PlanIdFlag = "plan-id" // UUID + InstanceIdFlag = "id" // instance id (unique per project) +) + +// Flag usage texts +const ( + DisplayNameUsage = "The displayed name to distinguish multiple instances." + DescriptionUsage = "A user chosen description to distinguish multiple instances." + PlanIdUsage = "Service Plan configures the size of the Instance." + InstanceIdUsage = "The project-unique identifier of this instance." +) + +// Flag shorthands +const ( + DisplayNameShorthand = "n" + DescriptionShorthand = "d" + InstanceIdShorthand = "i" +) + +// OpenApi generated code will have different types for by-instance-id and by-display-name API calls, which are currently impl. as separate endpoints. +// To make the code more flexible, we use a struct to hold the request model. +type RequestModel struct { + Value any +} + +func ValidateDisplayName(displayName *string) error { + if displayName == nil { + return &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s may not be empty", DisplayNameFlag), + } + } + + if len(*displayName) > displayNameMaximumChars { + return &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", DisplayNameFlag, displayNameMaximumChars), + } + } + if len(*displayName) < displayNameMinimumChars { + return &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s is too short (minimum length is %d characters)", DisplayNameFlag, displayNameMinimumChars), + } + } + displayNameRegex := regexp.MustCompile(displayNameRegex) + if !displayNameRegex.MatchString(*displayName) { + return &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s didn't match the required regex expression %s", DisplayNameFlag, displayNameRegex), + } + } + return nil +} + +func ValidatePlanId(planId *string) error { + if planId == nil { + return &cliErr.FlagValidationError{ + Flag: PlanIdFlag, + Details: fmt.Sprintf("%s may not be empty", PlanIdFlag), + } + } + + err := cliUtils.ValidateUUID(*planId) + if err != nil { + return &cliErr.FlagValidationError{ + Flag: PlanIdFlag, + Details: fmt.Sprintf("%s is not a valid UUID: %v", PlanIdFlag, err), + } + } + return nil +} + +func ValidateDescription(description string) error { + if len(description) > descriptionMaxLength { + return &cliErr.FlagValidationError{ + Flag: DescriptionFlag, + Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", DescriptionFlag, descriptionMaxLength), + } + } + + return nil +} + +func ValidateInstanceId(instanceId *string) error { + if instanceId == nil { + return &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s may not be empty", InstanceIdFlag), + } + } + + if *instanceId == "" { + return &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s may not be empty", InstanceIdFlag), + } + } + if len(*instanceId) < instanceIdMinLength { + return &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s is too short (minimum length is %d characters)", InstanceIdFlag, instanceIdMinLength), + } + } + if len(*instanceId) > instanceIdMaxLength { + return &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", InstanceIdFlag, instanceIdMaxLength), + } + } + + return nil +} diff --git a/internal/pkg/services/edge/common/instance/instance_test.go b/internal/pkg/services/edge/common/instance/instance_test.go new file mode 100755 index 000000000..70a7dd11d --- /dev/null +++ b/internal/pkg/services/edge/common/instance/instance_test.go @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package instance + +import ( + "fmt" + "strings" + "testing" + + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func TestValidateDisplayName(t *testing.T) { + type args struct { + displayName *string + } + tests := []struct { + name string + args *args + want error + }{ + // Valid cases + { + name: "valid minimum length", + args: &args{displayName: utils.Ptr("test")}, + }, + { + name: "valid maximum length", + args: &args{displayName: utils.Ptr("testname")}, + }, + { + name: "valid with hyphens", + args: &args{displayName: utils.Ptr("test-app")}, + }, + { + name: "valid with numbers", + args: &args{displayName: utils.Ptr("test123")}, + }, + { + name: "valid starting with letter", + args: &args{displayName: utils.Ptr("a-test")}, + }, + + // Error cases - nil pointer + { + name: "nil display name", + args: &args{displayName: nil}, + want: &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s may not be empty", DisplayNameFlag), + }, + }, + + // Error cases - length validation + { + name: "too short", + args: &args{displayName: utils.Ptr("abc")}, + want: &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s is too short (minimum length is %d characters)", DisplayNameFlag, displayNameMinimumChars), + }, + }, + { + name: "too long", + args: &args{displayName: utils.Ptr("verylongname")}, + want: &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", DisplayNameFlag, displayNameMaximumChars), + }, + }, + + // Error cases - regex validation + { + name: "starts with number", + args: &args{displayName: utils.Ptr("1test")}, + want: &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s didn't match the required regex expression %s", DisplayNameFlag, displayNameRegex), + }, + }, + { + name: "starts with hyphen", + args: &args{displayName: utils.Ptr("-test")}, + want: &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s didn't match the required regex expression %s", DisplayNameFlag, displayNameRegex), + }, + }, + { + name: "ends with hyphen", + args: &args{displayName: utils.Ptr("test-")}, + want: &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s didn't match the required regex expression %s", DisplayNameFlag, displayNameRegex), + }, + }, + { + name: "contains uppercase", + args: &args{displayName: utils.Ptr("Test")}, + want: &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s didn't match the required regex expression %s", DisplayNameFlag, displayNameRegex), + }, + }, + { + name: "contains special characters", + args: &args{displayName: utils.Ptr("test@")}, + want: &cliErr.FlagValidationError{ + Flag: DisplayNameFlag, + Details: fmt.Sprintf("%s didn't match the required regex expression %s", DisplayNameFlag, displayNameRegex), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidateDisplayName(tt.args.displayName) + testUtils.AssertError(t, err, tt.want) + }) + } +} + +func TestValidatePlanId(t *testing.T) { + type args struct { + planId *string + } + tests := []struct { + name string + args *args + want error + }{ + // Valid cases + { + name: "valid UUID v4", + args: &args{planId: utils.Ptr("550e8400-e29b-41d4-a716-446655440000")}, + }, + { + name: "valid UUID lowercase", + args: &args{planId: utils.Ptr("6ba7b810-9dad-11d1-80b4-00c04fd430c8")}, + }, + { + name: "valid UUID uppercase", + args: &args{planId: utils.Ptr("6BA7B810-9DAD-11D1-80B4-00C04FD430C8")}, + }, + { + name: "valid UUID without hyphens", + args: &args{planId: utils.Ptr("550e8400e29b41d4a716446655440000")}, + }, + + // Error cases - nil pointer + { + name: "nil plan id", + args: &args{planId: nil}, + want: &cliErr.FlagValidationError{ + Flag: PlanIdFlag, + Details: fmt.Sprintf("%s may not be empty", PlanIdFlag), + }, + }, + + // Error cases - invalid UUID format + { + name: "invalid UUID - too short", + args: &args{planId: utils.Ptr("550e8400-e29b-41d4-a716")}, + want: &cliErr.FlagValidationError{ + Flag: PlanIdFlag, + Details: fmt.Sprintf("%s is not a valid UUID: parse 550e8400-e29b-41d4-a716 as UUID: invalid UUID length: 23", PlanIdFlag), + }, + }, + { + name: "invalid UUID - invalid characters", + args: &args{planId: utils.Ptr("550e8400-e29b-41d4-a716-44665544000g")}, + want: &cliErr.FlagValidationError{ + Flag: PlanIdFlag, + Details: fmt.Sprintf("%s is not a valid UUID: parse 550e8400-e29b-41d4-a716-44665544000g as UUID: invalid UUID format", PlanIdFlag), + }, + }, + { + name: "not a UUID", + args: &args{planId: utils.Ptr("not-a-uuid")}, + want: &cliErr.FlagValidationError{ + Flag: PlanIdFlag, + Details: fmt.Sprintf("%s is not a valid UUID: parse not-a-uuid as UUID: invalid UUID length: 10", PlanIdFlag), + }, + }, + { + name: "empty string", + args: &args{planId: utils.Ptr("")}, + want: &cliErr.FlagValidationError{ + Flag: PlanIdFlag, + Details: fmt.Sprintf("%s is not a valid UUID: parse as UUID: invalid UUID length: 0", PlanIdFlag), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidatePlanId(tt.args.planId) + testUtils.AssertError(t, err, tt.want) + }) + } +} + +func TestValidateDescription(t *testing.T) { + type args struct { + description string + } + tests := []struct { + name string + args *args + want error + }{ + // Valid cases + { + name: "empty description", + args: &args{description: ""}, + }, + { + name: "short description", + args: &args{description: "A short description"}, + }, + { + name: "description at maximum length", + args: &args{description: strings.Repeat("a", descriptionMaxLength)}, + }, + { + name: "description with special characters", + args: &args{description: "Description with special chars: !@#$%^&*()"}, + }, + { + name: "description with unicode", + args: &args{description: "Description with unicode: 你好世界 🌍"}, + }, + + // Error cases + { + name: "description too long", + args: &args{description: strings.Repeat("a", descriptionMaxLength+1)}, + want: &cliErr.FlagValidationError{ + Flag: DescriptionFlag, + Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", DescriptionFlag, descriptionMaxLength), + }, + }, + { + name: "description way too long", + args: &args{description: strings.Repeat("a", descriptionMaxLength+100)}, + want: &cliErr.FlagValidationError{ + Flag: DescriptionFlag, + Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", DescriptionFlag, descriptionMaxLength), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidateDescription(tt.args.description) + testUtils.AssertError(t, err, tt.want) + }) + } +} + +func TestValidateInstanceId(t *testing.T) { + type args struct { + instanceId *string + } + tests := []struct { + name string + args *args + want error + }{ + // Valid cases + { + name: "valid instance id at minimum length", + args: &args{instanceId: utils.Ptr(strings.Repeat("a", instanceIdMinLength))}, + }, + { + name: "valid instance id at maximum length", + args: &args{instanceId: utils.Ptr(strings.Repeat("a", instanceIdMaxLength))}, + }, + { + name: "valid instance id with mixed characters", + args: &args{instanceId: utils.Ptr("test-instance")}, + }, + + // Error cases - nil pointer + { + name: "nil instance id", + args: &args{instanceId: nil}, + want: &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s may not be empty", InstanceIdFlag), + }, + }, + + // Error cases - empty string + { + name: "empty string", + args: &args{instanceId: utils.Ptr("")}, + want: &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s may not be empty", InstanceIdFlag), + }, + }, + + // Error cases - length validation + { + name: "too short", + args: &args{instanceId: utils.Ptr(strings.Repeat("a", instanceIdMinLength-1))}, + want: &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s is too short (minimum length is %d characters)", InstanceIdFlag, instanceIdMinLength), + }, + }, + { + name: "way too short", + args: &args{instanceId: utils.Ptr("a")}, + want: &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s is too short (minimum length is %d characters)", InstanceIdFlag, instanceIdMinLength), + }, + }, + { + name: "too long", + args: &args{instanceId: utils.Ptr(strings.Repeat("a", instanceIdMaxLength+1))}, + want: &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", InstanceIdFlag, instanceIdMaxLength), + }, + }, + { + name: "way too long", + args: &args{instanceId: utils.Ptr(strings.Repeat("a", instanceIdMaxLength+10))}, + want: &cliErr.FlagValidationError{ + Flag: InstanceIdFlag, + Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", InstanceIdFlag, instanceIdMaxLength), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidateInstanceId(tt.args.instanceId) + testUtils.AssertError(t, err, tt.want) + }) + } +} diff --git a/internal/pkg/services/edge/common/kubeconfig/kubeconfig.go b/internal/pkg/services/edge/common/kubeconfig/kubeconfig.go new file mode 100755 index 000000000..ef0918c8b --- /dev/null +++ b/internal/pkg/services/edge/common/kubeconfig/kubeconfig.go @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package kubeconfig + +import ( + "fmt" + "maps" + "math" + "os" + "path/filepath" + + "k8s.io/client-go/tools/clientcmd" +) + +// Validation constants taken from OpenApi spec. +const ( + expirationSecondsMax = 15552000 // 60 * 60 * 24 * 180 seconds = 180 days + expirationSecondsMin = 600 // 60 * 10 seconds = 10 minutes +) + +// Defaults taken from OpenApi spec. +const ( + ExpirationSecondsDefault = 3600 // 60 * 60 seconds = 1 hour +) + +// User input flags for kubeconfig commands +const ( + ExpirationFlag = "expiration" + DisableWritingFlag = "disable-writing" + FilepathFlag = "filepath" + OverwriteFlag = "overwrite" + SwitchContextFlag = "switch-context" +) + +// Flag usage texts +const ( + ExpirationUsage = "Expiration time for the kubeconfig, e.g. 5d. By default, the token is valid for 1h." + FilepathUsage = "Path to the kubeconfig file. A default is chosen by Kubernetes if not set." + DisableWritingUsage = "Disable writing the kubeconfig to a file." + OverwriteUsage = "Force overwrite the kubeconfig file if it exists." + SwitchContextUsage = "Switch to the context in the kubeconfig file to the new context." +) + +// Flag shorthands +const ( + ExpirationShorthand = "e" + DisableWritingShorthand = "" + FilepathShorthand = "f" + OverwriteShorthand = "" + SwitchContextShorthand = "" +) + +func ValidateExpiration(expiration *uint64) error { + if expiration != nil { + // We're using utils.ConvertToSeconds to convert the user input string to seconds, which is using + // math.MaxUint64 internally, if no special limits are set. However: the OpenApi v3 Spec + // only allows integers (int64). So we could end up in a overflow IF expirationSecondsMax + // ever is changed beyond the maximum value of int64. This check makes sure this won't happen. + maxExpiration := uint64(math.Min(expirationSecondsMax, math.MaxInt64)) + if *expiration > maxExpiration { + return fmt.Errorf("%s is too large (maximum is %d seconds)", ExpirationFlag, maxExpiration) + } + // If expiration is ever changed to int64 this check makes sure we never end up with negative expiration times. + minExpiration := uint64(math.Max(expirationSecondsMin, 0)) + if *expiration < minExpiration { + return fmt.Errorf("%s is too small (minimum is %d seconds)", ExpirationFlag, minExpiration) + } + } + return nil +} + +// EmptyKubeconfigError is returned when the kubeconfig content is empty. +type EmptyKubeconfigError struct{} + +// Error returns the error message. +func (e *EmptyKubeconfigError) Error() string { + return "no data for kubeconfig" +} + +// LoadKubeconfigError is returned when loading the kubeconfig fails. +type LoadKubeconfigError struct { + Err error +} + +// Error returns the error message. +func (e *LoadKubeconfigError) Error() string { + return fmt.Sprintf("load kubeconfig: %v", e.Err) +} + +// Unwrap returns the underlying error. +func (e *LoadKubeconfigError) Unwrap() error { + return e.Err +} + +// WriteKubeconfigError is returned when writing the kubeconfig fails. +type WriteKubeconfigError struct { + Err error +} + +// Error returns the error message. +func (e *WriteKubeconfigError) Error() string { + return fmt.Sprintf("write kubeconfig: %v", e.Err) +} + +// Unwrap returns the underlying error. +func (e *WriteKubeconfigError) Unwrap() error { + return e.Err +} + +// InvalidKubeconfigPathError is returned when an invalid kubeconfig path is provided. +type InvalidKubeconfigPathError struct { + Path string +} + +// Error returns the error message. +func (e *InvalidKubeconfigPathError) Error() string { + return fmt.Sprintf("invalid path: %s", e.Path) +} + +// mergeKubeconfig merges new kubeconfig data into a kubeconfig file. +// +// If the destination file does not exist, it will be created. If the file exists, +// the new data (clusters, contexts, and users) is merged into the existing +// configuration, overwriting entries with the same name and replacing the +// current-context if defined in the new data. +// +// The function takes the following parameters: +// - configPath: The path to the destination file. The file and the directory tree +// for the file will be created if it does not exist. +// - data: The new kubeconfig content to merge. Merge is performed based on standard +// kubeconfig structure. +// - switchContext: If true, the function will switch to the new context in the +// kubeconfig file after merging. +// +// It returns a nil error on success. On failure, it returns an error indicating +// if the provided data was empty, malformed, or if there were issues reading from +// or writing to the filesystem. +func mergeKubeconfig(filePath *string, data string, switchContext bool) error { + if filePath == nil { + return fmt.Errorf("no kubeconfig file provided to be merged") + } + path := *filePath + + // Check if the new kubeconfig data is empty + if data == "" { + return &EmptyKubeconfigError{} + } + + // Load and validate the data into a kubeconfig object + newConfig, err := clientcmd.Load([]byte(data)) + if err != nil { + return &LoadKubeconfigError{Err: err} + } + + // If the destination kubeconfig does not exist, create a new one. IsNotExist will ignore other errors. + // Other errors are handled separately by the following clientcmd.LoadFromFile clientcmd.LoadFromFile + if _, err := os.Stat(path); os.IsNotExist(err) { + return writeKubeconfig(&path, data) + } + + // If the file exists load and validate the existing kubeconfig into a config object + existingConfig, err := clientcmd.LoadFromFile(path) + if err != nil { + return &LoadKubeconfigError{Err: err} + } + + // Merge the new kubeconfig data into the existing config object + maps.Copy(existingConfig.AuthInfos, newConfig.AuthInfos) + maps.Copy(existingConfig.Clusters, newConfig.Clusters) + maps.Copy(existingConfig.Contexts, newConfig.Contexts) + + // If no CurrentContext is set or switchContext is true, set the CurrentContext to the CurrentContext of the new kubeconfig + if newConfig.CurrentContext != "" && (switchContext || existingConfig.CurrentContext == "") { + existingConfig.CurrentContext = newConfig.CurrentContext + } + + // Save the merged config to the file, creating missing directories as needed. + if err := clientcmd.WriteToFile(*existingConfig, path); err != nil { + return &WriteKubeconfigError{Err: err} + } + + return nil +} + +// writeKubeconfig writes kubeconfig data to a file, overwriting it if it exists. +// +// The function takes the following parameters: +// - configPath: The path to the destination file. The file and the directory tree +// for the file will be created if it does not exist. +// - data: The new kubeconfig content to write to the file. +// +// It returns a nil error on success. On failure, it returns an error indicating +// if the provided data was empty, malformed, or if there were issues reading from +// or writing to the filesystem. +func writeKubeconfig(filePath *string, data string) error { + if filePath == nil { + return fmt.Errorf("no kubeconfig file provided to be written") + } + path := *filePath + + // Check if the new kubeconfig data is empty + if data == "" { + return &EmptyKubeconfigError{} + } + + // Load and validate the data into a kubeconfig object + config, err := clientcmd.Load([]byte(data)) + if err != nil { + return &LoadKubeconfigError{Err: err} + } + + // Save the merged config to the file, creating missing directories as needed. + if err := clientcmd.WriteToFile(*config, path); err != nil { + return &WriteKubeconfigError{Err: err} + } + + return nil +} + +// getDefaultKubeconfigPath returns the default location for the kubeconfig file, +// following standard Kubernetes loading rules. +// +// It returns a string containing the absolute path to the default kubeconfig file. +func getDefaultKubeconfigPath() string { + return clientcmd.NewDefaultClientConfigLoadingRules().GetDefaultFilename() +} + +// Returns the absolute path to the kubeconfig file. +// If a file path is provided, it is validated and, if valid, returned as an absolute path. +// If nil is provided the default kubeconfig path is loaded and returned as an absolute path. +func getKubeconfigPath(filePath *string) (string, error) { + if filePath == nil { + return getDefaultKubeconfigPath(), nil + } + + if isValidFilePath(filePath) { + return filepath.Abs(*filePath) + } + return "", &InvalidKubeconfigPathError{Path: *filePath} +} + +// Basic filesystem path validation. Returns true if the provided string is a path. Returns false otherwise. +func isValidFilePath(filePath *string) bool { + if filePath == nil || *filePath == "" { + return false + } + + // Clean the path and check if it's valid + cleaned := filepath.Clean(*filePath) + if cleaned == "." || cleaned == string(filepath.Separator) { + return false + } + + // Try to get absolute path (this will fail for invalid paths) + _, err := filepath.Abs(*filePath) + // If no error, the path is valid (return true). Otherwise, it's invalid (return false). + return err == nil +} + +// Basic filesystem file existence check. Returns true if the file exists. Returns false otherwise. +func isExistingFile(filePath *string) bool { + // Check if the kubeconfig file exists + _, errStat := os.Stat(*filePath) + return !os.IsNotExist(errStat) +} + +// ConfirmationCallback is a function that prompts for confirmation with the given message +// and returns true if confirmed, false otherwise +type ConfirmationCallback func(message string) error + +// WriteOptions contains options for writing kubeconfig files +type WriteOptions struct { + Overwrite bool + SwitchContext bool + ConfirmFn ConfirmationCallback +} + +// WithOverwrite sets whether to overwrite existing files instead of merging +func (w WriteOptions) WithOverwrite(overwrite bool) WriteOptions { + w.Overwrite = overwrite + return w +} + +// WithSwitchContext sets whether to switch to the new context after writing +func (w WriteOptions) WithSwitchContext(switchContext bool) WriteOptions { + w.SwitchContext = switchContext + return w +} + +// WithConfirmation sets the confirmation callback function +func (w WriteOptions) WithConfirmation(fn ConfirmationCallback) WriteOptions { + w.ConfirmFn = fn + return w +} + +// NewWriteOptions creates a new WriteOptions with default values +func NewWriteOptions() WriteOptions { + return WriteOptions{ + Overwrite: false, + SwitchContext: false, + ConfirmFn: nil, + } +} + +// WriteKubeconfig writes the provided kubeconfig data to a file on the filesystem. +// By default, if the file already exists, it will be merged with the provided data. +// This behavior can be controlled using the provided options. +// +// The function takes the following parameters: +// - filePath: The path to the destination file. The file and the directory tree for the +// file will be created if it does not exist. If nil, the default kubeconfig path is used. +// - kubeconfig: The kubeconfig content to write. +// - options: Options for controlling the write behavior. +// +// It returns the file path actually used to write to on success. +func WriteKubeconfig(filePath *string, kubeconfig string, options WriteOptions) (*string, error) { + // Check if the provided filePath is valid or use the default kubeconfig path no filePath is provided + path, err := getKubeconfigPath(filePath) + if err != nil { + return nil, err + } + + if isExistingFile(&path) { + // If the file exists + if !options.Overwrite { + // If overwrite was not requested the default it to merge + if options.ConfirmFn != nil { + // If confirmation callback is provided, prompt the user for confirmation + prompt := fmt.Sprintf("Update your kubeconfig %q?", path) + err := options.ConfirmFn(prompt) + if err != nil { + // If the user doesn't confirm do not proceed with the merge + return nil, err + } + } + err := mergeKubeconfig(&path, kubeconfig, options.SwitchContext) + if err != nil { + return nil, err + } + return &path, err + } + // If overwrite was requested overwrite the existing file + if options.ConfirmFn != nil { + // If confirmation callback is provided, prompt the user for confirmation + prompt := fmt.Sprintf("Replace your kubeconfig %q?", path) + err := options.ConfirmFn(prompt) + if err != nil { + // If the user doesn't confirm do not proceed with the overwrite + return nil, err + } + // Fallthrough + } + } + // If the file doesn't exist or in case the user confirmed the overwrite (fallthrough) write the file + err = writeKubeconfig(&path, kubeconfig) + if err != nil { + return nil, err + } + return &path, err +} diff --git a/internal/pkg/services/edge/common/kubeconfig/kubeconfig_test.go b/internal/pkg/services/edge/common/kubeconfig/kubeconfig_test.go new file mode 100755 index 000000000..59bbba0b0 --- /dev/null +++ b/internal/pkg/services/edge/common/kubeconfig/kubeconfig_test.go @@ -0,0 +1,744 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package kubeconfig + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" + "testing" + + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "k8s.io/client-go/tools/clientcmd" +) + +var ( + testErrorMessage = "test error message" + errStringErrTest = errors.New(testErrorMessage) +) + +const ( + kubeconfig_1_yaml = ` +apiVersion: v1 +clusters: +- cluster: + server: https://server-1.com + name: cluster-1 +contexts: +- context: + cluster: cluster-1 + user: user-1 + name: context-1 +current-context: context-1 +kind: Config +preferences: {} +users: +- name: user-1 + user: {} +` + kubeconfig_2_yaml = ` +apiVersion: v1 +clusters: +- cluster: + server: https://server-2.com + name: cluster-2 +contexts: +- context: + cluster: cluster-2 + user: user-2 + name: context-2 +current-context: context-2 +kind: Config +users: +- name: user-2 + user: {} +` + overwriteKubeconfigTarget = ` +apiVersion: v1 +clusters: +- cluster: + server: https://server-1.com + name: cluster-1 +contexts: +- context: + cluster: cluster-1 + user: user-1 + name: context-1 +current-context: context-1 +kind: Config +users: +- name: user-1 + user: + token: old-token +` + overwriteKubeconfigSource = ` +apiVersion: v1 +clusters: +- cluster: + server: https://server-1-new.com + name: cluster-1 +contexts: +- context: + cluster: cluster-1 + user: user-1 + name: context-1 +current-context: context-1 +kind: Config +users: +- name: user-1 + user: + token: new-token +` +) + +func TestValidateExpiration(t *testing.T) { + type args struct { + expiration *uint64 + } + tests := []struct { + name string + args *args + want error + }{ + // Valid cases + { + name: "nil expiration", + args: &args{ + expiration: nil, + }, + }, + { + name: "valid expiration - minimum value", + args: &args{ + expiration: utils.Ptr(uint64(expirationSecondsMin)), + }, + }, + { + name: "valid expiration - maximum value", + args: &args{ + expiration: utils.Ptr(uint64(expirationSecondsMax)), + }, + }, + { + name: "valid expiration - default value", + args: &args{ + expiration: utils.Ptr(uint64(ExpirationSecondsDefault)), + }, + }, + { + name: "valid expiration - middle value", + args: &args{ + expiration: utils.Ptr(uint64(86400)), // 1 day + }, + }, + + // Error cases - below minimum + { + name: "expiration too small - below minimum", + args: &args{ + expiration: utils.Ptr(uint64(expirationSecondsMin - 1)), + }, + want: fmt.Errorf("%s is too small (minimum is %d seconds)", ExpirationFlag, expirationSecondsMin), + }, + { + name: "expiration too small - zero", + args: &args{ + expiration: utils.Ptr(uint64(0)), + }, + want: fmt.Errorf("%s is too small (minimum is %d seconds)", ExpirationFlag, expirationSecondsMin), + }, + + // Error cases - above maximum + { + name: "expiration too large - above maximum", + args: &args{ + expiration: utils.Ptr(uint64(expirationSecondsMax + 1)), + }, + want: fmt.Errorf("%s is too large (maximum is %d seconds)", ExpirationFlag, expirationSecondsMax), + }, + { + name: "expiration too large - way above maximum", + args: &args{ + expiration: utils.Ptr(uint64(9999999999999999999)), + }, + want: fmt.Errorf("%s is too large (maximum is %d seconds)", ExpirationFlag, expirationSecondsMax), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidateExpiration(tt.args.expiration) + testUtils.AssertError(t, err, tt.want) + }) + } +} + +func TestErrors(t *testing.T) { + type args struct { + err error + } + tests := []struct { + name string + args *args + wantErr error + }{ + // EmptyKubeconfigError + { + name: "EmptyKubeconfigError", + args: &args{ + err: &EmptyKubeconfigError{}, + }, + wantErr: &EmptyKubeconfigError{}, + }, + + // LoadKubeconfigError + { + name: "LoadKubeconfigError", + args: &args{ + err: &LoadKubeconfigError{Err: errStringErrTest}, + }, + wantErr: errStringErrTest, + }, + + // WriteKubeconfigError + { + name: "WriteKubeconfigError", + args: &args{ + err: &WriteKubeconfigError{Err: errStringErrTest}, + }, + wantErr: errStringErrTest, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testUtils.AssertError(t, tt.args.err, tt.wantErr) + }) + } +} + +// Already have comprehensive tests for WriteKubeconfig + +func TestWriteOptions(t *testing.T) { + confirmFn := func(_ string) error { return nil } + + type args struct { + modify func(WriteOptions) WriteOptions + check func(*testing.T, WriteOptions) + } + tests := []struct { + name string + args *args + }{ + // Default options + { + name: "NewWriteOptions creates default options", + args: &args{ + modify: func(o WriteOptions) WriteOptions { return o }, + check: func(t *testing.T, opts WriteOptions) { + if opts.Overwrite { + t.Error("expected Overwrite to be false by default") + } + if opts.SwitchContext { + t.Error("expected SwitchContext to be false by default") + } + if opts.ConfirmFn != nil { + t.Error("expected ConfirmFn to be nil by default") + } + }, + }, + }, + + // Individual option tests + { + name: "WithOverwrite sets overwrite flag", + args: &args{ + modify: func(o WriteOptions) WriteOptions { return o.WithOverwrite(true) }, + check: func(t *testing.T, opts WriteOptions) { + if !opts.Overwrite { + t.Error("expected Overwrite to be true") + } + }, + }, + }, + { + name: "WithSwitchContext sets switch context flag", + args: &args{ + modify: func(o WriteOptions) WriteOptions { return o.WithSwitchContext(true) }, + check: func(t *testing.T, opts WriteOptions) { + if !opts.SwitchContext { + t.Error("expected SwitchContext to be true") + } + }, + }, + }, + { + name: "WithConfirmation sets confirmation callback", + args: &args{ + modify: func(o WriteOptions) WriteOptions { return o.WithConfirmation(confirmFn) }, + check: func(t *testing.T, opts WriteOptions) { + if opts.ConfirmFn == nil { + t.Error("expected ConfirmFn to be set") + } + }, + }, + }, + + // Chained options + { + name: "options are chainable", + args: &args{ + modify: func(o WriteOptions) WriteOptions { + return o.WithOverwrite(true). + WithSwitchContext(true). + WithConfirmation(confirmFn) + }, + check: func(t *testing.T, opts WriteOptions) { + if !opts.Overwrite { + t.Error("expected Overwrite to be true") + } + if !opts.SwitchContext { + t.Error("expected SwitchContext to be true") + } + if opts.ConfirmFn == nil { + t.Error("expected ConfirmFn to be set") + } + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + opts := tt.args.modify(NewWriteOptions()) + tt.args.check(t, opts) + }) + } +} + +func TestGetDefaultKubeconfigPath(t *testing.T) { + type args struct { + kubeconfigEnv *string // nil means unset + } + tests := []struct { + name string + args *args + want string + }{ + // KUBECONFIG not set + { + name: "returns a non-empty path when KUBECONFIG is not set", + args: &args{kubeconfigEnv: nil}, + want: "", + }, + + // Single path + { + name: "returns path from KUBECONFIG if set", + args: &args{kubeconfigEnv: utils.Ptr("/test/kubeconfig_1_yaml")}, + want: "/test/kubeconfig_1_yaml", + }, + + // Multiple paths + { + name: "returns first path from KUBECONFIG if multiple are set", + args: &args{kubeconfigEnv: utils.Ptr("/test/kubeconfig_1_yaml" + string(os.PathListSeparator) + "/test/kubeconfig_2_yaml")}, + want: "/test/kubeconfig_1_yaml", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Save original env and restore after test + oldKubeconfig := os.Getenv("KUBECONFIG") + defer func() { + if err := os.Setenv("KUBECONFIG", oldKubeconfig); err != nil { + t.Logf("failed to restore KUBECONFIG: %v", err) + } + }() + + // Setup test environment + if tt.args.kubeconfigEnv == nil { + if err := os.Unsetenv("KUBECONFIG"); err != nil { + t.Fatalf("failed to unset KUBECONFIG: %v", err) + } + } else { + if err := os.Setenv("KUBECONFIG", *tt.args.kubeconfigEnv); err != nil { + t.Fatalf("failed to set KUBECONFIG: %v", err) + } + } + + // Run test + got := getDefaultKubeconfigPath() + + // If want is empty only make sure the returned path is not empty + // In that case we don't care about what path is default, only that one is. + want := filepath.Clean(tt.want) + if want == filepath.Clean("") { + if filepath.Clean(got) != "" { + return + } + } + + // Verify results + testUtils.AssertValue(t, filepath.Clean(got), want) + }) + } +} + +func TestGetKubeconfigPath(t *testing.T) { + type args struct { + path *string + checkPath func(t *testing.T, path string) + } + tests := []struct { + name string + args *args + wantErr error + }{ + { + name: "uses default path when nil provided", + args: &args{ + path: nil, + checkPath: func(t *testing.T, path string) { + if path == "" { + t.Error("expected non-empty path") + } + }, + }, + }, + { + name: "validates and returns absolute path when valid path provided", + args: &args{ + path: utils.Ptr("/tmp/kubeconfig"), + checkPath: func(t *testing.T, path string) { + if !filepath.IsAbs(path) { + t.Error("expected absolute path") + } + }, + }, + }, + { + name: "returns error for invalid path", + args: &args{ + path: utils.Ptr("."), + }, + wantErr: &InvalidKubeconfigPathError{Path: "."}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path, err := getKubeconfigPath(tt.args.path) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + if tt.args.checkPath != nil { + tt.args.checkPath(t, path) + } + }) + } +} + +func TestIsValidFilePath(t *testing.T) { + type args struct { + path *string + } + tests := []struct { + name string + args *args + + want bool + }{ + { + name: "valid path", + args: &args{ + path: utils.Ptr("/test/kubeconfig"), + }, + want: true, + }, + { + name: "nil path", + args: &args{ + path: nil, + }, + want: false, + }, + { + name: "empty path", + args: &args{ + path: utils.Ptr(""), + }, + want: false, + }, + { + name: "single dot", + args: &args{ + path: utils.Ptr("."), + }, + want: false, + }, + { + name: "single slash", + args: &args{ + path: utils.Ptr("/"), + }, + want: false, + }, + { + name: "relative path with parent directory", + args: &args{ + path: utils.Ptr("../kubeconfig"), + }, + want: true, + }, + { + name: "path with spaces", + args: &args{ + path: utils.Ptr("/test/kube config"), + }, + want: true, + }, + { + name: "complex but valid path", + args: &args{ + path: utils.Ptr("/test/kube-config.d/cluster1/config"), + }, + want: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := isValidFilePath(tt.args.path); got != tt.want { + t.Errorf("isValidFilePath() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestWriteKubeconfig(t *testing.T) { + testPath := filepath.Join(t.TempDir(), "config") + defaultTempFile := filepath.Join(t.TempDir(), "default-kubeconfig") + + type args struct { + path *string + content string + options WriteOptions + setupEnv func() + checkFile func(t *testing.T, path string) + } + tests := []struct { + name string + args *args + wantPath *string + wantErr any + }{ + { + name: "writes new file with default options", + args: &args{ + path: &testPath, + content: kubeconfig_1_yaml, + options: NewWriteOptions(), + checkFile: func(t *testing.T, path string) { + if !isExistingFile(&path) { + t.Error("file was not created") + } + }, + }, + wantPath: &testPath, + }, + { + name: "handles invalid file path", + args: &args{ + path: utils.Ptr("."), + content: kubeconfig_1_yaml, + options: NewWriteOptions(), + }, + wantErr: &InvalidKubeconfigPathError{Path: "."}, + }, + { + name: "handles empty kubeconfig", + args: &args{ + path: &testPath, + content: "", + options: NewWriteOptions(), + }, + wantErr: &EmptyKubeconfigError{}, + }, + { + name: "uses default path when nil provided", + args: &args{ + path: nil, + content: kubeconfig_1_yaml, + options: NewWriteOptions(), + setupEnv: func() { + t.Setenv("KUBECONFIG", defaultTempFile) + }, + }, + wantPath: &defaultTempFile, + }, + { + name: "overwrites existing file when option is set", + args: &args{ + path: &testPath, + content: kubeconfig_2_yaml, + options: NewWriteOptions().WithOverwrite(true), + setupEnv: func() { + // Pre-write first file + if _, err := WriteKubeconfig(&testPath, kubeconfig_1_yaml, NewWriteOptions()); err != nil { + t.Fatalf("failed to setup test: %v", err) + } + }, + checkFile: func(t *testing.T, path string) { + content, err := os.ReadFile(path) + if err != nil { + t.Fatalf("failed to read kubeconfig: %v", err) + } + if !strings.Contains(string(content), "server-2.com") { + t.Error("file was not overwritten") + } + }, + }, + wantPath: &testPath, + }, + { + name: "respects user confirmation - confirmed", + args: &args{ + path: &testPath, + content: kubeconfig_1_yaml, + options: NewWriteOptions().WithConfirmation(func(_ string) error { + return nil + }), + }, + wantPath: &testPath, + }, + { + name: "respects user confirmation - denied", + args: &args{ + path: &testPath, + content: kubeconfig_1_yaml, + options: NewWriteOptions().WithConfirmation(func(_ string) error { + return errStringErrTest + }), + }, + wantErr: errStringErrTest, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.args.setupEnv != nil { + tt.args.setupEnv() + } + + got, gotErr := WriteKubeconfig(tt.args.path, tt.args.content, tt.args.options) + if !testUtils.AssertError(t, gotErr, tt.wantErr) { + return + } + + testUtils.AssertValue(t, got, tt.wantPath) + + if tt.args.checkFile != nil { + tt.args.checkFile(t, *got) + } + }) + } +} + +func TestMergeKubeconfig(t *testing.T) { + type args struct { + path *string + content string + switchCtx bool + setupEnv func() + } + tests := []struct { + name string + args args + verify func(t *testing.T, path string) + wantErr error + }{ + { + name: "merges configs with conflicting names", + args: args{ + path: utils.Ptr(filepath.Join(t.TempDir(), "kubeconfig")), + content: overwriteKubeconfigSource, + switchCtx: true, + setupEnv: func() { + // Pre-write first file + if _, err := WriteKubeconfig(utils.Ptr(filepath.Join(t.TempDir(), "kubeconfig")), overwriteKubeconfigTarget, NewWriteOptions()); err != nil { + t.Fatalf("failed to setup test: %v", err) + } + }, + }, + verify: func(t *testing.T, path string) { + config, err := clientcmd.LoadFromFile(path) + if err != nil { + t.Fatalf("failed to load merged config: %v", err) + } + + cluster := config.Clusters["cluster-1"] + if cluster.Server != "https://server-1-new.com" { + t.Errorf("expected server to be 'https://server-1-new.com', got '%s'", cluster.Server) + } + + user := config.AuthInfos["user-1"] + if user.Token != "new-token" { + t.Errorf("expected token to be 'new-token', got '%s'", user.Token) + } + }, + }, + { + name: "handles nil file path", + args: args{ + path: nil, + content: kubeconfig_1_yaml, + switchCtx: false, + }, + wantErr: fmt.Errorf("no kubeconfig file provided to be merged"), + }, + { + name: "handles invalid config", + args: args{ + path: utils.Ptr(filepath.Join(t.TempDir(), "kubeconfig")), + content: "invalid yaml", + switchCtx: false, + }, + wantErr: &LoadKubeconfigError{}, + }, + { + name: "handles empty config", + args: args{ + path: utils.Ptr(filepath.Join(t.TempDir(), "kubeconfig")), + content: "", + switchCtx: false, + }, + wantErr: &EmptyKubeconfigError{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.args.setupEnv != nil { + tt.args.setupEnv() + } + + err := mergeKubeconfig(tt.args.path, tt.args.content, tt.args.switchCtx) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + + if tt.verify != nil { + if tt.args.path == nil { + t.Fatalf("expected path to be set") + } + tt.verify(t, *tt.args.path) + } + }) + } +} diff --git a/internal/pkg/services/edge/common/validation/input.go b/internal/pkg/services/edge/common/validation/input.go new file mode 100644 index 000000000..33a2d0c46 --- /dev/null +++ b/internal/pkg/services/edge/common/validation/input.go @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package validation + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" +) + +// Struct to model the instance identifier provided by the user (either instance-id or display-name) +type Identifier struct { + Flag string + Value string +} + +// GetValidatedInstanceIdentifier gets and validates the instance identifier provided by the user through the command-line flags. +// It checks for either an instance ID or a display name and validates the provided value. +// +// p is the printer used for logging. +// cmd is the cobra command that holds the flags. +// +// Returns an Identifier struct containing the flag and its value if a valid identifier is provided, otherwise returns an error. +// Indirect unit tests of GetValidatedInstanceIdentifier are done within the respective CLI packages. +func GetValidatedInstanceIdentifier(p *print.Printer, cmd *cobra.Command) (*Identifier, error) { + switch { + case cmd.Flags().Changed(commonInstance.InstanceIdFlag): + instanceIdValue := flags.FlagToStringPointer(p, cmd, commonInstance.InstanceIdFlag) + if err := commonInstance.ValidateInstanceId(instanceIdValue); err != nil { + return nil, err + } + return &Identifier{ + Flag: commonInstance.InstanceIdFlag, + Value: *instanceIdValue, + }, nil + case cmd.Flags().Changed(commonInstance.DisplayNameFlag): + displayNameValue := flags.FlagToStringPointer(p, cmd, commonInstance.DisplayNameFlag) + if err := commonInstance.ValidateDisplayName(displayNameValue); err != nil { + return nil, err + } + return &Identifier{ + Flag: commonInstance.DisplayNameFlag, + Value: *displayNameValue, + }, nil + default: + return nil, commonErr.NewNoIdentifierError("") + } +} diff --git a/internal/pkg/services/edge/common/validation/input_test.go b/internal/pkg/services/edge/common/validation/input_test.go new file mode 100755 index 000000000..0ccb2d3b2 --- /dev/null +++ b/internal/pkg/services/edge/common/validation/input_test.go @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package validation + +import ( + "testing" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + commonErr "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/error" + commonInstance "github.com/stackitcloud/stackit-cli/internal/pkg/services/edge/common/instance" + testUtils "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" +) + +func TestGetValidatedInstanceIdentifier(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + setup func(*cobra.Command) + want *Identifier + wantErr any + }{ + { + name: "instance id success", + setup: func(cmd *cobra.Command) { + cmd.Flags().String(commonInstance.InstanceIdFlag, "", "") + _ = cmd.Flags().Set(commonInstance.InstanceIdFlag, "edgesvc01") + }, + want: &Identifier{Flag: commonInstance.InstanceIdFlag, Value: "edgesvc01"}, + }, + { + name: "display name success", + setup: func(cmd *cobra.Command) { + cmd.Flags().String(commonInstance.DisplayNameFlag, "", "") + _ = cmd.Flags().Set(commonInstance.DisplayNameFlag, "edge01") + }, + want: &Identifier{Flag: commonInstance.DisplayNameFlag, Value: "edge01"}, + }, + { + name: "instance id validation error", + setup: func(cmd *cobra.Command) { + cmd.Flags().String(commonInstance.InstanceIdFlag, "", "") + _ = cmd.Flags().Set(commonInstance.InstanceIdFlag, "id") + }, + wantErr: "too short", + }, + { + name: "display name validation error", + setup: func(cmd *cobra.Command) { + cmd.Flags().String(commonInstance.DisplayNameFlag, "", "") + _ = cmd.Flags().Set(commonInstance.DisplayNameFlag, "x") + }, + wantErr: "too short", + }, + { + name: "no identifier", + setup: func(_ *cobra.Command) {}, + wantErr: &commonErr.NoIdentifierError{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + printer := print.NewPrinter() + cmd := &cobra.Command{Use: "test"} + tt.setup(cmd) + + got, err := GetValidatedInstanceIdentifier(printer, cmd) + if !testUtils.AssertError(t, err, tt.wantErr) { + return + } + if tt.want != nil { + testUtils.AssertValue(t, got, tt.want) + } + }) + } +} diff --git a/internal/pkg/testutils/assert.go b/internal/pkg/testutils/assert.go new file mode 100755 index 000000000..42c280a71 --- /dev/null +++ b/internal/pkg/testutils/assert.go @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package testutils + +// Package test provides utilities for validating CLI command test results with +// explicit helpers for error expectations and value comparisons. By splitting +// error and value handling the package keeps assertions simple and removes the +// need for dynamic type checks in every test case. +// +// Example usage: +// +// // Expect a specific error type +// if !test.AssertError(t, run(), &cliErr.FlagValidationError{}) { +// return +// } +// +// // Expect any error +// if !test.AssertError(t, run(), true) { +// return +// } +// +// // Expect error message substring +// if !test.AssertError(t, run(), "not found") { +// return +// } +// +// // Compare complex structs with private fields +// test.AssertValue(t, got, want, test.WithAllowUnexported(MyStruct{})) + +import ( + "errors" + "reflect" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" +) + +// AssertError verifies that an observed error satisfies the expected condition. +// +// Returns: +// - bool: True if the test should continue to value checks (i.e., no error occurred). +// +// Behavior: +// 1. If err is nil: +// - If want is nil or false: Success. +// - If want is anything else: Fails test (Expected error but got nil). +// 2. If err is non-nil: +// - If want is nil or false: Fails test (Unexpected error). +// - If want is true: Success (Any error accepted). +// - If want is string: Asserts err.Error() contains the string. +// - If want is error: Asserts errors.Is(err, want) or type match. +func AssertError(t testing.TB, got error, want any) bool { + t.Helper() + + // Case 1: No error occurred + if got == nil { + if want == nil || want == false { + return true + } + t.Errorf("got nil error, want %v", want) + return false + } + + // Case 2: Error occurred + if want == nil || want == false { + t.Errorf("got unexpected error: %v", got) + return false + } + + if want == true { + return false // Error expected and received, stop test + } + + // Handle string error type expectation + if wantStr, ok := want.(string); ok { + if !strings.Contains(got.Error(), wantStr) { + t.Errorf("got error %q, want substring %q", got, wantStr) + } + return false + } + + // Handle specific error type expectation + if wantErr, ok := want.(error); ok { + if checkErrorMatch(got, wantErr) { + return false + } + t.Errorf("got error %v, want %v", got, wantErr) + return false + } + + t.Errorf("invalid want type %T for AssertError", want) + return false +} + +func checkErrorMatch(got, want error) bool { + if errors.Is(got, want) { + return true + } + + // Fallback to type check using errors.As to handle wrapped errors + if want != nil { + typ := reflect.TypeOf(want) + // errors.As requires a pointer to the target type. + // reflect.New(typ) returns *T where T is the type of want. + target := reflect.New(typ).Interface() + if errors.As(got, target) { + return true + } + } + + return false +} + +// DiffFunc compares two values and returns a diff string. An empty string means +// equality. +type DiffFunc func(got, want any) string + +// ValueComparisonOption configures how HandleValueResult applies cmp options or +// diffing strategies. +type ValueComparisonOption func(*valueComparisonConfig) + +type valueComparisonConfig struct { + diffFunc DiffFunc + cmpOptions []cmp.Option +} + +func (config *valueComparisonConfig) getDiffFunc() DiffFunc { + if config.diffFunc != nil { + return config.diffFunc + } + return func(got, want any) string { + return cmp.Diff(got, want, config.cmpOptions...) + } +} + +// WithCmpOptions accumulates cmp.Options used during value comparison. +func WithAssertionCmpOptions(opts ...cmp.Option) ValueComparisonOption { + return func(config *valueComparisonConfig) { + config.cmpOptions = append(config.cmpOptions, opts...) + } +} + +// WithAllowUnexported enables comparison of unexported fields for the provided +// struct types. +func WithAllowUnexported(types ...any) ValueComparisonOption { + return WithAssertionCmpOptions(cmp.AllowUnexported(types...)) +} + +// WithDiffFunc sets a custom diffing function. Providing this option overrides +// the default cmp-based diff logic. +func WithDiffFunc(diffFunc DiffFunc) ValueComparisonOption { + return func(config *valueComparisonConfig) { + config.diffFunc = diffFunc + } +} + +// WithIgnoreFields ignores the specified fields on the provided type during comparison. +// It uses cmpopts.IgnoreFields to ensure type-safe filtering. +func WithIgnoreFields(typ any, names ...string) ValueComparisonOption { + return WithAssertionCmpOptions(cmpopts.IgnoreFields(typ, names...)) +} + +// AssertValue compares two values with cmp.Diff while allowing callers to +// tweak the diff strategy via ValueComparisonOption. A non-empty diff is +// reported as an error containing the diff output. +func AssertValue[T any](t testing.TB, got, want T, opts ...ValueComparisonOption) { + t.Helper() + // Configure comparison options + config := &valueComparisonConfig{} + for _, opt := range opts { + opt(config) + } + // Perform comparison and report diff + diff := config.getDiffFunc()(got, want) + if diff != "" { + t.Errorf("values do not match: %s", diff) + } +} diff --git a/internal/pkg/testutils/assert_test.go b/internal/pkg/testutils/assert_test.go new file mode 100755 index 000000000..ae683a54b --- /dev/null +++ b/internal/pkg/testutils/assert_test.go @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package testutils + +import ( + "errors" + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp/cmpopts" +) + +type customError struct{ msg string } + +func (e *customError) Error() string { return e.msg } + +type anotherError struct{ code int } + +func (e *anotherError) Error() string { return fmt.Sprintf("code=%d", e.code) } + +type mockTB struct { + testing.TB + failed bool + msg string +} + +func (m *mockTB) Helper() {} +func (m *mockTB) Errorf(format string, args ...any) { + m.failed = true + m.msg = fmt.Sprintf(format, args...) +} + +func TestAssertError(t *testing.T) { + t.Parallel() + + sentinel := errors.New("sentinel") + + tests := map[string]struct { + got error // The input provided as got to AssertError() + want any // The input provided as want to AssertError() + wantErr bool // Whether this comparison is expected to fail + }{ + "exact match": { + got: &customError{msg: "boom"}, + want: &customError{}, + wantErr: false, + }, + "error string message match": { + got: errors.New("same message"), + want: "same message", + wantErr: false, + }, + "error string mismatch": { + got: errors.New("different"), + want: "same message", + wantErr: true, + }, + "sentinel via errors.Is": { + got: fmt.Errorf("wrap: %w", sentinel), + want: sentinel, + wantErr: false, + }, + "any error (true)": { + got: errors.New("any"), + want: true, + wantErr: false, + }, + "nil expectation (nil)": { + got: nil, + want: nil, + wantErr: false, + }, + "nil expectation (false)": { + got: nil, + want: false, + wantErr: false, + }, + "nil error input with error expectation": { + got: nil, + want: true, + wantErr: true, + }, + "unexpected error (nil want)": { + got: errors.New("unexpected"), + want: nil, + wantErr: true, + }, + "type match without message": { + got: &customError{msg: "alpha"}, + want: &customError{msg: "beta"}, + wantErr: false, + }, + "type mismatch": { + got: &customError{msg: "alpha"}, + want: &anotherError{}, + wantErr: true, + }, + "no error when none expected": { + got: nil, + want: false, + wantErr: false, + }, + "error but want false": { + got: errors.New("boom"), + want: false, + wantErr: true, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + t.Parallel() + mock := &mockTB{} + result := AssertError(mock, tt.got, tt.want) + + // if the test failed but we didn't expect it to fail + if mock.failed != tt.wantErr { + t.Fatalf("AssertError() failed = %v, wantErr %v (msg: %s)", mock.failed, tt.wantErr, mock.msg) + } + // if we expected an error the result of AssertError() should be false (this is what AssertError() does in case of error) + if tt.wantErr && result != false { + t.Fatalf("AssertError() returned = %v, want %v", result, tt.wantErr) + } + }) + } +} + +func TestCheckErrorMatch(t *testing.T) { + t.Parallel() + + underlying := &customError{msg: "root"} + wrapped := fmt.Errorf("wrap: %w", underlying) + if !checkErrorMatch(wrapped, &customError{}) { + t.Fatalf("expected wrapped customError to match via errors.As") + } + + notMatch := errors.New("other") + if checkErrorMatch(notMatch, &anotherError{}) { + t.Fatalf("expected mismatch for unrelated error types") + } +} + +func TestAssertValue(t *testing.T) { + t.Parallel() + + type payload struct { + Visible string + hidden int + } + + customDiff := func(got, want any) string { + if reflect.DeepEqual(got, want) { + return "" + } + return "custom diff" + } + + tests := []struct { + name string + got any // The input provided as got to AssertValue() + want any // The input provided as want to AssertValue() + wantErr bool // Whether this comparison is expected to fail + opts []ValueComparisonOption + }{ + { + name: "allow unexported success", + got: payload{Visible: "ok", hidden: 1}, + want: payload{Visible: "ok", hidden: 1}, + opts: []ValueComparisonOption{WithAllowUnexported(payload{})}, + }, + { + name: "allow unexported mismatch", + got: payload{Visible: "oops", hidden: 1}, + want: payload{Visible: "ok", hidden: 1}, + opts: []ValueComparisonOption{WithAllowUnexported(payload{})}, + wantErr: true, + }, + { + name: "cmp options sort", + got: []string{"b", "a", "c"}, + want: []string{"a", "b", "c"}, + opts: []ValueComparisonOption{WithAssertionCmpOptions(cmpopts.SortSlices(func(a, b string) bool { return a < b }))}, + }, + { + name: "custom diff mismatch", + got: 1, + want: 2, + opts: []ValueComparisonOption{WithDiffFunc(customDiff)}, + wantErr: true, + }, + { + name: "default diff success", + got: 42, + want: 42, + }, + { + name: "default diff mismatch", + got: 1, + want: 2, + wantErr: true, + }, + { + name: "diff func overrides cmp options", + got: []string{"b"}, + want: []string{"a"}, + opts: []ValueComparisonOption{ + WithAssertionCmpOptions(cmpopts.SortSlices(func(a, b string) bool { return a < b })), + WithDiffFunc(func(_, _ any) string { return "" }), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + mock := &mockTB{} + AssertValue(mock, tt.got, tt.want, tt.opts...) + + // if the test failed but we didn't expect it to fail + if mock.failed != tt.wantErr { + t.Fatalf("AssertValue failed = %v, want %v (msg: %s)", mock.failed, tt.wantErr, mock.msg) + } + }) + } +} diff --git a/internal/pkg/testutils/parse_input.go b/internal/pkg/testutils/parse_input.go new file mode 100755 index 000000000..a0deafbc7 --- /dev/null +++ b/internal/pkg/testutils/parse_input.go @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package testutils + +import ( + "testing" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" +) + +// ParseInputTestCase aggregates all required elements to exercise a CLI parseInput +// function. It centralizes the common flag setup, validation, and result +// assertions used throughout the edge command test suites. +type ParseInputTestCase[T any] struct { + Name string + // Args simulates positional arguments passed to the command. + Args []string + // Flags sets simple single-value flags. + Flags map[string]string + // RepeatFlags sets flags that can be specified multiple times (e.g. slice flags). + RepeatFlags map[string][]string + WantModel T + WantErr any + CmdFactory func(*types.CmdParams) *cobra.Command + // ParseInputFunc is the function under test. It must accept the printer, command, and args. + ParseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error) +} + +// ParseInputCaseOption allows configuring the test execution behavior. +type ParseInputCaseOption func(*parseInputCaseConfig) + +type parseInputCaseConfig struct { + cmpOpts []ValueComparisonOption +} + +// WithParseInputCmpOptions sets custom comparison options for AssertValue. +func WithParseInputCmpOptions(opts ...ValueComparisonOption) ParseInputCaseOption { + return func(cfg *parseInputCaseConfig) { + cfg.cmpOpts = append(cfg.cmpOpts, opts...) + } +} + +func defaultParseInputCaseConfig() *parseInputCaseConfig { + return &parseInputCaseConfig{} +} + +// RunParseInputCase executes a single parse-input test case using the provided +// configuration. It mirrors the typical table-driven pattern while removing the +// boilerplate repeated across tests. The helper short-circuits as soon as an +// expected error is encountered. +func RunParseInputCase[T any](t *testing.T, tc ParseInputTestCase[T], opts ...ParseInputCaseOption) { + t.Helper() + + cfg := defaultParseInputCaseConfig() + for _, opt := range opts { + opt(cfg) + } + + if tc.CmdFactory == nil { + t.Fatalf("parse input case %q missing CmdFactory", tc.Name) + } + if tc.ParseInputFunc == nil { + t.Fatalf("parse input case %q missing ParseInputFunc", tc.Name) + } + + printer := print.NewPrinter() + cmd := tc.CmdFactory(&types.CmdParams{Printer: printer}) + if cmd == nil { + t.Fatalf("parse input case %q produced nil command", tc.Name) + } + if printer.Cmd == nil { + printer.Cmd = cmd + } + + if err := globalflags.Configure(cmd.Flags()); err != nil { + t.Fatalf("configure global flags: %v", err) + } + + // Set regular flag values. + for flag, value := range tc.Flags { + if err := cmd.Flags().Set(flag, value); err != nil { + AssertError(t, err, tc.WantErr) + return + } + } + + // Set repeated flag values. + for flag, values := range tc.RepeatFlags { + for _, value := range values { + if err := cmd.Flags().Set(flag, value); err != nil { + AssertError(t, err, tc.WantErr) + return + } + } + } + + // Test cobra argument validation. + if err := cmd.ValidateArgs(tc.Args); err != nil { + AssertError(t, err, tc.WantErr) + return + } + + // Test cobra required flags validation. + if err := cmd.ValidateRequiredFlags(); err != nil { + AssertError(t, err, tc.WantErr) + return + } + + // Test cobra flag group validation. + if err := cmd.ValidateFlagGroups(); err != nil { + AssertError(t, err, tc.WantErr) + return + } + + // Test parse input function. + got, err := tc.ParseInputFunc(printer, cmd, tc.Args) + if !AssertError(t, err, tc.WantErr) { + return + } + + AssertValue(t, got, tc.WantModel, cfg.cmpOpts...) +} diff --git a/internal/pkg/testutils/parse_input_test.go b/internal/pkg/testutils/parse_input_test.go new file mode 100755 index 000000000..32008eea3 --- /dev/null +++ b/internal/pkg/testutils/parse_input_test.go @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG + +package testutils + +import ( + "errors" + "testing" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" +) + +type parseInputTestModel struct { + Value string + Args []string + RepeatValue []string + hidden string +} + +func newTestCmdFactory(flagSetup func(*cobra.Command)) func(*types.CmdParams) *cobra.Command { + return func(*types.CmdParams) *cobra.Command { + cmd := &cobra.Command{Use: "test"} + if flagSetup != nil { + flagSetup(cmd) + } + return cmd + } +} + +func TestRunParseInputCase(t *testing.T) { + sentinel := errors.New("parse failed") + tests := []struct { + name string + flagSetup func(*cobra.Command) + flags map[string]string + repeatFlags map[string][]string + args []string + cmpOpts []ParseInputCaseOption + wantModel *parseInputTestModel + wantErr any + parseFunc func(*print.Printer, *cobra.Command, []string) (*parseInputTestModel, error) + expectParseCall bool + }{ + { + name: "success", + flagSetup: func(cmd *cobra.Command) { + cmd.Flags().String("name", "", "") + }, + flags: map[string]string{"name": "edge"}, + cmpOpts: []ParseInputCaseOption{WithParseInputCmpOptions(WithAllowUnexported(parseInputTestModel{}))}, + wantModel: &parseInputTestModel{Value: "edge", hidden: "protected"}, + parseFunc: func(_ *print.Printer, cmd *cobra.Command, _ []string) (*parseInputTestModel, error) { + val, _ := cmd.Flags().GetString("name") + return &parseInputTestModel{Value: val, hidden: "protected"}, nil + }, + expectParseCall: true, + }, + { + name: "flag set failure", + flagSetup: func(cmd *cobra.Command) { + cmd.Flags().Int("count", 0, "") + }, + flags: map[string]string{"count": "invalid"}, + wantErr: "invalid syntax", + parseFunc: func(_ *print.Printer, _ *cobra.Command, _ []string) (*parseInputTestModel, error) { + return &parseInputTestModel{}, nil + }, + expectParseCall: false, + }, + { + name: "flag group validation", + flagSetup: func(cmd *cobra.Command) { + cmd.Flags().String("first", "", "") + cmd.Flags().String("second", "", "") + cmd.MarkFlagsRequiredTogether("first", "second") + }, + flags: map[string]string{"first": "only"}, + wantErr: "must all be set", + parseFunc: func(_ *print.Printer, _ *cobra.Command, _ []string) (*parseInputTestModel, error) { + return &parseInputTestModel{}, nil + }, + expectParseCall: false, + }, + { + name: "parse func error", + flagSetup: func(cmd *cobra.Command) { + cmd.Flags().Bool("ok", false, "") + }, + flags: map[string]string{"ok": "true"}, + wantErr: sentinel, + parseFunc: func(_ *print.Printer, _ *cobra.Command, _ []string) (*parseInputTestModel, error) { + return nil, sentinel + }, + expectParseCall: true, + }, + { + name: "args success", + flagSetup: func(cmd *cobra.Command) { + cmd.Args = cobra.ExactArgs(1) + }, + args: []string{"arg1"}, + cmpOpts: []ParseInputCaseOption{WithParseInputCmpOptions(WithAllowUnexported(parseInputTestModel{}))}, + wantModel: &parseInputTestModel{Args: []string{"arg1"}}, + parseFunc: func(_ *print.Printer, _ *cobra.Command, args []string) (*parseInputTestModel, error) { + return &parseInputTestModel{Args: args}, nil + }, + expectParseCall: true, + }, + { + name: "args validation failure", + flagSetup: func(cmd *cobra.Command) { + cmd.Args = cobra.NoArgs + }, + args: []string{"arg1"}, + wantErr: "unknown command", + parseFunc: func(_ *print.Printer, _ *cobra.Command, _ []string) (*parseInputTestModel, error) { + return &parseInputTestModel{}, nil + }, + expectParseCall: false, + }, + { + name: "repeat flags success", + flagSetup: func(cmd *cobra.Command) { + cmd.Flags().StringSlice("tags", []string{}, "") + }, + repeatFlags: map[string][]string{"tags": {"tag1", "tag2"}}, + cmpOpts: []ParseInputCaseOption{WithParseInputCmpOptions(WithAllowUnexported(parseInputTestModel{}))}, + wantModel: &parseInputTestModel{RepeatValue: []string{"tag1", "tag2"}}, + parseFunc: func(_ *print.Printer, cmd *cobra.Command, _ []string) (*parseInputTestModel, error) { + val, _ := cmd.Flags().GetStringSlice("tags") + return &parseInputTestModel{RepeatValue: val}, nil + }, + expectParseCall: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmdFactory := newTestCmdFactory(tt.flagSetup) + var parseCalled bool + parseFn := tt.parseFunc + if parseFn == nil { + parseFn = func(*print.Printer, *cobra.Command, []string) (*parseInputTestModel, error) { + return &parseInputTestModel{}, nil + } + } + + RunParseInputCase(t, ParseInputTestCase[*parseInputTestModel]{ + Name: tt.name, + Flags: tt.flags, + RepeatFlags: tt.repeatFlags, + Args: tt.args, + WantModel: tt.wantModel, + WantErr: tt.wantErr, + CmdFactory: cmdFactory, + ParseInputFunc: func(pr *print.Printer, cmd *cobra.Command, args []string) (*parseInputTestModel, error) { + parseCalled = true + return parseFn(pr, cmd, args) + }, + }, tt.cmpOpts...) + + if parseCalled != tt.expectParseCall { + t.Fatalf("parseCalled = %v, expect %v", parseCalled, tt.expectParseCall) + } + }) + } +} From b8fe54983ef862da50af26ca31dcd7027d89408a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6kce=20G=C3=B6k=20Klingel?= <161626272+GokceGK@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:02:54 +0100 Subject: [PATCH 605/619] escape html encoding to marshal json output completely (#1226) --- internal/pkg/print/print.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/pkg/print/print.go b/internal/pkg/print/print.go index 4098b9cb5..ea6ed1b6f 100644 --- a/internal/pkg/print/print.go +++ b/internal/pkg/print/print.go @@ -2,6 +2,7 @@ package print import ( "bufio" + "bytes" "encoding/json" "errors" "fmt" @@ -256,10 +257,15 @@ func (p *Printer) DebugInputModel(model any) { func (p *Printer) OutputResult(outputFormat string, output any, prettyOutputFunc func() error) error { switch outputFormat { case JSONOutputFormat: - details, err := json.MarshalIndent(output, "", " ") + buffer := &bytes.Buffer{} + encoder := json.NewEncoder(buffer) + encoder.SetEscapeHTML(false) + encoder.SetIndent("", " ") + err := encoder.Encode(output) if err != nil { return fmt.Errorf("marshal json: %w", err) } + details := buffer.Bytes() p.Outputln(string(details)) return nil From bde28f216a45178c4eb2eae7769a6d1d575f1b6e Mon Sep 17 00:00:00 2001 From: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:50:15 +0100 Subject: [PATCH 606/619] fix(deps): update module github.com/stackitcloud/stackit-sdk-go/services/secretsmanager to v0.14.0 (#1227) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 819818a8b..b5e4497c4 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 - github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.3 + github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.14.0 github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 diff --git a/go.sum b/go.sum index 6c2cf3173..b8c231a84 100644 --- a/go.sum +++ b/go.sum @@ -642,8 +642,8 @@ github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 h1:VDIXO github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2/go.mod h1:9zyEzPL4DnmU/SHq+SuMWTSO5BPxM1Z4g8Fp28n00ds= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 h1:ShK5AFExNRAVUMsbeoVQhCxb7GpNSmzq15jJuaBUSFo= github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3/go.mod h1:P1uhYJpSvhUXTnTGSEZqWf97J2+1Z6VuVwmUOlnhiwI= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.3 h1:9DZDISle23rdgWH8YBBujCWnEqUOQ9RAh6/G8wEHb3w= -github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.13.3/go.mod h1:dMBt/b/LXfXTDLQTCW6PRhBlbl41q7XS+5mAyBezSJk= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.14.0 h1:8cFo0UG2r9kWwUAHRBTAG5wEt4G80+wkWdjQW6DhU6Y= +github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.14.0/go.mod h1:dMBt/b/LXfXTDLQTCW6PRhBlbl41q7XS+5mAyBezSJk= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 h1:lOlg8zYL2nwMi1JxDYW2p8LL4cSB3eoOjlqPHioDWU0= github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4/go.mod h1:MBlzqmewliF1LKeOBdOuT+aQrtc3y7p1Kd1fWkjecKQ= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 h1:1gLKXD91qOYUpackMuu0PdRwrm2Z8vFK+k8H7SF0xbg= From 1931b7403c3bf05c37f4b60f4f99871b9c70d570 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 16:20:56 +0100 Subject: [PATCH 607/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/edge from 0.2.0 to 0.3.0 (#1228) --- go.mod | 2 +- go.sum | 4 ++-- internal/cmd/beta/edge/instance/create/create.go | 8 ++++---- internal/cmd/beta/edge/instance/create/create_test.go | 10 +++++----- internal/cmd/beta/edge/instance/delete/delete_test.go | 4 ++-- .../cmd/beta/edge/instance/describe/describe_test.go | 4 ++-- internal/cmd/beta/edge/instance/list/list.go | 2 +- internal/cmd/beta/edge/instance/list/list_test.go | 6 +++--- internal/cmd/beta/edge/instance/update/update_test.go | 4 ++-- .../cmd/beta/edge/kubeconfig/create/create_test.go | 4 ++-- internal/cmd/beta/edge/plans/list/list_test.go | 4 ++-- internal/cmd/beta/edge/token/create/create_test.go | 4 ++-- internal/pkg/services/edge/client/client.go | 4 ++-- 13 files changed, 30 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index b5e4497c4..e76b34f45 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 - github.com/stackitcloud/stackit-sdk-go/services/edge v0.2.0 + github.com/stackitcloud/stackit-sdk-go/services/edge v0.3.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 diff --git a/go.sum b/go.sum index b8c231a84..6a84b55a3 100644 --- a/go.sum +++ b/go.sum @@ -608,8 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 h1:4YFY5PG github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3/go.mod h1:BNiIZkDqwSV1LkWDjMKxVb9pxQ/HMIsXJ0AQ8pFoAo4= -github.com/stackitcloud/stackit-sdk-go/services/edge v0.2.0 h1:ElmnEg3V4MisAgqqJFxl3nCmKraxbHtN+vv1DNiWYfM= -github.com/stackitcloud/stackit-sdk-go/services/edge v0.2.0/go.mod h1:tFDkVkK+ESBTiH2XIcMPPR/pJJmeqT1VNDghg+ZxfMI= +github.com/stackitcloud/stackit-sdk-go/services/edge v0.3.0 h1:JL34T5IjuZjt+XGOBqkutnZnUd41jz9J9Lr8ZgPUiZI= +github.com/stackitcloud/stackit-sdk-go/services/edge v0.3.0/go.mod h1:tFDkVkK+ESBTiH2XIcMPPR/pJJmeqT1VNDghg+ZxfMI= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjUZg5qprXG5rDmPnM6dsvplMk/vg= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1/go.mod h1:3nTaj8IGjNNGYUD2CpuXkXwc5c4giTUmoPggFhjVFxo= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 h1:U/x0tc487X9msMS5yZYjrBAAKrCx87Trmt0kh8JiARA= diff --git a/internal/cmd/beta/edge/instance/create/create.go b/internal/cmd/beta/edge/instance/create/create.go index bc264ddb5..72f7ec2d2 100755 --- a/internal/cmd/beta/edge/instance/create/create.go +++ b/internal/cmd/beta/edge/instance/create/create.go @@ -124,7 +124,7 @@ type createRequestSpec struct { // Exported fields allow tests to inspect the request inputs ProjectID string Region string - Payload edge.PostInstancesPayload + Payload edge.CreateInstancePayload // Execute is a closure that wraps the actual SDK call Execute func() (*edge.Instance, error) @@ -191,15 +191,15 @@ func run(ctx context.Context, model *inputModel, apiClient client.APIClient) (*e // buildRequest constructs the spec that can be tested. func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*createRequestSpec, error) { - req := apiClient.PostInstances(ctx, model.ProjectId, model.Region) + req := apiClient.CreateInstance(ctx, model.ProjectId, model.Region) // Build request payload - payload := edge.PostInstancesPayload{ + payload := edge.CreateInstancePayload{ DisplayName: &model.DisplayName, Description: &model.Description, PlanId: &model.PlanId, } - req = req.PostInstancesPayload(payload) + req = req.CreateInstancePayload(payload) return &createRequestSpec{ ProjectID: model.ProjectId, diff --git a/internal/cmd/beta/edge/instance/create/create_test.go b/internal/cmd/beta/edge/instance/create/create_test.go index bbec4b074..b3e873533 100755 --- a/internal/cmd/beta/edge/instance/create/create_test.go +++ b/internal/cmd/beta/edge/instance/create/create_test.go @@ -41,7 +41,7 @@ type mockExecutable struct { resp *edge.Instance } -func (m *mockExecutable) PostInstancesPayload(_ edge.PostInstancesPayload) edge.ApiPostInstancesRequest { +func (m *mockExecutable) CreateInstancePayload(_ edge.CreateInstancePayload) edge.ApiCreateInstanceRequest { // This method is needed to satisfy the interface. It allows chaining in buildRequest. return m } @@ -57,10 +57,10 @@ func (m *mockExecutable) Execute() (*edge.Instance, error) { // mockAPIClient is a mock for the client.APIClient interface type mockAPIClient struct { - postInstancesMock edge.ApiPostInstancesRequest + postInstancesMock edge.ApiCreateInstanceRequest } -func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { +func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { if m.postInstancesMock != nil { return m.postInstancesMock } @@ -80,7 +80,7 @@ func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiG func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { return nil } -func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { +func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { return nil } func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { @@ -291,7 +291,7 @@ func TestBuildRequest(t *testing.T) { want: &createRequestSpec{ ProjectID: testProjectId, Region: testRegion, - Payload: edge.PostInstancesPayload{ + Payload: edge.CreateInstancePayload{ DisplayName: &testName, Description: &testDescription, PlanId: &testPlanId, diff --git a/internal/cmd/beta/edge/instance/delete/delete_test.go b/internal/cmd/beta/edge/instance/delete/delete_test.go index 2772b8c97..c15a3e7d7 100755 --- a/internal/cmd/beta/edge/instance/delete/delete_test.go +++ b/internal/cmd/beta/edge/instance/delete/delete_test.go @@ -74,7 +74,7 @@ func (m *mockAPIClient) DeleteInstanceByName(_ context.Context, _, _, _ string) } // Unused methods to satisfy the client.APIClient interface. -func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { +func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { return nil } func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { @@ -83,7 +83,7 @@ func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiG func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { return nil } -func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { +func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { return nil } func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { diff --git a/internal/cmd/beta/edge/instance/describe/describe_test.go b/internal/cmd/beta/edge/instance/describe/describe_test.go index 1f08cd0c6..913a9c221 100755 --- a/internal/cmd/beta/edge/instance/describe/describe_test.go +++ b/internal/cmd/beta/edge/instance/describe/describe_test.go @@ -75,10 +75,10 @@ func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edg } // Unused methods to satisfy the interface -func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { +func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { return nil } -func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { +func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { return nil } func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { diff --git a/internal/cmd/beta/edge/instance/list/list.go b/internal/cmd/beta/edge/instance/list/list.go index ca84cca87..6a589bfdd 100755 --- a/internal/cmd/beta/edge/instance/list/list.go +++ b/internal/cmd/beta/edge/instance/list/list.go @@ -154,7 +154,7 @@ func run(ctx context.Context, model *inputModel, apiClient client.APIClient) ([] // buildRequest constructs the spec that can be tested. func buildRequest(ctx context.Context, model *inputModel, apiClient client.APIClient) (*listRequestSpec, error) { - req := apiClient.GetInstances(ctx, model.ProjectId, model.Region) + req := apiClient.ListInstances(ctx, model.ProjectId, model.Region) return &listRequestSpec{ ProjectID: model.ProjectId, diff --git a/internal/cmd/beta/edge/instance/list/list_test.go b/internal/cmd/beta/edge/instance/list/list_test.go index 2c809d95f..a53214ed6 100755 --- a/internal/cmd/beta/edge/instance/list/list_test.go +++ b/internal/cmd/beta/edge/instance/list/list_test.go @@ -52,10 +52,10 @@ func (m *mockExecutable) Execute() (*edge.InstanceList, error) { // mockAPIClient is a mock for the edge.APIClient interface type mockAPIClient struct { - getInstancesMock edge.ApiGetInstancesRequest + getInstancesMock edge.ApiListInstancesRequest } -func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { +func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { if m.getInstancesMock != nil { return m.getInstancesMock } @@ -63,7 +63,7 @@ func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGet } // Unused methods to satisfy the interface -func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { +func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { return nil } func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { diff --git a/internal/cmd/beta/edge/instance/update/update_test.go b/internal/cmd/beta/edge/instance/update/update_test.go index 434a74337..61e78d50d 100755 --- a/internal/cmd/beta/edge/instance/update/update_test.go +++ b/internal/cmd/beta/edge/instance/update/update_test.go @@ -88,7 +88,7 @@ func (m *mockAPIClient) UpdateInstanceByName(_ context.Context, _, _, _ string) } // Unused methods to satisfy the interface -func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { +func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { return nil } func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { @@ -97,7 +97,7 @@ func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiG func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { return nil } -func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { +func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { return nil } func (m *mockAPIClient) DeleteInstance(_ context.Context, _, _, _ string) edge.ApiDeleteInstanceRequest { diff --git a/internal/cmd/beta/edge/kubeconfig/create/create_test.go b/internal/cmd/beta/edge/kubeconfig/create/create_test.go index b1fbe2810..1a353e303 100755 --- a/internal/cmd/beta/edge/kubeconfig/create/create_test.go +++ b/internal/cmd/beta/edge/kubeconfig/create/create_test.go @@ -142,7 +142,7 @@ func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiLi return nil } -func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { +func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { return nil } @@ -162,7 +162,7 @@ func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edg return nil } -func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { +func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { return nil } diff --git a/internal/cmd/beta/edge/plans/list/list_test.go b/internal/cmd/beta/edge/plans/list/list_test.go index 6b6f78275..d2fcb595f 100755 --- a/internal/cmd/beta/edge/plans/list/list_test.go +++ b/internal/cmd/beta/edge/plans/list/list_test.go @@ -63,14 +63,14 @@ func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiLi } // Unused methods to satisfy the interface -func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { +func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { return nil } func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { return nil } -func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { +func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { return nil } diff --git a/internal/cmd/beta/edge/token/create/create_test.go b/internal/cmd/beta/edge/token/create/create_test.go index 8a78d5e29..c41e62044 100755 --- a/internal/cmd/beta/edge/token/create/create_test.go +++ b/internal/cmd/beta/edge/token/create/create_test.go @@ -99,7 +99,7 @@ func (m *mockAPIClient) ListPlansProject(_ context.Context, _ string) edge.ApiLi return nil } -func (m *mockAPIClient) PostInstances(_ context.Context, _, _ string) edge.ApiPostInstancesRequest { +func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { return nil } func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiGetInstanceRequest { @@ -108,7 +108,7 @@ func (m *mockAPIClient) GetInstance(_ context.Context, _, _, _ string) edge.ApiG func (m *mockAPIClient) GetInstanceByName(_ context.Context, _, _, _ string) edge.ApiGetInstanceByNameRequest { return nil } -func (m *mockAPIClient) GetInstances(_ context.Context, _, _ string) edge.ApiGetInstancesRequest { +func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { return nil } func (m *mockAPIClient) UpdateInstance(_ context.Context, _, _, _ string) edge.ApiUpdateInstanceRequest { diff --git a/internal/pkg/services/edge/client/client.go b/internal/pkg/services/edge/client/client.go index 566e4cc05..1965fcb49 100644 --- a/internal/pkg/services/edge/client/client.go +++ b/internal/pkg/services/edge/client/client.go @@ -15,12 +15,12 @@ import ( // APIClient is an interface that consolidates all client functionality to allow for mocking of the API client during testing. type APIClient interface { - PostInstances(ctx context.Context, projectId, region string) edge.ApiPostInstancesRequest + CreateInstance(ctx context.Context, projectId, region string) edge.ApiCreateInstanceRequest DeleteInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiDeleteInstanceRequest DeleteInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiDeleteInstanceByNameRequest GetInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiGetInstanceRequest GetInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiGetInstanceByNameRequest - GetInstances(ctx context.Context, projectId, region string) edge.ApiGetInstancesRequest + ListInstances(ctx context.Context, projectId, region string) edge.ApiListInstancesRequest UpdateInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiUpdateInstanceRequest UpdateInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiUpdateInstanceByNameRequest GetKubeconfigByInstanceId(ctx context.Context, projectId, region, instanceId string) edge.ApiGetKubeconfigByInstanceIdRequest From 62cb4c5a41c05e350ffd5d4d47233d70c9872657 Mon Sep 17 00:00:00 2001 From: Robert Ruf <240721653+RobertRuf@users.noreply.github.com> Date: Thu, 15 Jan 2026 11:35:16 +0100 Subject: [PATCH 608/619] Update to stackit-sdk-go/services/edge v0.3.0 (#1231) --- .../beta/edge/instance/create/create_test.go | 12 +++++----- .../cmd/beta/edge/instance/list/list_test.go | 14 +++++------ internal/pkg/services/edge/client/client.go | 24 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/internal/cmd/beta/edge/instance/create/create_test.go b/internal/cmd/beta/edge/instance/create/create_test.go index b3e873533..e4ce1482d 100755 --- a/internal/cmd/beta/edge/instance/create/create_test.go +++ b/internal/cmd/beta/edge/instance/create/create_test.go @@ -57,12 +57,12 @@ func (m *mockExecutable) Execute() (*edge.Instance, error) { // mockAPIClient is a mock for the client.APIClient interface type mockAPIClient struct { - postInstancesMock edge.ApiCreateInstanceRequest + createInstanceMock edge.ApiCreateInstanceRequest } func (m *mockAPIClient) CreateInstance(_ context.Context, _, _ string) edge.ApiCreateInstanceRequest { - if m.postInstancesMock != nil { - return m.postInstancesMock + if m.createInstanceMock != nil { + return m.createInstanceMock } return &mockExecutable{} } @@ -285,7 +285,7 @@ func TestBuildRequest(t *testing.T) { args: args{ model: fixtureInputModel(), client: &mockAPIClient{ - postInstancesMock: &mockExecutable{}, + createInstanceMock: &mockExecutable{}, }, }, want: &createRequestSpec{ @@ -331,7 +331,7 @@ func TestRun(t *testing.T) { args: args{ model: fixtureInputModel(), client: &mockAPIClient{ - postInstancesMock: &mockExecutable{ + createInstanceMock: &mockExecutable{ resp: &edge.Instance{Id: &testInstanceId}, }, }, @@ -343,7 +343,7 @@ func TestRun(t *testing.T) { args: args{ model: fixtureInputModel(), client: &mockAPIClient{ - postInstancesMock: &mockExecutable{ + createInstanceMock: &mockExecutable{ executeFails: true, }, }, diff --git a/internal/cmd/beta/edge/instance/list/list_test.go b/internal/cmd/beta/edge/instance/list/list_test.go index a53214ed6..3b5adc6dc 100755 --- a/internal/cmd/beta/edge/instance/list/list_test.go +++ b/internal/cmd/beta/edge/instance/list/list_test.go @@ -52,12 +52,12 @@ func (m *mockExecutable) Execute() (*edge.InstanceList, error) { // mockAPIClient is a mock for the edge.APIClient interface type mockAPIClient struct { - getInstancesMock edge.ApiListInstancesRequest + listInstancesMock edge.ApiListInstancesRequest } func (m *mockAPIClient) ListInstances(_ context.Context, _, _ string) edge.ApiListInstancesRequest { - if m.getInstancesMock != nil { - return m.getInstancesMock + if m.listInstancesMock != nil { + return m.listInstancesMock } return &mockExecutable{} } @@ -291,7 +291,7 @@ func TestRun(t *testing.T) { args: args{ model: fixtureInputModel(), client: &mockAPIClient{ - getInstancesMock: &mockExecutable{ + listInstancesMock: &mockExecutable{ executeResp: &edge.InstanceList{Instances: &[]edge.Instance{}}, }, }, @@ -303,7 +303,7 @@ func TestRun(t *testing.T) { args: args{ model: fixtureInputModel(), client: &mockAPIClient{ - getInstancesMock: &mockExecutable{ + listInstancesMock: &mockExecutable{ executeFails: true, }, }, @@ -426,7 +426,7 @@ func TestBuildRequest(t *testing.T) { args: args{ model: fixtureInputModel(), client: &mockAPIClient{ - getInstancesMock: &mockExecutable{}, + listInstancesMock: &mockExecutable{}, }, }, }, @@ -442,7 +442,7 @@ func TestBuildRequest(t *testing.T) { model.Limit = utils.Ptr(int64(10)) }), client: &mockAPIClient{ - getInstancesMock: &mockExecutable{}, + listInstancesMock: &mockExecutable{}, }, }, }, diff --git a/internal/pkg/services/edge/client/client.go b/internal/pkg/services/edge/client/client.go index 1965fcb49..88ec7e2c4 100644 --- a/internal/pkg/services/edge/client/client.go +++ b/internal/pkg/services/edge/client/client.go @@ -15,18 +15,18 @@ import ( // APIClient is an interface that consolidates all client functionality to allow for mocking of the API client during testing. type APIClient interface { - CreateInstance(ctx context.Context, projectId, region string) edge.ApiCreateInstanceRequest - DeleteInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiDeleteInstanceRequest - DeleteInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiDeleteInstanceByNameRequest - GetInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiGetInstanceRequest - GetInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiGetInstanceByNameRequest - ListInstances(ctx context.Context, projectId, region string) edge.ApiListInstancesRequest - UpdateInstance(ctx context.Context, projectId, region, instanceId string) edge.ApiUpdateInstanceRequest - UpdateInstanceByName(ctx context.Context, projectId, region, instanceName string) edge.ApiUpdateInstanceByNameRequest - GetKubeconfigByInstanceId(ctx context.Context, projectId, region, instanceId string) edge.ApiGetKubeconfigByInstanceIdRequest - GetKubeconfigByInstanceName(ctx context.Context, projectId, region, instanceName string) edge.ApiGetKubeconfigByInstanceNameRequest - GetTokenByInstanceId(ctx context.Context, projectId, region, instanceId string) edge.ApiGetTokenByInstanceIdRequest - GetTokenByInstanceName(ctx context.Context, projectId, region, instanceName string) edge.ApiGetTokenByInstanceNameRequest + CreateInstance(ctx context.Context, projectId, regionId string) edge.ApiCreateInstanceRequest + DeleteInstance(ctx context.Context, projectId, regionId, instanceId string) edge.ApiDeleteInstanceRequest + DeleteInstanceByName(ctx context.Context, projectId, regionId, displayName string) edge.ApiDeleteInstanceByNameRequest + GetInstance(ctx context.Context, projectId, regionId, instanceId string) edge.ApiGetInstanceRequest + GetInstanceByName(ctx context.Context, projectId, regionId, displayName string) edge.ApiGetInstanceByNameRequest + ListInstances(ctx context.Context, projectId, regionId string) edge.ApiListInstancesRequest + UpdateInstance(ctx context.Context, projectId, regionId, instanceId string) edge.ApiUpdateInstanceRequest + UpdateInstanceByName(ctx context.Context, projectId, regionId, displayName string) edge.ApiUpdateInstanceByNameRequest + GetKubeconfigByInstanceId(ctx context.Context, projectId, regionId, instanceId string) edge.ApiGetKubeconfigByInstanceIdRequest + GetKubeconfigByInstanceName(ctx context.Context, projectId, regionId, displayName string) edge.ApiGetKubeconfigByInstanceNameRequest + GetTokenByInstanceId(ctx context.Context, projectId, regionId, instanceId string) edge.ApiGetTokenByInstanceIdRequest + GetTokenByInstanceName(ctx context.Context, projectId, regionId, displayName string) edge.ApiGetTokenByInstanceNameRequest ListPlansProject(ctx context.Context, projectId string) edge.ApiListPlansProjectRequest } From 0c4a1e57ef444f2f3c9b153bd13c0b2c07447df6 Mon Sep 17 00:00:00 2001 From: cgoetz-inovex Date: Fri, 16 Jan 2026 09:57:08 +0100 Subject: [PATCH 609/619] Feat/stackittpr 442 depedency cooldowns (#1233) * feat(deps) configure 7 day cooldown for external dependencies * feat(deps) remove renovate config in favor of dependabot * fix(deps) manage internal vs external dependencies via cooldown.exclude --- .github/dependabot.yml | 5 +++++ .github/renovate.json | 15 --------------- .github/workflows/renovate.yaml | 19 ------------------- 3 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 .github/renovate.json delete mode 100644 .github/workflows/renovate.yaml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5400a08cb..3a4e09fe6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,7 +4,12 @@ updates: directory: "/" schedule: interval: "daily" + cooldown: + default-days: 7 + exclude: ["github.com/stackitcloud*"] - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" + cooldown: + default-days: 7 diff --git a/.github/renovate.json b/.github/renovate.json deleted file mode 100644 index 31621a1ba..000000000 --- a/.github/renovate.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:recommended"], - "prHourlyLimit": 10, - "labels": ["renovate"], - "repositories": ["stackitcloud/stackit-cli"], - "enabledManagers": ["gomod", "github-actions"], - "packageRules": [ - { - "matchSourceUrls": ["https://github.com/stackitcloud/stackit-sdk-go"], - "groupName": "STACKIT SDK modules" - } - ], - "postUpdateOptions": ["gomodTidy", "gomodUpdateImportPaths"] -} diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml deleted file mode 100644 index c2e439819..000000000 --- a/.github/workflows/renovate.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Renovate - -on: - schedule: - - cron: "0 0 * * *" - workflow_dispatch: - -jobs: - renovate: - name: Renovate - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v6 - - name: Self-hosted Renovate - uses: renovatebot/github-action@v44.2.4 - with: - configurationFile: .github/renovate.json - token: ${{ secrets.RENOVATE_TOKEN }} From e537facbe88ad99e3cf30074757b797dbf6cb8df Mon Sep 17 00:00:00 2001 From: Maximilian Geberl <48486938+dergeberl@users.noreply.github.com> Date: Fri, 16 Jan 2026 10:15:35 +0100 Subject: [PATCH 610/619] feat(config): add ignore-existing for profile create (#1094) * feat(config): add ignore-existing for profile create * Fix typo and set profile if needed in case setProfile is true * make generate-docs * Fix typo * Add docs to ignore-existing flag --------- Co-authored-by: cgoetz-inovex --- docs/stackit_config_profile_create.md | 8 +++++--- internal/cmd/config/profile/create/create.go | 13 +++++++++---- internal/pkg/config/profiles.go | 13 +++++++++++-- internal/pkg/config/profiles_test.go | 2 +- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/stackit_config_profile_create.md b/docs/stackit_config_profile_create.md index 595c96fad..abc5004ad 100644 --- a/docs/stackit_config_profile_create.md +++ b/docs/stackit_config_profile_create.md @@ -9,6 +9,7 @@ The profile name can be provided via the STACKIT_CLI_PROFILE environment variabl The environment variable takes precedence over the argument. If you do not want to set the profile as active, use the --no-set flag. If you want to create the new profile with the initial default configurations, use the --empty flag. +If you want to create the new profile and ignore the error for an already existing profile, use the --ignore-existing flag. ``` stackit config profile create PROFILE [flags] @@ -27,9 +28,10 @@ stackit config profile create PROFILE [flags] ### Options ``` - --empty Create the profile with the initial default configurations - -h, --help Help for "stackit config profile create" - --no-set Do not set the profile as the active profile + --empty Create the profile with the initial default configurations + -h, --help Help for "stackit config profile create" + --ignore-existing Suppress the error if the profile exists already. An existing profile will not be modified or overwritten + --no-set Do not set the profile as the active profile ``` ### Options inherited from parent commands diff --git a/internal/cmd/config/profile/create/create.go b/internal/cmd/config/profile/create/create.go index bc7a1790f..e87ed5838 100644 --- a/internal/cmd/config/profile/create/create.go +++ b/internal/cmd/config/profile/create/create.go @@ -19,13 +19,15 @@ import ( const ( profileArg = "PROFILE" - noSetFlag = "no-set" - fromEmptyProfile = "empty" + noSetFlag = "no-set" + ignoreExistingFlag = "ignore-existing" + fromEmptyProfile = "empty" ) type inputModel struct { *globalflags.GlobalFlagModel NoSet bool + IgnoreExisting bool FromEmptyProfile bool Profile string } @@ -34,12 +36,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("create %s", profileArg), Short: "Creates a CLI configuration profile", - Long: fmt.Sprintf("%s\n%s\n%s\n%s\n%s", + Long: fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", "Creates a CLI configuration profile based on the currently active profile and sets it as active.", `The profile name can be provided via the STACKIT_CLI_PROFILE environment variable or as an argument in this command.`, "The environment variable takes precedence over the argument.", "If you do not want to set the profile as active, use the --no-set flag.", "If you want to create the new profile with the initial default configurations, use the --empty flag.", + "If you want to create the new profile and ignore the error for an already existing profile, use the --ignore-existing flag.", ), Args: args.SingleArg(profileArg, nil), Example: examples.Build( @@ -56,7 +59,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - err = config.CreateProfile(params.Printer, model.Profile, !model.NoSet, model.FromEmptyProfile) + err = config.CreateProfile(params.Printer, model.Profile, !model.NoSet, model.IgnoreExisting, model.FromEmptyProfile) if err != nil { return fmt.Errorf("create profile: %w", err) } @@ -85,6 +88,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(noSetFlag, false, "Do not set the profile as the active profile") + cmd.Flags().Bool(ignoreExistingFlag, false, "Suppress the error if the profile exists already. An existing profile will not be modified or overwritten") cmd.Flags().Bool(fromEmptyProfile, false, "Create the profile with the initial default configurations") } @@ -103,6 +107,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu Profile: profile, FromEmptyProfile: flags.FlagToBoolValue(p, cmd, fromEmptyProfile), NoSet: flags.FlagToBoolValue(p, cmd, noSetFlag), + IgnoreExisting: flags.FlagToBoolValue(p, cmd, ignoreExistingFlag), } p.DebugInputModel(model) diff --git a/internal/pkg/config/profiles.go b/internal/pkg/config/profiles.go index db47ce5d3..17d2fd352 100644 --- a/internal/pkg/config/profiles.go +++ b/internal/pkg/config/profiles.go @@ -79,8 +79,8 @@ func GetProfileFromEnv() (string, bool) { // CreateProfile creates a new profile. // If emptyProfile is true, it creates an empty profile. Otherwise, copies the config from the current profile to the new profile. // If setProfile is true, it sets the new profile as the active profile. -// If the profile already exists, it returns an error. -func CreateProfile(p *print.Printer, profile string, setProfile, emptyProfile bool) error { +// If the profile already exists and ignoreExisting is false, it returns an error. +func CreateProfile(p *print.Printer, profile string, setProfile, ignoreExisting, emptyProfile bool) error { err := ValidateProfile(profile) if err != nil { return fmt.Errorf("validate profile: %w", err) @@ -98,6 +98,15 @@ func CreateProfile(p *print.Printer, profile string, setProfile, emptyProfile bo // Error if the profile already exists _, err = os.Stat(configFolderPath) if err == nil { + if ignoreExisting { + if setProfile { + err = SetProfile(p, profile) + if err != nil { + return fmt.Errorf("set profile: %w", err) + } + } + return nil + } return fmt.Errorf("profile %q already exists", profile) } diff --git a/internal/pkg/config/profiles_test.go b/internal/pkg/config/profiles_test.go index 327c9dcf8..0039dc024 100644 --- a/internal/pkg/config/profiles_test.go +++ b/internal/pkg/config/profiles_test.go @@ -210,7 +210,7 @@ func TestExportProfile(t *testing.T) { // Create prerequisite profile p := print.NewPrinter() profileName := "export-profile-test" - err = CreateProfile(p, profileName, true, false) + err = CreateProfile(p, profileName, true, false, false) if err != nil { t.Fatalf("could not create prerequisite profile, %v", err) } From 75adbf98c5d557ccb92c8a0f8c6bf01adaf72eb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 14:42:10 +0100 Subject: [PATCH 611/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/ske (#1236) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e76b34f45..dfcbf6ead 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4 - github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.6.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.4.0 github.com/zalando/go-keyring v0.2.6 golang.org/x/mod v0.32.0 diff --git a/go.sum b/go.sum index 6a84b55a3..175b01d6d 100644 --- a/go.sum +++ b/go.sum @@ -654,8 +654,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4 h1:h4aS github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4/go.mod h1:Iv+svIxk5baXnvrEdvVl5JZri6a3H/2OrQDlRWmUFMI= github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0 h1:DRp1p0Gb1YZSnFXgkiKTHQD9bFfqn6OC3PcsDjqGJiw= github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0/go.mod h1:XHOtGgBwwCqPSoQt2ojIRb/BeOd4kICwb9RuMXXFGt8= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1 h1:HVlBylGwXVR3qDUGwUMqofAcLEawRaWSgeYXbyAcN1E= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.5.1/go.mod h1:NzcTU5GGlUF6Lys3Ra7ylRj4ZKxJr3f/29/yoE5tjPI= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.6.0 h1:Dab1jzN0u9c67lvELoWf1RuagjO3eUBRytoX8SYL8Zs= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.6.0/go.mod h1:NzcTU5GGlUF6Lys3Ra7ylRj4ZKxJr3f/29/yoE5tjPI= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.4.0 h1:KgIRTw4gpxx8qoiaLGLbXPVDcBgCxPl60gigw+tizYc= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.4.0/go.mod h1:fd13ANCU/Pye8uDd/6E0I605+6PYfHuVIQpPEK2Ph6c= github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g= From 19ac1033b8603ea95d755add1aa6295bb6f2aef6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 13:48:00 +0000 Subject: [PATCH 612/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/edge (#1235) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dfcbf6ead..a71f78960 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 - github.com/stackitcloud/stackit-sdk-go/services/edge v0.3.0 + github.com/stackitcloud/stackit-sdk-go/services/edge v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 diff --git a/go.sum b/go.sum index 175b01d6d..0dd6ccd27 100644 --- a/go.sum +++ b/go.sum @@ -608,8 +608,8 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 h1:4YFY5PG github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3/go.mod h1:BNiIZkDqwSV1LkWDjMKxVb9pxQ/HMIsXJ0AQ8pFoAo4= -github.com/stackitcloud/stackit-sdk-go/services/edge v0.3.0 h1:JL34T5IjuZjt+XGOBqkutnZnUd41jz9J9Lr8ZgPUiZI= -github.com/stackitcloud/stackit-sdk-go/services/edge v0.3.0/go.mod h1:tFDkVkK+ESBTiH2XIcMPPR/pJJmeqT1VNDghg+ZxfMI= +github.com/stackitcloud/stackit-sdk-go/services/edge v0.4.0 h1:+96JOe4oS9BhdH4kHfc5jcl9DVIZiHrMN0/PXn8uWoI= +github.com/stackitcloud/stackit-sdk-go/services/edge v0.4.0/go.mod h1:tFDkVkK+ESBTiH2XIcMPPR/pJJmeqT1VNDghg+ZxfMI= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 h1:3JKXfI5hdcXcRVBjUZg5qprXG5rDmPnM6dsvplMk/vg= github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1/go.mod h1:3nTaj8IGjNNGYUD2CpuXkXwc5c4giTUmoPggFhjVFxo= github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 h1:U/x0tc487X9msMS5yZYjrBAAKrCx87Trmt0kh8JiARA= From 0414285b63df1c7ba68139221d9f209332e58d7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 16:51:07 +0100 Subject: [PATCH 613/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/loadbalancer (#1238) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a71f78960..d550b62bf 100644 --- a/go.mod +++ b/go.mod @@ -264,7 +264,7 @@ require ( github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/stackitcloud/stackit-sdk-go/services/kms v1.2.0 - github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2 + github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.0 github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.4.2 diff --git a/go.sum b/go.sum index 0dd6ccd27..6c60e8bc5 100644 --- a/go.sum +++ b/go.sum @@ -618,8 +618,8 @@ github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 h1:WCSuqD6AoOD/D8u github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1/go.mod h1:qq6rNvOuSQ1HDZie8gy4Wzso+a9DrgOODNPyKeBljK4= github.com/stackitcloud/stackit-sdk-go/services/kms v1.2.0 h1:Ar2n9GKmrTN80G/Ta1R+fL5aX5nEoxL6ODVJl3emzho= github.com/stackitcloud/stackit-sdk-go/services/kms v1.2.0/go.mod h1:sHMFoYvVrkRZcH13DkLvp48nW+ssRVVVuwqJHDGpa5M= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2 h1:DwwRMzvnKWTbfmLvq2xe+mYhv5fA1AwWdQGznI05sGc= -github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2/go.mod h1:dYmNdSNDKUG+E0SwuFWu+c8CuMBF/l6w1bdzAHxQao0= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.0 h1:ZyaB4jL71p+FWI/cXgP+p6t4iw1oAeGbLLOz4cs3dmI= +github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.0/go.mod h1:dYmNdSNDKUG+E0SwuFWu+c8CuMBF/l6w1bdzAHxQao0= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+FtFDYOm1kv/gJrGBZLjhVOXJOuYfFY= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3/go.mod h1:305j9bvzJ+3c4csOw4SUfLSSxRbkpL0osbvqMI89FeM= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOwjKMWpKl0nrqiq7psTf4NJv0IKgwTkc= From edf7b5ca558bf85a6d4230ae9165cb188c75835d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 15:58:05 +0000 Subject: [PATCH 614/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/alb (#1237) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d550b62bf..b66c645a9 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stackitcloud/stackit-sdk-go/core v0.20.1 - github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0 + github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/edge v0.4.0 diff --git a/go.sum b/go.sum index 6c60e8bc5..257b45b63 100644 --- a/go.sum +++ b/go.sum @@ -602,8 +602,8 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98edvw2Cd3DcnkepncP3M= github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0 h1:RJBgbgZ4w7/e++n7pPTiCwFivll9RHovb4BfR/9CzlA= -github.com/stackitcloud/stackit-sdk-go/services/alb v0.8.0/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0 h1:P24WoKPt14dfUiUJ4czIv+IiVmdCFQGrKgVtw23fxNg= +github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 h1:4YFY5PG4vP/NiEP1uxCwh+kQHEU7iHG6syuFD7NPqcw= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= From 4074118fb7b5992c52c7f7af9ca5321e097d893e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20H=C3=B6nle?= Date: Tue, 20 Jan 2026 14:40:18 +0100 Subject: [PATCH 615/619] chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serverbackup from v1.3.4 to v1.3.5 (#1239) relates to STACKITCLI-304 and #1202 --- go.mod | 2 +- go.sum | 4 ++-- internal/pkg/services/serverbackup/utils/utils_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index b66c645a9..8be4407af 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.18.2 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.14.0 - github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 + github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.5 github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.2.4 diff --git a/go.sum b/go.sum index 257b45b63..7bc67cf83 100644 --- a/go.sum +++ b/go.sum @@ -644,8 +644,8 @@ github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3 h1:ShK5AFExNRA github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.3.3/go.mod h1:P1uhYJpSvhUXTnTGSEZqWf97J2+1Z6VuVwmUOlnhiwI= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.14.0 h1:8cFo0UG2r9kWwUAHRBTAG5wEt4G80+wkWdjQW6DhU6Y= github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.14.0/go.mod h1:dMBt/b/LXfXTDLQTCW6PRhBlbl41q7XS+5mAyBezSJk= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4 h1:lOlg8zYL2nwMi1JxDYW2p8LL4cSB3eoOjlqPHioDWU0= -github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.4/go.mod h1:MBlzqmewliF1LKeOBdOuT+aQrtc3y7p1Kd1fWkjecKQ= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.5 h1:pAoqz4K17ZWcLusu7Dxkx3HGQAIYCk7SmZeAu9HHUrQ= +github.com/stackitcloud/stackit-sdk-go/services/serverbackup v1.3.5/go.mod h1:MBlzqmewliF1LKeOBdOuT+aQrtc3y7p1Kd1fWkjecKQ= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3 h1:1gLKXD91qOYUpackMuu0PdRwrm2Z8vFK+k8H7SF0xbg= github.com/stackitcloud/stackit-sdk-go/services/serverupdate v1.2.3/go.mod h1:V34YusCRsq/3bJ/HxUk0wslLjVWWE/QVe70AZ+XrDPE= github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.11.3 h1:XV3pPXpdvQjR5Z90FFutU4iqCHfejDYQAL840Y4ztLM= diff --git a/internal/pkg/services/serverbackup/utils/utils_test.go b/internal/pkg/services/serverbackup/utils/utils_test.go index 73b915b3a..7262fdd6e 100644 --- a/internal/pkg/services/serverbackup/utils/utils_test.go +++ b/internal/pkg/services/serverbackup/utils/utils_test.go @@ -88,7 +88,7 @@ func TestCanDisableBackupService(t *testing.T) { LastRestoredAt: utils.Ptr("test timestamp"), Name: utils.Ptr("test name"), Size: utils.Ptr(int64(5)), - Status: serverbackup.BACKUPSTATUS_BACKING_UP.Ptr(), + Status: serverbackup.BACKUPSTATUS_IN_PROGRESS.Ptr(), VolumeBackups: nil, }, }, From 9069021b2d72e05e552925435d3d2b9561c72360 Mon Sep 17 00:00:00 2001 From: Michael Eischer <9106997+MichaelEischer@users.noreply.github.com> Date: Thu, 22 Jan 2026 14:47:04 +0100 Subject: [PATCH 616/619] feat: encrypt cache used by `ske kubeconfig login` (#1244) encrypt the caching of kubeconfig login --- internal/pkg/auth/storage.go | 24 +++--- internal/pkg/cache/cache.go | 120 ++++++++++++++++++++++++-- internal/pkg/cache/cache_test.go | 140 ++++++++++++++++++++++++------- 3 files changed, 238 insertions(+), 46 deletions(-) diff --git a/internal/pkg/auth/storage.go b/internal/pkg/auth/storage.go index 5e857f6a7..686a0f677 100644 --- a/internal/pkg/auth/storage.go +++ b/internal/pkg/auth/storage.go @@ -27,16 +27,18 @@ const ( ) const ( - SESSION_EXPIRES_AT_UNIX authFieldKey = "session_expires_at_unix" - ACCESS_TOKEN authFieldKey = "access_token" - REFRESH_TOKEN authFieldKey = "refresh_token" - SERVICE_ACCOUNT_TOKEN authFieldKey = "service_account_token" - SERVICE_ACCOUNT_EMAIL authFieldKey = "service_account_email" - USER_EMAIL authFieldKey = "user_email" - SERVICE_ACCOUNT_KEY authFieldKey = "service_account_key" - PRIVATE_KEY authFieldKey = "private_key" - TOKEN_CUSTOM_ENDPOINT authFieldKey = "token_custom_endpoint" - IDP_TOKEN_ENDPOINT authFieldKey = "idp_token_endpoint" //nolint:gosec // linter false positive + SESSION_EXPIRES_AT_UNIX authFieldKey = "session_expires_at_unix" + ACCESS_TOKEN authFieldKey = "access_token" + REFRESH_TOKEN authFieldKey = "refresh_token" + SERVICE_ACCOUNT_TOKEN authFieldKey = "service_account_token" + SERVICE_ACCOUNT_EMAIL authFieldKey = "service_account_email" + USER_EMAIL authFieldKey = "user_email" + SERVICE_ACCOUNT_KEY authFieldKey = "service_account_key" + PRIVATE_KEY authFieldKey = "private_key" + TOKEN_CUSTOM_ENDPOINT authFieldKey = "token_custom_endpoint" + IDP_TOKEN_ENDPOINT authFieldKey = "idp_token_endpoint" //nolint:gosec // linter false positive + CACHE_ENCRYPTION_KEY authFieldKey = "cache_encryption_key" + CACHE_ENCRYPTION_KEY_AGE authFieldKey = "cache_encryption_key_age" ) const ( @@ -59,6 +61,8 @@ var authFieldKeys = []authFieldKey{ TOKEN_CUSTOM_ENDPOINT, IDP_TOKEN_ENDPOINT, authFlowType, + CACHE_ENCRYPTION_KEY, + CACHE_ENCRYPTION_KEY_AGE, } // All fields that are set when a user logs in diff --git a/internal/pkg/cache/cache.go b/internal/pkg/cache/cache.go index cf019ecb2..beaf87d12 100644 --- a/internal/pkg/cache/cache.go +++ b/internal/pkg/cache/cache.go @@ -1,26 +1,87 @@ package cache import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" "errors" "fmt" "os" "path/filepath" "regexp" + "strconv" + "time" + + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" ) var ( - cacheFolderPath string + cacheDirOverwrite string // for testing only + cacheFolderPath string + cacheEncryptionKey []byte identifierRegex = regexp.MustCompile("^[a-zA-Z0-9-]+$") ErrorInvalidCacheIdentifier = fmt.Errorf("invalid cache identifier") ) +const ( + cacheKeyMaxAge = 90 * 24 * time.Hour +) + func Init() error { - cacheDir, err := os.UserCacheDir() - if err != nil { - return fmt.Errorf("get user cache dir: %w", err) + var cacheDir string + if cacheDirOverwrite == "" { + var err error + cacheDir, err = os.UserCacheDir() + if err != nil { + return fmt.Errorf("get user cache dir: %w", err) + } + } else { + cacheDir = cacheDirOverwrite } + cacheFolderPath = filepath.Join(cacheDir, "stackit") + + // Encryption keys should only be used a limited number of times for aes-gcm. + // Thus, refresh the key periodically. This will invalidate all cached entries. + key, _ := auth.GetAuthField(auth.CACHE_ENCRYPTION_KEY) + age, _ := auth.GetAuthField(auth.CACHE_ENCRYPTION_KEY_AGE) + cacheEncryptionKey = nil + var keyAge time.Time + if age != "" { + ageSeconds, err := strconv.ParseInt(age, 10, 64) + if err == nil { + keyAge = time.Unix(ageSeconds, 0) + } + } + if key != "" && keyAge.Add(cacheKeyMaxAge).After(time.Now()) { + cacheEncryptionKey, _ = base64.StdEncoding.DecodeString(key) + // invalid key length + if len(cacheEncryptionKey) != 32 { + cacheEncryptionKey = nil + } + } + if len(cacheEncryptionKey) == 0 { + cacheEncryptionKey = make([]byte, 32) + _, err := rand.Read(cacheEncryptionKey) + if err != nil { + return fmt.Errorf("cache encryption key: %w", err) + } + key := base64.StdEncoding.EncodeToString(cacheEncryptionKey) + err = auth.SetAuthField(auth.CACHE_ENCRYPTION_KEY, key) + if err != nil { + return fmt.Errorf("save cache encryption key: %w", err) + } + err = auth.SetAuthField(auth.CACHE_ENCRYPTION_KEY_AGE, fmt.Sprint(time.Now().Unix())) + if err != nil { + return fmt.Errorf("save cache encryption key age: %w", err) + } + // cleanup old cache entries as they won't be readable anymore + if err := cleanupCache(); err != nil { + return err + } + } return nil } @@ -32,7 +93,21 @@ func GetObject(identifier string) ([]byte, error) { return nil, ErrorInvalidCacheIdentifier } - return os.ReadFile(filepath.Join(cacheFolderPath, identifier)) + data, err := os.ReadFile(filepath.Join(cacheFolderPath, identifier)) + if err != nil { + return nil, err + } + + block, err := aes.NewCipher(cacheEncryptionKey) + if err != nil { + return nil, err + } + aead, err := cipher.NewGCMWithRandomNonce(block) + if err != nil { + return nil, err + } + + return aead.Open(nil, nil, data, nil) } func PutObject(identifier string, data []byte) error { @@ -48,7 +123,17 @@ func PutObject(identifier string, data []byte) error { return err } - return os.WriteFile(filepath.Join(cacheFolderPath, identifier), data, 0o600) + block, err := aes.NewCipher(cacheEncryptionKey) + if err != nil { + return err + } + aead, err := cipher.NewGCMWithRandomNonce(block) + if err != nil { + return err + } + encrypted := aead.Seal(nil, nil, data, nil) + + return os.WriteFile(filepath.Join(cacheFolderPath, identifier), encrypted, 0o600) } func DeleteObject(identifier string) error { @@ -71,3 +156,26 @@ func validateCacheFolderPath() error { } return nil } + +func cleanupCache() error { + if err := validateCacheFolderPath(); err != nil { + return err + } + + entries, err := os.ReadDir(cacheFolderPath) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil + } + return err + } + + for _, entry := range entries { + name := entry.Name() + err := DeleteObject(name) + if err != nil && !errors.Is(err, ErrorInvalidCacheIdentifier) { + return err + } + } + return nil +} diff --git a/internal/pkg/cache/cache_test.go b/internal/pkg/cache/cache_test.go index cc68c6590..4ef45891b 100644 --- a/internal/pkg/cache/cache_test.go +++ b/internal/pkg/cache/cache_test.go @@ -6,10 +6,20 @@ import ( "path/filepath" "testing" + "github.com/google/go-cmp/cmp" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/auth" ) -func TestGetObject(t *testing.T) { +func overwriteCacheDir(t *testing.T) func() { + cacheDirOverwrite = t.TempDir() + return func() { + cacheDirOverwrite = "" + } +} + +func TestGetObjectErrors(t *testing.T) { + defer overwriteCacheDir(t)() if err := Init(); err != nil { t.Fatalf("cache init failed: %s", err) } @@ -17,25 +27,16 @@ func TestGetObject(t *testing.T) { tests := []struct { description string identifier string - expectFile bool expectedErr error }{ - { - description: "identifier exists", - identifier: "test-cache-get-exists", - expectFile: true, - expectedErr: nil, - }, { description: "identifier does not exist", identifier: "test-cache-get-not-exists", - expectFile: false, expectedErr: os.ErrNotExist, }, { description: "identifier is invalid", identifier: "in../../valid", - expectFile: false, expectedErr: ErrorInvalidCacheIdentifier, }, } @@ -44,17 +45,6 @@ func TestGetObject(t *testing.T) { t.Run(tt.description, func(t *testing.T) { id := tt.identifier + "-" + uuid.NewString() - // setup - if tt.expectFile { - err := os.MkdirAll(cacheFolderPath, 0o750) - if err != nil { - t.Fatalf("create cache folder: %s", err.Error()) - } - path := filepath.Join(cacheFolderPath, id) - if err := os.WriteFile(path, []byte("dummy"), 0o600); err != nil { - t.Fatalf("setup: WriteFile (%s) failed", path) - } - } // test file, err := GetObject(id) @@ -62,19 +52,14 @@ func TestGetObject(t *testing.T) { t.Fatalf("returned error (%q) does not match %q", err.Error(), tt.expectedErr.Error()) } - if tt.expectFile { - if len(file) < 1 { - t.Fatalf("expected a file but byte array is empty (len %d)", len(file)) - } - } else { - if len(file) > 0 { - t.Fatalf("didn't expect a file, but byte array is not empty (len %d)", len(file)) - } + if len(file) > 0 { + t.Fatalf("didn't expect a file, but byte array is not empty (len %d)", len(file)) } }) } } func TestPutObject(t *testing.T) { + defer overwriteCacheDir(t)() if err := Init(); err != nil { t.Fatalf("cache init failed: %s", err) } @@ -128,6 +113,10 @@ func TestPutObject(t *testing.T) { // setup if tt.existingFile { + err := os.MkdirAll(cacheFolderPath, 0o750) + if err != nil { + t.Fatalf("create cache folder: %s", err.Error()) + } if err := os.WriteFile(path, []byte("dummy"), 0o600); err != nil { t.Fatalf("setup: WriteFile (%s) failed", path) } @@ -149,6 +138,7 @@ func TestPutObject(t *testing.T) { } func TestDeleteObject(t *testing.T) { + defer overwriteCacheDir(t)() if err := Init(); err != nil { t.Fatalf("cache init failed: %s", err) } @@ -186,8 +176,11 @@ func TestDeleteObject(t *testing.T) { // setup if tt.existingFile { + if err := os.MkdirAll(cacheFolderPath, 0o700); err != nil { + t.Fatalf("setup: MkdirAll (%s) failed: %v", path, err) + } if err := os.WriteFile(path, []byte("dummy"), 0o600); err != nil { - t.Fatalf("setup: WriteFile (%s) failed", path) + t.Fatalf("setup: WriteFile (%s) failed: %v", path, err) } } // test @@ -205,3 +198,90 @@ func TestDeleteObject(t *testing.T) { }) } } + +func clearKeys(t *testing.T) { + t.Helper() + err := auth.DeleteAuthField(auth.CACHE_ENCRYPTION_KEY) + if err != nil { + t.Fatalf("delete cache encryption key: %v", err) + } + err = auth.DeleteAuthField(auth.CACHE_ENCRYPTION_KEY_AGE) + if err != nil { + t.Fatalf("delete cache encryption key age: %v", err) + } +} + +func TestWriteAndRead(t *testing.T) { + for _, tt := range []struct { + name string + clearKeys bool + }{ + { + name: "normal", + }, + { + name: "fresh keys", + clearKeys: true, + }, + } { + t.Run(tt.name, func(t *testing.T) { + defer overwriteCacheDir(t)() + if tt.clearKeys { + clearKeys(t) + } + if err := Init(); err != nil { + t.Fatalf("cache init failed: %s", err) + } + + id := "test-cycle-" + uuid.NewString() + data := []byte("test-data") + err := PutObject(id, data) + if err != nil { + t.Fatalf("putobject failed: %v", err) + } + + readData, err := GetObject(id) + if err != nil { + t.Fatalf("getobject failed: %v", err) + } + + diff := cmp.Diff(data, readData) + if diff != "" { + t.Fatalf("unexpected data diff: %v", diff) + } + }) + } +} + +func TestCacheCleanup(t *testing.T) { + defer overwriteCacheDir(t)() + if err := Init(); err != nil { + t.Fatalf("cache init failed: %s", err) + } + + id := "test-cycle-" + uuid.NewString() + data := []byte("test-data") + err := PutObject(id, data) + if err != nil { + t.Fatalf("putobject failed: %v", err) + } + + clearKeys(t) + + // initialize again to trigger cache cleanup + if err := Init(); err != nil { + t.Fatalf("cache init failed: %s", err) + } + + _, err = GetObject(id) + if !errors.Is(err, os.ErrNotExist) { + t.Fatalf("getobject failed with unexpected error: %v", err) + } +} + +func TestInit(t *testing.T) { + // test that init without cache directory overwrite works + if err := Init(); err != nil { + t.Fatalf("cache init failed: %s", err) + } +} From c74c23cba2d1db7a605f5eea2f85be1bba074ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6kce=20G=C3=B6k=20Klingel?= <161626272+GokceGK@users.noreply.github.com> Date: Mon, 26 Jan 2026 16:38:30 +0100 Subject: [PATCH 617/619] Onboard Logs service -instance commands (#1184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * onboard logs service -instance * Update internal/cmd/beta/logs/instance/delete/delete.go Co-authored-by: Ruben Hönle * Update internal/cmd/beta/logs/instance/list/list_test.go Co-authored-by: Ruben Hönle * Update internal/cmd/beta/logs/instance/list/list.go Co-authored-by: Ruben Hönle * remove obsolete check // add missing unit test * fix linter issues * fix possible nil pointer issue // extend unit tests * update logs service version // remove workaround --------- Co-authored-by: Ruben Hönle --- docs/stackit_beta.md | 1 + docs/stackit_beta_logs.md | 34 ++ docs/stackit_beta_logs_instance.md | 38 +++ docs/stackit_beta_logs_instance_create.md | 50 +++ docs/stackit_beta_logs_instance_delete.md | 40 +++ docs/stackit_beta_logs_instance_describe.md | 43 +++ docs/stackit_beta_logs_instance_list.md | 44 +++ docs/stackit_beta_logs_instance_update.md | 50 +++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 4 + internal/cmd/beta/beta.go | 2 + .../cmd/beta/logs/instance/create/create.go | 176 ++++++++++ .../beta/logs/instance/create/create_test.go | 256 +++++++++++++++ .../cmd/beta/logs/instance/delete/delete.go | 129 ++++++++ .../beta/logs/instance/delete/delete_test.go | 174 ++++++++++ .../beta/logs/instance/describe/describe.go | 118 +++++++ .../logs/instance/describe/describe_test.go | 191 +++++++++++ internal/cmd/beta/logs/instance/instance.go | 34 ++ internal/cmd/beta/logs/instance/list/list.go | 147 +++++++++ .../cmd/beta/logs/instance/list/list_test.go | 195 +++++++++++ .../cmd/beta/logs/instance/update/update.go | 165 ++++++++++ .../beta/logs/instance/update/update_test.go | 306 ++++++++++++++++++ internal/cmd/beta/logs/logs.go | 26 ++ internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 13 + internal/pkg/config/config.go | 3 + internal/pkg/services/logs/client/client.go | 14 + internal/pkg/services/logs/utils/utils.go | 30 ++ .../pkg/services/logs/utils/utils_test.go | 96 ++++++ 32 files changed, 2393 insertions(+) create mode 100644 docs/stackit_beta_logs.md create mode 100644 docs/stackit_beta_logs_instance.md create mode 100644 docs/stackit_beta_logs_instance_create.md create mode 100644 docs/stackit_beta_logs_instance_delete.md create mode 100644 docs/stackit_beta_logs_instance_describe.md create mode 100644 docs/stackit_beta_logs_instance_list.md create mode 100644 docs/stackit_beta_logs_instance_update.md create mode 100644 internal/cmd/beta/logs/instance/create/create.go create mode 100644 internal/cmd/beta/logs/instance/create/create_test.go create mode 100644 internal/cmd/beta/logs/instance/delete/delete.go create mode 100644 internal/cmd/beta/logs/instance/delete/delete_test.go create mode 100644 internal/cmd/beta/logs/instance/describe/describe.go create mode 100644 internal/cmd/beta/logs/instance/describe/describe_test.go create mode 100644 internal/cmd/beta/logs/instance/instance.go create mode 100644 internal/cmd/beta/logs/instance/list/list.go create mode 100644 internal/cmd/beta/logs/instance/list/list_test.go create mode 100644 internal/cmd/beta/logs/instance/update/update.go create mode 100644 internal/cmd/beta/logs/instance/update/update_test.go create mode 100644 internal/cmd/beta/logs/logs.go create mode 100644 internal/pkg/services/logs/client/client.go create mode 100644 internal/pkg/services/logs/utils/utils.go create mode 100644 internal/pkg/services/logs/utils/utils_test.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index a0c177662..78b58b1f7 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -45,6 +45,7 @@ stackit beta [flags] * [stackit beta edge-cloud](./stackit_beta_edge-cloud.md) - Provides functionality for edge services. * [stackit beta intake](./stackit_beta_intake.md) - Provides functionality for intake * [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS +* [stackit beta logs](./stackit_beta_logs.md) - Provides functionality for Logs * [stackit beta sfs](./stackit_beta_sfs.md) - Provides functionality for SFS (stackit file storage) * [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex diff --git a/docs/stackit_beta_logs.md b/docs/stackit_beta_logs.md new file mode 100644 index 000000000..91998e3c1 --- /dev/null +++ b/docs/stackit_beta_logs.md @@ -0,0 +1,34 @@ +## stackit beta logs + +Provides functionality for Logs + +### Synopsis + +Provides functionality for Logs. + +``` +stackit beta logs [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta logs" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta logs instance](./stackit_beta_logs_instance.md) - Provides functionality for Logs instances + diff --git a/docs/stackit_beta_logs_instance.md b/docs/stackit_beta_logs_instance.md new file mode 100644 index 000000000..85831068e --- /dev/null +++ b/docs/stackit_beta_logs_instance.md @@ -0,0 +1,38 @@ +## stackit beta logs instance + +Provides functionality for Logs instances + +### Synopsis + +Provides functionality for Logs instances. + +``` +stackit beta logs instance [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta logs instance" +``` + +### 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 beta logs](./stackit_beta_logs.md) - Provides functionality for Logs +* [stackit beta logs instance create](./stackit_beta_logs_instance_create.md) - Creates a Logs instance +* [stackit beta logs instance delete](./stackit_beta_logs_instance_delete.md) - Deletes the given Logs instance +* [stackit beta logs instance describe](./stackit_beta_logs_instance_describe.md) - Shows details of a Logs instance +* [stackit beta logs instance list](./stackit_beta_logs_instance_list.md) - Lists Logs instances +* [stackit beta logs instance update](./stackit_beta_logs_instance_update.md) - Updates a Logs instance + diff --git a/docs/stackit_beta_logs_instance_create.md b/docs/stackit_beta_logs_instance_create.md new file mode 100644 index 000000000..3d00e6cea --- /dev/null +++ b/docs/stackit_beta_logs_instance_create.md @@ -0,0 +1,50 @@ +## stackit beta logs instance create + +Creates a Logs instance + +### Synopsis + +Creates a Logs instance. + +``` +stackit beta logs instance create [flags] +``` + +### Examples + +``` + Create a Logs instance with name "my-instance" and retention time 10 days + $ stackit beta logs instance create --display-name "my-instance" --retention-days 10 + + Create a Logs instance with name "my-instance", retention time 10 days, and a description + $ stackit beta logs instance create --display-name "my-instance" --retention-days 10 --description "Description of the instance" + + Create a Logs instance with name "my-instance", retention time 10 days, and restrict access to a specific range of IP addresses. + $ stackit beta logs instance create --display-name "my-instance" --retention-days 10 --acl 1.2.3.0/24 +``` + +### Options + +``` + --acl strings Access control list + --description string Description + --display-name string Display name + -h, --help Help for "stackit beta logs instance create" + --retention-days int The days for how long the logs should be stored before being cleaned up +``` + +### 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 beta logs instance](./stackit_beta_logs_instance.md) - Provides functionality for Logs instances + diff --git a/docs/stackit_beta_logs_instance_delete.md b/docs/stackit_beta_logs_instance_delete.md new file mode 100644 index 000000000..a64cedb3e --- /dev/null +++ b/docs/stackit_beta_logs_instance_delete.md @@ -0,0 +1,40 @@ +## stackit beta logs instance delete + +Deletes the given Logs instance + +### Synopsis + +Deletes the given Logs instance. + +``` +stackit beta logs instance delete INSTANCE_ID [flags] +``` + +### Examples + +``` + Delete a Logs instance with ID "xxx" + $ stackit beta logs instance delete "xxx" +``` + +### Options + +``` + -h, --help Help for "stackit beta logs instance delete" +``` + +### 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 beta logs instance](./stackit_beta_logs_instance.md) - Provides functionality for Logs instances + diff --git a/docs/stackit_beta_logs_instance_describe.md b/docs/stackit_beta_logs_instance_describe.md new file mode 100644 index 000000000..18218a879 --- /dev/null +++ b/docs/stackit_beta_logs_instance_describe.md @@ -0,0 +1,43 @@ +## stackit beta logs instance describe + +Shows details of a Logs instance + +### Synopsis + +Shows details of a Logs instance + +``` +stackit beta logs instance describe INSTANCE_ID [flags] +``` + +### Examples + +``` + Get details of a Logs instance with ID "xxx" + $ stackit beta logs instance describe xxx + + Get details of a Logs instance with ID "xxx" in JSON format + $ stackit beta logs instance describe xxx --output-format json +``` + +### Options + +``` + -h, --help Help for "stackit beta logs instance 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 beta logs instance](./stackit_beta_logs_instance.md) - Provides functionality for Logs instances + diff --git a/docs/stackit_beta_logs_instance_list.md b/docs/stackit_beta_logs_instance_list.md new file mode 100644 index 000000000..6e53961ee --- /dev/null +++ b/docs/stackit_beta_logs_instance_list.md @@ -0,0 +1,44 @@ +## stackit beta logs instance list + +Lists Logs instances + +### Synopsis + +Lists Logs instances within the project. + +``` +stackit beta logs instance list [flags] +``` + +### Examples + +``` + List all Logs instances + $ stackit beta logs instance list + + List the first 10 Logs instances + $ stackit beta logs instance list --limit=10 +``` + +### Options + +``` + -h, --help Help for "stackit beta logs instance list" + --limit int Limit the output to the first n elements +``` + +### 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 beta logs instance](./stackit_beta_logs_instance.md) - Provides functionality for Logs instances + diff --git a/docs/stackit_beta_logs_instance_update.md b/docs/stackit_beta_logs_instance_update.md new file mode 100644 index 000000000..da546c4cf --- /dev/null +++ b/docs/stackit_beta_logs_instance_update.md @@ -0,0 +1,50 @@ +## stackit beta logs instance update + +Updates a Logs instance + +### Synopsis + +Updates a Logs instance. + +``` +stackit beta logs instance update INSTANCE_ID [flags] +``` + +### Examples + +``` + Update the display name of the Logs instance with ID "xxx" + $ stackit beta logs instance update xxx --display-name new-name + + Update the retention time of the Logs instance with ID "xxx" + $ stackit beta logs instance update xxx --retention-days 40 + + Update the ACL of the Logs instance with ID "xxx" + $ stackit beta logs instance update xxx --acl 1.2.3.0/24 +``` + +### Options + +``` + --acl strings Access control list + --description string Description + --display-name string Display name + -h, --help Help for "stackit beta logs instance update" + --retention-days int The days for how long the logs should be stored before being cleaned up +``` + +### 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 beta logs instance](./stackit_beta_logs_instance.md) - Provides functionality for Logs instances + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 211bc1113..8613d2a1d 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -41,6 +41,7 @@ stackit config set [flags] --kms-custom-endpoint string KMS API base URL, used in calls to this API --load-balancer-custom-endpoint string Load Balancer API base URL, used in calls to this API --logme-custom-endpoint string LogMe API base URL, used in calls to this API + --logs-custom-endpoint string Logs API base URL, used in calls to this API --mariadb-custom-endpoint string MariaDB API base URL, used in calls to this API --mongodbflex-custom-endpoint string MongoDB Flex API base URL, used in calls to this API --object-storage-custom-endpoint string Object Storage API base URL, used in calls to this API diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 07b161c8c..89c6116e0 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -39,6 +39,7 @@ stackit config unset [flags] --kms-custom-endpoint KMS API base URL. If unset, uses the default base URL --load-balancer-custom-endpoint Load Balancer API base URL. If unset, uses the default base URL --logme-custom-endpoint LogMe API base URL. If unset, uses the default base URL + --logs-custom-endpoint Logs API base URL. If unset, uses the default base URL --mariadb-custom-endpoint MariaDB API base URL. If unset, uses the default base URL --mongodbflex-custom-endpoint MongoDB Flex API base URL. If unset, uses the default base URL --object-storage-custom-endpoint Object Storage API base URL. If unset, uses the default base URL diff --git a/go.mod b/go.mod index 8be4407af..3e2effedc 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0 github.com/stackitcloud/stackit-sdk-go/services/intake v0.4.1 + github.com/stackitcloud/stackit-sdk-go/services/logs v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.5 github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.3 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.2 diff --git a/go.sum b/go.sum index 7bc67cf83..d28aa738a 100644 --- a/go.sum +++ b/go.sum @@ -622,6 +622,10 @@ github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.0 h1:ZyaB4jL71 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.0/go.mod h1:dYmNdSNDKUG+E0SwuFWu+c8CuMBF/l6w1bdzAHxQao0= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+FtFDYOm1kv/gJrGBZLjhVOXJOuYfFY= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3/go.mod h1:305j9bvzJ+3c4csOw4SUfLSSxRbkpL0osbvqMI89FeM= +github.com/stackitcloud/stackit-sdk-go/services/logs v0.3.0 h1:N1gerABK2vH7/PBkxZeaWYJ7dz3rjeCHuto+FAuGx3w= +github.com/stackitcloud/stackit-sdk-go/services/logs v0.3.0/go.mod h1:m4IjH1/RtJOF072kjAB0E/ejoIc++myrKmIahphfO6Q= +github.com/stackitcloud/stackit-sdk-go/services/logs v0.4.0 h1:EOUVSKvu/m5N+psxeB69IIpANev/jw6HIw2yfh/HO7w= +github.com/stackitcloud/stackit-sdk-go/services/logs v0.4.0/go.mod h1:m4IjH1/RtJOF072kjAB0E/ejoIc++myrKmIahphfO6Q= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOwjKMWpKl0nrqiq7psTf4NJv0IKgwTkc= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3/go.mod h1:TMl5WcpjzUiAlLWaxMKbu9ysDzFziSPgg4xLxj9jjfY= github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.5.5 h1:tPISli81nuvLc5DPqgpvYPSjTySV0wXtMtkfdNXG4CU= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 973a87c21..5bd94a17c 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,6 +3,7 @@ package beta import ( "fmt" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs" "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" @@ -47,4 +48,5 @@ func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(edge.NewCmd(params)) cmd.AddCommand(intake.NewCmd(params)) cmd.AddCommand(kms.NewCmd(params)) + cmd.AddCommand(logs.NewCmd(params)) } diff --git a/internal/cmd/beta/logs/instance/create/create.go b/internal/cmd/beta/logs/instance/create/create.go new file mode 100644 index 000000000..2dafa7c1e --- /dev/null +++ b/internal/cmd/beta/logs/instance/create/create.go @@ -0,0 +1,176 @@ +package create + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/logs" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/logs/client" + + "github.com/stackitcloud/stackit-cli/internal/pkg/examples" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/logs/wait" +) + +const ( + displayNameFlag = "display-name" + retentionDaysFlag = "retention-days" + aclFlag = "acl" + descriptionFlag = "description" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + + DisplayName *string + RetentionDays *int64 + ACL *[]string + Description *string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Creates a Logs instance", + Long: "Creates a Logs instance.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a Logs instance with name "my-instance" and retention time 10 days`, + `$ stackit beta logs instance create --display-name "my-instance" --retention-days 10`), + examples.NewExample( + `Create a Logs instance with name "my-instance", retention time 10 days, and a description`, + `$ stackit beta logs instance create --display-name "my-instance" --retention-days 10 --description "Description of the instance"`), + examples.NewExample( + `Create a Logs instance with name "my-instance", retention time 10 days, and restrict access to a specific range of IP addresses.`, + `$ stackit beta logs instance create --display-name "my-instance" --retention-days 10 --acl 1.2.3.0/24`), + ), + 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 a Logs instance for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + if err != nil { + return err + } + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create Logs instance: %w", err) + } + if resp == nil { + return fmt.Errorf("create Logs instance: empty response from API") + } + if resp.Id == nil { + return fmt.Errorf("create Logs instance: instance id missing in response") + } + instanceId := *resp.Id + + // Wait for async operation, if async mode not enabled + if !model.Async { + s := spinner.New(params.Printer) + s.Start("Creating instance") + _, err = wait.CreateLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + if err != nil { + return fmt.Errorf("wait for logs instance creation: %w", err) + } + s.Stop() + } + + return outputResult(params.Printer, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(displayNameFlag, "", "Display name") + cmd.Flags().String(descriptionFlag, "", "Description") + cmd.Flags().StringSlice(aclFlag, []string{}, "Access control list") + cmd.Flags().Int64(retentionDaysFlag, 0, "The days for how long the logs should be stored before being cleaned up") + + err := flags.MarkFlagsRequired(cmd, displayNameFlag, retentionDaysFlag) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &cliErr.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + DisplayName: flags.FlagToStringPointer(p, cmd, displayNameFlag), + RetentionDays: flags.FlagToInt64Pointer(p, cmd, retentionDaysFlag), + Description: flags.FlagToStringPointer(p, cmd, descriptionFlag), + ACL: flags.FlagToStringSlicePointer(p, cmd, aclFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *logs.APIClient) logs.ApiCreateLogsInstanceRequest { + req := apiClient.CreateLogsInstance(ctx, model.ProjectId, model.Region) + + req = req.CreateLogsInstancePayload(logs.CreateLogsInstancePayload{ + DisplayName: model.DisplayName, + Description: model.Description, + RetentionDays: model.RetentionDays, + Acl: model.ACL, + }) + return req +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *logs.LogsInstance) error { + if resp == nil { + return fmt.Errorf("create logs instance response is empty") + } else if model == nil || model.GlobalFlagModel == nil { + return fmt.Errorf("input model is nil") + } + + return p.OutputResult(model.OutputFormat, resp, func() error { + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, utils.PtrString(resp.Id)) + return nil + }) +} diff --git a/internal/cmd/beta/logs/instance/create/create_test.go b/internal/cmd/beta/logs/instance/create/create_test.go new file mode 100644 index 000000000..a1835d54c --- /dev/null +++ b/internal/cmd/beta/logs/instance/create/create_test.go @@ -0,0 +1,256 @@ +package create + +import ( + "context" + "strconv" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/logs" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +const ( + testRegion = "eu01" + testDisplayName = "my-logs-instance" + testDescription = "my instance description" + testAcl = "198.51.100.14/24" + testRetentionDays = 32 +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &logs.APIClient{} + testProjectId = uuid.NewString() +) + +// Flags +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + displayNameFlag: testDisplayName, + retentionDaysFlag: strconv.Itoa(testRetentionDays), + descriptionFlag: testDescription, + aclFlag: testAcl, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + DisplayName: utils.Ptr(testDisplayName), + Description: utils.Ptr(testDescription), + RetentionDays: utils.Ptr(int64(testRetentionDays)), + ACL: utils.Ptr([]string{testAcl}), + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *logs.ApiCreateLogsInstanceRequest)) logs.ApiCreateLogsInstanceRequest { + request := testClient.CreateLogsInstance(testCtx, testProjectId, testRegion) + request = request.CreateLogsInstancePayload(logs.CreateLogsInstancePayload{ + DisplayName: utils.Ptr(testDisplayName), + Description: utils.Ptr(testDescription), + RetentionDays: utils.Ptr(int64(testRetentionDays)), + Acl: utils.Ptr([]string{testAcl}), + }) + + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "optional flags omitted", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, descriptionFlag) + delete(flagValues, aclFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.Description = nil + model.ACL = nil + }), + }, + { + description: "no values provided", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "display name missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, displayNameFlag) + }), + isValid: false, + }, + { + description: "retention days missing (required)", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, retentionDaysFlag) + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest logs.ApiCreateLogsInstanceRequest + }{ + { + description: "base case", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "no optional values", + model: fixtureInputModel(func(model *inputModel) { + model.Description = nil + model.ACL = nil + }), + expectedRequest: fixtureRequest().CreateLogsInstancePayload(logs.CreateLogsInstancePayload{ + DisplayName: utils.Ptr(testDisplayName), + RetentionDays: utils.Ptr(int64(testRetentionDays)), + Description: nil, + Acl: nil, + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, tt.model, testClient) + diff := cmp.Diff(tt.expectedRequest, request, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + model *inputModel + instance *logs.LogsInstance + wantErr bool + }{ + { + description: "nil response", + instance: nil, + wantErr: true, + }, + { + description: "model is nil", + instance: &logs.LogsInstance{}, + model: nil, + wantErr: true, + }, + { + description: "global flag nil", + instance: &logs.LogsInstance{}, + model: &inputModel{GlobalFlagModel: nil}, + wantErr: true, + }, + { + description: "default output", + instance: &logs.LogsInstance{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, + wantErr: false, + }, + { + description: "json output", + instance: &logs.LogsInstance{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.JSONOutputFormat}}, + wantErr: false, + }, + { + description: "yaml output", + instance: &logs.LogsInstance{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.YAMLOutputFormat}}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.model, "label", tt.instance) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/logs/instance/delete/delete.go b/internal/cmd/beta/logs/instance/delete/delete.go new file mode 100644 index 000000000..3344a3a93 --- /dev/null +++ b/internal/cmd/beta/logs/instance/delete/delete.go @@ -0,0 +1,129 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/logs" + + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/stackitcloud/stackit-cli/internal/pkg/services/logs/client" + logsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/logs/utils" + "github.com/stackitcloud/stackit-sdk-go/services/logs/wait" +) + +const ( + argInstanceID = "INSTANCE_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + InstanceID string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("delete %s", argInstanceID), + Short: "Deletes the given Logs instance", + Long: "Deletes the given Logs instance.", + Args: args.SingleArg(argInstanceID, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a Logs instance with ID "xxx"`, + `$ stackit beta logs instance delete "xxx"`), + ), + 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 + } + + instanceLabel, err := logsUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceID) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) + instanceLabel = model.InstanceID + } + + prompt := fmt.Sprintf("Are you sure you want to delete instance %q from project %q? (This cannot be undone)", instanceLabel, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + err = req.Execute() + if err != nil { + return fmt.Errorf("delete Logs instance: %w", err) + } + + // Wait for async operation, if async mode not enabled + 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) + if err != nil { + return fmt.Errorf("wait for Logs instance deletion: %w", err) + } + s.Stop() + } + + operationState := "Deleted" + if model.Async { + operationState = "Triggered deletion of" + } + params.Printer.Outputf("%s instance %q\n", operationState, instanceLabel) + return nil + }, + } + + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + instanceId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + InstanceID: instanceId, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *logs.APIClient) logs.ApiDeleteLogsInstanceRequest { + req := apiClient.DeleteLogsInstance(ctx, model.ProjectId, model.Region, model.InstanceID) + return req +} diff --git a/internal/cmd/beta/logs/instance/delete/delete_test.go b/internal/cmd/beta/logs/instance/delete/delete_test.go new file mode 100644 index 000000000..7b89cccb0 --- /dev/null +++ b/internal/cmd/beta/logs/instance/delete/delete_test.go @@ -0,0 +1,174 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/services/logs" +) + +const ( + testRegion = "eu02" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &logs.APIClient{} + testProjectId = uuid.NewString() + testInstanceId = uuid.NewString() +) + +// Args +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testInstanceId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +// Flags +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 +} + +// Input Model +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + InstanceID: testInstanceId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +// Request +func fixtureRequest(mods ...func(request *logs.ApiDeleteLogsInstanceRequest)) logs.ApiDeleteLogsInstanceRequest { + request := testClient.DeleteLogsInstance(testCtx, testProjectId, testRegion, testInstanceId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + expectedModel: fixtureInputModel(), + isValid: true, + }, + { + description: "no args (instanceID)", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "instance id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "instance id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest logs.ApiDeleteLogsInstanceRequest + }{ + { + description: "base case", + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/logs/instance/describe/describe.go b/internal/cmd/beta/logs/instance/describe/describe.go new file mode 100644 index 000000000..66d27d99a --- /dev/null +++ b/internal/cmd/beta/logs/instance/describe/describe.go @@ -0,0 +1,118 @@ +package describe + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/logs" + + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/logs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +const ( + argInstanceID = "INSTANCE_ID" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + InstanceID string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("describe %s", argInstanceID), + Short: "Shows details of a Logs instance", + Long: "Shows details of a Logs instance", + Args: args.SingleArg(argInstanceID, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get details of a Logs instance with ID "xxx"`, + `$ stackit beta logs instance describe xxx`, + ), + examples.NewExample( + `Get details of a Logs instance with ID "xxx" in JSON format`, + "$ stackit beta logs instance describe xxx --output-format json"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return err + } + + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + req := buildRequest(ctx, model, apiClient) + + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get instance: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + model := &inputModel{ + GlobalFlagModel: globalFlags, + InstanceID: inputArgs[0], + } + p.DebugInputModel(model) + return model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *logs.APIClient) logs.ApiGetLogsInstanceRequest { + return apiClient.GetLogsInstance(ctx, model.ProjectId, model.Region, model.InstanceID) +} + +func outputResult(p *print.Printer, outputFormat string, instance *logs.LogsInstance) error { + if instance == nil { + return fmt.Errorf("instance response is empty") + } + return p.OutputResult(outputFormat, instance, func() error { + table := tables.NewTable() + table.AddRow("ID", utils.PtrString(instance.Id)) + table.AddSeparator() + table.AddRow("DISPLAY NAME", utils.PtrString(instance.DisplayName)) + table.AddSeparator() + table.AddRow("RETENTION DAYS", utils.PtrString(instance.RetentionDays)) + table.AddSeparator() + table.AddRow("ACL IP RANGES", utils.PtrString(instance.Acl)) + table.AddSeparator() + table.AddRow("DATA SOURCE", utils.PtrString(instance.DatasourceUrl)) + table.AddSeparator() + table.AddRow("OTLP INGEST", utils.PtrString(instance.IngestOtlpUrl)) + table.AddSeparator() + table.AddRow("INGEST", utils.PtrString(instance.IngestUrl)) + table.AddSeparator() + table.AddRow("QUERY RANGE", utils.PtrString(instance.QueryRangeUrl)) + table.AddSeparator() + table.AddRow("QUERY", utils.PtrString(instance.QueryUrl)) + + err := table.Display(p) + if err != nil { + return fmt.Errorf("display table: %w", err) + } + return nil + }) +} diff --git a/internal/cmd/beta/logs/instance/describe/describe_test.go b/internal/cmd/beta/logs/instance/describe/describe_test.go new file mode 100644 index 000000000..661ce4aa5 --- /dev/null +++ b/internal/cmd/beta/logs/instance/describe/describe_test.go @@ -0,0 +1,191 @@ +package describe + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-sdk-go/services/logs" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &logs.APIClient{} +var testProjectId = uuid.NewString() +var testInstanceId = 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, + }, + InstanceID: testInstanceId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *logs.ApiGetLogsInstanceRequest)) logs.ApiGetLogsInstanceRequest { + request := testClient.GetLogsInstance(testCtx, testProjectId, testRegion, testInstanceId) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: []string{testInstanceId}, + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "project id missing", + argValues: []string{testInstanceId}, + flagValues: fixtureFlagValues(func(m map[string]string) { delete(m, globalflags.ProjectIdFlag) }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: []string{testInstanceId}, + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: []string{testInstanceId}, + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "invalid instance id", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest logs.ApiGetLogsInstanceRequest + }{ + { + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *logs.LogsInstance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "default output", + args: args{outputFormat: "default", instance: &logs.LogsInstance{}}, + wantErr: false, + }, + { + name: "json output", + args: args{outputFormat: print.JSONOutputFormat, instance: &logs.LogsInstance{}}, + wantErr: false, + }, + { + name: "yaml output", + args: args{outputFormat: print.YAMLOutputFormat, instance: &logs.LogsInstance{}}, + wantErr: false, + }, + { + name: "nil instance", + args: args{instance: nil}, + wantErr: true, + }, + } + 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.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/logs/instance/instance.go b/internal/cmd/beta/logs/instance/instance.go new file mode 100644 index 000000000..ad099a9d1 --- /dev/null +++ b/internal/cmd/beta/logs/instance/instance.go @@ -0,0 +1,34 @@ +package instance + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs/instance/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs/instance/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs/instance/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs/instance/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs/instance/update" + "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: "instance", + Short: "Provides functionality for Logs instances", + Long: "Provides functionality for Logs instances.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) +} diff --git a/internal/cmd/beta/logs/instance/list/list.go b/internal/cmd/beta/logs/instance/list/list.go new file mode 100644 index 000000000..226c3b5c3 --- /dev/null +++ b/internal/cmd/beta/logs/instance/list/list.go @@ -0,0 +1,147 @@ +package list + +import ( + "context" + "fmt" + + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/logs/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/logs" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +const ( + limitFlag = "limit" +) + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Lists Logs instances", + Long: "Lists Logs instances within the project.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all Logs instances`, + `$ stackit beta logs instance list`, + ), + examples.NewExample( + `List the first 10 Logs instances`, + `$ stackit beta logs instance list --limit=10`, + ), + ), + 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 + } + + // Call API + request := buildRequest(ctx, model, apiClient) + + response, err := request.Execute() + if err != nil { + return fmt.Errorf("list Logs instances: %w", err) + } + items := response.GetInstances() + + // Truncate output + if model.Limit != nil && len(items) > int(*model.Limit) { + items = items[:*model.Limit] + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, items) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *logs.APIClient) logs.ApiListLogsInstancesRequest { + request := apiClient.ListLogsInstances(ctx, model.ProjectId, model.Region) + + return request +} + +func outputResult(p *print.Printer, outputFormat, projectLabel string, instances []logs.LogsInstance) error { + return p.OutputResult(outputFormat, instances, func() error { + if len(instances) == 0 { + p.Outputf("No Logs instances found for project %q", projectLabel) + return nil + } + + table := tables.NewTable() + table.SetHeader("NAME", "ID", "STATUS") + for _, instance := range instances { + table.AddRow( + utils.PtrString(instance.DisplayName), + utils.PtrString(instance.Id), + utils.PtrString(instance.Status), + ) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + }) +} diff --git a/internal/cmd/beta/logs/instance/list/list_test.go b/internal/cmd/beta/logs/instance/list/list_test.go new file mode 100644 index 000000000..987d0e8d8 --- /dev/null +++ b/internal/cmd/beta/logs/instance/list/list_test.go @@ -0,0 +1,195 @@ +package list + +import ( + "context" + "testing" + + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-sdk-go/services/logs" +) + +const ( + testRegion = "eu01" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &logs.APIClient{} +var testProjectId = uuid.NewString() + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + limitFlag: "10", + } + 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, + }, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *logs.ApiListLogsInstancesRequest)) logs.ApiListLogsInstancesRequest { + request := testClient.ListLogsInstances(testCtx, testProjectId, testRegion) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + flagValues: map[string]string{}, + isValid: false, + }, + { + 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, + }, + { + description: "limit invalid", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "invalid" + }), + isValid: false, + }, + { + description: "limit invalid 2", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[limitFlag] = "0" + }), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest logs.ApiListLogsInstancesRequest + }{ + { + 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), + 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 + instances []logs.LogsInstance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "empty instances slice", + args: args{ + instances: []logs.LogsInstance{}, + }, + wantErr: false, + }, + { + name: "empty instance in instances slice", + args: args{ + instances: []logs.LogsInstance{{}}, + }, + 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.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/logs/instance/update/update.go b/internal/cmd/beta/logs/instance/update/update.go new file mode 100644 index 000000000..2e6fcea0b --- /dev/null +++ b/internal/cmd/beta/logs/instance/update/update.go @@ -0,0 +1,165 @@ +package update + +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/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/logs/client" + logsUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/logs/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/logs" +) + +const ( + argInstanceID = "INSTANCE_ID" + + displayNameFlag = "display-name" + retentionDaysFlag = "retention-days" + aclFlag = "acl" + descriptionFlag = "description" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + InstanceID string + DisplayName *string + RetentionDays *int64 + ACL *[]string + Description *string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: fmt.Sprintf("update %s", argInstanceID), + Short: "Updates a Logs instance", + Long: "Updates a Logs instance.", + Args: args.SingleArg(argInstanceID, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Update the display name of the Logs instance with ID "xxx"`, + "$ stackit beta logs instance update xxx --display-name new-name"), + examples.NewExample( + `Update the retention time of the Logs instance with ID "xxx"`, + "$ stackit beta logs instance update xxx --retention-days 40"), + examples.NewExample( + `Update the ACL of the Logs instance with ID "xxx"`, + "$ stackit beta logs instance update xxx --acl 1.2.3.0/24"), + ), + 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 + } + + instanceLabel, err := logsUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.Region, model.InstanceID) + if err != nil { + params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) + instanceLabel = model.InstanceID + } + + prompt := fmt.Sprintf("Are you sure you want to update instance %s?", instanceLabel) + err = params.Printer.PromptForConfirmation(prompt) + + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update logs instance: %w", err) + } + + return outputResult(params.Printer, model, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().String(displayNameFlag, "", "Display name") + cmd.Flags().String(descriptionFlag, "", "Description") + cmd.Flags().StringSlice(aclFlag, []string{}, "Access control list") + cmd.Flags().Int64(retentionDaysFlag, 0, "The days for how long the logs should be stored before being cleaned up") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + instanceId := inputArgs[0] + + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + displayName := flags.FlagToStringPointer(p, cmd, displayNameFlag) + retentionDays := flags.FlagToInt64Pointer(p, cmd, retentionDaysFlag) + acl := flags.FlagToStringSlicePointer(p, cmd, aclFlag) + description := flags.FlagToStringPointer(p, cmd, descriptionFlag) + + if displayName == nil && retentionDays == nil && acl == nil && description == nil { + return nil, &errors.EmptyUpdateError{} + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + InstanceID: instanceId, + DisplayName: displayName, + ACL: acl, + Description: description, + RetentionDays: retentionDays, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *logs.APIClient) logs.ApiUpdateLogsInstanceRequest { + req := apiClient.UpdateLogsInstance(ctx, model.ProjectId, model.Region, model.InstanceID) + req = req.UpdateLogsInstancePayload(logs.UpdateLogsInstancePayload{ + DisplayName: model.DisplayName, + Acl: model.ACL, + RetentionDays: model.RetentionDays, + Description: model.Description, + }) + return req +} + +func outputResult(p *print.Printer, model *inputModel, projectLabel string, instance *logs.LogsInstance) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } else if model == nil || model.GlobalFlagModel == nil { + return fmt.Errorf("input model is nil") + } + return p.OutputResult(model.OutputFormat, instance, func() error { + p.Outputf("Updated instance %q for project %q.\n", utils.PtrString(instance.DisplayName), projectLabel) + return nil + }) +} diff --git a/internal/cmd/beta/logs/instance/update/update_test.go b/internal/cmd/beta/logs/instance/update/update_test.go new file mode 100644 index 000000000..b885d5677 --- /dev/null +++ b/internal/cmd/beta/logs/instance/update/update_test.go @@ -0,0 +1,306 @@ +package update + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/logs" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" +) + +type testCtxKey struct{} + +const ( + testRegion = "eu01" +) + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &logs.APIClient{} + testProjectId = uuid.NewString() + testInstanceId = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argValues []string)) []string { + argValues := []string{ + testInstanceId, + } + for _, mod := range mods { + mod(argValues) + } + return argValues +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + displayNameFlag: "name", + aclFlag: "0.0.0.0/0", + retentionDaysFlag: "60", + descriptionFlag: "Example", + } + 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, + }, + InstanceID: testInstanceId, + DisplayName: utils.Ptr("name"), + ACL: utils.Ptr([]string{"0.0.0.0/0"}), + RetentionDays: utils.Ptr(int64(60)), + Description: utils.Ptr("Example"), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *logs.ApiUpdateLogsInstanceRequest)) logs.ApiUpdateLogsInstanceRequest { + request := testClient.UpdateLogsInstance(testCtx, testProjectId, testRegion, testInstanceId) + request = request.UpdateLogsInstancePayload(logs.UpdateLogsInstancePayload{ + DisplayName: utils.Ptr("name"), + Acl: utils.Ptr([]string{"0.0.0.0/0"}), + RetentionDays: utils.Ptr(int64(60)), + Description: utils.Ptr("Example"), + }) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + primaryFlagValues []string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argValues: []string{}, + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "no arg values", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "no flag values", + argValues: fixtureArgValues(), + flagValues: map[string]string{}, + isValid: false, + }, + { + description: "required flags only (no values to update)", + argValues: fixtureArgValues(), + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + }, + isValid: false, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + InstanceID: testInstanceId, + }, + }, + { + description: "update all fields", + argValues: fixtureArgValues(), + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, + displayNameFlag: "display-name", + aclFlag: "0.0.0.0/24", + descriptionFlag: "description", + retentionDaysFlag: "60", + }, + isValid: true, + expectedModel: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + InstanceID: testInstanceId, + DisplayName: utils.Ptr("display-name"), + ACL: utils.Ptr([]string{"0.0.0.0/24"}), + RetentionDays: utils.Ptr(int64(60)), + Description: utils.Ptr("description"), + }, + }, + { + description: "project id missing", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "project id invalid 1", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "" + }), + isValid: false, + }, + { + description: "project id invalid 2", + argValues: fixtureArgValues(), + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[globalflags.ProjectIdFlag] = "invalid-uuid" + }), + isValid: false, + }, + { + description: "instance id invalid 1", + argValues: []string{""}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "instance id invalid 2", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest logs.ApiUpdateLogsInstanceRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureRequest(), + }, + { + description: "required fields only", + model: &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Region: testRegion, + Verbosity: globalflags.VerbosityDefault, + }, + InstanceID: testInstanceId, + }, + expectedRequest: testClient.UpdateLogsInstance(testCtx, testProjectId, testRegion, testInstanceId). + UpdateLogsInstancePayload(logs.UpdateLogsInstancePayload{}), + }, + } + + 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), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + model *inputModel + instance *logs.LogsInstance + wantErr bool + }{ + { + description: "nil response", + instance: nil, + wantErr: true, + }, + { + description: "default output", + instance: &logs.LogsInstance{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, + wantErr: false, + }, + { + description: "model is nil", + instance: &logs.LogsInstance{}, + model: nil, + wantErr: true, + }, + { + description: "global flag nil", + instance: &logs.LogsInstance{}, + model: &inputModel{GlobalFlagModel: nil}, + wantErr: true, + }, + { + description: "json output", + instance: &logs.LogsInstance{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.JSONOutputFormat}}, + wantErr: false, + }, + { + description: "yaml output", + instance: &logs.LogsInstance{}, + model: &inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{OutputFormat: print.YAMLOutputFormat}}, + wantErr: false, + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + err := outputResult(p, tt.model, "label", tt.instance) + if (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/beta/logs/logs.go b/internal/cmd/beta/logs/logs.go new file mode 100644 index 000000000..d7e0b803a --- /dev/null +++ b/internal/cmd/beta/logs/logs.go @@ -0,0 +1,26 @@ +package logs + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs/instance" + "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: "logs", + Short: "Provides functionality for Logs", + Long: "Provides functionality for Logs.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(instance.NewCmd(params)) +} diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 64ee916f4..a4ff8b428 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -50,6 +50,7 @@ const ( iaasCustomEndpointFlag = "iaas-custom-endpoint" tokenCustomEndpointFlag = "token-custom-endpoint" intakeCustomEndpointFlag = "intake-custom-endpoint" + logsCustomEndpointFlag = "logs-custom-endpoint" sfsCustomEndpointFlag = "sfs-custom-endpoint" ) @@ -167,6 +168,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(iaasCustomEndpointFlag, "", "IaaS API base URL, used in calls to this API") cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication.") cmd.Flags().String(intakeCustomEndpointFlag, "", "Intake API base URL, used in calls to this API") + cmd.Flags().String(logsCustomEndpointFlag, "", "Logs API base URL, used in calls to this API") cmd.Flags().String(sfsCustomEndpointFlag, "", "SFS API base URL, used in calls to this API") err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) @@ -230,6 +232,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.IntakeCustomEndpointKey, cmd.Flags().Lookup(intakeCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.LogsCustomEndpointKey, cmd.Flags().Lookup(logsCustomEndpointFlag)) + cobra.CheckErr(err) err = viper.BindPFlag(config.SfsCustomEndpointKey, cmd.Flags().Lookup(sfsCustomEndpointFlag)) cobra.CheckErr(err) } diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index c20aa131c..460cdf9d4 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -55,6 +55,7 @@ const ( iaasCustomEndpointFlag = "iaas-custom-endpoint" tokenCustomEndpointFlag = "token-custom-endpoint" intakeCustomEndpointFlag = "intake-custom-endpoint" + logsCustomEndpointFlag = "logs-custom-endpoint" ) type inputModel struct { @@ -96,6 +97,7 @@ type inputModel struct { IaaSCustomEndpoint bool TokenCustomEndpoint bool IntakeCustomEndpoint bool + LogsCustomEndpoint bool } func NewCmd(params *types.CmdParams) *cobra.Command { @@ -225,6 +227,9 @@ func NewCmd(params *types.CmdParams) *cobra.Command { if model.IntakeCustomEndpoint { viper.Set(config.IntakeCustomEndpointKey, "") } + if model.LogsCustomEndpoint { + viper.Set(config.LogsCustomEndpointKey, "") + } if model.SfsCustomEndpoint { viper.Set(config.SfsCustomEndpointKey, "") } @@ -278,6 +283,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(iaasCustomEndpointFlag, false, "IaaS API base URL. If unset, uses the default base URL") cmd.Flags().Bool(tokenCustomEndpointFlag, false, "Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication.") cmd.Flags().Bool(intakeCustomEndpointFlag, false, "Intake API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(logsCustomEndpointFlag, false, "Logs API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sfsCustomEndpointFlag, false, "SFS API base URL. If unset, uses the default base URL") } @@ -321,6 +327,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { IaaSCustomEndpoint: flags.FlagToBoolValue(p, cmd, iaasCustomEndpointFlag), TokenCustomEndpoint: flags.FlagToBoolValue(p, cmd, tokenCustomEndpointFlag), IntakeCustomEndpoint: flags.FlagToBoolValue(p, cmd, intakeCustomEndpointFlag), + LogsCustomEndpoint: flags.FlagToBoolValue(p, cmd, logsCustomEndpointFlag), } p.DebugInputModel(model) diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 37ee8f7d2..65c6cb35b 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -47,6 +47,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool iaasCustomEndpointFlag: true, tokenCustomEndpointFlag: true, intakeCustomEndpointFlag: true, + logsCustomEndpointFlag: true, } for _, mod := range mods { mod(flagValues) @@ -90,6 +91,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { IaaSCustomEndpoint: true, TokenCustomEndpoint: true, IntakeCustomEndpoint: true, + LogsCustomEndpoint: true, } for _, mod := range mods { mod(model) @@ -149,6 +151,7 @@ func TestParseInput(t *testing.T) { model.IaaSCustomEndpoint = false model.TokenCustomEndpoint = false model.IntakeCustomEndpoint = false + model.LogsCustomEndpoint = false }), }, { @@ -331,6 +334,16 @@ func TestParseInput(t *testing.T) { model.TokenCustomEndpoint = false }), }, + { + description: "logs custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[logsCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.LogsCustomEndpoint = false + }), + }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index a60bbd17b..32761f275 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -51,6 +51,7 @@ const ( TokenCustomEndpointKey = "token_custom_endpoint" GitCustomEndpointKey = "git_custom_endpoint" IntakeCustomEndpointKey = "intake_custom_endpoint" + LogsCustomEndpointKey = "logs_custom_endpoint" ProjectNameKey = "project_name" DefaultProfileName = "default" @@ -114,6 +115,7 @@ var ConfigKeys = []string{ GitCustomEndpointKey, IntakeCustomEndpointKey, AlbCustomEndpoint, + LogsCustomEndpointKey, } var defaultConfigFolderPath string @@ -203,6 +205,7 @@ func setConfigDefaults() { viper.SetDefault(GitCustomEndpointKey, "") viper.SetDefault(IntakeCustomEndpointKey, "") viper.SetDefault(AlbCustomEndpoint, "") + viper.SetDefault(LogsCustomEndpointKey, "") } func getConfigFilePath(configFolder string) string { diff --git a/internal/pkg/services/logs/client/client.go b/internal/pkg/services/logs/client/client.go new file mode 100644 index 000000000..6bce9b246 --- /dev/null +++ b/internal/pkg/services/logs/client/client.go @@ -0,0 +1,14 @@ +package client + +import ( + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/logs" + + "github.com/spf13/viper" +) + +func ConfigureClient(p *print.Printer, cliVersion string) (*logs.APIClient, error) { + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.LogsCustomEndpointKey), false, genericclient.CreateApiClient[*logs.APIClient](logs.NewAPIClient)) +} diff --git a/internal/pkg/services/logs/utils/utils.go b/internal/pkg/services/logs/utils/utils.go new file mode 100644 index 000000000..4008db158 --- /dev/null +++ b/internal/pkg/services/logs/utils/utils.go @@ -0,0 +1,30 @@ +package utils + +import ( + "context" + "errors" + "fmt" + + "github.com/stackitcloud/stackit-sdk-go/services/logs" +) + +var ( + ErrResponseNil = errors.New("response is nil") + ErrNameNil = errors.New("display name is nil") +) + +type LogsClient interface { + GetLogsInstanceExecute(ctx context.Context, projectId, regionId, instanceId string) (*logs.LogsInstance, error) +} + +func GetInstanceName(ctx context.Context, apiClient LogsClient, projectId, regionId, instanceId string) (string, error) { + resp, err := apiClient.GetLogsInstanceExecute(ctx, projectId, regionId, instanceId) + if err != nil { + return "", fmt.Errorf("get Logs instance: %w", err) + } else if resp == nil { + return "", ErrResponseNil + } else if resp.DisplayName == nil { + return "", ErrNameNil + } + return *resp.DisplayName, nil +} diff --git a/internal/pkg/services/logs/utils/utils_test.go b/internal/pkg/services/logs/utils/utils_test.go new file mode 100644 index 000000000..0c21b4d09 --- /dev/null +++ b/internal/pkg/services/logs/utils/utils_test.go @@ -0,0 +1,96 @@ +package utils + +import ( + "context" + "fmt" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/logs" + + "github.com/google/uuid" +) + +var ( + testProjectId = uuid.NewString() + testInstanceId = uuid.NewString() +) + +const ( + testInstanceName = "instance" + testRegion = "eu01" +) + +type logsClientMocked struct { + getInstanceFails bool + getInstanceResp *logs.LogsInstance +} + +func (m *logsClientMocked) GetLogsInstanceExecute(_ context.Context, _, _, _ string) (*logs.LogsInstance, error) { + if m.getInstanceFails { + return nil, fmt.Errorf("could not get instance") + } + return m.getInstanceResp, nil +} + +func TestGetInstanceName(t *testing.T) { + tests := []struct { + description string + getInstanceFails bool + getInstanceResp *logs.LogsInstance + isValid bool + expectedOutput string + }{ + { + description: "base", + getInstanceResp: &logs.LogsInstance{ + DisplayName: utils.Ptr(testInstanceName), + }, + isValid: true, + expectedOutput: testInstanceName, + }, + { + description: "get instance fails", + getInstanceFails: true, + isValid: false, + }, + { + description: "response is nil", + getInstanceFails: false, + getInstanceResp: nil, + isValid: false, + }, + { + description: "name in response is nil", + getInstanceFails: false, + getInstanceResp: &logs.LogsInstance{ + DisplayName: nil, + }, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &logsClientMocked{ + getInstanceFails: tt.getInstanceFails, + getInstanceResp: tt.getInstanceResp, + } + + output, err := GetInstanceName(context.Background(), client, testProjectId, testRegion, testInstanceId) + + if tt.isValid && err != nil { + t.Errorf("failed on valid input") + } + if !tt.isValid && err == nil { + t.Errorf("did not fail on invalid input") + } + if !tt.isValid { + return + } + if output != tt.expectedOutput { + t.Errorf("expected output to be %s, got %s", tt.expectedOutput, output) + } + }) + } +} From d65f2189d07f2c647336eac89d9890ef6396b6a7 Mon Sep 17 00:00:00 2001 From: cgoetz-inovex Date: Tue, 27 Jan 2026 10:04:38 +0100 Subject: [PATCH 618/619] feat(cdn): add cdn client, config, list command (#1100) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(cdn): add cdn client, config, list command * fix(cdn): generate docs * fix(cdn) fix linting issues * Update internal/cmd/beta/cdn/distribution/list/list.go Co-authored-by: Ruben Hönle * Update internal/cmd/beta/cdn/distribution/list/list.go Co-authored-by: Ruben Hönle * fix(cdn): rename sortBy params, use EnumSliceToStringSlice * fix(cdn): make `testNextPageID`, `testID` and `testStatus` constant * fix(cdn): add cdn subcommand to beta, generate docs * feat(cdn) add limit flag to distribution list * feat(cdn): add distribution create cmd * fix(cdn): generate distribution create docs * squash this * feat(cdn) implement cdn distribution create/delete/describe/update * squash * squash * fix(cdn) regenerate docs * fix(cdn) linting issues * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/secretsmanager (#1112) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serverbackup (#1111) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/ske (#1110) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serverupdate (#1109) * chore(deps): bump renovatebot/github-action from 44.0.3 to 44.0.4 (#1113) * feat(kms) describe key, keyring, wrappingkey (#1107) * feat(kms) describe key, keyring, wrappingkey * fix(kms): do not reuse buffer during output tests * fix(kms) use constant Time for TestOutputResult for constant table widths * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/rabbitmq (#1118) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/alb (#1117) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mongodbflex (#1116) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serviceaccount (#1115) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/serviceenablement (#1123) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/dns (#1122) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/iaas (#1121) * fix(alb): print valid JSON/YAML output for list cmds (#1045) relates to STACKITCLI-273 / #893 * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/mariadb (#1129) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/redis (#1128) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/runcommand (#1127) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/authorization (#1120) * chore: increase linter timeout (#1131) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/intake (#1132) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/loadbalancer (#1133) * fix: log browser url to stderr instead of stdout (#1136) fixes #1125 * fix(deps): update module github.com/goccy/go-yaml to v1.19.0 (#1137) * feat(mongodbflex): add readAnyDatabase and stackitAdmin roles for users (#1049) Co-authored-by: Ruben Hoenle * fix: refresh token flow uses x-www-form encoding (#1135) * chore(deps): update renovatebot/github-action action to v44.0.5 (#1141) * chore(deps): bump github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex (#1139) * feat(cdn): add cdn client, config, list command * feat(cdn) implement cdn distribution create/delete/describe/update * fix(cdn) manual merge fixes * fix(cdn) review fixes - test Min - test JoinStringMap - rm superfluous var for constant - rm file committed by accident - add nil checks when dereferencing pointers * fix(cdn) replace utils.Min usage with builtin min * Update internal/cmd/beta/cdn/distribution/list/list.go Co-authored-by: Ruben Hönle * fix(cdn) apply review comments - replace single char names with more descriptive ones - remove predefined mod functions - deduplicate ParseOriginRequestHeaders and test it - deduplicate ParseGeofencing and test it - add test FlagTo* funcs * fix(cdn) fix merge errors * fix(cdn) more merge errors, and single char renames * fix(cdn) JoinStringMap: define order * fix(cdn) define geofencing order * fix(cdn) review changes - fix `ID` spelling - add missing new line at end of output - rm TODO comment * feat(printer) make PromptForPassword scripting compatible * fix(cdn) add example to pass password in script * fix(docs) generate docs * fix(printer) make TestPromptForPassword compatible with older go versions * fix(printer) fix/ignore linting issues * fix(cdn) adjust list TestOutputResult expected to new printer changes * fix(cdn) rm superfluous model.AssumeYes checks * fix(fmt) run fmt --------- Co-authored-by: Ruben Hönle Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Co-authored-by: stackit-pipeline <142982727+stackit-pipeline@users.noreply.github.com> Co-authored-by: Piet van der Meulen Co-authored-by: Jorge Turrado Ferrero --- docs/stackit_beta.md | 1 + docs/stackit_beta_cdn.md | 34 ++ docs/stackit_beta_cdn_distribution.md | 38 ++ docs/stackit_beta_cdn_distribution_create.md | 68 +++ docs/stackit_beta_cdn_distribution_delete.md | 40 ++ .../stackit_beta_cdn_distribution_describe.md | 44 ++ docs/stackit_beta_cdn_distribution_list.md | 45 ++ docs/stackit_beta_cdn_distribution_update.md | 57 ++ docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 3 +- go.sum | 2 + internal/cmd/beta/beta.go | 4 +- internal/cmd/beta/cdn/cdn.go | 25 + .../beta/cdn/distribution/create/create.go | 340 +++++++++++ .../cdn/distribution/create/create_test.go | 542 ++++++++++++++++++ .../beta/cdn/distribution/delete/delete.go | 92 +++ .../cdn/distribution/delete/delete_test.go | 130 +++++ .../cdn/distribution/describe/describe.go | 219 +++++++ .../distribution/describe/describe_test.go | 409 +++++++++++++ .../cmd/beta/cdn/distribution/distribution.go | 32 ++ .../cmd/beta/cdn/distribution/list/list.go | 175 ++++++ .../beta/cdn/distribution/list/list_test.go | 471 +++++++++++++++ .../beta/cdn/distribution/update/update.go | 337 +++++++++++ .../cdn/distribution/update/update_test.go | 365 ++++++++++++ internal/cmd/config/set/set.go | 4 + internal/cmd/config/unset/unset.go | 7 + internal/cmd/config/unset/unset_test.go | 13 + internal/pkg/config/config.go | 3 + internal/pkg/flags/flag_to_value.go | 28 + internal/pkg/flags/flag_to_value_test.go | 113 ++++ internal/pkg/print/print.go | 15 +- internal/pkg/print/print_test.go | 49 ++ internal/pkg/services/cdn/client/client.go | 13 + internal/pkg/services/cdn/utils/utils.go | 40 ++ internal/pkg/services/cdn/utils/utils_test.go | 94 +++ internal/pkg/testutils/testutils.go | 16 + internal/pkg/utils/strings.go | 19 + internal/pkg/utils/strings_test.go | 36 ++ 39 files changed, 3920 insertions(+), 5 deletions(-) create mode 100644 docs/stackit_beta_cdn.md create mode 100644 docs/stackit_beta_cdn_distribution.md create mode 100644 docs/stackit_beta_cdn_distribution_create.md create mode 100644 docs/stackit_beta_cdn_distribution_delete.md create mode 100644 docs/stackit_beta_cdn_distribution_describe.md create mode 100644 docs/stackit_beta_cdn_distribution_list.md create mode 100644 docs/stackit_beta_cdn_distribution_update.md create mode 100644 internal/cmd/beta/cdn/cdn.go create mode 100644 internal/cmd/beta/cdn/distribution/create/create.go create mode 100644 internal/cmd/beta/cdn/distribution/create/create_test.go create mode 100644 internal/cmd/beta/cdn/distribution/delete/delete.go create mode 100644 internal/cmd/beta/cdn/distribution/delete/delete_test.go create mode 100644 internal/cmd/beta/cdn/distribution/describe/describe.go create mode 100644 internal/cmd/beta/cdn/distribution/describe/describe_test.go create mode 100644 internal/cmd/beta/cdn/distribution/distribution.go create mode 100644 internal/cmd/beta/cdn/distribution/list/list.go create mode 100644 internal/cmd/beta/cdn/distribution/list/list_test.go create mode 100644 internal/cmd/beta/cdn/distribution/update/update.go create mode 100644 internal/cmd/beta/cdn/distribution/update/update_test.go create mode 100644 internal/pkg/services/cdn/client/client.go create mode 100644 internal/pkg/services/cdn/utils/utils.go create mode 100644 internal/pkg/services/cdn/utils/utils_test.go diff --git a/docs/stackit_beta.md b/docs/stackit_beta.md index 78b58b1f7..079333c69 100644 --- a/docs/stackit_beta.md +++ b/docs/stackit_beta.md @@ -42,6 +42,7 @@ stackit beta [flags] * [stackit](./stackit.md) - Manage STACKIT resources using the command line * [stackit beta alb](./stackit_beta_alb.md) - Manages application loadbalancers +* [stackit beta cdn](./stackit_beta_cdn.md) - Manage CDN resources * [stackit beta edge-cloud](./stackit_beta_edge-cloud.md) - Provides functionality for edge services. * [stackit beta intake](./stackit_beta_intake.md) - Provides functionality for intake * [stackit beta kms](./stackit_beta_kms.md) - Provides functionality for KMS diff --git a/docs/stackit_beta_cdn.md b/docs/stackit_beta_cdn.md new file mode 100644 index 000000000..b0a99f688 --- /dev/null +++ b/docs/stackit_beta_cdn.md @@ -0,0 +1,34 @@ +## stackit beta cdn + +Manage CDN resources + +### Synopsis + +Manage the lifecycle of CDN resources. + +``` +stackit beta cdn [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta cdn" +``` + +### 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 beta](./stackit_beta.md) - Contains beta STACKIT CLI commands +* [stackit beta cdn distribution](./stackit_beta_cdn_distribution.md) - Manage CDN distributions + diff --git a/docs/stackit_beta_cdn_distribution.md b/docs/stackit_beta_cdn_distribution.md new file mode 100644 index 000000000..c9c26a931 --- /dev/null +++ b/docs/stackit_beta_cdn_distribution.md @@ -0,0 +1,38 @@ +## stackit beta cdn distribution + +Manage CDN distributions + +### Synopsis + +Manage the lifecycle of CDN distributions. + +``` +stackit beta cdn distribution [flags] +``` + +### Options + +``` + -h, --help Help for "stackit beta cdn distribution" +``` + +### 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 beta cdn](./stackit_beta_cdn.md) - Manage CDN resources +* [stackit beta cdn distribution create](./stackit_beta_cdn_distribution_create.md) - Create a CDN distribution +* [stackit beta cdn distribution delete](./stackit_beta_cdn_distribution_delete.md) - Delete a CDN distribution +* [stackit beta cdn distribution describe](./stackit_beta_cdn_distribution_describe.md) - Describe a CDN distribution +* [stackit beta cdn distribution list](./stackit_beta_cdn_distribution_list.md) - List CDN distributions +* [stackit beta cdn distribution update](./stackit_beta_cdn_distribution_update.md) - Update a CDN distribution + diff --git a/docs/stackit_beta_cdn_distribution_create.md b/docs/stackit_beta_cdn_distribution_create.md new file mode 100644 index 000000000..f52da0cf1 --- /dev/null +++ b/docs/stackit_beta_cdn_distribution_create.md @@ -0,0 +1,68 @@ +## stackit beta cdn distribution create + +Create a CDN distribution + +### Synopsis + +Create a CDN distribution for a given originUrl in multiple regions. + +``` +stackit beta cdn distribution create [flags] +``` + +### Examples + +``` + Create a CDN distribution with an HTTP backend + $ stackit beta cdn distribution create --http --http-origin-url https://example.com \ +--regions AF,EU + + Create a CDN distribution with an Object Storage backend + $ stackit beta cdn distribution create --bucket --bucket-url https://bucket.example.com \ +--bucket-credentials-access-key-id yyyy --bucket-region EU \ +--regions AF,EU + + Create a CDN distribution passing the password via stdin, take care that there's a '\n' at the end of the input' + $ cat secret.txt | stackit beta cdn distribution create -y --project-id xxx \ +--bucket --bucket-url https://bucket.example.com --bucekt-credentials-access-key-id yyyy --bucket-region EU \ +--regions AF,EU +``` + +### Options + +``` + --blocked-countries strings Comma-separated list of ISO 3166-1 alpha-2 country codes to block (e.g., 'US,DE,FR') + --blocked-ips strings Comma-separated list of IPv4 addresses to block (e.g., '10.0.0.8,127.0.0.1') + --bucket Use Object Storage backend + --bucket-credentials-access-key-id string Access Key ID for Object Storage backend + --bucket-region string Region for Object Storage backend + --bucket-url string Bucket URL for Object Storage backend + --default-cache-duration string ISO8601 duration string for default cache duration (e.g., 'PT1H30M' for 1 hour and 30 minutes) + -h, --help Help for "stackit beta cdn distribution create" + --http Use HTTP backend + --http-geofencing stringArray Geofencing rules for HTTP backend in the format 'https://example.com US,DE'. URL and countries have to be quoted. Repeatable. + --http-origin-request-headers strings Origin request headers for HTTP backend in the format 'HeaderName: HeaderValue', repeatable. WARNING: do not store sensitive values in the headers! + --http-origin-url string Origin URL for HTTP backend + --loki Enable Loki log sink for the CDN distribution + --loki-push-url string Push URL for log sink + --loki-username string Username for log sink + --monthly-limit-bytes int Monthly limit in bytes for the CDN distribution + --optimizer Enable optimizer for the CDN distribution (paid feature). + --regions strings Regions in which content should be cached, multiple of: ["EU" "US" "AF" "SA" "ASIA"] (default []) +``` + +### 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 beta cdn distribution](./stackit_beta_cdn_distribution.md) - Manage CDN distributions + diff --git a/docs/stackit_beta_cdn_distribution_delete.md b/docs/stackit_beta_cdn_distribution_delete.md new file mode 100644 index 000000000..7313b5a39 --- /dev/null +++ b/docs/stackit_beta_cdn_distribution_delete.md @@ -0,0 +1,40 @@ +## stackit beta cdn distribution delete + +Delete a CDN distribution + +### Synopsis + +Delete a CDN distribution by its ID. + +``` +stackit beta cdn distribution delete [flags] +``` + +### Examples + +``` + Delete a CDN distribution with ID "xxx" + $ stackit beta cdn distribution delete xxx +``` + +### Options + +``` + -h, --help Help for "stackit beta cdn distribution delete" +``` + +### 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 beta cdn distribution](./stackit_beta_cdn_distribution.md) - Manage CDN distributions + diff --git a/docs/stackit_beta_cdn_distribution_describe.md b/docs/stackit_beta_cdn_distribution_describe.md new file mode 100644 index 000000000..1e8f68a7e --- /dev/null +++ b/docs/stackit_beta_cdn_distribution_describe.md @@ -0,0 +1,44 @@ +## stackit beta cdn distribution describe + +Describe a CDN distribution + +### Synopsis + +Describe a CDN distribution by its ID. + +``` +stackit beta cdn distribution describe [flags] +``` + +### Examples + +``` + Get details of a CDN distribution with ID "xxx" + $ stackit beta cdn distribution describe xxx + + Get details of a CDN, including WAF details, for ID "xxx" + $ stackit beta cdn distribution describe xxx --with-waf +``` + +### Options + +``` + -h, --help Help for "stackit beta cdn distribution describe" + --with-waf Include WAF details in the distribution description +``` + +### 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 beta cdn distribution](./stackit_beta_cdn_distribution.md) - Manage CDN distributions + diff --git a/docs/stackit_beta_cdn_distribution_list.md b/docs/stackit_beta_cdn_distribution_list.md new file mode 100644 index 000000000..4fc5d2750 --- /dev/null +++ b/docs/stackit_beta_cdn_distribution_list.md @@ -0,0 +1,45 @@ +## stackit beta cdn distribution list + +List CDN distributions + +### Synopsis + +List all CDN distributions in your account. + +``` +stackit beta cdn distribution list [flags] +``` + +### Examples + +``` + List all CDN distributions + $ stackit beta cdn distribution list + + List all CDN distributions sorted by id + $ stackit beta cdn distribution list --sort-by=id +``` + +### Options + +``` + -- int Limit the output to the first n elements + -h, --help Help for "stackit beta cdn distribution list" + --sort-by string Sort entries by a specific field, one of ["id" "createdAt" "updatedAt" "originUrl" "status" "originUrlRelated"] (default "createdAt") +``` + +### 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 beta cdn distribution](./stackit_beta_cdn_distribution.md) - Manage CDN distributions + diff --git a/docs/stackit_beta_cdn_distribution_update.md b/docs/stackit_beta_cdn_distribution_update.md new file mode 100644 index 000000000..f8f26dec9 --- /dev/null +++ b/docs/stackit_beta_cdn_distribution_update.md @@ -0,0 +1,57 @@ +## stackit beta cdn distribution update + +Update a CDN distribution + +### Synopsis + +Update a CDN distribution by its ID, allowing replacement of its regions. + +``` +stackit beta cdn distribution update [flags] +``` + +### Examples + +``` + update a CDN distribution with ID "123e4567-e89b-12d3-a456-426614174000" to not use optimizer + $ stackit beta cdn update 123e4567-e89b-12d3-a456-426614174000 --optimizer=false +``` + +### Options + +``` + --blocked-countries strings Comma-separated list of ISO 3166-1 alpha-2 country codes to block (e.g., 'US,DE,FR') + --blocked-ips strings Comma-separated list of IPv4 addresses to block (e.g., '10.0.0.8,127.0.0.1') + --bucket Use Object Storage backend + --bucket-credentials-access-key-id string Access Key ID for Object Storage backend + --bucket-region string Region for Object Storage backend + --bucket-url string Bucket URL for Object Storage backend + --default-cache-duration string ISO8601 duration string for default cache duration (e.g., 'PT1H30M' for 1 hour and 30 minutes) + -h, --help Help for "stackit beta cdn distribution update" + --http Use HTTP backend + --http-geofencing stringArray Geofencing rules for HTTP backend in the format 'https://example.com US,DE'. URL and countries have to be quoted. Repeatable. + --http-origin-request-headers strings Origin request headers for HTTP backend in the format 'HeaderName: HeaderValue', repeatable. WARNING: do not store sensitive values in the headers! + --http-origin-url string Origin URL for HTTP backend + --loki Enable Loki log sink for the CDN distribution + --loki-push-url string Push URL for log sink + --loki-username string Username for log sink + --monthly-limit-bytes int Monthly limit in bytes for the CDN distribution + --optimizer Enable optimizer for the CDN distribution (paid feature). + --regions strings Regions in which content should be cached, multiple of: ["EU" "US" "AF" "SA" "ASIA"] (default []) +``` + +### 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 beta cdn distribution](./stackit_beta_cdn_distribution.md) - Manage CDN distributions + diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 8613d2a1d..c1f104958 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -31,6 +31,7 @@ stackit config set [flags] ``` --allowed-url-domain string Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command --authorization-custom-endpoint string Authorization API base URL, used in calls to this API + --cdn-custom-endpoint string CDN API base URL, used in calls to this API --dns-custom-endpoint string DNS API base URL, used in calls to this API --edge-custom-endpoint string Edge API base URL, used in calls to this API -h, --help Help for "stackit config set" diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 89c6116e0..4f0f7f229 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -29,6 +29,7 @@ stackit config unset [flags] --allowed-url-domain Domain name, used for the verification of the URLs that are given in the IDP endpoint and curl commands. If unset, defaults to stackit.cloud --async Configuration option to run commands asynchronously --authorization-custom-endpoint Authorization API base URL. If unset, uses the default base URL + --cdn-custom-endpoint Custom CDN endpoint URL. If unset, uses the default base URL --dns-custom-endpoint DNS API base URL. If unset, uses the default base URL --edge-custom-endpoint Edge API base URL. If unset, uses the default base URL -h, --help Help for "stackit config unset" diff --git a/go.mod b/go.mod index 3e2effedc..11590a48d 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.20.1 github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 + github.com/stackitcloud/stackit-sdk-go/services/cdn v1.8.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/edge v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 @@ -278,7 +279,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect + k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/go.sum b/go.sum index d28aa738a..709f665a1 100644 --- a/go.sum +++ b/go.sum @@ -604,6 +604,8 @@ github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98e github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0 h1:P24WoKPt14dfUiUJ4czIv+IiVmdCFQGrKgVtw23fxNg= github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= +github.com/stackitcloud/stackit-sdk-go/services/cdn v1.8.1 h1:CiOlfCsCDwHP0kas7qyhfp5XtL2kVmn9e4wjtc3LO10= +github.com/stackitcloud/stackit-sdk-go/services/cdn v1.8.1/go.mod h1:PyZ6g9JsGZZyeISAF+5E7L1lAlMnmbl2YbPj5Teu8to= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 h1:4YFY5PG4vP/NiEP1uxCwh+kQHEU7iHG6syuFD7NPqcw= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= diff --git a/internal/cmd/beta/beta.go b/internal/cmd/beta/beta.go index 5bd94a17c..bf3bd4129 100644 --- a/internal/cmd/beta/beta.go +++ b/internal/cmd/beta/beta.go @@ -3,13 +3,14 @@ package beta import ( "fmt" - "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs" "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/edge" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/intake" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/kms" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/logs" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sfs" "github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -49,4 +50,5 @@ func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { cmd.AddCommand(intake.NewCmd(params)) cmd.AddCommand(kms.NewCmd(params)) cmd.AddCommand(logs.NewCmd(params)) + cmd.AddCommand(cdn.NewCmd(params)) } diff --git a/internal/cmd/beta/cdn/cdn.go b/internal/cmd/beta/cdn/cdn.go new file mode 100644 index 000000000..257633ef0 --- /dev/null +++ b/internal/cmd/beta/cdn/cdn.go @@ -0,0 +1,25 @@ +package cdn + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn/distribution" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "cdn", + Short: "Manage CDN resources", + Long: "Manage the lifecycle of CDN resources.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(distribution.NewCommand(params)) +} diff --git a/internal/cmd/beta/cdn/distribution/create/create.go b/internal/cmd/beta/cdn/distribution/create/create.go new file mode 100644 index 000000000..19c5d3ca8 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/create/create.go @@ -0,0 +1,340 @@ +package create + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/cdn/client" + cdnUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/cdn/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +const ( + flagRegion = "regions" + flagHTTP = "http" + flagHTTPOriginURL = "http-origin-url" + flagHTTPGeofencing = "http-geofencing" + flagHTTPOriginRequestHeaders = "http-origin-request-headers" + flagBucket = "bucket" + flagBucketURL = "bucket-url" + flagBucketCredentialsAccessKeyID = "bucket-credentials-access-key-id" //nolint:gosec // linter false positive + flagBucketRegion = "bucket-region" + flagBlockedCountries = "blocked-countries" + flagBlockedIPs = "blocked-ips" + flagDefaultCacheDuration = "default-cache-duration" + flagLoki = "loki" + flagLokiUsername = "loki-username" + flagLokiPushURL = "loki-push-url" + flagMonthlyLimitBytes = "monthly-limit-bytes" + flagOptimizer = "optimizer" +) + +type httpInputModel struct { + OriginURL string + Geofencing *map[string][]string + OriginRequestHeaders *map[string]string +} + +type bucketInputModel struct { + URL string + AccessKeyID string + Password string + Region string +} + +type lokiInputModel struct { + Username string + Password string + PushURL string +} + +type inputModel struct { + *globalflags.GlobalFlagModel + Regions []cdn.Region + HTTP *httpInputModel + Bucket *bucketInputModel + BlockedCountries []string + BlockedIPs []string + DefaultCacheDuration string + MonthlyLimitBytes *int64 + Loki *lokiInputModel + Optimizer bool +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Create a CDN distribution", + Long: "Create a CDN distribution for a given originUrl in multiple regions.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `Create a CDN distribution with an HTTP backend`, + `$ stackit beta cdn distribution create --http --http-origin-url https://example.com \ +--regions AF,EU`, + ), + examples.NewExample( + `Create a CDN distribution with an Object Storage backend`, + `$ stackit beta cdn distribution create --bucket --bucket-url https://bucket.example.com \ +--bucket-credentials-access-key-id yyyy --bucket-region EU \ +--regions AF,EU`, + ), + examples.NewExample( + `Create a CDN distribution passing the password via stdin, take care that there's a '\n' at the end of the input'`, + `$ cat secret.txt | stackit beta cdn distribution create -y --project-id xxx \ +--bucket --bucket-url https://bucket.example.com --bucekt-credentials-access-key-id yyyy --bucket-region EU \ +--regions AF,EU`, + ), + ), + PreRun: func(cmd *cobra.Command, _ []string) { + // either flagHTTP or flagBucket must be set, depending on which we mark other flags as required + if flags.FlagToBoolValue(params.Printer, cmd, flagHTTP) { + err := cmd.MarkFlagRequired(flagHTTPOriginURL) + cobra.CheckErr(err) + } else { + err := flags.MarkFlagsRequired(cmd, flagBucketURL, flagBucketCredentialsAccessKeyID, flagBucketRegion) + cobra.CheckErr(err) + } + // if user uses loki, mark related flags as required + if flags.FlagToBoolValue(params.Printer, cmd, flagLoki) { + err := flags.MarkFlagsRequired(cmd, flagLokiUsername, flagLokiPushURL) + cobra.CheckErr(err) + } + }, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return err + } + if model.Bucket != nil { + pw, err := params.Printer.PromptForPassword("enter your secret access key for the object storage bucket: ") + if err != nil { + return fmt.Errorf("reading secret access key: %w", err) + } + model.Bucket.Password = pw + } + if model.Loki != nil { + pw, err := params.Printer.PromptForPassword("enter your password for the loki log sink: ") + if err != nil { + return fmt.Errorf("reading loki password: %w", err) + } + model.Loki.Password = pw + } + + 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 + } + + prompt := fmt.Sprintf("Are you sure you want to create a CDN distribution for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + + req := buildRequest(ctx, model, apiClient) + + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("create CDN distribution: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.EnumSliceFlag(false, []string{}, sdkUtils.EnumSliceToStringSlice(cdn.AllowedRegionEnumValues)...), flagRegion, fmt.Sprintf("Regions in which content should be cached, multiple of: %q", cdn.AllowedRegionEnumValues)) + cmd.Flags().Bool(flagHTTP, false, "Use HTTP backend") + cmd.Flags().String(flagHTTPOriginURL, "", "Origin URL for HTTP backend") + cmd.Flags().StringSlice(flagHTTPOriginRequestHeaders, []string{}, "Origin request headers for HTTP backend in the format 'HeaderName: HeaderValue', repeatable. WARNING: do not store sensitive values in the headers!") + cmd.Flags().StringArray(flagHTTPGeofencing, []string{}, "Geofencing rules for HTTP backend in the format 'https://example.com US,DE'. URL and countries have to be quoted. Repeatable.") + cmd.Flags().Bool(flagBucket, false, "Use Object Storage backend") + cmd.Flags().String(flagBucketURL, "", "Bucket URL for Object Storage backend") + cmd.Flags().String(flagBucketCredentialsAccessKeyID, "", "Access Key ID for Object Storage backend") + cmd.Flags().String(flagBucketRegion, "", "Region for Object Storage backend") + cmd.Flags().StringSlice(flagBlockedCountries, []string{}, "Comma-separated list of ISO 3166-1 alpha-2 country codes to block (e.g., 'US,DE,FR')") + cmd.Flags().StringSlice(flagBlockedIPs, []string{}, "Comma-separated list of IPv4 addresses to block (e.g., '10.0.0.8,127.0.0.1')") + cmd.Flags().String(flagDefaultCacheDuration, "", "ISO8601 duration string for default cache duration (e.g., 'PT1H30M' for 1 hour and 30 minutes)") + cmd.Flags().Bool(flagLoki, false, "Enable Loki log sink for the CDN distribution") + cmd.Flags().String(flagLokiUsername, "", "Username for log sink") + cmd.Flags().String(flagLokiPushURL, "", "Push URL for log sink") + cmd.Flags().Int64(flagMonthlyLimitBytes, 0, "Monthly limit in bytes for the CDN distribution") + cmd.Flags().Bool(flagOptimizer, false, "Enable optimizer for the CDN distribution (paid feature).") + cmd.MarkFlagsMutuallyExclusive(flagHTTP, flagBucket) + cmd.MarkFlagsOneRequired(flagHTTP, flagBucket) + err := flags.MarkFlagsRequired(cmd, flagRegion) + cobra.CheckErr(err) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + regionStrings := flags.FlagToStringSliceValue(p, cmd, flagRegion) + regions := make([]cdn.Region, 0, len(regionStrings)) + for _, regionStr := range regionStrings { + regions = append(regions, cdn.Region(regionStr)) + } + + var http *httpInputModel + if flags.FlagToBoolValue(p, cmd, flagHTTP) { + originURL := flags.FlagToStringValue(p, cmd, flagHTTPOriginURL) + + var geofencing *map[string][]string + geofencingInput := flags.FlagToStringArrayValue(p, cmd, flagHTTPGeofencing) + if geofencingInput != nil { + geofencing = cdnUtils.ParseGeofencing(p, geofencingInput) + } + + var originRequestHeaders *map[string]string + originRequestHeadersInput := flags.FlagToStringSliceValue(p, cmd, flagHTTPOriginRequestHeaders) + if originRequestHeadersInput != nil { + originRequestHeaders = cdnUtils.ParseOriginRequestHeaders(p, originRequestHeadersInput) + } + + http = &httpInputModel{ + OriginURL: originURL, + Geofencing: geofencing, + OriginRequestHeaders: originRequestHeaders, + } + } + + var bucket *bucketInputModel + if flags.FlagToBoolValue(p, cmd, flagBucket) { + bucketURL := flags.FlagToStringValue(p, cmd, flagBucketURL) + accessKeyID := flags.FlagToStringValue(p, cmd, flagBucketCredentialsAccessKeyID) + region := flags.FlagToStringValue(p, cmd, flagBucketRegion) + + bucket = &bucketInputModel{ + URL: bucketURL, + AccessKeyID: accessKeyID, + Password: "", + Region: region, + } + } + + blockedCountries := flags.FlagToStringSliceValue(p, cmd, flagBlockedCountries) + blockedIPs := flags.FlagToStringSliceValue(p, cmd, flagBlockedIPs) + cacheDuration := flags.FlagToStringValue(p, cmd, flagDefaultCacheDuration) + monthlyLimit := flags.FlagToInt64Pointer(p, cmd, flagMonthlyLimitBytes) + + var loki *lokiInputModel + if flags.FlagToBoolValue(p, cmd, flagLoki) { + loki = &lokiInputModel{ + Username: flags.FlagToStringValue(p, cmd, flagLokiUsername), + PushURL: flags.FlagToStringValue(p, cmd, flagLokiPushURL), + Password: "", + } + } + + optimizer := flags.FlagToBoolValue(p, cmd, flagOptimizer) + + model := inputModel{ + GlobalFlagModel: globalFlags, + Regions: regions, + HTTP: http, + Bucket: bucket, + BlockedCountries: blockedCountries, + BlockedIPs: blockedIPs, + DefaultCacheDuration: cacheDuration, + MonthlyLimitBytes: monthlyLimit, + Loki: loki, + Optimizer: optimizer, + } + + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *cdn.APIClient) cdn.ApiCreateDistributionRequest { + req := apiClient.CreateDistribution(ctx, model.ProjectId) + var backend cdn.CreateDistributionPayloadGetBackendArgType + if model.HTTP != nil { + backend = cdn.CreateDistributionPayloadGetBackendArgType{ + HttpBackendCreate: &cdn.HttpBackendCreate{ + Geofencing: model.HTTP.Geofencing, + OriginRequestHeaders: model.HTTP.OriginRequestHeaders, + OriginUrl: &model.HTTP.OriginURL, + Type: utils.Ptr("http"), + }, + } + } else { + backend = cdn.CreateDistributionPayloadGetBackendArgType{ + BucketBackendCreate: &cdn.BucketBackendCreate{ + BucketUrl: &model.Bucket.URL, + Credentials: cdn.NewBucketCredentials( + model.Bucket.AccessKeyID, + model.Bucket.Password, + ), + Region: &model.Bucket.Region, + Type: utils.Ptr("bucket"), + }, + } + } + + payload := cdn.NewCreateDistributionPayload( + backend, + model.Regions, + ) + if len(model.BlockedCountries) > 0 { + payload.BlockedCountries = &model.BlockedCountries + } + if len(model.BlockedIPs) > 0 { + payload.BlockedIps = &model.BlockedIPs + } + if model.DefaultCacheDuration != "" { + payload.DefaultCacheDuration = utils.Ptr(model.DefaultCacheDuration) + } + if model.Loki != nil { + payload.LogSink = &cdn.CreateDistributionPayloadGetLogSinkArgType{ + LokiLogSinkCreate: &cdn.LokiLogSinkCreate{ + Credentials: &cdn.LokiLogSinkCredentials{ + Password: &model.Loki.Password, + Username: &model.Loki.Username, + }, + PushUrl: &model.Loki.PushURL, + Type: utils.Ptr("loki"), + }, + } + } + payload.MonthlyLimitBytes = model.MonthlyLimitBytes + if model.Optimizer { + payload.Optimizer = &cdn.CreateDistributionPayloadGetOptimizerArgType{ + Enabled: utils.Ptr(true), + } + } + return req.CreateDistributionPayload(*payload) +} + +func outputResult(p *print.Printer, outputFormat, projectLabel string, resp *cdn.CreateDistributionResponse) error { + if resp == nil { + return fmt.Errorf("create distribution response is nil") + } + return p.OutputResult(outputFormat, resp, func() error { + p.Outputf("Created CDN distribution for %q. ID: %s\n", projectLabel, utils.PtrString(resp.Distribution.Id)) + return nil + }) +} diff --git a/internal/cmd/beta/cdn/distribution/create/create_test.go b/internal/cmd/beta/cdn/distribution/create/create_test.go new file mode 100644 index 000000000..4276f34a7 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/create/create_test.go @@ -0,0 +1,542 @@ +package create + +import ( + "bytes" + "context" + "fmt" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" + "k8s.io/utils/ptr" +) + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &cdn.APIClient{} +var testProjectId = uuid.NewString() + +const testRegions = cdn.REGION_EU + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + flagRegion: string(testRegions), + } + flagsHTTPBackend()(flagValues) + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func flagsHTTPBackend() func(flagValues map[string]string) { + return func(flagValues map[string]string) { + delete(flagValues, flagBucket) + flagValues[flagHTTP] = "true" + flagValues[flagHTTPOriginURL] = "https://http-backend.example.com" + } +} + +func flagsBucketBackend() func(flagValues map[string]string) { + return func(flagValues map[string]string) { + delete(flagValues, flagHTTP) + flagValues[flagBucket] = "true" + flagValues[flagBucketURL] = "https://bucket-backend.example.com" + flagValues[flagBucketCredentialsAccessKeyID] = "access-key-id" + flagValues[flagBucketRegion] = "eu" + } +} + +func flagsLoki() func(flagValues map[string]string) { + return func(flagValues map[string]string) { + flagValues[flagLoki] = "true" + flagValues[flagLokiPushURL] = "https://loki.example.com" + flagValues[flagLokiUsername] = "loki-user" + } +} + +func flagRegions(regions ...cdn.Region) func(flagValues map[string]string) { + return func(flagValues map[string]string) { + if len(regions) == 0 { + delete(flagValues, flagRegion) + return + } + stringRegions := sdkUtils.EnumSliceToStringSlice(regions) + flagValues[flagRegion] = strings.Join(stringRegions, ",") + } +} + +func fixtureModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + Regions: []cdn.Region{testRegions}, + } + modelHTTPBackend()(model) + for _, mod := range mods { + mod(model) + } + return model +} + +func modelRegions(regions ...cdn.Region) func(model *inputModel) { + return func(model *inputModel) { + model.Regions = regions + } +} + +func modelHTTPBackend() func(model *inputModel) { + return func(model *inputModel) { + model.Bucket = nil + model.HTTP = &httpInputModel{ + OriginURL: "https://http-backend.example.com", + } + } +} + +func modelBucketBackend() func(model *inputModel) { + return func(model *inputModel) { + model.HTTP = nil + model.Bucket = &bucketInputModel{ + URL: "https://bucket-backend.example.com", + AccessKeyID: "access-key-id", + Region: "eu", + } + } +} + +func modelLoki() func(model *inputModel) { + return func(model *inputModel) { + model.Loki = &lokiInputModel{ + PushURL: "https://loki.example.com", + Username: "loki-user", + } + } +} + +func fixturePayload(mods ...func(payload *cdn.CreateDistributionPayload)) cdn.CreateDistributionPayload { + payload := *cdn.NewCreateDistributionPayload( + cdn.CreateDistributionPayloadGetBackendArgType{ + HttpBackendCreate: &cdn.HttpBackendCreate{ + Type: utils.Ptr("http"), + OriginUrl: utils.Ptr("https://http-backend.example.com"), + }, + }, + []cdn.Region{testRegions}, + ) + for _, mod := range mods { + mod(&payload) + } + return payload +} + +func payloadRegions(regions ...cdn.Region) func(payload *cdn.CreateDistributionPayload) { + return func(payload *cdn.CreateDistributionPayload) { + payload.Regions = ®ions + } +} + +func payloadBucketBackend() func(payload *cdn.CreateDistributionPayload) { + return func(payload *cdn.CreateDistributionPayload) { + payload.Backend = &cdn.CreateDistributionPayloadGetBackendArgType{ + BucketBackendCreate: &cdn.BucketBackendCreate{ + Type: utils.Ptr("bucket"), + BucketUrl: utils.Ptr("https://bucket-backend.example.com"), + Region: utils.Ptr("eu"), + Credentials: cdn.NewBucketCredentials( + "access-key-id", + "", + ), + }, + } + } +} + +func payloadLoki() func(payload *cdn.CreateDistributionPayload) { + return func(payload *cdn.CreateDistributionPayload) { + payload.LogSink = &cdn.CreateDistributionPayloadGetLogSinkArgType{ + LokiLogSinkCreate: &cdn.LokiLogSinkCreate{ + Type: utils.Ptr("loki"), + PushUrl: utils.Ptr("https://loki.example.com"), + Credentials: cdn.NewLokiLogSinkCredentials("", "loki-user"), + }, + } + } +} + +func fixtureRequest(mods ...func(payload *cdn.CreateDistributionPayload)) cdn.ApiCreateDistributionRequest { + req := testClient.CreateDistribution(testCtx, testProjectId) + req = req.CreateDistributionPayload(fixturePayload(mods...)) + return req +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expected *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expected: fixtureModel(), + }, + { + 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, + }, + { + description: "regions missing", + flagValues: fixtureFlagValues(flagRegions()), + isValid: false, + }, + { + description: "multiple regions", + flagValues: fixtureFlagValues(flagRegions(cdn.REGION_EU, cdn.REGION_AF)), + isValid: true, + expected: fixtureModel(modelRegions(cdn.REGION_EU, cdn.REGION_AF)), + }, + { + description: "bucket backend", + flagValues: fixtureFlagValues(flagsBucketBackend()), + isValid: true, + expected: fixtureModel(modelBucketBackend()), + }, + { + description: "bucket backend missing url", + flagValues: fixtureFlagValues( + flagsBucketBackend(), + func(flagValues map[string]string) { + delete(flagValues, flagBucketURL) + }, + ), + isValid: false, + }, + { + description: "bucket backend missing access key id", + flagValues: fixtureFlagValues( + flagsBucketBackend(), + func(flagValues map[string]string) { + delete(flagValues, flagBucketCredentialsAccessKeyID) + }, + ), + isValid: false, + }, + { + description: "bucket backend missing region", + flagValues: fixtureFlagValues( + flagsBucketBackend(), + func(flagValues map[string]string) { + delete(flagValues, flagBucketRegion) + }, + ), + isValid: false, + }, + { + description: "http backend missing url", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + delete(flagValues, flagHTTPOriginURL) + }, + ), + isValid: false, + }, + { + description: "http backend with geofencing", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagHTTPGeofencing] = "https://dach.example.com DE,AT,CH" + }, + ), + isValid: true, + expected: fixtureModel( + func(model *inputModel) { + model.HTTP.Geofencing = &map[string][]string{ + "https://dach.example.com": {"DE", "AT", "CH"}, + } + }, + ), + }, + { + description: "http backend with origin request headers", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagHTTPOriginRequestHeaders] = "X-Custom-Header:Value1,X-Another-Header:Value2" + }, + ), + isValid: true, + expected: fixtureModel( + func(model *inputModel) { + model.HTTP.OriginRequestHeaders = &map[string]string{ + "X-Custom-Header": "Value1", + "X-Another-Header": "Value2", + } + }, + ), + }, + { + description: "with blocked countries", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagBlockedCountries] = "DE,AT" + }), + isValid: true, + expected: fixtureModel( + func(model *inputModel) { + model.BlockedCountries = []string{"DE", "AT"} + }, + ), + }, + { + description: "with blocked IPs", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagBlockedIPs] = "127.0.0.1,10.0.0.8" + }), + isValid: true, + expected: fixtureModel( + func(model *inputModel) { + model.BlockedIPs = []string{"127.0.0.1", "10.0.0.8"} + }), + }, + { + description: "with default cache duration", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagDefaultCacheDuration] = "PT1H30M" + }), + isValid: true, + expected: fixtureModel( + func(model *inputModel) { + model.DefaultCacheDuration = "PT1H30M" + }), + }, + { + description: "with optimizer", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagOptimizer] = "true" + }), + isValid: true, + expected: fixtureModel( + func(model *inputModel) { + model.Optimizer = true + }), + }, + { + description: "with loki", + flagValues: fixtureFlagValues( + flagsLoki(), + ), + isValid: true, + expected: fixtureModel( + modelLoki(), + ), + }, + { + description: "loki with missing username", + flagValues: fixtureFlagValues( + flagsLoki(), + func(flagValues map[string]string) { + delete(flagValues, flagLokiUsername) + }, + ), + isValid: false, + }, + { + description: "loki with missing push url", + flagValues: fixtureFlagValues( + flagsLoki(), + func(flagValues map[string]string) { + delete(flagValues, flagLokiPushURL) + }, + ), + isValid: false, + }, + { + description: "with monthly limit bytes", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagMonthlyLimitBytes] = "1073741824" // 1 GiB + }), + isValid: true, + expected: fixtureModel( + func(model *inputModel) { + model.MonthlyLimitBytes = ptr.To[int64](1073741824) + }), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expected, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expected cdn.ApiCreateDistributionRequest + }{ + { + description: "base", + model: fixtureModel(), + expected: fixtureRequest(), + }, + { + description: "multiple regions", + model: fixtureModel(modelRegions(cdn.REGION_AF, cdn.REGION_EU)), + expected: fixtureRequest(payloadRegions(cdn.REGION_AF, cdn.REGION_EU)), + }, + { + description: "bucket backend", + model: fixtureModel(modelBucketBackend()), + expected: fixtureRequest(payloadBucketBackend()), + }, + { + description: "http backend with geofencing and origin request headers", + model: fixtureModel( + func(model *inputModel) { + model.HTTP.Geofencing = &map[string][]string{ + "https://dach.example.com": {"DE", "AT", "CH"}, + } + model.HTTP.OriginRequestHeaders = &map[string]string{ + "X-Custom-Header": "Value1", + "X-Another-Header": "Value2", + } + }, + ), + expected: fixtureRequest( + func(payload *cdn.CreateDistributionPayload) { + payload.Backend.HttpBackendCreate.Geofencing = &map[string][]string{ + "https://dach.example.com": {"DE", "AT", "CH"}, + } + payload.Backend.HttpBackendCreate.OriginRequestHeaders = &map[string]string{ + "X-Custom-Header": "Value1", + "X-Another-Header": "Value2", + } + }, + ), + }, + { + description: "with full options", + model: fixtureModel( + func(model *inputModel) { + model.MonthlyLimitBytes = ptr.To[int64](5368709120) // 5 GiB + model.Optimizer = true + model.BlockedCountries = []string{"DE", "AT"} + model.BlockedIPs = []string{"127.0.0.1"} + model.DefaultCacheDuration = "PT2H" + }, + ), + expected: fixtureRequest( + func(payload *cdn.CreateDistributionPayload) { + payload.MonthlyLimitBytes = utils.Ptr[int64](5368709120) + payload.Optimizer = &cdn.CreateDistributionPayloadGetOptimizerArgType{ + Enabled: utils.Ptr(true), + } + payload.BlockedCountries = &[]string{"DE", "AT"} + payload.BlockedIps = &[]string{"127.0.0.1"} + payload.DefaultCacheDuration = utils.Ptr("PT2H") + }, + ), + }, + { + description: "loki", + model: fixtureModel( + modelLoki(), + ), + expected: fixtureRequest(payloadLoki()), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, tt.model, testClient) + + diff := cmp.Diff(request, tt.expected, + cmp.AllowUnexported(tt.expected), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + outputFormat string + response *cdn.CreateDistributionResponse + expected string + wantErr bool + }{ + { + description: "nil response", + outputFormat: "table", + response: nil, + wantErr: true, + }, + { + description: "table output", + outputFormat: "table", + response: &cdn.CreateDistributionResponse{ + Distribution: &cdn.Distribution{ + Id: ptr.To("dist-1234"), + }, + }, + expected: fmt.Sprintf("Created CDN distribution for %q. ID: dist-1234\n", testProjectId), + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + buffer := &bytes.Buffer{} + p.Cmd.SetOut(buffer) + if err := outputResult(p, tt.outputFormat, testProjectId, tt.response); (err != nil) != tt.wantErr { + t.Fatalf("outputResult: %v", err) + } + if buffer.String() != tt.expected { + t.Errorf("want:\n%s\ngot:\n%s", tt.expected, buffer.String()) + } + }) + } +} diff --git a/internal/cmd/beta/cdn/distribution/delete/delete.go b/internal/cmd/beta/cdn/distribution/delete/delete.go new file mode 100644 index 000000000..78baebdc4 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/delete/delete.go @@ -0,0 +1,92 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "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/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/cdn/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +const argDistributionID = "DISTRIBUTION_ID" + +type inputModel struct { + *globalflags.GlobalFlagModel + DistributionID string +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a CDN distribution", + Long: "Delete a CDN distribution by its ID.", + Args: args.SingleArg(argDistributionID, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Delete a CDN distribution with ID "xxx"`, + `$ stackit beta cdn distribution delete xxx`, + ), + ), + 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 + } + + prompt := fmt.Sprintf("Are you sure you want to delete the CDN distribution %q for project %q?", model.DistributionID, projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + _, err = req.Execute() + if err != nil { + return fmt.Errorf("delete loadbalancer: %w", err) + } + + params.Printer.Outputf("CDN distribution %q deleted.\n", model.DistributionID) + return nil + }, + } + return cmd +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + + distributionID := inputArgs[0] + model := inputModel{ + GlobalFlagModel: globalFlags, + DistributionID: distributionID, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *cdn.APIClient) cdn.ApiDeleteDistributionRequest { + return apiClient.DeleteDistribution(ctx, model.ProjectId, model.DistributionID) +} diff --git a/internal/cmd/beta/cdn/distribution/delete/delete_test.go b/internal/cmd/beta/cdn/distribution/delete/delete_test.go new file mode 100644 index 000000000..03ec87f46 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/delete/delete_test.go @@ -0,0 +1,130 @@ +package delete + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") + testProjectId = uuid.NewString() + testClient = &cdn.APIClient{} + testDistributionID = uuid.NewString() +) + +func fixtureArgValues(mods ...func(argVales []string)) []string { + argVales := []string{ + testDistributionID, + } + for _, m := range mods { + m(argVales) + } + return argVales +} + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, m := range mods { + m(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + DistributionID: testDistributionID, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *cdn.ApiDeleteDistributionRequest)) cdn.ApiDeleteDistributionRequest { + request := testClient.DeleteDistribution(testCtx, testProjectId, testDistributionID) + for _, mod := range mods { + mod(&request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argsValues []string + flagValues map[string]string + isValid bool + expectedModel *inputModel + }{ + { + description: "base", + argsValues: fixtureArgValues(), + flagValues: fixtureFlagValues(), + isValid: true, + expectedModel: fixtureInputModel(), + }, + { + description: "no values", + argsValues: []string{}, + flagValues: map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + }, + isValid: false, + }, + { + description: "no arg values", + argsValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expectedModel, tt.argsValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedResult cdn.ApiDeleteDistributionRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedResult: fixtureRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, tt.model, testClient) + + diff := cmp.Diff(request, tt.expectedResult, + cmp.AllowUnexported(tt.expectedResult), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/cdn/distribution/describe/describe.go b/internal/cmd/beta/cdn/distribution/describe/describe.go new file mode 100644 index 000000000..9d4897f72 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/describe/describe.go @@ -0,0 +1,219 @@ +package describe + +import ( + "context" + "fmt" + "slices" + "strings" + + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/cdn/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +const distributionIDArg = "DISTRIBUTION_ID_ARG" +const flagWithWaf = "with-waf" + +type inputModel struct { + *globalflags.GlobalFlagModel + DistributionID string + WithWAF bool +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "describe", + Short: "Describe a CDN distribution", + Long: "Describe a CDN distribution by its ID.", + Args: args.SingleArg(distributionIDArg, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `Get details of a CDN distribution with ID "xxx"`, + `$ stackit beta cdn distribution describe xxx`, + ), + examples.NewExample( + `Get details of a CDN, including WAF details, for ID "xxx"`, + `$ stackit beta cdn distribution describe xxx --with-waf`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return err + } + + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("read distribution: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Bool(flagWithWaf, false, "Include WAF details in the distribution description") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + model := &inputModel{ + GlobalFlagModel: globalFlags, + DistributionID: inputArgs[0], + WithWAF: flags.FlagToBoolValue(p, cmd, flagWithWaf), + } + p.DebugInputModel(model) + return model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *cdn.APIClient) cdn.ApiGetDistributionRequest { + return apiClient.GetDistribution(ctx, model.ProjectId, model.DistributionID).WithWafStatus(model.WithWAF) +} + +func outputResult(p *print.Printer, outputFormat string, distribution *cdn.GetDistributionResponse) error { + if distribution == nil { + return fmt.Errorf("distribution response is empty") + } + return p.OutputResult(outputFormat, distribution, func() error { + d := distribution.Distribution + var content []tables.Table + + content = append(content, buildDistributionTable(d)) + + if d.Waf != nil { + content = append(content, buildWAFTable(d)) + } + + err := tables.DisplayTables(p, content) + if err != nil { + return fmt.Errorf("display table: %w", err) + } + return nil + }) +} + +func buildDistributionTable(d *cdn.Distribution) tables.Table { + regions := strings.Join(sdkUtils.EnumSliceToStringSlice(*d.Config.Regions), ", ") + defaultCacheDuration := "" + if d.Config.DefaultCacheDuration != nil && d.Config.DefaultCacheDuration.IsSet() { + defaultCacheDuration = *d.Config.DefaultCacheDuration.Get() + } + logSinkPushUrl := "" + if d.Config.LogSink != nil && d.Config.LogSink.LokiLogSink != nil { + logSinkPushUrl = *d.Config.LogSink.LokiLogSink.PushUrl + } + monthlyLimitBytes := "" + if d.Config.MonthlyLimitBytes != nil { + monthlyLimitBytes = fmt.Sprintf("%d", *d.Config.MonthlyLimitBytes) + } + optimizerEnabled := "" + if d.Config.Optimizer != nil { + optimizerEnabled = fmt.Sprintf("%t", *d.Config.Optimizer.Enabled) + } + table := tables.NewTable() + table.SetTitle("Distribution") + table.AddRow("ID", utils.PtrString(d.Id)) + table.AddSeparator() + table.AddRow("STATUS", utils.PtrString(d.Status)) + table.AddSeparator() + table.AddRow("REGIONS", regions) + table.AddSeparator() + table.AddRow("CREATED AT", utils.PtrString(d.CreatedAt)) + table.AddSeparator() + table.AddRow("UPDATED AT", utils.PtrString(d.UpdatedAt)) + table.AddSeparator() + table.AddRow("PROJECT ID", utils.PtrString(d.ProjectId)) + table.AddSeparator() + if d.Errors != nil && len(*d.Errors) > 0 { + var errorDescriptions []string + for _, err := range *d.Errors { + errorDescriptions = append(errorDescriptions, *err.En) + } + table.AddRow("ERRORS", strings.Join(errorDescriptions, "\n")) + table.AddSeparator() + } + if d.Config.Backend.BucketBackend != nil { + b := d.Config.Backend.BucketBackend + table.AddRow("BACKEND TYPE", "BUCKET") + table.AddSeparator() + table.AddRow("BUCKET URL", utils.PtrString(b.BucketUrl)) + table.AddSeparator() + table.AddRow("BUCKET REGION", utils.PtrString(b.Region)) + table.AddSeparator() + } else if d.Config.Backend.HttpBackend != nil { + h := d.Config.Backend.HttpBackend + var geofencing []string + if h.Geofencing != nil { + for k, v := range *h.Geofencing { + geofencing = append(geofencing, fmt.Sprintf("%s: %s", k, strings.Join(v, ", "))) + } + } + slices.Sort(geofencing) + table.AddRow("BACKEND TYPE", "HTTP") + table.AddSeparator() + table.AddRow("HTTP ORIGIN URL", utils.PtrString(h.OriginUrl)) + table.AddSeparator() + if h.OriginRequestHeaders != nil { + table.AddRow("HTTP ORIGIN REQUEST HEADERS", utils.JoinStringMap(*h.OriginRequestHeaders, ": ", ", ")) + table.AddSeparator() + } + table.AddRow("HTTP GEOFENCING PROPERTIES", strings.Join(geofencing, "\n")) + table.AddSeparator() + } + table.AddRow("BLOCKED COUNTRIES", strings.Join(*d.Config.BlockedCountries, ", ")) + table.AddSeparator() + table.AddRow("BLOCKED IPS", strings.Join(*d.Config.BlockedIps, ", ")) + table.AddSeparator() + table.AddRow("DEFAULT CACHE DURATION", defaultCacheDuration) + table.AddSeparator() + table.AddRow("LOG SINK PUSH URL", logSinkPushUrl) + table.AddSeparator() + table.AddRow("MONTHLY LIMIT (BYTES)", monthlyLimitBytes) + table.AddSeparator() + table.AddRow("OPTIMIZER ENABLED", optimizerEnabled) + table.AddSeparator() + return table +} + +func buildWAFTable(d *cdn.Distribution) tables.Table { + table := tables.NewTable() + table.SetTitle("WAF") + for _, disabled := range *d.Waf.DisabledRules { + table.AddRow("DISABLED RULE ID", utils.PtrString(disabled.Id)) + table.AddSeparator() + } + for _, enabled := range *d.Waf.EnabledRules { + table.AddRow("ENABLED RULE ID", utils.PtrString(enabled.Id)) + table.AddSeparator() + } + for _, logOnly := range *d.Waf.LogOnlyRules { + table.AddRow("LOG-ONLY RULE ID", utils.PtrString(logOnly.Id)) + table.AddSeparator() + } + return table +} diff --git a/internal/cmd/beta/cdn/distribution/describe/describe_test.go b/internal/cmd/beta/cdn/distribution/describe/describe_test.go new file mode 100644 index 000000000..78037f8d1 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/describe/describe_test.go @@ -0,0 +1,409 @@ +package describe + +import ( + "bytes" + "context" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +type testCtxKey struct{} + +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "test") + testProjectID = uuid.NewString() + testDistributionID = uuid.NewString() + testClient = &cdn.APIClient{} + testTime = time.Time{} +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectID, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectID, + Verbosity: globalflags.VerbosityDefault, + }, + DistributionID: testDistributionID, + WithWAF: false, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureResponse(mods ...func(resp *cdn.GetDistributionResponse)) *cdn.GetDistributionResponse { + response := &cdn.GetDistributionResponse{ + Distribution: &cdn.Distribution{ + Config: &cdn.Config{ + Backend: &cdn.ConfigBackend{ + BucketBackend: &cdn.BucketBackend{ + BucketUrl: utils.Ptr("https://example.com"), + Region: utils.Ptr("eu"), + Type: utils.Ptr("bucket"), + }, + }, + BlockedCountries: utils.Ptr([]string{}), + BlockedIps: utils.Ptr([]string{}), + DefaultCacheDuration: nil, + LogSink: nil, + MonthlyLimitBytes: nil, + Optimizer: nil, + Regions: &[]cdn.Region{cdn.REGION_EU}, + Waf: nil, + }, + CreatedAt: utils.Ptr(testTime), + Domains: &[]cdn.Domain{}, + Errors: nil, + Id: utils.Ptr(testDistributionID), + ProjectId: utils.Ptr(testProjectID), + Status: utils.Ptr(cdn.DISTRIBUTIONSTATUS_ACTIVE), + UpdatedAt: utils.Ptr(testTime), + Waf: nil, + }, + } + for _, mod := range mods { + mod(response) + } + return response +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + args []string + flags map[string]string + isValid bool + expected *inputModel + }{ + { + description: "base", + args: []string{testDistributionID}, + flags: fixtureFlagValues(), + isValid: true, + expected: fixtureInputModel(), + }, + { + description: "no args", + args: []string{}, + flags: fixtureFlagValues(), + isValid: false, + }, + { + description: "invalid distribution id", + args: []string{"invalid-uuid"}, + flags: fixtureFlagValues(), + isValid: false, + }, + { + description: "missing project id", + args: []string{testDistributionID}, + flags: map[string]string{}, + isValid: false, + }, + { + description: "invalid project id", + args: []string{testDistributionID}, + flags: map[string]string{ + globalflags.ProjectIdFlag: "invalid-uuid", + }, + isValid: false, + }, + { + description: "with WAF", + args: []string{testDistributionID}, + flags: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[flagWithWaf] = "true" + }), + isValid: true, + expected: fixtureInputModel(func(model *inputModel) { + model.WithWAF = true + }), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expected, tt.args, tt.flags, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expected cdn.ApiGetDistributionRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expected: testClient.GetDistribution(testCtx, testProjectID, testDistributionID).WithWafStatus(false), + }, + { + description: "with WAF", + model: fixtureInputModel(func(model *inputModel) { + model.WithWAF = true + }), + expected: testClient.GetDistribution(testCtx, testProjectID, testDistributionID).WithWafStatus(true), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + got := buildRequest(testCtx, tt.model, testClient) + diff := cmp.Diff(got, tt.expected, + cmp.AllowUnexported(tt.expected), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + format string + distribution *cdn.GetDistributionResponse + wantErr bool + expected string + }{ + { + description: "empty", + format: "table", + wantErr: true, + }, + { + description: "no errors", + format: "table", + distribution: fixtureResponse(), + //nolint:staticcheck //you can't use escape sequences in ``-string-literals + expected: fmt.Sprintf(` + Distribution  + ID │ %-37s +────────────────────────┼────────────────────────────────────── + STATUS │ ACTIVE +────────────────────────┼────────────────────────────────────── + REGIONS │ EU +────────────────────────┼────────────────────────────────────── + CREATED AT │ %-37s +────────────────────────┼────────────────────────────────────── + UPDATED AT │ %-37s +────────────────────────┼────────────────────────────────────── + PROJECT ID │ %-37s +────────────────────────┼────────────────────────────────────── + BACKEND TYPE │ BUCKET +────────────────────────┼────────────────────────────────────── + BUCKET URL │ https://example.com +────────────────────────┼────────────────────────────────────── + BUCKET REGION │ eu +────────────────────────┼────────────────────────────────────── + BLOCKED COUNTRIES │ +────────────────────────┼────────────────────────────────────── + BLOCKED IPS │ +────────────────────────┼────────────────────────────────────── + DEFAULT CACHE DURATION │ +────────────────────────┼────────────────────────────────────── + LOG SINK PUSH URL │ +────────────────────────┼────────────────────────────────────── + MONTHLY LIMIT (BYTES) │ +────────────────────────┼────────────────────────────────────── + OPTIMIZER ENABLED │ + +`, + testDistributionID, + testTime, + testTime, + testProjectID), + }, + { + description: "with errors", + format: "table", + distribution: fixtureResponse( + func(r *cdn.GetDistributionResponse) { + r.Distribution.Errors = &[]cdn.StatusError{ + { + En: utils.Ptr("First error message"), + }, + { + En: utils.Ptr("Second error message"), + }, + } + }, + ), + //nolint:staticcheck //you can't use escape sequences in ``-string-literals + expected: fmt.Sprintf(` + Distribution  + ID │ %-37s +────────────────────────┼────────────────────────────────────── + STATUS │ ACTIVE +────────────────────────┼────────────────────────────────────── + REGIONS │ EU +────────────────────────┼────────────────────────────────────── + CREATED AT │ %-37s +────────────────────────┼────────────────────────────────────── + UPDATED AT │ %-37s +────────────────────────┼────────────────────────────────────── + PROJECT ID │ %-37s +────────────────────────┼────────────────────────────────────── + ERRORS │ First error message + │ Second error message +────────────────────────┼────────────────────────────────────── + BACKEND TYPE │ BUCKET +────────────────────────┼────────────────────────────────────── + BUCKET URL │ https://example.com +────────────────────────┼────────────────────────────────────── + BUCKET REGION │ eu +────────────────────────┼────────────────────────────────────── + BLOCKED COUNTRIES │ +────────────────────────┼────────────────────────────────────── + BLOCKED IPS │ +────────────────────────┼────────────────────────────────────── + DEFAULT CACHE DURATION │ +────────────────────────┼────────────────────────────────────── + LOG SINK PUSH URL │ +────────────────────────┼────────────────────────────────────── + MONTHLY LIMIT (BYTES) │ +────────────────────────┼────────────────────────────────────── + OPTIMIZER ENABLED │ + +`, testDistributionID, + testTime, + testTime, + testProjectID), + }, + { + description: "full", + format: "table", + distribution: fixtureResponse( + func(r *cdn.GetDistributionResponse) { + r.Distribution.Waf = &cdn.DistributionWaf{ + EnabledRules: &[]cdn.WafStatusRuleBlock{ + {Id: utils.Ptr("rule-id-1")}, + {Id: utils.Ptr("rule-id-2")}, + }, + DisabledRules: &[]cdn.WafStatusRuleBlock{ + {Id: utils.Ptr("rule-id-3")}, + {Id: utils.Ptr("rule-id-4")}, + }, + LogOnlyRules: &[]cdn.WafStatusRuleBlock{ + {Id: utils.Ptr("rule-id-5")}, + {Id: utils.Ptr("rule-id-6")}, + }, + } + r.Distribution.Config.Backend = &cdn.ConfigBackend{ + HttpBackend: &cdn.HttpBackend{ + OriginUrl: utils.Ptr("https://origin.example.com"), + OriginRequestHeaders: &map[string]string{ + "X-Custom-Header": "CustomValue", + }, + Geofencing: &map[string][]string{ + "origin1.example.com": {"US", "CA"}, + "origin2.example.com": {"FR", "DE"}, + }, + }, + } + r.Distribution.Config.BlockedCountries = &[]string{"US", "CN"} + r.Distribution.Config.BlockedIps = &[]string{"127.0.0.1"} + r.Distribution.Config.DefaultCacheDuration = cdn.NewNullableString(utils.Ptr("P1DT2H30M")) + r.Distribution.Config.LogSink = &cdn.ConfigLogSink{ + LokiLogSink: &cdn.LokiLogSink{ + PushUrl: utils.Ptr("https://logs.example.com"), + }, + } + r.Distribution.Config.MonthlyLimitBytes = utils.Ptr(int64(104857600)) + r.Distribution.Config.Optimizer = &cdn.Optimizer{ + Enabled: utils.Ptr(true), + } + }), + //nolint:staticcheck //you can't use escape sequences in ``-string-literals + expected: fmt.Sprintf(` + Distribution  + ID │ %-37s +─────────────────────────────┼────────────────────────────────────── + STATUS │ ACTIVE +─────────────────────────────┼────────────────────────────────────── + REGIONS │ EU +─────────────────────────────┼────────────────────────────────────── + CREATED AT │ %-37s +─────────────────────────────┼────────────────────────────────────── + UPDATED AT │ %-37s +─────────────────────────────┼────────────────────────────────────── + PROJECT ID │ %-37s +─────────────────────────────┼────────────────────────────────────── + BACKEND TYPE │ HTTP +─────────────────────────────┼────────────────────────────────────── + HTTP ORIGIN URL │ https://origin.example.com +─────────────────────────────┼────────────────────────────────────── + HTTP ORIGIN REQUEST HEADERS │ X-Custom-Header: CustomValue +─────────────────────────────┼────────────────────────────────────── + HTTP GEOFENCING PROPERTIES │ origin1.example.com: US, CA + │ origin2.example.com: FR, DE +─────────────────────────────┼────────────────────────────────────── + BLOCKED COUNTRIES │ US, CN +─────────────────────────────┼────────────────────────────────────── + BLOCKED IPS │ 127.0.0.1 +─────────────────────────────┼────────────────────────────────────── + DEFAULT CACHE DURATION │ P1DT2H30M +─────────────────────────────┼────────────────────────────────────── + LOG SINK PUSH URL │ https://logs.example.com +─────────────────────────────┼────────────────────────────────────── + MONTHLY LIMIT (BYTES) │ 104857600 +─────────────────────────────┼────────────────────────────────────── + OPTIMIZER ENABLED │ true + + + WAF  + DISABLED RULE ID │ rule-id-3 +──────────────────┼─────────── + DISABLED RULE ID │ rule-id-4 +──────────────────┼─────────── + ENABLED RULE ID │ rule-id-1 +──────────────────┼─────────── + ENABLED RULE ID │ rule-id-2 +──────────────────┼─────────── + LOG-ONLY RULE ID │ rule-id-5 +──────────────────┼─────────── + LOG-ONLY RULE ID │ rule-id-6 + +`, testDistributionID, testTime, testTime, testProjectID), + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + var buf bytes.Buffer + p.Cmd.SetOut(&buf) + if err := outputResult(p, tt.format, tt.distribution); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + diff := cmp.Diff(buf.String(), tt.expected) + if diff != "" { + t.Fatalf("outputResult() output mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/internal/cmd/beta/cdn/distribution/distribution.go b/internal/cmd/beta/cdn/distribution/distribution.go new file mode 100644 index 000000000..defb471c2 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/distribution.go @@ -0,0 +1,32 @@ +package distribution + +import ( + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn/distribution/create" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn/distribution/delete" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn/distribution/describe" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn/distribution/list" + "github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn/distribution/update" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" +) + +func NewCommand(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "distribution", + Short: "Manage CDN distributions", + Long: "Manage the lifecycle of CDN distributions.", + Args: cobra.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd, params) + return cmd +} + +func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { + cmd.AddCommand(list.NewCmd(params)) + cmd.AddCommand(describe.NewCmd(params)) + cmd.AddCommand(create.NewCmd(params)) + cmd.AddCommand(update.NewCmd(params)) + cmd.AddCommand(delete.NewCmd(params)) +} diff --git a/internal/cmd/beta/cdn/distribution/list/list.go b/internal/cmd/beta/cdn/distribution/list/list.go new file mode 100644 index 000000000..aae2b0db0 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/list/list.go @@ -0,0 +1,175 @@ +package list + +import ( + "context" + "fmt" + "math" + "strings" + + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/cdn/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + SortBy string + Limit *int32 +} + +const ( + sortByFlag = "sort-by" + limitFlag = "" + maxPageSize = int32(100) +) + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List CDN distributions", + Long: "List all CDN distributions in your account.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all CDN distributions`, + `$ stackit beta cdn distribution list`, + ), + examples.NewExample( + `List all CDN distributions sorted by id`, + `$ stackit beta cdn distribution list --sort-by=id`, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + + model, err := parseInput(params.Printer, cmd, args) + if err != nil { + return err + } + + apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) + if err != nil { + return err + } + + distributions, err := fetchDistributions(ctx, model, apiClient) + if err != nil { + return fmt.Errorf("fetch distributions: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, distributions) + }, + } + + configureFlags(cmd) + return cmd +} + +var sortByFlagOptions = []string{"id", "createdAt", "updatedAt", "originUrl", "status", "originUrlRelated"} + +func configureFlags(cmd *cobra.Command) { + // same default as apiClient + cmd.Flags().Var(flags.EnumFlag(false, "createdAt", sortByFlagOptions...), sortByFlag, fmt.Sprintf("Sort entries by a specific field, one of %q", sortByFlagOptions)) + cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements") +} + +func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt32Pointer(p, cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + SortBy: flags.FlagWithDefaultToStringValue(p, cmd, sortByFlag), + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *cdn.APIClient, nextPageID cdn.ListDistributionsResponseGetNextPageIdentifierAttributeType, pageLimit int32) cdn.ApiListDistributionsRequest { + req := apiClient.ListDistributions(ctx, model.ProjectId) + req = req.SortBy(model.SortBy) + req = req.PageSize(pageLimit) + if nextPageID != nil { + req = req.PageIdentifier(*nextPageID) + } + return req +} + +func outputResult(p *print.Printer, outputFormat string, distributions []cdn.Distribution) error { + if distributions == nil { + distributions = make([]cdn.Distribution, 0) // otherwise prints null in json output + } + return p.OutputResult(outputFormat, distributions, func() error { + if len(distributions) == 0 { + p.Outputln("No CDN distributions found") + return nil + } + + table := tables.NewTable() + table.SetHeader("ID", "REGIONS", "STATUS") + for _, d := range distributions { + var joinedRegions string + if d.Config != nil && d.Config.Regions != nil { + joinedRegions = strings.Join(sdkUtils.EnumSliceToStringSlice(*d.Config.Regions), ", ") + } + table.AddRow( + utils.PtrString(d.Id), + joinedRegions, + utils.PtrString(d.Status), + ) + } + err := table.Display(p) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + return nil + }) +} + +func fetchDistributions(ctx context.Context, model *inputModel, apiClient *cdn.APIClient) ([]cdn.Distribution, error) { + var nextPageID cdn.ListDistributionsResponseGetNextPageIdentifierAttributeType + var distributions []cdn.Distribution + received := int32(0) + limit := int32(math.MaxInt32) + if model.Limit != nil { + limit = min(limit, *model.Limit) + } + for { + want := min(maxPageSize, limit-received) + request := buildRequest(ctx, model, apiClient, nextPageID, want) + response, err := request.Execute() + if err != nil { + return nil, fmt.Errorf("list distributions: %w", err) + } + if response.Distributions != nil { + distributions = append(distributions, *response.Distributions...) + } + nextPageID = response.NextPageIdentifier + received += want + if nextPageID == nil || received >= limit { + break + } + } + return distributions, nil +} diff --git a/internal/cmd/beta/cdn/distribution/list/list_test.go b/internal/cmd/beta/cdn/distribution/list/list_test.go new file mode 100644 index 000000000..8e5d71aa9 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/list/list_test.go @@ -0,0 +1,471 @@ +package list + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "slices" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +type testCtxKey struct{} + +var testProjectId = uuid.NewString() +var testClient = &cdn.APIClient{} +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + +const ( + testNextPageID = "next-page-id-123" + testID = "dist-1" + testStatus = cdn.DISTRIBUTIONSTATUS_ACTIVE +) + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, mod := range mods { + mod(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + m := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + ProjectId: testProjectId, + Verbosity: globalflags.VerbosityDefault, + }, + SortBy: "createdAt", + } + for _, mod := range mods { + mod(m) + } + return m +} + +func fixtureRequest(mods ...func(request cdn.ApiListDistributionsRequest) cdn.ApiListDistributionsRequest) cdn.ApiListDistributionsRequest { + request := testClient.ListDistributions(testCtx, testProjectId) + request = request.PageSize(100) + request = request.SortBy("createdAt") + for _, mod := range mods { + request = mod(request) + } + return request +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expected *inputModel + }{ + { + description: "base", + flagValues: fixtureFlagValues(), + isValid: true, + expected: fixtureInputModel(), + }, + { + description: "no project id", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, globalflags.ProjectIdFlag) + }), + isValid: false, + }, + { + description: "sort by id", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sortByFlag] = "id" + }), + isValid: true, + expected: fixtureInputModel(func(model *inputModel) { + model.SortBy = "id" + }), + }, + { + description: "sort by origin-url", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sortByFlag] = "originUrl" + }), + isValid: true, + expected: fixtureInputModel(func(model *inputModel) { + model.SortBy = "originUrl" + }), + }, + { + description: "sort by status", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sortByFlag] = "status" + }), + isValid: true, + expected: fixtureInputModel(func(model *inputModel) { + model.SortBy = "status" + }), + }, + { + description: "sort by created", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sortByFlag] = "createdAt" + }), + isValid: true, + expected: fixtureInputModel(func(model *inputModel) { + model.SortBy = "createdAt" + }), + }, + { + description: "sort by updated", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sortByFlag] = "updatedAt" + }), + isValid: true, + expected: fixtureInputModel(func(model *inputModel) { + model.SortBy = "updatedAt" + }), + }, + { + description: "sort by originUrlRelated", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sortByFlag] = "originUrlRelated" + }), + isValid: true, + expected: fixtureInputModel(func(model *inputModel) { + model.SortBy = "originUrlRelated" + }), + }, + { + description: "invalid sort by", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + flagValues[sortByFlag] = "invalid" + }), + isValid: false, + }, + { + description: "missing sort by uses default", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + delete(flagValues, sortByFlag) + }, + ), + isValid: true, + expected: fixtureInputModel(func(model *inputModel) { + model.SortBy = "createdAt" + }), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expected, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + inputModel *inputModel + nextPageID *string + expected cdn.ApiListDistributionsRequest + }{ + { + description: "base", + inputModel: fixtureInputModel(), + expected: fixtureRequest(), + }, + { + description: "sort by updatedAt", + inputModel: fixtureInputModel(func(model *inputModel) { + model.SortBy = "updatedAt" + }), + expected: fixtureRequest(func(req cdn.ApiListDistributionsRequest) cdn.ApiListDistributionsRequest { + return req.SortBy("updatedAt") + }), + }, + { + description: "with next page id", + inputModel: fixtureInputModel(), + nextPageID: utils.Ptr(testNextPageID), + expected: fixtureRequest(func(req cdn.ApiListDistributionsRequest) cdn.ApiListDistributionsRequest { + return req.PageIdentifier(testNextPageID) + }), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + req := buildRequest(testCtx, tt.inputModel, testClient, tt.nextPageID, maxPageSize) + diff := cmp.Diff(req, tt.expected, + cmp.AllowUnexported(tt.expected), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Errorf("buildRequest() mismatch (-want +got):\n%s", diff) + } + }) + } +} + +type testResponse struct { + statusCode int + body cdn.ListDistributionsResponse +} + +func fixtureTestResponse(mods ...func(resp *testResponse)) testResponse { + resp := testResponse{ + statusCode: 200, + } + for _, mod := range mods { + mod(&resp) + } + return resp +} + +func fixtureDistributions(count int) []cdn.Distribution { + distributions := make([]cdn.Distribution, count) + for i := 0; i < count; i++ { + id := fmt.Sprintf("dist-%d", i+1) + distributions[i] = cdn.Distribution{ + Id: &id, + } + } + return distributions +} + +func TestFetchDistributions(t *testing.T) { + tests := []struct { + description string + limit int32 + responses []testResponse + expected []cdn.Distribution + fails bool + }{ + { + description: "no distributions", + responses: []testResponse{ + fixtureTestResponse(), + }, + expected: nil, + }, + { + description: "single distribution, single page", + responses: []testResponse{ + fixtureTestResponse( + func(resp *testResponse) { + resp.body.Distributions = &[]cdn.Distribution{ + {Id: utils.Ptr("dist-1")}, + } + }, + ), + }, + expected: []cdn.Distribution{ + {Id: utils.Ptr("dist-1")}, + }, + }, + { + description: "multiple distributions, multiple pages", + responses: []testResponse{ + fixtureTestResponse( + func(resp *testResponse) { + resp.body.NextPageIdentifier = utils.Ptr(testNextPageID) + resp.body.Distributions = &[]cdn.Distribution{ + {Id: utils.Ptr("dist-1")}, + } + }, + ), + fixtureTestResponse( + func(resp *testResponse) { + resp.body.Distributions = &[]cdn.Distribution{ + {Id: utils.Ptr("dist-2")}, + } + }, + ), + }, + expected: []cdn.Distribution{ + {Id: utils.Ptr("dist-1")}, + {Id: utils.Ptr("dist-2")}, + }, + }, + { + description: "API error", + responses: []testResponse{ + fixtureTestResponse( + func(resp *testResponse) { + resp.statusCode = 500 + }, + ), + }, + fails: true, + }, + { + description: "API error on second page", + responses: []testResponse{ + fixtureTestResponse( + func(resp *testResponse) { + resp.body.NextPageIdentifier = utils.Ptr(testNextPageID) + resp.body.Distributions = &[]cdn.Distribution{ + {Id: utils.Ptr("dist-1")}, + } + }, + ), + fixtureTestResponse( + func(resp *testResponse) { + resp.statusCode = 500 + }, + ), + }, + fails: true, + }, + { + description: "limit across 2 pages", + limit: 110, + responses: []testResponse{ + fixtureTestResponse( + func(resp *testResponse) { + resp.body.NextPageIdentifier = utils.Ptr(testNextPageID) + distributions := fixtureDistributions(100) + resp.body.Distributions = &distributions + }, + ), + fixtureTestResponse( + func(resp *testResponse) { + distributions := fixtureDistributions(10) + resp.body.Distributions = &distributions + }, + ), + }, + expected: slices.Concat(fixtureDistributions(100), fixtureDistributions(10)), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + callCount := 0 + handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + resp := tt.responses[callCount] + callCount++ + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(resp.statusCode) + bs, err := json.Marshal(resp.body) + if err != nil { + t.Fatalf("marshal: %v", err) + } + _, err = w.Write(bs) + if err != nil { + t.Fatalf("write: %v", err) + } + }) + server := httptest.NewServer(handler) + defer server.Close() + client, err := cdn.NewAPIClient( + sdkConfig.WithEndpoint(server.URL), + sdkConfig.WithoutAuthentication(), + ) + if err != nil { + t.Fatalf("failed to create test client: %v", err) + } + var mods []func(m *inputModel) + if tt.limit > 0 { + mods = append(mods, func(m *inputModel) { + m.Limit = utils.Ptr(tt.limit) + }) + } + model := fixtureInputModel(mods...) + got, err := fetchDistributions(testCtx, model, client) + if err != nil { + if !tt.fails { + t.Fatalf("fetchDistributions() unexpected error: %v", err) + } + return + } + if callCount != len(tt.responses) { + t.Errorf("fetchDistributions() expected %d calls, got %d", len(tt.responses), callCount) + } + diff := cmp.Diff(got, tt.expected) + if diff != "" { + t.Errorf("fetchDistributions() mismatch (-want +got):\n%s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + outputFormat string + distributions []cdn.Distribution + expected string + }{ + { + description: "no distributions", + outputFormat: "json", + distributions: []cdn.Distribution{}, + expected: `[] + +`, + }, + { + description: "no distributions nil slice", + outputFormat: "json", + expected: `[] + +`, + }, + { + description: "single distribution", + outputFormat: "table", + distributions: []cdn.Distribution{ + { + Id: utils.Ptr(testID), + Config: &cdn.Config{ + Regions: &[]cdn.Region{ + cdn.REGION_EU, + cdn.REGION_AF, + }, + }, + Status: utils.Ptr(testStatus), + }, + }, + expected: ` + ID │ REGIONS │ STATUS +────────┼─────────┼──────── + dist-1 │ EU, AF │ ACTIVE + +`, + }, + { + description: "no distributions, table format", + outputFormat: "table", + expected: "No CDN distributions found\n", + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + buffer := &bytes.Buffer{} + p.Cmd.SetOut(buffer) + if err := outputResult(p, tt.outputFormat, tt.distributions); err != nil { + t.Fatalf("outputResult: %v", err) + } + if buffer.String() != tt.expected { + t.Errorf("want:\n%s\ngot:\n%s", tt.expected, buffer.String()) + } + }) + } +} diff --git a/internal/cmd/beta/cdn/distribution/update/update.go b/internal/cmd/beta/cdn/distribution/update/update.go new file mode 100644 index 000000000..07fa3022a --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/update/update.go @@ -0,0 +1,337 @@ +package update + +import ( + "context" + "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" + "github.com/stackitcloud/stackit-cli/internal/pkg/flags" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/cdn/client" + cdnUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/cdn/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +const ( + argDistributionID = "DISTRIBUTION_ID" + flagRegions = "regions" + flagHTTP = "http" + flagHTTPOriginURL = "http-origin-url" + flagHTTPGeofencing = "http-geofencing" + flagHTTPOriginRequestHeaders = "http-origin-request-headers" + flagBucket = "bucket" + flagBucketURL = "bucket-url" + flagBucketCredentialsAccessKeyID = "bucket-credentials-access-key-id" //nolint:gosec // linter false positive + flagBucketRegion = "bucket-region" + flagBlockedCountries = "blocked-countries" + flagBlockedIPs = "blocked-ips" + flagDefaultCacheDuration = "default-cache-duration" + flagLoki = "loki" + flagLokiUsername = "loki-username" + flagLokiPushURL = "loki-push-url" + flagMonthlyLimitBytes = "monthly-limit-bytes" + flagOptimizer = "optimizer" +) + +type bucketInputModel struct { + URL string + AccessKeyID string + Password string + Region string +} + +type httpInputModel struct { + Geofencing *map[string][]string + OriginRequestHeaders *map[string]string + OriginURL string +} + +type lokiInputModel struct { + Password string + Username string + PushURL string +} + +type inputModel struct { + *globalflags.GlobalFlagModel + DistributionID string + Regions []cdn.Region + Bucket *bucketInputModel + HTTP *httpInputModel + BlockedCountries []string + BlockedIPs []string + DefaultCacheDuration string + MonthlyLimitBytes *int64 + Loki *lokiInputModel + Optimizer *bool +} + +func NewCmd(params *types.CmdParams) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Update a CDN distribution", + Long: "Update a CDN distribution by its ID, allowing replacement of its regions.", + Args: args.SingleArg(argDistributionID, utils.ValidateUUID), + Example: examples.Build( + examples.NewExample( + `update a CDN distribution with ID "123e4567-e89b-12d3-a456-426614174000" to not use optimizer`, + `$ stackit beta cdn update 123e4567-e89b-12d3-a456-426614174000 --optimizer=false`, + ), + ), + RunE: func(cmd *cobra.Command, inputArgs []string) error { + ctx := context.Background() + model, err := parseInput(params.Printer, cmd, inputArgs) + if err != nil { + return err + } + if model.Bucket != nil { + pw, err := params.Printer.PromptForPassword("enter your secret access key for the object storage bucket: ") + if err != nil { + return fmt.Errorf("reading secret access key: %w", err) + } + model.Bucket.Password = pw + } + if model.Loki != nil { + pw, err := params.Printer.PromptForPassword("enter your password for the loki log sink: ") + if err != nil { + return fmt.Errorf("reading loki password: %w", err) + } + model.Loki.Password = pw + } + + 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 + } + + prompt := fmt.Sprintf("Are you sure you want to update a CDN distribution for project %q?", projectLabel) + err = params.Printer.PromptForConfirmation(prompt) + if err != nil { + return err + } + + req := buildRequest(ctx, apiClient, model) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("update CDN distribution: %w", err) + } + + return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.EnumSliceFlag(false, []string{}, sdkUtils.EnumSliceToStringSlice(cdn.AllowedRegionEnumValues)...), flagRegions, fmt.Sprintf("Regions in which content should be cached, multiple of: %q", cdn.AllowedRegionEnumValues)) + cmd.Flags().Bool(flagHTTP, false, "Use HTTP backend") + cmd.Flags().String(flagHTTPOriginURL, "", "Origin URL for HTTP backend") + cmd.Flags().StringSlice(flagHTTPOriginRequestHeaders, []string{}, "Origin request headers for HTTP backend in the format 'HeaderName: HeaderValue', repeatable. WARNING: do not store sensitive values in the headers!") + cmd.Flags().StringArray(flagHTTPGeofencing, []string{}, "Geofencing rules for HTTP backend in the format 'https://example.com US,DE'. URL and countries have to be quoted. Repeatable.") + cmd.Flags().Bool(flagBucket, false, "Use Object Storage backend") + cmd.Flags().String(flagBucketURL, "", "Bucket URL for Object Storage backend") + cmd.Flags().String(flagBucketCredentialsAccessKeyID, "", "Access Key ID for Object Storage backend") + cmd.Flags().String(flagBucketRegion, "", "Region for Object Storage backend") + cmd.Flags().StringSlice(flagBlockedCountries, []string{}, "Comma-separated list of ISO 3166-1 alpha-2 country codes to block (e.g., 'US,DE,FR')") + cmd.Flags().StringSlice(flagBlockedIPs, []string{}, "Comma-separated list of IPv4 addresses to block (e.g., '10.0.0.8,127.0.0.1')") + cmd.Flags().String(flagDefaultCacheDuration, "", "ISO8601 duration string for default cache duration (e.g., 'PT1H30M' for 1 hour and 30 minutes)") + cmd.Flags().Bool(flagLoki, false, "Enable Loki log sink for the CDN distribution") + cmd.Flags().String(flagLokiUsername, "", "Username for log sink") + cmd.Flags().String(flagLokiPushURL, "", "Push URL for log sink") + cmd.Flags().Int64(flagMonthlyLimitBytes, 0, "Monthly limit in bytes for the CDN distribution") + cmd.Flags().Bool(flagOptimizer, false, "Enable optimizer for the CDN distribution (paid feature).") + cmd.MarkFlagsMutuallyExclusive(flagHTTP, flagBucket) +} + +func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + globalFlags := globalflags.Parse(p, cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + distributionID := inputArgs[0] + + regionStrings := flags.FlagToStringSliceValue(p, cmd, flagRegions) + regions := make([]cdn.Region, 0, len(regionStrings)) + for _, regionStr := range regionStrings { + regions = append(regions, cdn.Region(regionStr)) + } + + var http *httpInputModel + if flags.FlagToBoolValue(p, cmd, flagHTTP) { + originURL := flags.FlagToStringValue(p, cmd, flagHTTPOriginURL) + + var geofencing *map[string][]string + geofencingInput := flags.FlagToStringArrayValue(p, cmd, flagHTTPGeofencing) + if geofencingInput != nil { + geofencing = cdnUtils.ParseGeofencing(p, geofencingInput) + } + + var originRequestHeaders *map[string]string + originRequestHeadersInput := flags.FlagToStringSliceValue(p, cmd, flagHTTPOriginRequestHeaders) + if originRequestHeadersInput != nil { + originRequestHeaders = cdnUtils.ParseOriginRequestHeaders(p, originRequestHeadersInput) + } + + http = &httpInputModel{ + OriginURL: originURL, + Geofencing: geofencing, + OriginRequestHeaders: originRequestHeaders, + } + } + + var bucket *bucketInputModel + if flags.FlagToBoolValue(p, cmd, flagBucket) { + bucketURL := flags.FlagToStringValue(p, cmd, flagBucketURL) + accessKeyID := flags.FlagToStringValue(p, cmd, flagBucketCredentialsAccessKeyID) + region := flags.FlagToStringValue(p, cmd, flagBucketRegion) + + bucket = &bucketInputModel{ + URL: bucketURL, + AccessKeyID: accessKeyID, + Password: "", + Region: region, + } + } + + blockedCountries := flags.FlagToStringSliceValue(p, cmd, flagBlockedCountries) + blockedIPs := flags.FlagToStringSliceValue(p, cmd, flagBlockedIPs) + cacheDuration := flags.FlagToStringValue(p, cmd, flagDefaultCacheDuration) + monthlyLimit := flags.FlagToInt64Pointer(p, cmd, flagMonthlyLimitBytes) + + var loki *lokiInputModel + if flags.FlagToBoolValue(p, cmd, flagLoki) { + loki = &lokiInputModel{ + Username: flags.FlagToStringValue(p, cmd, flagLokiUsername), + PushURL: flags.FlagToStringValue(p, cmd, flagLokiPushURL), + Password: "", + } + } + + var optimizer *bool + if cmd.Flags().Changed(flagOptimizer) { + o := flags.FlagToBoolValue(p, cmd, flagOptimizer) + optimizer = &o + } + + model := inputModel{ + GlobalFlagModel: globalFlags, + DistributionID: distributionID, + Regions: regions, + HTTP: http, + Bucket: bucket, + BlockedCountries: blockedCountries, + BlockedIPs: blockedIPs, + DefaultCacheDuration: cacheDuration, + MonthlyLimitBytes: monthlyLimit, + Loki: loki, + Optimizer: optimizer, + } + + p.DebugInputModel(model) + return &model, nil +} + +func buildRequest(ctx context.Context, apiClient *cdn.APIClient, model *inputModel) cdn.ApiPatchDistributionRequest { + req := apiClient.PatchDistribution(ctx, model.ProjectId, model.DistributionID) + payload := cdn.NewPatchDistributionPayload() + cfg := &cdn.ConfigPatch{} + payload.Config = cfg + if len(model.Regions) > 0 { + cfg.Regions = &model.Regions + } + if model.Bucket != nil { + bucket := &cdn.BucketBackendPatch{ + Type: utils.Ptr("bucket"), + } + cfg.Backend = &cdn.ConfigPatchBackend{ + BucketBackendPatch: bucket, + } + if model.Bucket.URL != "" { + bucket.BucketUrl = utils.Ptr(model.Bucket.URL) + } + if model.Bucket.AccessKeyID != "" { + bucket.Credentials = cdn.NewBucketCredentials( + model.Bucket.AccessKeyID, + model.Bucket.Password, + ) + } + if model.Bucket.Region != "" { + bucket.Region = utils.Ptr(model.Bucket.Region) + } + } else if model.HTTP != nil { + http := &cdn.HttpBackendPatch{ + Type: utils.Ptr("http"), + } + cfg.Backend = &cdn.ConfigPatchBackend{ + HttpBackendPatch: http, + } + if model.HTTP.OriginRequestHeaders != nil { + http.OriginRequestHeaders = model.HTTP.OriginRequestHeaders + } + if model.HTTP.Geofencing != nil { + http.Geofencing = model.HTTP.Geofencing + } + if model.HTTP.OriginURL != "" { + http.OriginUrl = utils.Ptr(model.HTTP.OriginURL) + } + } + if len(model.BlockedCountries) > 0 { + cfg.BlockedCountries = &model.BlockedCountries + } + if len(model.BlockedIPs) > 0 { + cfg.BlockedIps = &model.BlockedIPs + } + if model.DefaultCacheDuration != "" { + cfg.DefaultCacheDuration = cdn.NewNullableString(&model.DefaultCacheDuration) + } + if model.MonthlyLimitBytes != nil && *model.MonthlyLimitBytes > 0 { + cfg.MonthlyLimitBytes = model.MonthlyLimitBytes + } + if model.Loki != nil { + loki := &cdn.LokiLogSinkPatch{} + cfg.LogSink = cdn.NewNullableConfigPatchLogSink(&cdn.ConfigPatchLogSink{ + LokiLogSinkPatch: loki, + }) + if model.Loki.PushURL != "" { + loki.PushUrl = utils.Ptr(model.Loki.PushURL) + } + if model.Loki.Username != "" { + loki.Credentials = cdn.NewLokiLogSinkCredentials( + model.Loki.Password, + model.Loki.Username, + ) + } + } + if model.Optimizer != nil { + cfg.Optimizer = &cdn.OptimizerPatch{ + Enabled: model.Optimizer, + } + } + req = req.PatchDistributionPayload(*payload) + return req +} + +func outputResult(p *print.Printer, outputFormat, projectLabel string, resp *cdn.PatchDistributionResponse) error { + if resp == nil { + return fmt.Errorf("update distribution response is empty") + } + return p.OutputResult(outputFormat, resp, func() error { + p.Outputf("Updated CDN distribution for %q. ID: %s\n", projectLabel, utils.PtrString(resp.Distribution.Id)) + return nil + }) +} diff --git a/internal/cmd/beta/cdn/distribution/update/update_test.go b/internal/cmd/beta/cdn/distribution/update/update_test.go new file mode 100644 index 000000000..bf3dd11f5 --- /dev/null +++ b/internal/cmd/beta/cdn/distribution/update/update_test.go @@ -0,0 +1,365 @@ +package update + +import ( + "bytes" + "context" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "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/types" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" + "k8s.io/utils/ptr" +) + +const testCacheDuration = "P1DT12H" + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &cdn.APIClient{} +var testProjectId = uuid.NewString() +var testDistributionID = uuid.NewString() + +const testMonthlyLimitBytes int64 = 1048576 + +func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { + flagValues := map[string]string{ + globalflags.ProjectIdFlag: testProjectId, + } + for _, m := range mods { + m(flagValues) + } + return flagValues +} + +func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { + model := &inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{ + Verbosity: globalflags.VerbosityDefault, + ProjectId: testProjectId, + }, + DistributionID: testDistributionID, + Regions: []cdn.Region{}, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(payload *cdn.PatchDistributionPayload)) cdn.ApiPatchDistributionRequest { + req := testClient.PatchDistribution(testCtx, testProjectId, testDistributionID) + if payload := fixturePayload(mods...); payload != nil { + req = req.PatchDistributionPayload(*fixturePayload(mods...)) + } + return req +} + +func fixturePayload(mods ...func(payload *cdn.PatchDistributionPayload)) *cdn.PatchDistributionPayload { + payload := cdn.NewPatchDistributionPayload() + payload.Config = &cdn.ConfigPatch{} + for _, m := range mods { + m(payload) + } + return payload +} + +func TestParseInput(t *testing.T) { + tests := []struct { + description string + argValues []string + flagValues map[string]string + isValid bool + expected *inputModel + }{ + { + description: "base", + argValues: []string{testDistributionID}, + flagValues: fixtureFlagValues(), + isValid: true, + expected: fixtureInputModel(), + }, + { + description: "distribution id missing", + argValues: []string{}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "invalid distribution id", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "project id missing", + argValues: []string{testDistributionID}, + flagValues: fixtureFlagValues(func(flagValues map[string]string) { delete(flagValues, globalflags.ProjectIdFlag) }), + isValid: false, + }, + { + description: "invalid distribution id", + argValues: []string{"invalid-uuid"}, + flagValues: fixtureFlagValues(), + isValid: false, + }, + { + description: "both backends", + argValues: []string{testDistributionID}, + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagHTTP] = "true" + flagValues[flagBucket] = "true" + }, + ), + isValid: false, + }, + { + description: "max config without backend", + argValues: []string{testDistributionID}, + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagRegions] = "EU,US" + flagValues[flagBlockedCountries] = "DE,AT,CH" + flagValues[flagBlockedIPs] = "127.0.0.1,10.0.0.8" + flagValues[flagDefaultCacheDuration] = "P1DT12H" + flagValues[flagLoki] = "true" + flagValues[flagLokiUsername] = "loki-user" + flagValues[flagLokiPushURL] = "https://loki.example.com" + flagValues[flagMonthlyLimitBytes] = fmt.Sprintf("%d", testMonthlyLimitBytes) + flagValues[flagOptimizer] = "true" + }, + ), + isValid: true, + expected: fixtureInputModel( + func(model *inputModel) { + model.Regions = []cdn.Region{cdn.REGION_EU, cdn.REGION_US} + model.BlockedCountries = []string{"DE", "AT", "CH"} + model.BlockedIPs = []string{"127.0.0.1", "10.0.0.8"} + model.DefaultCacheDuration = "P1DT12H" + model.Loki = &lokiInputModel{ + Username: "loki-user", + PushURL: "https://loki.example.com", + } + model.MonthlyLimitBytes = utils.Ptr(testMonthlyLimitBytes) + model.Optimizer = utils.Ptr(true) + }, + ), + }, + { + description: "max config http backend", + argValues: []string{testDistributionID}, + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagHTTP] = "true" + flagValues[flagHTTPOriginURL] = "https://origin.example.com" + flagValues[flagHTTPOriginRequestHeaders] = "X-Example-Header: example-value, X-Another-Header: another-value" + flagValues[flagHTTPGeofencing] = "https://dach.example.com DE,AT,CH" + }, + ), + isValid: true, + expected: fixtureInputModel( + func(model *inputModel) { + model.HTTP = &httpInputModel{ + OriginURL: "https://origin.example.com", + OriginRequestHeaders: &map[string]string{ + "X-Example-Header": "example-value", + "X-Another-Header": "another-value", + }, + Geofencing: &map[string][]string{ + "https://dach.example.com": {"DE", "AT", "CH"}, + }, + } + }, + ), + }, + { + description: "max config bucket backend", + argValues: []string{testDistributionID}, + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues[flagBucket] = "true" + flagValues[flagBucketURL] = "https://bucket.example.com" + flagValues[flagBucketRegion] = "EU" + flagValues[flagBucketCredentialsAccessKeyID] = "access-key-id" + }, + ), + isValid: true, + expected: fixtureInputModel( + func(model *inputModel) { + model.Bucket = &bucketInputModel{ + URL: "https://bucket.example.com", + Region: "EU", + AccessKeyID: "access-key-id", + } + }, + ), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + testutils.TestParseInput(t, NewCmd, parseInput, tt.expected, tt.argValues, tt.flagValues, tt.isValid) + }) + } +} + +func TestBuildRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expected cdn.ApiPatchDistributionRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expected: fixtureRequest(), + }, + { + description: "max without backend", + model: fixtureInputModel( + func(model *inputModel) { + model.Regions = []cdn.Region{cdn.REGION_EU, cdn.REGION_US} + model.BlockedCountries = []string{"DE", "AT", "CH"} + model.BlockedIPs = []string{"127.0.0.1", "10.0.0.8"} + model.DefaultCacheDuration = testCacheDuration + model.MonthlyLimitBytes = utils.Ptr(testMonthlyLimitBytes) + model.Loki = &lokiInputModel{ + Password: "loki-pass", + Username: "loki-user", + PushURL: "https://loki.example.com", + } + model.Optimizer = utils.Ptr(true) + }, + ), + expected: fixtureRequest( + func(payload *cdn.PatchDistributionPayload) { + payload.Config.Regions = &[]cdn.Region{cdn.REGION_EU, cdn.REGION_US} + payload.Config.BlockedCountries = &[]string{"DE", "AT", "CH"} + payload.Config.BlockedIps = &[]string{"127.0.0.1", "10.0.0.8"} + payload.Config.DefaultCacheDuration = cdn.NewNullableString(utils.Ptr(testCacheDuration)) + payload.Config.MonthlyLimitBytes = utils.Ptr(testMonthlyLimitBytes) + payload.Config.LogSink = cdn.NewNullableConfigPatchLogSink(&cdn.ConfigPatchLogSink{ + LokiLogSinkPatch: &cdn.LokiLogSinkPatch{ + Credentials: cdn.NewLokiLogSinkCredentials("loki-pass", "loki-user"), + PushUrl: utils.Ptr("https://loki.example.com"), + }, + }) + payload.Config.Optimizer = &cdn.OptimizerPatch{ + Enabled: utils.Ptr(true), + } + }, + ), + }, + { + description: "max http backend", + model: fixtureInputModel( + func(model *inputModel) { + model.HTTP = &httpInputModel{ + Geofencing: &map[string][]string{"https://dach.example.com": {"DE", "AT", "CH"}}, + OriginRequestHeaders: &map[string]string{"X-Example-Header": "example-value", "X-Another-Header": "another-value"}, + OriginURL: "https://http-backend.example.com", + } + }), + expected: fixtureRequest( + func(payload *cdn.PatchDistributionPayload) { + payload.Config.Backend = &cdn.ConfigPatchBackend{ + HttpBackendPatch: &cdn.HttpBackendPatch{ + Geofencing: &map[string][]string{"https://dach.example.com": {"DE", "AT", "CH"}}, + OriginRequestHeaders: &map[string]string{ + "X-Example-Header": "example-value", + "X-Another-Header": "another-value", + }, + OriginUrl: utils.Ptr("https://http-backend.example.com"), + Type: utils.Ptr("http"), + }, + } + }), + }, + { + description: "max bucket backend", + model: fixtureInputModel( + func(model *inputModel) { + model.Bucket = &bucketInputModel{ + URL: "https://bucket.example.com", + AccessKeyID: "bucket-access-key-id", + Password: "bucket-pass", + Region: "EU", + } + }), + expected: fixtureRequest( + func(payload *cdn.PatchDistributionPayload) { + payload.Config.Backend = &cdn.ConfigPatchBackend{ + BucketBackendPatch: &cdn.BucketBackendPatch{ + BucketUrl: utils.Ptr("https://bucket.example.com"), + Credentials: cdn.NewBucketCredentials("bucket-access-key-id", "bucket-pass"), + Region: utils.Ptr("EU"), + Type: utils.Ptr("bucket"), + }, + } + }), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildRequest(testCtx, testClient, tt.model) + + diff := cmp.Diff(request, tt.expected, + cmp.AllowUnexported(tt.expected, cdn.NullableString{}, cdn.NullableConfigPatchLogSink{}), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestOutputResult(t *testing.T) { + tests := []struct { + description string + outputFormat string + response *cdn.PatchDistributionResponse + expected string + wantErr bool + }{ + { + description: "nil response", + outputFormat: "table", + response: nil, + wantErr: true, + }, + { + description: "table output", + outputFormat: "table", + response: &cdn.PatchDistributionResponse{ + Distribution: &cdn.Distribution{ + Id: ptr.To("dist-1234"), + }, + }, + expected: fmt.Sprintf("Updated CDN distribution for %q. ID: dist-1234\n", testProjectId), + }, + } + + p := print.NewPrinter() + p.Cmd = NewCmd(&types.CmdParams{Printer: p}) + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + buffer := &bytes.Buffer{} + p.Cmd.SetOut(buffer) + if err := outputResult(p, tt.outputFormat, testProjectId, tt.response); (err != nil) != tt.wantErr { + t.Fatalf("outputResult: %v", err) + } + if buffer.String() != tt.expected { + t.Errorf("want:\n%s\ngot:\n%s", tt.expected, buffer.String()) + } + }) + } +} diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index a4ff8b428..9bb2713b5 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -52,6 +52,7 @@ const ( intakeCustomEndpointFlag = "intake-custom-endpoint" logsCustomEndpointFlag = "logs-custom-endpoint" sfsCustomEndpointFlag = "sfs-custom-endpoint" + cdnCustomEndpointFlag = "cdn-custom-endpoint" ) type inputModel struct { @@ -170,6 +171,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(intakeCustomEndpointFlag, "", "Intake API base URL, used in calls to this API") cmd.Flags().String(logsCustomEndpointFlag, "", "Logs API base URL, used in calls to this API") cmd.Flags().String(sfsCustomEndpointFlag, "", "SFS API base URL, used in calls to this API") + cmd.Flags().String(cdnCustomEndpointFlag, "", "CDN API base URL, used in calls to this API") err := viper.BindPFlag(config.SessionTimeLimitKey, cmd.Flags().Lookup(sessionTimeLimitFlag)) cobra.CheckErr(err) @@ -236,6 +238,8 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) err = viper.BindPFlag(config.SfsCustomEndpointKey, cmd.Flags().Lookup(sfsCustomEndpointFlag)) cobra.CheckErr(err) + err = viper.BindPFlag(config.CDNCustomEndpointKey, cmd.Flags().Lookup(cdnCustomEndpointFlag)) + cobra.CheckErr(err) } func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index 460cdf9d4..bf63e4474 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -56,6 +56,7 @@ const ( tokenCustomEndpointFlag = "token-custom-endpoint" intakeCustomEndpointFlag = "intake-custom-endpoint" logsCustomEndpointFlag = "logs-custom-endpoint" + cdnCustomEndpointFlag = "cdn-custom-endpoint" ) type inputModel struct { @@ -98,6 +99,7 @@ type inputModel struct { TokenCustomEndpoint bool IntakeCustomEndpoint bool LogsCustomEndpoint bool + CDNCustomEndpoint bool } func NewCmd(params *types.CmdParams) *cobra.Command { @@ -233,6 +235,9 @@ func NewCmd(params *types.CmdParams) *cobra.Command { if model.SfsCustomEndpoint { viper.Set(config.SfsCustomEndpointKey, "") } + if model.CDNCustomEndpoint { + viper.Set(config.CDNCustomEndpointKey, "") + } err := config.Write() if err != nil { @@ -285,6 +290,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(intakeCustomEndpointFlag, false, "Intake API base URL. If unset, uses the default base URL") cmd.Flags().Bool(logsCustomEndpointFlag, false, "Logs API base URL. If unset, uses the default base URL") cmd.Flags().Bool(sfsCustomEndpointFlag, false, "SFS API base URL. If unset, uses the default base URL") + cmd.Flags().Bool(cdnCustomEndpointFlag, false, "Custom CDN endpoint URL. If unset, uses the default base URL") } func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { @@ -328,6 +334,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) *inputModel { TokenCustomEndpoint: flags.FlagToBoolValue(p, cmd, tokenCustomEndpointFlag), IntakeCustomEndpoint: flags.FlagToBoolValue(p, cmd, intakeCustomEndpointFlag), LogsCustomEndpoint: flags.FlagToBoolValue(p, cmd, logsCustomEndpointFlag), + CDNCustomEndpoint: flags.FlagToBoolValue(p, cmd, cdnCustomEndpointFlag), } p.DebugInputModel(model) diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 65c6cb35b..dda5dcaee 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -48,6 +48,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool tokenCustomEndpointFlag: true, intakeCustomEndpointFlag: true, logsCustomEndpointFlag: true, + cdnCustomEndpointFlag: true, } for _, mod := range mods { mod(flagValues) @@ -92,6 +93,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { TokenCustomEndpoint: true, IntakeCustomEndpoint: true, LogsCustomEndpoint: true, + CDNCustomEndpoint: true, } for _, mod := range mods { mod(model) @@ -152,6 +154,7 @@ func TestParseInput(t *testing.T) { model.TokenCustomEndpoint = false model.IntakeCustomEndpoint = false model.LogsCustomEndpoint = false + model.CDNCustomEndpoint = false }), }, { @@ -344,6 +347,16 @@ func TestParseInput(t *testing.T) { model.LogsCustomEndpoint = false }), }, + { + description: "cdn custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[cdnCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.CDNCustomEndpoint = false + }), + }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 32761f275..e8532775f 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -50,6 +50,7 @@ const ( IaaSCustomEndpointKey = "iaas_custom_endpoint" TokenCustomEndpointKey = "token_custom_endpoint" GitCustomEndpointKey = "git_custom_endpoint" + CDNCustomEndpointKey = "cdn_custom_endpoint" IntakeCustomEndpointKey = "intake_custom_endpoint" LogsCustomEndpointKey = "logs_custom_endpoint" @@ -116,6 +117,7 @@ var ConfigKeys = []string{ IntakeCustomEndpointKey, AlbCustomEndpoint, LogsCustomEndpointKey, + CDNCustomEndpointKey, } var defaultConfigFolderPath string @@ -206,6 +208,7 @@ func setConfigDefaults() { viper.SetDefault(IntakeCustomEndpointKey, "") viper.SetDefault(AlbCustomEndpoint, "") viper.SetDefault(LogsCustomEndpointKey, "") + viper.SetDefault(CDNCustomEndpointKey, "") } func getConfigFilePath(configFolder string) string { diff --git a/internal/pkg/flags/flag_to_value.go b/internal/pkg/flags/flag_to_value.go index 6385ba65a..f08904982 100644 --- a/internal/pkg/flags/flag_to_value.go +++ b/internal/pkg/flags/flag_to_value.go @@ -47,6 +47,20 @@ func FlagToStringSliceValue(p *print.Printer, cmd *cobra.Command, flag string) [ return nil } +// Returns the flag's value as a []string. +// Returns nil if flag is not set, if its value can not be converted to []string, or if the flag does not exist. +func FlagToStringArrayValue(p *print.Printer, cmd *cobra.Command, flag string) []string { + value, err := cmd.Flags().GetStringArray(flag) + if err != nil { + p.Debug(print.ErrorLevel, "convert flag to string array value: %v", err) + return nil + } + if !cmd.Flag(flag).Changed { + return nil + } + return value +} + // Returns a pointer to the flag's value. // Returns nil if the flag is not set, if its value can not be converted to map[string]string, or if the flag does not exist. func FlagToStringToStringPointer(p *print.Printer, cmd *cobra.Command, flag string) *map[string]string { //nolint:gocritic //convenient for setting the SDK payload @@ -75,6 +89,20 @@ func FlagToInt64Pointer(p *print.Printer, cmd *cobra.Command, flag string) *int6 return nil } +// Returns a pointer to the flag's value. +// Returns nil if the flag is not set, if its value can not be converted to int64, or if the flag does not exist. +func FlagToInt32Pointer(p *print.Printer, cmd *cobra.Command, flag string) *int32 { + value, err := cmd.Flags().GetInt32(flag) + if err != nil { + p.Debug(print.ErrorLevel, "convert flag to Int pointer: %v", err) + return nil + } + if cmd.Flag(flag).Changed { + return &value + } + return nil +} + // Returns a pointer to the flag's value. // Returns nil if the flag is not set, if its value can not be converted to string, or if the flag does not exist. func FlagToStringPointer(p *print.Printer, cmd *cobra.Command, flag string) *string { diff --git a/internal/pkg/flags/flag_to_value_test.go b/internal/pkg/flags/flag_to_value_test.go index 5a71f40db..08d25ed9b 100644 --- a/internal/pkg/flags/flag_to_value_test.go +++ b/internal/pkg/flags/flag_to_value_test.go @@ -71,3 +71,116 @@ func TestFlagToStringToStringPointer(t *testing.T) { }) } } + +func TestFlagToStringArrayValue(t *testing.T) { + const flagName = "geofencing" + tests := []struct { + name string + flagValues []string + want []string + }{ + { + name: "flag unset", + flagValues: nil, + want: nil, + }, + { + name: "single flag value", + flagValues: []string{ + "https://foo.example.com DE,CH", + }, + want: []string{ + "https://foo.example.com DE,CH", + }, + }, + { + name: "multiple flag value", + flagValues: []string{ + "https://foo.example.com DE,CH", + "https://bar.example.com AT", + }, + want: []string{ + "https://foo.example.com DE,CH", + "https://bar.example.com AT", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + cmd := func() *cobra.Command { + cmd := &cobra.Command{ + Use: "greet", + Short: "A simple greeting command", + Long: "A simple greeting command", + Run: func(_ *cobra.Command, _ []string) { + fmt.Println("Hello world") + }, + } + cmd.Flags().StringArray(flagName, []string{}, "url to multiple region codes, repeatable") + return cmd + }() + // set the flag value if a value use given, else consider the flag unset + if tt.flagValues != nil { + for _, val := range tt.flagValues { + err := cmd.Flags().Set(flagName, val) + if err != nil { + t.Error(err) + } + } + } + + if got := FlagToStringArrayValue(p, cmd, flagName); !reflect.DeepEqual(got, tt.want) { + t.Errorf("FlagToStringArrayValue() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestFlagToInt32Pointer(t *testing.T) { + const flagName = "limit" + tests := []struct { + name string + flagValue *string + want *int32 + }{ + { + name: "flag unset", + flagValue: nil, + want: nil, + }, + { + name: "flag value", + flagValue: utils.Ptr("42"), + want: utils.Ptr(int32(42)), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := print.NewPrinter() + cmd := func() *cobra.Command { + cmd := &cobra.Command{ + Use: "greet", + Short: "A simple greeting command", + Long: "A simple greeting command", + Run: func(_ *cobra.Command, _ []string) { + fmt.Println("Hello world") + }, + } + cmd.Flags().Int32(flagName, 0, "limit") + return cmd + }() + // set the flag value if a value use given, else consider the flag unset + if tt.flagValue != nil { + err := cmd.Flags().Set(flagName, *tt.flagValue) + if err != nil { + t.Error(err) + } + } + + if got := FlagToInt32Pointer(p, cmd, flagName); !reflect.DeepEqual(got, tt.want) { + t.Errorf("FlagToInt32Pointer() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/pkg/print/print.go b/internal/pkg/print/print.go index ea6ed1b6f..6754db285 100644 --- a/internal/pkg/print/print.go +++ b/internal/pkg/print/print.go @@ -182,11 +182,20 @@ func (p *Printer) PromptForEnter(prompt string) error { func (p *Printer) PromptForPassword(prompt string) (string, error) { p.Cmd.PrintErr(prompt) defer p.Outputln("") - bytePassword, err := term.ReadPassword(int(syscall.Stdin)) + if term.IsTerminal(syscall.Stdin) { + bytePassword, err := term.ReadPassword(syscall.Stdin) + if err != nil { + return "", fmt.Errorf("read password: %w", err) + } + return string(bytePassword), nil + } + // Fallback for non-terminal environments + reader := bufio.NewReader(p.Cmd.InOrStdin()) + pw, err := reader.ReadString('\n') if err != nil { - return "", fmt.Errorf("read password: %w", err) + return "", fmt.Errorf("read password from non-terminal: %w", err) } - return string(bytePassword), nil + return pw[:len(pw)-1], nil // remove trailing newline } // Shows the content in the command's stdout using the "less" command diff --git a/internal/pkg/print/print_test.go b/internal/pkg/print/print_test.go index d52af5241..1867b9e03 100644 --- a/internal/pkg/print/print_test.go +++ b/internal/pkg/print/print_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "log/slog" + "sync" "testing" "github.com/spf13/cobra" @@ -945,3 +946,51 @@ func TestOutputResult(t *testing.T) { }) } } + +func TestPromptForPassword(t *testing.T) { + tests := []struct { + description string + input string + }{ + { + description: "password", + input: "mypassword\n", + }, + { + description: "empty password", + input: "\n", + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + cmd := &cobra.Command{} + r, w := io.Pipe() + defer func() { + r.Close() //nolint:errcheck // ignore error on close + w.Close() //nolint:errcheck // ignore error on close + }() + cmd.SetIn(r) + p := &Printer{ + Cmd: cmd, + Verbosity: ErrorLevel, + } + var pw string + var err error + var wg sync.WaitGroup + wg.Add(1) + go func() { + pw, err = p.PromptForPassword("Enter password: ") + wg.Done() + }() + w.Write([]byte(tt.input)) //nolint:errcheck // ignore error + wg.Wait() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + withoutNewline := tt.input[:len(tt.input)-1] + if pw != withoutNewline { + t.Fatalf("unexpected password: got %q, want %q", pw, withoutNewline) + } + }) + } +} diff --git a/internal/pkg/services/cdn/client/client.go b/internal/pkg/services/cdn/client/client.go new file mode 100644 index 000000000..afefb7a92 --- /dev/null +++ b/internal/pkg/services/cdn/client/client.go @@ -0,0 +1,13 @@ +package client + +import ( + "github.com/spf13/viper" + "github.com/stackitcloud/stackit-cli/internal/pkg/config" + genericclient "github.com/stackitcloud/stackit-cli/internal/pkg/generic-client" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-sdk-go/services/cdn" +) + +func ConfigureClient(p *print.Printer, cliVersion string) (*cdn.APIClient, error) { + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.CDNCustomEndpointKey), true, cdn.NewAPIClient) +} diff --git a/internal/pkg/services/cdn/utils/utils.go b/internal/pkg/services/cdn/utils/utils.go new file mode 100644 index 000000000..f9b903420 --- /dev/null +++ b/internal/pkg/services/cdn/utils/utils.go @@ -0,0 +1,40 @@ +package utils + +import ( + "strings" + + "github.com/stackitcloud/stackit-cli/internal/pkg/print" +) + +func ParseGeofencing(p *print.Printer, geofencingInput []string) *map[string][]string { //nolint:gocritic // convenient for setting the SDK payload + geofencing := make(map[string][]string) + for _, in := range geofencingInput { + firstSpace := strings.IndexRune(in, ' ') + if firstSpace == -1 { + p.Debug(print.ErrorLevel, "invalid geofencing entry (no space found): %q", in) + continue + } + urlPart := in[:firstSpace] + countriesPart := in[firstSpace+1:] + geofencing[urlPart] = nil + countries := strings.Split(countriesPart, ",") + for _, country := range countries { + country = strings.TrimSpace(country) + geofencing[urlPart] = append(geofencing[urlPart], country) + } + } + return &geofencing +} + +func ParseOriginRequestHeaders(p *print.Printer, originRequestHeadersInput []string) *map[string]string { //nolint:gocritic // convenient for setting the SDK payload + originRequestHeaders := make(map[string]string) + for _, in := range originRequestHeadersInput { + parts := strings.Split(in, ":") + if len(parts) != 2 { + p.Debug(print.ErrorLevel, "invalid origin request header entry (no colon found): %q", in) + continue + } + originRequestHeaders[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) + } + return &originRequestHeaders +} diff --git a/internal/pkg/services/cdn/utils/utils_test.go b/internal/pkg/services/cdn/utils/utils_test.go new file mode 100644 index 000000000..9de52e3c4 --- /dev/null +++ b/internal/pkg/services/cdn/utils/utils_test.go @@ -0,0 +1,94 @@ +package utils + +import ( + "reflect" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/print" +) + +func TestParseGeofencing(t *testing.T) { + tests := []struct { + name string + input []string + want map[string][]string + }{ + { + name: "empty input", + input: nil, + want: map[string][]string{}, + }, + { + name: "single entry", + input: []string{ + "https://example.com US,CA,MX", + }, + want: map[string][]string{ + "https://example.com": {"US", "CA", "MX"}, + }, + }, + { + name: "multiple entries", + input: []string{ + "https://example.com US,CA,MX", + "https://another.com DE,FR", + }, + want: map[string][]string{ + "https://example.com": {"US", "CA", "MX"}, + "https://another.com": {"DE", "FR"}, + }, + }, + } + printer := print.NewPrinter() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := ParseGeofencing(printer, tt.input) + if !reflect.DeepEqual(got, &tt.want) { + t.Errorf("ParseGeofencing() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestParseOriginRequestHeaders(t *testing.T) { + tests := []struct { + name string + input []string + want map[string]string + }{ + { + name: "empty input", + input: nil, + want: map[string]string{}, + }, + { + name: "single entry", + input: []string{ + "X-Custom-Header: Value1", + }, + want: map[string]string{ + "X-Custom-Header": "Value1", + }, + }, + { + name: "multiple entries", + input: []string{ + "X-Custom-Header1: Value1", + "X-Custom-Header2: Value2", + }, + want: map[string]string{ + "X-Custom-Header1": "Value1", + "X-Custom-Header2": "Value2", + }, + }, + } + printer := print.NewPrinter() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := ParseOriginRequestHeaders(printer, tt.input) + if !reflect.DeepEqual(got, &tt.want) { + t.Errorf("ParseOriginRequestHeaders() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/pkg/testutils/testutils.go b/internal/pkg/testutils/testutils.go index 1a045cfbf..ceecf888a 100644 --- a/internal/pkg/testutils/testutils.go +++ b/internal/pkg/testutils/testutils.go @@ -13,6 +13,7 @@ import ( // TestParseInput centralizes the logic to test a combination of inputs (arguments, flags) for a cobra command func TestParseInput[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, isValid bool) { + t.Helper() TestParseInputWithAdditionalFlags(t, cmdFactory, parseInputFunc, expectedModel, argValues, flagValues, map[string][]string{}, isValid) } @@ -63,6 +64,21 @@ func TestParseInputWithOptions[T any](t *testing.T, cmdFactory func(*types.CmdPa } } + if cmd.PreRun != nil { + // can be used for dynamic flag configuration + cmd.PreRun(cmd, argValues) + } + + if cmd.PreRunE != nil { + err := cmd.PreRunE(cmd, argValues) + if err != nil { + if !isValid { + return + } + t.Fatalf("error in PreRunE: %v", err) + } + } + err = cmd.ValidateArgs(argValues) if err != nil { if !isValid { diff --git a/internal/pkg/utils/strings.go b/internal/pkg/utils/strings.go index 401287fa1..64817f4ee 100644 --- a/internal/pkg/utils/strings.go +++ b/internal/pkg/utils/strings.go @@ -1,6 +1,8 @@ package utils import ( + "fmt" + "slices" "strings" "unicode/utf8" ) @@ -26,6 +28,23 @@ func JoinStringKeysPtr(m map[string]any, sep string) string { return JoinStringKeys(m, sep) } +// JoinStringMap concatenates the key-value pairs of a string map, key and value separated by keyValueSeparator, key value pairs separated by separator. +func JoinStringMap(m map[string]string, keyValueSeparator, separator string) string { + if m == nil { + return "" + } + keys := make([]string, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + slices.Sort(keys) + parts := make([]string, 0, len(m)) + for _, k := range keys { + parts = append(parts, fmt.Sprintf("%s%s%s", k, keyValueSeparator, m[k])) + } + return strings.Join(parts, separator) +} + // JoinStringPtr concatenates the strings of a string slice pointer, each separatore by the // [sep] string. func JoinStringPtr(vals *[]string, sep string) string { diff --git a/internal/pkg/utils/strings_test.go b/internal/pkg/utils/strings_test.go index a7fb023bc..6f0279045 100644 --- a/internal/pkg/utils/strings_test.go +++ b/internal/pkg/utils/strings_test.go @@ -30,3 +30,39 @@ func TestTruncate(t *testing.T) { }) } } + +func TestJoinStringMap(t *testing.T) { + tests := []struct { + name string + input map[string]string + want string + }{ + { + name: "nil map", + input: nil, + want: "", + }, + { + name: "empty map", + input: map[string]string{}, + want: "", + }, + { + name: "single element", + input: map[string]string{"key1": "value1"}, + want: "key1=value1", + }, + { + name: "multiple elements", + input: map[string]string{"key1": "value1", "key2": "value2"}, + want: "key1=value1, key2=value2", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := JoinStringMap(tt.input, "=", ", "); got != tt.want { + t.Errorf("JoinStringMap() = %v, want %v", got, tt.want) + } + }) + } +} From 2b34f71cc28f7bd81e787ff66941d18729eb9ba4 Mon Sep 17 00:00:00 2001 From: Alexander Dahmen Date: Wed, 28 Jan 2026 09:58:36 +0100 Subject: [PATCH 619/619] chore(cdn): Update CDN version from v1beta2 to v1 (#1252) Signed-off-by: Alexander Dahmen --- docs/stackit_beta_cdn_distribution_update.md | 4 ++-- go.mod | 2 +- go.sum | 6 ++---- internal/cmd/beta/cdn/distribution/update/update.go | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/stackit_beta_cdn_distribution_update.md b/docs/stackit_beta_cdn_distribution_update.md index f8f26dec9..435429c6a 100644 --- a/docs/stackit_beta_cdn_distribution_update.md +++ b/docs/stackit_beta_cdn_distribution_update.md @@ -13,8 +13,8 @@ stackit beta cdn distribution update [flags] ### Examples ``` - update a CDN distribution with ID "123e4567-e89b-12d3-a456-426614174000" to not use optimizer - $ stackit beta cdn update 123e4567-e89b-12d3-a456-426614174000 --optimizer=false + update a CDN distribution with ID "xxx" to not use optimizer + $ stackit beta cdn distribution update xxx --optimizer=false ``` ### Options diff --git a/go.mod b/go.mod index 11590a48d..45355a2c5 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/core v0.20.1 github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0 github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 - github.com/stackitcloud/stackit-sdk-go/services/cdn v1.8.1 + github.com/stackitcloud/stackit-sdk-go/services/cdn v1.9.1 github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 github.com/stackitcloud/stackit-sdk-go/services/edge v0.4.0 github.com/stackitcloud/stackit-sdk-go/services/git v0.10.1 diff --git a/go.sum b/go.sum index 709f665a1..1a3cb2015 100644 --- a/go.sum +++ b/go.sum @@ -604,10 +604,10 @@ github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98e github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ= github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0 h1:P24WoKPt14dfUiUJ4czIv+IiVmdCFQGrKgVtw23fxNg= github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0/go.mod h1:63XvbCslxdfWEp+0Q4OSzQrpbY4kvVODOiIEAEEVH8M= -github.com/stackitcloud/stackit-sdk-go/services/cdn v1.8.1 h1:CiOlfCsCDwHP0kas7qyhfp5XtL2kVmn9e4wjtc3LO10= -github.com/stackitcloud/stackit-sdk-go/services/cdn v1.8.1/go.mod h1:PyZ6g9JsGZZyeISAF+5E7L1lAlMnmbl2YbPj5Teu8to= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 h1:4YFY5PG4vP/NiEP1uxCwh+kQHEU7iHG6syuFD7NPqcw= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0/go.mod h1:v4xdRA5P8Vr+zLdHh+ODgspN0WJG04wLImIJoYjrPK4= +github.com/stackitcloud/stackit-sdk-go/services/cdn v1.9.1 h1:PiNC8VmLqi1WUnBSPefjDXThD43Fvb87p+Y6H8onGA0= +github.com/stackitcloud/stackit-sdk-go/services/cdn v1.9.1/go.mod h1:Nnfe/Zv4Z8F56Ljw/MfXjL0/2Ajia4bGuL/CZuvIXk8= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3 h1:KD/FxU/cJIzfyMvwiOvTlSWq87ISENpHNmw/quznGnw= github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.3/go.mod h1:BNiIZkDqwSV1LkWDjMKxVb9pxQ/HMIsXJ0AQ8pFoAo4= github.com/stackitcloud/stackit-sdk-go/services/edge v0.4.0 h1:+96JOe4oS9BhdH4kHfc5jcl9DVIZiHrMN0/PXn8uWoI= @@ -624,8 +624,6 @@ github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.0 h1:ZyaB4jL71 github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.0/go.mod h1:dYmNdSNDKUG+E0SwuFWu+c8CuMBF/l6w1bdzAHxQao0= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3 h1:fUQLWs2WsXFh+FtFDYOm1kv/gJrGBZLjhVOXJOuYfFY= github.com/stackitcloud/stackit-sdk-go/services/logme v0.25.3/go.mod h1:305j9bvzJ+3c4csOw4SUfLSSxRbkpL0osbvqMI89FeM= -github.com/stackitcloud/stackit-sdk-go/services/logs v0.3.0 h1:N1gerABK2vH7/PBkxZeaWYJ7dz3rjeCHuto+FAuGx3w= -github.com/stackitcloud/stackit-sdk-go/services/logs v0.3.0/go.mod h1:m4IjH1/RtJOF072kjAB0E/ejoIc++myrKmIahphfO6Q= github.com/stackitcloud/stackit-sdk-go/services/logs v0.4.0 h1:EOUVSKvu/m5N+psxeB69IIpANev/jw6HIw2yfh/HO7w= github.com/stackitcloud/stackit-sdk-go/services/logs v0.4.0/go.mod h1:m4IjH1/RtJOF072kjAB0E/ejoIc++myrKmIahphfO6Q= github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.25.3 h1:Y5Ct3Zi5UcIOwjKMWpKl0nrqiq7psTf4NJv0IKgwTkc= diff --git a/internal/cmd/beta/cdn/distribution/update/update.go b/internal/cmd/beta/cdn/distribution/update/update.go index 07fa3022a..0c6662e60 100644 --- a/internal/cmd/beta/cdn/distribution/update/update.go +++ b/internal/cmd/beta/cdn/distribution/update/update.go @@ -82,8 +82,8 @@ func NewCmd(params *types.CmdParams) *cobra.Command { Args: args.SingleArg(argDistributionID, utils.ValidateUUID), Example: examples.Build( examples.NewExample( - `update a CDN distribution with ID "123e4567-e89b-12d3-a456-426614174000" to not use optimizer`, - `$ stackit beta cdn update 123e4567-e89b-12d3-a456-426614174000 --optimizer=false`, + `update a CDN distribution with ID "xxx" to not use optimizer`, + `$ stackit beta cdn distribution update xxx --optimizer=false`, ), ), RunE: func(cmd *cobra.Command, inputArgs []string) error {